blob: 7e8e4378decff4dd39219e2d19d4dc7b021bf259 [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. Buchcik25799ce2005-02-15 14:39:48 +000055 #define ELEM_INFO_ENABLED 1
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000056
57/* #define IDC_ENABLED 1 */
58
59/* #define IDC_VALUE_SUPPORT 1 */
60
61/* #define IDC_XPATH_SUPPORT 1 */
62
63/* #define DEBUG_IDC 1 */
64
Daniel Veillardc0826a72004-08-10 14:17:33 +000065
Daniel Veillard4255d502002-04-16 15:50:10 +000066#define UNBOUNDED (1 << 30)
67#define TODO \
68 xmlGenericError(xmlGenericErrorContext, \
69 "Unimplemented block at %s:%d\n", \
70 __FILE__, __LINE__);
71
William M. Brack2f2a6632004-08-20 23:09:47 +000072#define XML_SCHEMAS_NO_NAMESPACE (const xmlChar *) "##"
Daniel Veillardc0826a72004-08-10 14:17:33 +000073
Daniel Veillard4255d502002-04-16 15:50:10 +000074/*
75 * The XML Schemas namespaces
76 */
77static const xmlChar *xmlSchemaNs = (const xmlChar *)
78 "http://www.w3.org/2001/XMLSchema";
79
80static const xmlChar *xmlSchemaInstanceNs = (const xmlChar *)
81 "http://www.w3.org/2001/XMLSchema-instance";
82
Daniel Veillardc0826a72004-08-10 14:17:33 +000083static const xmlChar *xmlSchemaElemDesElemDecl = (const xmlChar *)
84 "Element decl.";
85static const xmlChar *xmlSchemaElemDesElemRef = (const xmlChar *)
86 "Element ref.";
87static const xmlChar *xmlSchemaElemDesAttrDecl = (const xmlChar *)
88 "Attribute decl.";
89static const xmlChar *xmlSchemaElemDesAttrRef = (const xmlChar *)
90 "Attribute ref.";
91static const xmlChar *xmlSchemaElemDesST = (const xmlChar *)
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000092 "simple type";
Daniel Veillardc0826a72004-08-10 14:17:33 +000093static const xmlChar *xmlSchemaElemDesCT = (const xmlChar *)
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000094 "complex type";
Daniel Veillardc0826a72004-08-10 14:17:33 +000095
Daniel Veillard4255d502002-04-16 15:50:10 +000096#define IS_SCHEMA(node, type) \
97 ((node != NULL) && (node->ns != NULL) && \
98 (xmlStrEqual(node->name, (const xmlChar *) type)) && \
99 (xmlStrEqual(node->ns->href, xmlSchemaNs)))
100
Daniel Veillardc0826a72004-08-10 14:17:33 +0000101#define FREE_AND_NULL(str) \
102 if (str != NULL) { \
103 xmlFree(str); \
104 str = NULL; \
105 }
106
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000107#define IS_ANYTYPE(item) \
108 ((item->type == XML_SCHEMA_TYPE_BASIC) && \
109 (item->builtInType == XML_SCHEMAS_ANYTYPE))
110
111#define IS_COMPLEX_TYPE(item) \
112 ((item->type == XML_SCHEMA_TYPE_COMPLEX) || \
113 (item->builtInType == XML_SCHEMAS_ANYTYPE))
114
115#define IS_SIMPLE_TYPE(item) \
116 ((item->type == XML_SCHEMA_TYPE_SIMPLE) || \
117 ((item->type == XML_SCHEMA_TYPE_BASIC) && \
118 (item->builtInType != XML_SCHEMAS_ANYTYPE)))
119
Daniel Veillardc0826a72004-08-10 14:17:33 +0000120#define XML_SCHEMAS_VAL_WTSP_PRESERVE 0
121#define XML_SCHEMAS_VAL_WTSP_REPLACE 1
122#define XML_SCHEMAS_VAL_WTSP_COLLAPSE 2
123
Daniel Veillard4255d502002-04-16 15:50:10 +0000124#define XML_SCHEMAS_PARSE_ERROR 1
125
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000126#define SCHEMAS_PARSE_OPTIONS XML_PARSE_NOENT
127
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000128
129/*
130* XML_SCHEMA_VAL_XSI_ASSEMBLE_TNS_COMPOSE
131* allow to assemble schemata with
132* the same target namespace from
133* different sources; otherwise, the first
134* encountered schema with a specific target
135* namespace will be used only *
136
137*
138* XML_SCHEMA_VAL_LOCATE_BY_NSNAME = 1<<2
139* locate schemata to be imported
140* using the namespace name; otherwise
141* the location URI will be used */
142
143/*
144* xmlSchemaParserOption:
145*
146* This is the set of XML Schema parser options.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000147*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000148typedef enum {
149 XML_SCHEMA_PAR_LOCATE_BY_NSNAME = 1<<0
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000150 * locate schemata to be imported
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000151 * using the namespace name; otherwise
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000152 * the location URI will be used *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000153} xmlSchemaParserOption;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000154*/
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000155
156/*
157XMLPUBFUN int XMLCALL
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000158 xmlSchemaParserCtxtSetOptions(xmlSchemaParserCtxtPtr ctxt,
159 int options);
160XMLPUBFUN int XMLCALL
161 xmlSchemaParserCtxtGetOptions(xmlSchemaParserCtxtPtr ctxt);
162
163*/
164
165typedef struct _xmlSchemaAssemble xmlSchemaAssemble;
166typedef xmlSchemaAssemble *xmlSchemaAssemblePtr;
167struct _xmlSchemaAssemble {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000168 void **items; /* used for dynamic addition of schemata */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000169 int nbItems; /* used for dynamic addition of schemata */
170 int sizeItems; /* used for dynamic addition of schemata */
171};
172
Daniel Veillard4255d502002-04-16 15:50:10 +0000173struct _xmlSchemaParserCtxt {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000174 void *userData; /* user specific data block */
175 xmlSchemaValidityErrorFunc error; /* the callback in case of errors */
176 xmlSchemaValidityWarningFunc warning; /* the callback in case of warning */
Daniel Veillarde19fc232002-04-22 16:01:24 +0000177 xmlSchemaValidError err;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000178 int nberrors;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000179 xmlStructuredErrorFunc serror;
Daniel Veillard4255d502002-04-16 15:50:10 +0000180
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000181 xmlSchemaPtr topschema; /* The main schema */
182 xmlHashTablePtr namespaces; /* Hash table of namespaces to schemas */
183
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000184 xmlSchemaPtr schema; /* The schema in use */
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000185 const xmlChar *container; /* the current element, group, ... */
Daniel Veillard4255d502002-04-16 15:50:10 +0000186 int counter;
187
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000188 const xmlChar *URL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000189 xmlDocPtr doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +0000190 int preserve; /* Whether the doc should be freed */
Daniel Veillard4255d502002-04-16 15:50:10 +0000191
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000192 const char *buffer;
193 int size;
Daniel Veillard6045c902002-10-09 21:13:59 +0000194
Daniel Veillard4255d502002-04-16 15:50:10 +0000195 /*
196 * Used to build complex element content models
197 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000198 xmlAutomataPtr am;
Daniel Veillard4255d502002-04-16 15:50:10 +0000199 xmlAutomataStatePtr start;
200 xmlAutomataStatePtr end;
201 xmlAutomataStatePtr state;
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000202
203 xmlDictPtr dict; /* dictionnary for interned string names */
Daniel Veillardb0f397e2003-12-23 23:30:53 +0000204 int includes; /* the inclusion level, 0 for root or imports */
Daniel Veillard01fa6152004-06-29 17:04:39 +0000205 xmlSchemaTypePtr ctxtType; /* The current context simple/complex type */
206 xmlSchemaTypePtr parentItem; /* The current parent schema item */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000207 xmlSchemaAssemblePtr assemble;
208 int options;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000209 xmlSchemaValidCtxtPtr vctxt;
Daniel Veillard4255d502002-04-16 15:50:10 +0000210};
211
212
213#define XML_SCHEMAS_ATTR_UNKNOWN 1
214#define XML_SCHEMAS_ATTR_CHECKED 2
Daniel Veillard3646d642004-06-02 19:19:14 +0000215#define XML_SCHEMAS_ATTR_PROHIBITED 3
216#define XML_SCHEMAS_ATTR_MISSING 4
217#define XML_SCHEMAS_ATTR_INVALID_VALUE 5
218#define XML_SCHEMAS_ATTR_TYPE_NOT_RESOLVED 6
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000219#define XML_SCHEMAS_ATTR_INVALID_FIXED_VALUE 7
220#define XML_SCHEMAS_ATTR_DEFAULT 8
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +0000221#define XML_SCHEMAS_ATTR_VALIDATE_VALUE 9
222#define XML_SCHEMAS_ATTR_WILD_NO_DECL 10
Daniel Veillard4255d502002-04-16 15:50:10 +0000223
224typedef struct _xmlSchemaAttrState xmlSchemaAttrState;
225typedef xmlSchemaAttrState *xmlSchemaAttrStatePtr;
226struct _xmlSchemaAttrState {
Daniel Veillard3646d642004-06-02 19:19:14 +0000227 xmlSchemaAttrStatePtr next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000228 xmlAttrPtr attr;
229 int state;
Daniel Veillard3646d642004-06-02 19:19:14 +0000230 xmlSchemaAttributePtr decl;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000231 const xmlChar *value;
Daniel Veillard4255d502002-04-16 15:50:10 +0000232};
233
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000234typedef struct _xmlSchemaBasicItem xmlSchemaBasicItem;
235typedef xmlSchemaBasicItem *xmlSchemaBasicItemPtr;
236struct _xmlSchemaBasicItem {
237 xmlSchemaTypeType type;
238 xmlSchemaAnnotPtr annot;
239};
240
241typedef struct _xmlSchemaItemQNRef xmlSchemaItemQNRef;
242typedef xmlSchemaItemQNRef *xmlSchemaItemQNRefPtr;
243struct _xmlSchemaItemQNRef {
244 xmlSchemaBasicItemPtr item;
245 const xmlChar *name;
246 const xmlChar *targetNamespace;
247};
248
249typedef struct _xmlSchemaIDC xmlSchemaIDC;
250typedef xmlSchemaIDC *xmlSchemaIDCPtr;
251
252/**
253 * xmlSchemaIDCSelect:
254 *
255 * The identity-constraint "field" and "selector" item, holding the
256 * XPath expression.
257 */
258typedef struct _xmlSchemaIDCSelect xmlSchemaIDCSelect;
259typedef xmlSchemaIDCSelect *xmlSchemaIDCSelectPtr;
260struct _xmlSchemaIDCSelect {
261 xmlSchemaIDCSelectPtr next;
262 xmlSchemaIDCPtr idc;
263 int index; /* an index position if significant for IDC key-sequences */
264 const xmlChar *xpath; /* the XPath expression */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +0000265 void *xpathComp; /* the compiled XPath expression */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000266};
267
268/**
269 * xmlSchemaIDC:
270 *
271 * The identity-constraint definition component.
272 */
273
274struct _xmlSchemaIDC {
275 xmlSchemaTypeType type;
276 xmlSchemaAnnotPtr annot;
277 xmlSchemaIDCPtr next;
278 xmlNodePtr node;
279 const xmlChar *name;
280 const xmlChar *targetNamespace;
281 xmlSchemaIDCSelectPtr selector;
282 xmlSchemaIDCSelectPtr fields;
283 int nbFields;
284 xmlSchemaItemQNRefPtr ref;
285};
286
287/**
288 * xmlSchemaIDCAug:
289 *
290 * The augmented IDC information used for validation.
291 */
292typedef struct _xmlSchemaIDCAug xmlSchemaIDCAug;
293typedef xmlSchemaIDCAug *xmlSchemaIDCAugPtr;
294struct _xmlSchemaIDCAug {
295 xmlSchemaIDCAugPtr next; /* next in a list */
296 xmlSchemaIDCPtr def; /* the IDC definition */
297 int bubbleDepth; /* the lowest level to which IDC
298 tables need to be bubbled upwards */
299};
300
301/**
302 * xmlSchemaPSVIIDCKeySequence:
303 *
304 * The key sequence of a node table item.
305 */
306typedef struct _xmlSchemaPSVIIDCKey xmlSchemaPSVIIDCKey;
307typedef xmlSchemaPSVIIDCKey *xmlSchemaPSVIIDCKeyPtr;
308struct _xmlSchemaPSVIIDCKey {
309 xmlSchemaTypePtr type;
310 xmlSchemaValPtr compValue;
311};
312
313/**
314 * xmlSchemaPSVIIDCNode:
315 *
316 * The node table item of a node table.
317 */
318typedef struct _xmlSchemaPSVIIDCNode xmlSchemaPSVIIDCNode;
319typedef xmlSchemaPSVIIDCNode *xmlSchemaPSVIIDCNodePtr;
320struct _xmlSchemaPSVIIDCNode {
321 xmlNodePtr node;
322 xmlSchemaPSVIIDCKeyPtr *keys;
323};
324
325/**
326 * xmlSchemaPSVIIDCBinding:
327 *
328 * The identity-constraint binding item of the [identity-constraint table].
329 */
330typedef struct _xmlSchemaPSVIIDCBinding xmlSchemaPSVIIDCBinding;
331typedef xmlSchemaPSVIIDCBinding *xmlSchemaPSVIIDCBindingPtr;
332struct _xmlSchemaPSVIIDCBinding {
333 xmlSchemaPSVIIDCBindingPtr next; /* next binding of a specific node */
334 xmlSchemaIDCPtr definition; /* the IDC definition */
335 xmlSchemaPSVIIDCNodePtr *nodeTable; /* array of key-sequences */
336 int nbNodes; /* number of entries in the node table */
337 int sizeNodes; /* size of the node table */
338 int nbDupls; /* number of already identified duplicates in the node
339 table */
340 /* int nbKeys; number of keys in each key-sequence */
341};
342
343#define XPATH_STATE_OBJ_TYPE_IDC_SELECTOR 1
344#define XPATH_STATE_OBJ_TYPE_IDC_FIELD 2
345
346#define XPATH_STATE_OBJ_MATCHES -2
347#define XPATH_STATE_OBJ_BLOCKED -3
348
349typedef struct _xmlSchemaIDCMatcher xmlSchemaIDCMatcher;
350typedef xmlSchemaIDCMatcher *xmlSchemaIDCMatcherPtr;
351
352/**
353 * xmlSchemaIDCStateObj:
354 *
355 * The state object used to evaluate XPath expressions.
356 */
357typedef struct _xmlSchemaIDCStateObj xmlSchemaIDCStateObj;
358typedef xmlSchemaIDCStateObj *xmlSchemaIDCStateObjPtr;
359struct _xmlSchemaIDCStateObj {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +0000360 int type;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000361 xmlSchemaIDCStateObjPtr next; /* next if in a list */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +0000362 int depth; /* depth of creation */
363 int *history; /* list of (depth, state-id) tuples */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000364 int nbHistory;
365 int sizeHistory;
366 xmlSchemaIDCMatcherPtr matcher; /* the correspondent field/selector
367 matcher */
368 xmlSchemaIDCSelectPtr sel;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +0000369 void *xpathCtxt;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000370};
371
372#define IDC_MATCHER 0
373
374/**
375 * xmlSchemaIDCMatcher:
376 *
377 * Used to IDC selectors (and fields) successively.
378 */
379struct _xmlSchemaIDCMatcher {
380 int type;
381 int depth; /* the tree depth at creation time */
382 xmlSchemaIDCMatcherPtr next; /* next in the list */
383 xmlSchemaIDCAugPtr aidc; /* the augmented IDC item */
384 xmlSchemaPSVIIDCKeyPtr **keySeqs; /* the key-sequences of the target
385 elements */
386 int sizeKeySeqs;
387 xmlSchemaPSVIIDCKeyPtr **refKeySeqs;
388 int nbRefKeySeqs;
389 int sizeRefKeySeqs;
390 int targetDepth;
391};
392
393/*
394* Element info flags.
395*/
396#define XML_SCHEMA_ELEM_INFO_VALUE_NEEDED 1<<0
397
398/**
399 * xmlSchemaElemInfo:
400 *
401 * Holds information of an element node.
402 */
403typedef struct _xmlSchemaElemInfo xmlSchemaElemInfo;
404typedef xmlSchemaElemInfo *xmlSchemaElemInfoPtr;
405struct _xmlSchemaElemInfo {
406 int depth;
407 int flags; /* combination of element info flags */
408 xmlNodePtr node;
409 const xmlChar *localName;
410 const xmlChar *namespaceName;
411 xmlSchemaTypePtr typeDef; /* the complex/simple type definition if any */
412 xmlSchemaValPtr value; /* the pre-computed value if any */
413 xmlSchemaPSVIIDCBindingPtr idcTable; /* the table of PSVI IDC bindings
414 for the scope element*/
415 xmlSchemaIDCMatcherPtr idcMatchers; /* the IDC matchers for the scope
416 element */
417};
418
Daniel Veillard4255d502002-04-16 15:50:10 +0000419/**
420 * xmlSchemaValidCtxt:
421 *
422 * A Schemas validation context
423 */
424
425struct _xmlSchemaValidCtxt {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000426 void *userData; /* user specific data block */
427 xmlSchemaValidityErrorFunc error; /* the callback in case of errors */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000428 xmlSchemaValidityWarningFunc warning; /* the callback in case of warning */
Daniel Veillard659e71e2003-10-10 14:10:40 +0000429 xmlStructuredErrorFunc serror;
Daniel Veillard4255d502002-04-16 15:50:10 +0000430
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000431 xmlSchemaPtr schema; /* The schema in use */
432 xmlDocPtr doc;
Daniel Veillard4255d502002-04-16 15:50:10 +0000433 xmlParserInputBufferPtr input;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000434 xmlCharEncoding enc;
435 xmlSAXHandlerPtr sax;
436 void *user_data;
Daniel Veillard4255d502002-04-16 15:50:10 +0000437
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000438 xmlDocPtr myDoc;
439 int err;
440 int nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +0000441
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000442 xmlNodePtr node;
443 xmlNodePtr cur;
444 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +0000445
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000446 xmlRegExecCtxtPtr regexp;
447 xmlSchemaValPtr value;
Daniel Veillard4255d502002-04-16 15:50:10 +0000448
Daniel Veillard3646d642004-06-02 19:19:14 +0000449 xmlSchemaAttrStatePtr attrTop;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000450 xmlSchemaAttrStatePtr attr;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000451 /* xmlNodePtr scope; not used */
Daniel Veillardc0826a72004-08-10 14:17:33 +0000452 int valueWS;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000453 int options;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000454 xmlNodePtr validationRoot;
455 xmlSchemaParserCtxtPtr pctxt;
456 int xsiAssemble;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000457#ifdef ELEM_INFO_ENABLED
458 int depth;
459 xmlSchemaElemInfoPtr *elemInfos; /* array of element informations */
460 int sizeElemInfos;
461 xmlSchemaElemInfoPtr elemInfo; /* the current element information */
462#endif
463#ifdef IDC_ENABLED
464 xmlSchemaIDCAugPtr aidcs; /* a list of augmented IDC informations */
465
466 xmlSchemaIDCStateObjPtr xpathStates; /* first active state object. */
467 xmlSchemaIDCStateObjPtr xpathStatePool; /* first stored state object. */
468
469 xmlSchemaPSVIIDCNodePtr *idcNodes; /* list of all IDC node-table entries*/
470 int nbIdcNodes;
471 int sizeIdcNodes;
472
473 xmlSchemaPSVIIDCKeyPtr *idcKeys; /* list of all IDC node-table entries */
474 int nbIdcKeys;
475 int sizeIdcKeys;
476#endif
Daniel Veillard4255d502002-04-16 15:50:10 +0000477};
478
Daniel Veillard1d913862003-11-21 00:28:39 +0000479/*
480 * These are the entries in the schemas importSchemas hash table
481 */
482typedef struct _xmlSchemaImport xmlSchemaImport;
483typedef xmlSchemaImport *xmlSchemaImportPtr;
484struct _xmlSchemaImport {
485 const xmlChar *schemaLocation;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000486 xmlSchemaPtr schema; /* not used any more */
William M. Brack2f2a6632004-08-20 23:09:47 +0000487 xmlDocPtr doc;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000488 int isMain;
Daniel Veillard1d913862003-11-21 00:28:39 +0000489};
Daniel Veillard4255d502002-04-16 15:50:10 +0000490
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000491/*
492 * These are the entries associated to includes in a schemas
493 */
494typedef struct _xmlSchemaInclude xmlSchemaInclude;
495typedef xmlSchemaInclude *xmlSchemaIncludePtr;
496struct _xmlSchemaInclude {
497 xmlSchemaIncludePtr next;
498
499 const xmlChar *schemaLocation;
500 xmlDocPtr doc;
501};
502
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000503typedef struct _xmlSchemaParticle xmlSchemaParticle;
504typedef xmlSchemaParticle *xmlSchemaParticlePtr;
505struct _xmlSchemaParticle {
506 xmlSchemaTypeType type;
507 xmlSchemaParticlePtr next; /* the next particle if in a list */
508 int minOccurs;
509 int maxOccurs;
510 xmlSchemaTypePtr term;
511};
512
513
514typedef struct _xmlSchemaModelGroup xmlSchemaModelGroup;
515typedef xmlSchemaModelGroup *xmlSchemaModelGroupPtr;
516struct _xmlSchemaModelGroup {
517 xmlSchemaTypeType type;
518 int compositor; /* one of all, choice or sequence */
519 xmlSchemaParticlePtr particles; /* list of particles */
520 xmlSchemaAnnotPtr annot;
521};
522
523typedef struct _xmlSchemaModelGroupDef xmlSchemaModelGroupDef;
524typedef xmlSchemaModelGroupDef *xmlSchemaModelGroupDefPtr;
525struct _xmlSchemaModelGroupDef {
526 xmlSchemaTypeType type;
527 const xmlChar *name;
528 const xmlChar *targetNamespace;
529 xmlSchemaModelGroupPtr modelGroup;
530 xmlSchemaAnnotPtr annot;
531};
532
Daniel Veillard4255d502002-04-16 15:50:10 +0000533/************************************************************************
534 * *
535 * Some predeclarations *
536 * *
537 ************************************************************************/
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000538
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000539static int xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt,
540 xmlSchemaPtr schema,
541 xmlNodePtr node);
Daniel Veillard01fa6152004-06-29 17:04:39 +0000542static void
543xmlSchemaTypeFixup(xmlSchemaTypePtr typeDecl,
544 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name);
545static const char *
546xmlSchemaFacetTypeToString(xmlSchemaTypeType type);
547static int
548xmlSchemaValidateSimpleTypeValue(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000549 xmlSchemaTypePtr type,
Daniel Veillard01fa6152004-06-29 17:04:39 +0000550 const xmlChar *value,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000551 int fireErrors,
Daniel Veillardc0826a72004-08-10 14:17:33 +0000552 int applyFacets,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000553 int normalize,
554 int checkNodes);
555static int
556xmlSchemaValidateElementByDeclaration(xmlSchemaValidCtxtPtr ctxt,
557 xmlSchemaElementPtr elemDecl);
558static int
559xmlSchemaValidateElementByWildcard(xmlSchemaValidCtxtPtr ctxt,
560 xmlSchemaTypePtr type);
561static int
562xmlSchemaHasElemOrCharContent(xmlNodePtr node);
William M. Brack2f2a6632004-08-20 23:09:47 +0000563static int
564xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
565 xmlNodePtr node);
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +0000566static void
567xmlSchemaCheckDefaults(xmlSchemaTypePtr typeDecl,
568 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name);
William M. Brack87640d52004-04-17 14:58:15 +0000569
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000570/************************************************************************
571 * *
572 * Datatype error handlers *
573 * *
574 ************************************************************************/
575
576/**
577 * xmlSchemaPErrMemory:
578 * @node: a context node
579 * @extra: extra informations
580 *
581 * Handle an out of memory condition
582 */
583static void
584xmlSchemaPErrMemory(xmlSchemaParserCtxtPtr ctxt,
585 const char *extra, xmlNodePtr node)
586{
587 if (ctxt != NULL)
588 ctxt->nberrors++;
589 __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, node, NULL,
590 extra);
591}
592
593/**
594 * xmlSchemaPErr:
595 * @ctxt: the parsing context
596 * @node: the context node
597 * @error: the error code
598 * @msg: the error message
599 * @str1: extra data
600 * @str2: extra data
601 *
602 * Handle a parser error
603 */
604static void
605xmlSchemaPErr(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
606 const char *msg, const xmlChar * str1, const xmlChar * str2)
607{
608 xmlGenericErrorFunc channel = NULL;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000609 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000610 void *data = NULL;
611
612 if (ctxt != NULL) {
613 ctxt->nberrors++;
614 channel = ctxt->error;
615 data = ctxt->userData;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000616 schannel = ctxt->serror;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000617 }
Daniel Veillard659e71e2003-10-10 14:10:40 +0000618 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000619 error, XML_ERR_ERROR, NULL, 0,
620 (const char *) str1, (const char *) str2, NULL, 0, 0,
621 msg, str1, str2);
622}
623
624/**
625 * xmlSchemaPErr2:
626 * @ctxt: the parsing context
627 * @node: the context node
628 * @node: the current child
629 * @error: the error code
630 * @msg: the error message
631 * @str1: extra data
632 * @str2: extra data
633 *
634 * Handle a parser error
635 */
636static void
637xmlSchemaPErr2(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
638 xmlNodePtr child, int error,
639 const char *msg, const xmlChar * str1, const xmlChar * str2)
640{
641 if (child != NULL)
642 xmlSchemaPErr(ctxt, child, error, msg, str1, str2);
643 else
644 xmlSchemaPErr(ctxt, node, error, msg, str1, str2);
645}
646
Daniel Veillard01fa6152004-06-29 17:04:39 +0000647
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000648/**
Daniel Veillard3646d642004-06-02 19:19:14 +0000649 * xmlSchemaPErrExt:
650 * @ctxt: the parsing context
651 * @node: the context node
652 * @error: the error code
653 * @strData1: extra data
654 * @strData2: extra data
655 * @strData3: extra data
656 * @msg: the message
657 * @str1: extra parameter for the message display
658 * @str2: extra parameter for the message display
659 * @str3: extra parameter for the message display
660 * @str4: extra parameter for the message display
661 * @str5: extra parameter for the message display
662 *
663 * Handle a parser error
664 */
665static void
666xmlSchemaPErrExt(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
667 const xmlChar * strData1, const xmlChar * strData2,
668 const xmlChar * strData3, const char *msg, const xmlChar * str1,
669 const xmlChar * str2, const xmlChar * str3, const xmlChar * str4,
670 const xmlChar * str5)
671{
672
673 xmlGenericErrorFunc channel = NULL;
674 xmlStructuredErrorFunc schannel = NULL;
675 void *data = NULL;
676
677 if (ctxt != NULL) {
678 ctxt->nberrors++;
679 channel = ctxt->error;
680 data = ctxt->userData;
681 schannel = ctxt->serror;
682 }
683 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
684 error, XML_ERR_ERROR, NULL, 0,
685 (const char *) strData1, (const char *) strData2,
William M. Brack803812b2004-06-03 02:11:24 +0000686 (const char *) strData3, 0, 0, msg, str1, str2,
687 str3, str4, str5);
Daniel Veillard3646d642004-06-02 19:19:14 +0000688}
Daniel Veillard01fa6152004-06-29 17:04:39 +0000689
Daniel Veillard3646d642004-06-02 19:19:14 +0000690
691/**
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000692 * xmlSchemaVTypeErrMemory:
693 * @node: a context node
694 * @extra: extra informations
695 *
696 * Handle an out of memory condition
697 */
698static void
699xmlSchemaVErrMemory(xmlSchemaValidCtxtPtr ctxt,
700 const char *extra, xmlNodePtr node)
701{
702 if (ctxt != NULL) {
703 ctxt->nberrors++;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +0000704 ctxt->err = XML_SCHEMAV_INTERNAL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000705 }
706 __xmlSimpleError(XML_FROM_SCHEMASV, XML_ERR_NO_MEMORY, node, NULL,
707 extra);
708}
709
710/**
711 * xmlSchemaVErr3:
712 * @ctxt: the validation context
713 * @node: the context node
714 * @error: the error code
715 * @msg: the error message
716 * @str1: extra data
717 * @str2: extra data
718 * @str3: extra data
719 *
720 * Handle a validation error
721 */
722static void
723xmlSchemaVErr3(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node, int error,
724 const char *msg, const xmlChar *str1, const xmlChar *str2,
725 const xmlChar *str3)
726{
Daniel Veillard659e71e2003-10-10 14:10:40 +0000727 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000728 xmlGenericErrorFunc channel = NULL;
729 void *data = NULL;
730
731 if (ctxt != NULL) {
732 ctxt->nberrors++;
733 ctxt->err = error;
734 channel = ctxt->error;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000735 schannel = ctxt->serror;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000736 data = ctxt->userData;
737 }
738 /* reajust to global error numbers */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +0000739 /* Removed, since the old schema error codes have been
740 * substituted for the global error codes.
741 *
742 * error += XML_SCHEMAV_NOROOT - XML_SCHEMAS_ERR_NOROOT;
743 */
Daniel Veillard659e71e2003-10-10 14:10:40 +0000744 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASV,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000745 error, XML_ERR_ERROR, NULL, 0,
746 (const char *) str1, (const char *) str2,
747 (const char *) str3, 0, 0,
748 msg, str1, str2, str3);
749}
Daniel Veillardc0826a72004-08-10 14:17:33 +0000750
751/**
752 * xmlSchemaVErrExt:
753 * @ctxt: the validation context
754 * @node: the context node
755 * @error: the error code
756 * @msg: the message
757 * @str1: extra parameter for the message display
758 * @str2: extra parameter for the message display
759 * @str3: extra parameter for the message display
760 * @str4: extra parameter for the message display
761 * @str5: extra parameter for the message display
762 *
763 * Handle a validation error
764 */
765static void
766xmlSchemaVErrExt(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node, int error,
767 const char *msg, const xmlChar * str1,
768 const xmlChar * str2, const xmlChar * str3,
769 const xmlChar * str4, const xmlChar * str5)
770{
771 xmlStructuredErrorFunc schannel = NULL;
772 xmlGenericErrorFunc channel = NULL;
773 void *data = NULL;
774
775 if (ctxt != NULL) {
776 ctxt->nberrors++;
777 ctxt->err = error;
778 channel = ctxt->error;
779 schannel = ctxt->serror;
780 data = ctxt->userData;
781 }
782 /* reajust to global error numbers */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +0000783 /* Removed, since the old schema error codes have been
784 * substituted for the global error codes.
785 *
786 * error += XML_SCHEMAV_NOROOT - XML_SCHEMAS_ERR_NOROOT;
787 */
Daniel Veillardc0826a72004-08-10 14:17:33 +0000788 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
789 error, XML_ERR_ERROR, NULL, 0, NULL, NULL, NULL, 0, 0,
790 msg, str1, str2, str3, str4, str5);
791}
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000792/**
793 * xmlSchemaVErr:
794 * @ctxt: the validation context
795 * @node: the context node
796 * @error: the error code
797 * @msg: the error message
798 * @str1: extra data
799 * @str2: extra data
800 *
801 * Handle a validation error
802 */
803static void
804xmlSchemaVErr(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node, int error,
805 const char *msg, const xmlChar * str1, const xmlChar * str2)
806{
Daniel Veillard659e71e2003-10-10 14:10:40 +0000807 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000808 xmlGenericErrorFunc channel = NULL;
809 void *data = NULL;
810
811 if (ctxt != NULL) {
812 ctxt->nberrors++;
813 ctxt->err = error;
814 channel = ctxt->error;
815 data = ctxt->userData;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000816 schannel = ctxt->serror;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000817 }
818 /* reajust to global error numbers */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +0000819 /* Removed, since the old schema error codes have been
820 * substituted for the global error codes.
821 *
822 * error += XML_SCHEMAV_NOROOT - XML_SCHEMAS_ERR_NOROOT;
823 */
Daniel Veillard659e71e2003-10-10 14:10:40 +0000824 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASV,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000825 error, XML_ERR_ERROR, NULL, 0,
826 (const char *) str1, (const char *) str2, NULL, 0, 0,
827 msg, str1, str2);
828}
Daniel Veillard4255d502002-04-16 15:50:10 +0000829
Daniel Veillardc0826a72004-08-10 14:17:33 +0000830/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000831 * xmlSchemaGetAttrName:
Daniel Veillardc0826a72004-08-10 14:17:33 +0000832 * @attr: the attribute declaration/use
833 *
834 * Returns the name of the attribute; if the attribute
835 * is a reference, the name of the referenced global type will be returned.
836 */
837static const xmlChar *
838xmlSchemaGetAttrName(xmlSchemaAttributePtr attr)
839{
840 if (attr->ref != NULL)
841 return(attr->ref);
842 else
843 return(attr->name);
844}
845
846/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000847 * xmlSchemaGetAttrTargetNsURI:
Daniel Veillardc0826a72004-08-10 14:17:33 +0000848 * @type: the type (element or attribute)
849 *
850 * Returns the target namespace URI of the type; if the type is a reference,
851 * the target namespace of the referenced type will be returned.
852 */
853static const xmlChar *
854xmlSchemaGetAttrTargetNsURI(xmlSchemaAttributePtr attr)
855{
856 if (attr->ref != NULL)
857 return (attr->refNs);
858 else
859 return(attr->targetNamespace);
860}
861
862/**
863 * xmlSchemaFormatNsUriLocal:
864 * @buf: the string buffer
865 * @uri: the namespace URI
866 * @local: the local name
867 *
868 * Returns a representation of the given URI used
869 * for error reports.
870 *
871 * Returns an empty string, if @ns is NULL, a formatted
872 * string otherwise.
873 */
874static const xmlChar*
875xmlSchemaFormatNsUriLocal(xmlChar **buf,
876 const xmlChar *uri, const xmlChar *local)
877{
878 if (*buf != NULL)
879 xmlFree(*buf);
880 if (uri == NULL) {
881 *buf = xmlStrdup(BAD_CAST "{'");
882 *buf = xmlStrcat(*buf, local);
883 } else {
884 *buf = xmlStrdup(BAD_CAST "{'");
885 *buf = xmlStrcat(*buf, uri);
886 *buf = xmlStrcat(*buf, BAD_CAST "', '");
887 *buf = xmlStrcat(*buf, local);
888 }
889 *buf = xmlStrcat(*buf, BAD_CAST "'}");
890 return ((const xmlChar *) *buf);
891}
892
893/**
894 * xmlSchemaFormatNsPrefixLocal:
895 * @buf: the string buffer
896 * @ns: the namespace
897 * @local: the local name
898 *
899 * Returns a representation of the given URI used
900 * for error reports.
901 *
902 * Returns an empty string, if @ns is NULL, a formatted
903 * string otherwise.
904 */
905static const xmlChar*
906xmlSchemaFormatNsPrefixLocal(xmlChar **buf,
907 xmlNsPtr ns, const xmlChar *local)
908{
909 if (*buf != NULL) {
910 xmlFree(*buf);
911 *buf = NULL;
912 }
913 if ((ns == NULL) || (ns->prefix == NULL))
914 return(local);
915 else {
916 *buf = xmlStrdup(ns->prefix);
917 *buf = xmlStrcat(*buf, BAD_CAST ":");
918 *buf = xmlStrcat(*buf, local);
919 }
920 return ((const xmlChar *) *buf);
921}
922
923/**
924 * xmlSchemaFormatItemForReport:
925 * @buf: the string buffer
926 * @itemDes: the designation of the item
927 * @itemName: the name of the item
928 * @item: the item as an object
929 * @itemNode: the node of the item
930 * @local: the local name
931 * @parsing: if the function is used during the parse
932 *
933 * Returns a representation of the given item used
934 * for error reports.
935 *
936 * The following order is used to build the resulting
937 * designation if the arguments are not NULL:
938 * 1a. If itemDes not NULL -> itemDes
939 * 1b. If (itemDes not NULL) and (itemName not NULL)
940 * -> itemDes + itemName
941 * 2. If the preceding was NULL and (item not NULL) -> item
942 * 3. If the preceding was NULL and (itemNode not NULL) -> itemNode
943 *
944 * If the itemNode is an attribute node, the name of the attribute
945 * will be appended to the result.
946 *
947 * Returns the formatted string and sets @buf to the resulting value.
948 */
949static xmlChar*
950xmlSchemaFormatItemForReport(xmlChar **buf,
951 const xmlChar *itemDes,
952 xmlSchemaTypePtr item,
953 xmlNodePtr itemNode,
954 int parsing)
955{
956 xmlChar *str = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +0000957 int named = 1;
Daniel Veillardc0826a72004-08-10 14:17:33 +0000958
959 if (*buf != NULL) {
960 xmlFree(*buf);
961 *buf = NULL;
962 }
963
William M. Brack2f2a6632004-08-20 23:09:47 +0000964 if (itemDes != NULL) {
965 *buf = xmlStrdup(itemDes);
966 } else if (item != NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000967 switch (item->type) {
968 case XML_SCHEMA_TYPE_BASIC:
Daniel Veillardc0826a72004-08-10 14:17:33 +0000969 if (item->builtInType == XML_SCHEMAS_ANYTYPE)
970 *buf = xmlStrdup(BAD_CAST "'anyType'");
971 else if (item->builtInType == XML_SCHEMAS_ANYSIMPLETYPE)
972 *buf = xmlStrdup(BAD_CAST "'anySimpleType'");
973 else {
974 /* *buf = xmlStrdup(BAD_CAST "bi "); */
975 /* *buf = xmlStrcat(*buf, xmlSchemaElemDesST); */
976 *buf = xmlStrdup(BAD_CAST "'");
977 *buf = xmlStrcat(*buf, item->name);
978 *buf = xmlStrcat(*buf, BAD_CAST "'");
979 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000980 break;
981 case XML_SCHEMA_TYPE_SIMPLE:
Daniel Veillardc0826a72004-08-10 14:17:33 +0000982 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL) {
983 *buf = xmlStrdup(xmlSchemaElemDesST);
984 *buf = xmlStrcat(*buf, BAD_CAST " '");
985 *buf = xmlStrcat(*buf, item->name);
986 *buf = xmlStrcat(*buf, BAD_CAST "'");
987 } else {
988 *buf = xmlStrdup(xmlSchemaElemDesST);
Daniel Veillardc0826a72004-08-10 14:17:33 +0000989 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000990 break;
991 case XML_SCHEMA_TYPE_COMPLEX:
Daniel Veillardc0826a72004-08-10 14:17:33 +0000992 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL) {
993 *buf = xmlStrdup(xmlSchemaElemDesCT);
994 *buf = xmlStrcat(*buf, BAD_CAST " '");
995 *buf = xmlStrcat(*buf, item->name);
996 *buf = xmlStrcat(*buf, BAD_CAST "'");
997 } else {
998 *buf = xmlStrdup(xmlSchemaElemDesCT);
Daniel Veillardc0826a72004-08-10 14:17:33 +0000999 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001000 break;
1001 case XML_SCHEMA_TYPE_ATTRIBUTE: {
1002 xmlSchemaAttributePtr attr;
1003
1004 attr = (xmlSchemaAttributePtr) item;
1005 if ((attr->flags & XML_SCHEMAS_TYPE_GLOBAL) ||
1006 (attr->ref == NULL)) {
1007 *buf = xmlStrdup(xmlSchemaElemDesAttrDecl);
1008 *buf = xmlStrcat(*buf, BAD_CAST " '");
1009 *buf = xmlStrcat(*buf, attr->name);
1010 *buf = xmlStrcat(*buf, BAD_CAST "'");
1011 } else {
1012 *buf = xmlStrdup(xmlSchemaElemDesAttrRef);
1013 *buf = xmlStrcat(*buf, BAD_CAST " '");
1014 *buf = xmlStrcat(*buf, attr->refPrefix);
1015 *buf = xmlStrcat(*buf, BAD_CAST ":");
1016 *buf = xmlStrcat(*buf, attr->ref);
1017 *buf = xmlStrcat(*buf, BAD_CAST "'");
1018 }
1019 }
1020 break;
1021 case XML_SCHEMA_TYPE_ELEMENT: {
1022 xmlSchemaElementPtr elem;
Daniel Veillardc0826a72004-08-10 14:17:33 +00001023
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001024 elem = (xmlSchemaElementPtr) item;
1025 if ((elem->flags & XML_SCHEMAS_TYPE_GLOBAL) ||
1026 (elem->ref == NULL)) {
1027 *buf = xmlStrdup(xmlSchemaElemDesElemDecl);
1028 *buf = xmlStrcat(*buf, BAD_CAST " '");
1029 *buf = xmlStrcat(*buf, elem->name);
1030 *buf = xmlStrcat(*buf, BAD_CAST "'");
1031 } else {
1032 *buf = xmlStrdup(xmlSchemaElemDesElemRef);
1033 *buf = xmlStrcat(*buf, BAD_CAST " '");
1034 *buf = xmlStrcat(*buf, elem->refPrefix);
1035 *buf = xmlStrcat(*buf, BAD_CAST ":");
1036 *buf = xmlStrcat(*buf, elem->ref);
1037 *buf = xmlStrcat(*buf, BAD_CAST "'");
1038 }
1039 }
1040 break;
1041 case XML_SCHEMA_TYPE_IDC_UNIQUE:
1042 case XML_SCHEMA_TYPE_IDC_KEY:
1043 case XML_SCHEMA_TYPE_IDC_KEYREF:
1044 if (item->type == XML_SCHEMA_TYPE_IDC_UNIQUE)
1045 *buf = xmlStrdup(BAD_CAST "unique '");
1046 else if (item->type == XML_SCHEMA_TYPE_IDC_KEY)
1047 *buf = xmlStrdup(BAD_CAST "key '");
1048 else
1049 *buf = xmlStrdup(BAD_CAST "keyRef '");
1050 *buf = xmlStrcat(*buf, ((xmlSchemaIDCPtr) item)->name);
1051 *buf = xmlStrcat(*buf, BAD_CAST "'");
1052 break;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00001053 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
1054 TODO
1055 break;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001056 default:
William M. Brack2f2a6632004-08-20 23:09:47 +00001057 named = 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001058 }
William M. Brack2f2a6632004-08-20 23:09:47 +00001059 } else
1060 named = 0;
1061
1062 if ((named == 0) && (itemNode != NULL)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00001063 xmlNodePtr elem;
1064
1065 if (itemNode->type == XML_ATTRIBUTE_NODE)
1066 elem = itemNode->parent;
1067 else
1068 elem = itemNode;
1069 *buf = xmlStrdup(BAD_CAST "Element '");
1070 if (parsing)
1071 *buf = xmlStrcat(*buf, elem->name);
1072 else
1073 *buf = xmlStrcat(*buf,
1074 xmlSchemaFormatNsPrefixLocal(&str, elem->ns, elem->name));
1075 *buf = xmlStrcat(*buf, BAD_CAST "'");
1076 }
1077 if ((itemNode != NULL) && (itemNode->type == XML_ATTRIBUTE_NODE)) {
1078 *buf = xmlStrcat(*buf, BAD_CAST ", attribute '");
1079 *buf = xmlStrcat(*buf, xmlSchemaFormatNsPrefixLocal(&str,
1080 itemNode->ns, itemNode->name));
1081 *buf = xmlStrcat(*buf, BAD_CAST "'");
1082 }
1083 FREE_AND_NULL(str);
1084
1085 return (*buf);
1086}
1087
1088/**
1089 * xmlSchemaPFormatItemDes:
1090 * @buf: the string buffer
1091 * @item: the item as a schema object
1092 * @itemNode: the item as a node
1093 *
1094 * If the pointer to @buf is not NULL and @but holds no value,
1095 * the value is set to a item designation using
1096 * xmlSchemaFormatItemForReport. This one avoids adding
1097 * an attribute designation postfix.
1098 *
1099 * Returns a string of all enumeration elements.
1100 */
1101static void
1102xmlSchemaPRequestItemDes(xmlChar **buf,
1103 xmlSchemaTypePtr item,
1104 xmlNodePtr itemNode)
1105{
1106 if ((buf == 0) || (*buf != NULL))
1107 return;
1108 if (itemNode->type == XML_ATTRIBUTE_NODE)
1109 itemNode = itemNode->parent;
1110 xmlSchemaFormatItemForReport(buf, NULL, item, itemNode, 1);
1111}
1112
1113/**
1114 * xmlSchemaFormatFacetEnumSet:
1115 * @buf: the string buffer
1116 * @type: the type holding the enumeration facets
1117 *
1118 * Builds a string consisting of all enumeration elements.
1119 *
1120 * Returns a string of all enumeration elements.
1121 */
1122static const xmlChar *
1123xmlSchemaFormatFacetEnumSet(xmlChar **buf, xmlSchemaTypePtr type)
1124{
1125 xmlSchemaFacetLinkPtr link;
1126
1127 if (*buf != NULL)
1128 xmlFree(*buf);
1129 *buf = NULL;
1130 for (link = type->facetSet; link != NULL; link = link->next) {
1131 if (link->facet->type == XML_SCHEMA_FACET_ENUMERATION) {
1132 if (*buf == NULL) {
1133 *buf = xmlStrdup(BAD_CAST "'");
1134 *buf = xmlStrcat(*buf, link->facet->value);
1135 *buf = xmlStrcat(*buf, BAD_CAST "'");
1136 } else {
1137 *buf = xmlStrcat(*buf, BAD_CAST ", '");
1138 *buf = xmlStrcat(*buf, link->facet->value);
1139 *buf = xmlStrcat(*buf, BAD_CAST "'");
1140 }
1141 }
1142 }
1143 return ((const xmlChar *) *buf);
1144}
1145
1146/**
1147 * xmlSchemaVFacetErr:
1148 * @ctxt: the schema validation context
1149 * @error: the error code
1150 * @node: the node to be validated
1151 * @value: the value of the node
1152 * @type: the type holding the facet
1153 * @facet: the facet
1154 * @message: the error message of NULL
1155 * @str1: extra data
1156 * @str2: extra data
1157 * @str3: extra data
1158 *
1159 * Reports a facet validation error.
1160 * TODO: Should this report the value of an element as well?
1161 */
1162static void
1163xmlSchemaVFacetErr(xmlSchemaValidCtxtPtr ctxt,
1164 xmlParserErrors error,
1165 xmlNodePtr node,
1166 const xmlChar *value,
1167 unsigned long length,
1168 xmlSchemaTypePtr type,
1169 xmlSchemaFacetPtr facet,
1170 const char *message,
1171 const xmlChar *str1,
1172 const xmlChar *str2,
1173 const xmlChar *str3)
1174{
1175 xmlChar *str = NULL, *msg = NULL;
1176 xmlSchemaTypeType facetType;
1177
1178 xmlSchemaFormatItemForReport(&msg, NULL, NULL, node, 0);
1179 msg = xmlStrcat(msg, BAD_CAST " [");
1180 msg = xmlStrcat(msg, xmlSchemaFormatItemForReport(&str, NULL, type, NULL, 0));
1181 msg = xmlStrcat(msg, BAD_CAST ", facet '");
1182 if (error == XML_SCHEMAV_CVC_ENUMERATION_VALID) {
1183 facetType = XML_SCHEMA_FACET_ENUMERATION;
1184 /*
1185 * If enumerations are validated, one must not expect the
1186 * facet to be given.
1187 */
1188 } else
1189 facetType = facet->type;
1190 msg = xmlStrcat(msg, BAD_CAST xmlSchemaFacetTypeToString(facetType));
1191 msg = xmlStrcat(msg, BAD_CAST "']: ");
1192 if (message == NULL) {
1193 /*
1194 * Use a default message.
1195 */
1196 if ((facetType == XML_SCHEMA_FACET_LENGTH) ||
1197 (facetType == XML_SCHEMA_FACET_MINLENGTH) ||
1198 (facetType == XML_SCHEMA_FACET_MAXLENGTH)) {
1199
1200 char len[25], actLen[25];
1201
1202 /* FIXME, TODO: What is the max expected string length of the
1203 * this value?
1204 */
1205 if (node->type == XML_ATTRIBUTE_NODE)
1206 msg = xmlStrcat(msg, BAD_CAST "The value '%s' has a length of '%s'; ");
1207 else
1208 msg = xmlStrcat(msg, BAD_CAST "The value has a length of '%s'; ");
1209
1210 snprintf(len, 24, "%lu", xmlSchemaGetFacetValueAsULong(facet));
1211 snprintf(actLen, 24, "%lu", length);
1212
1213 if (facetType == XML_SCHEMA_FACET_LENGTH)
1214 msg = xmlStrcat(msg,
1215 BAD_CAST "this differs from the allowed length of '%s'.\n");
1216 else if (facetType == XML_SCHEMA_FACET_MAXLENGTH)
1217 msg = xmlStrcat(msg,
1218 BAD_CAST "this exceeds the allowed maximum length of '%s'.\n");
1219 else if (facetType == XML_SCHEMA_FACET_MINLENGTH)
1220 msg = xmlStrcat(msg,
1221 BAD_CAST "this underruns the allowed minimum length of '%s'.\n");
1222
1223 if (node->type == XML_ATTRIBUTE_NODE)
1224 xmlSchemaVErrExt(ctxt, node, error,
1225 (const char *) msg,
1226 value, (const xmlChar *) actLen, (const xmlChar *) len,
1227 NULL, NULL);
1228 else
1229 xmlSchemaVErr(ctxt, node, error,
1230 (const char *) msg,
1231 (const xmlChar *) actLen, (const xmlChar *) len);
1232
1233 } else if (facetType == XML_SCHEMA_FACET_ENUMERATION) {
1234 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not an element "
1235 "of the set {%s}.\n");
1236 xmlSchemaVErr(ctxt, node, error, (const char *) msg, value,
1237 xmlSchemaFormatFacetEnumSet(&str, type));
1238 } else if (facetType == XML_SCHEMA_FACET_PATTERN) {
1239 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not accepted "
1240 "by the pattern '%s'.\n");
1241 xmlSchemaVErr(ctxt, node, error, (const char *) msg, value,
1242 facet->value);
1243 } else if (node->type == XML_ATTRIBUTE_NODE) {
1244 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not facet-valid.\n");
1245 xmlSchemaVErr(ctxt, node, error, (const char *) msg, value, NULL);
1246 } else {
1247 msg = xmlStrcat(msg, BAD_CAST "The value is not facet-valid.\n");
1248 xmlSchemaVErr(ctxt, node, error, (const char *) msg, NULL, NULL);
1249 }
1250 } else {
1251 msg = xmlStrcat(msg, (const xmlChar *) message);
1252 msg = xmlStrcat(msg, BAD_CAST ".\n");
1253 xmlSchemaVErr3(ctxt, node, error, (const char *) msg, str1, str2, str3);
1254 }
1255 FREE_AND_NULL(str)
1256 xmlFree(msg);
1257}
1258
1259/**
1260 * xmlSchemaVSimpleTypeErr:
1261 * @ctxt: the schema validation context
1262 * @error: the error code
1263 * @type: the type used for validation
1264 * @node: the node containing the validated value
1265 * @value: the validated value
1266 *
1267 * Reports a simple type validation error.
1268 * TODO: Should this report the value of an element as well?
1269 */
1270static void
1271xmlSchemaVSimpleTypeErr(xmlSchemaValidCtxtPtr ctxt,
1272 xmlParserErrors error,
1273 xmlNodePtr node,
1274 const xmlChar *value,
1275 xmlSchemaTypePtr type)
1276{
1277 xmlChar *str = NULL, *msg = NULL;
1278
1279 xmlSchemaFormatItemForReport(&msg, NULL, NULL, node, 0);
1280 msg = xmlStrcat(msg, BAD_CAST " [");
1281 msg = xmlStrcat(msg, xmlSchemaFormatItemForReport(&str, NULL, type, NULL, 0));
1282 if (node->type == XML_ATTRIBUTE_NODE) {
1283 msg = xmlStrcat(msg, BAD_CAST "]: The value '%s' is not valid.\n");
1284 xmlSchemaVErr(ctxt, node, error, (const char *) msg, value, NULL);
1285 } else {
1286 msg = xmlStrcat(msg, BAD_CAST "]: The character content is not valid.\n");
1287 xmlSchemaVErr(ctxt, node, error, (const char *) msg, NULL, NULL);
1288 }
1289 FREE_AND_NULL(str)
1290 xmlFree(msg);
1291}
1292
1293/**
William M. Brack2f2a6632004-08-20 23:09:47 +00001294 * xmlSchemaVComplexTypeErr:
1295 * @ctxt: the schema validation context
1296 * @error: the error code
1297 * @node: the node containing the validated value
1298 * @type: the complex type used for validation
1299 * @message: the error message
1300 *
1301 * Reports a complex type validation error.
1302 */
1303static void
1304xmlSchemaVComplexTypeErr(xmlSchemaValidCtxtPtr ctxt,
1305 xmlParserErrors error,
1306 xmlNodePtr node,
1307 xmlSchemaTypePtr type,
1308 const char *message)
1309{
1310 xmlChar *str = NULL, *msg = NULL;
1311
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00001312 xmlSchemaFormatItemForReport(&msg, NULL, NULL, node, 0);
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +00001313 /* Specify the complex type only if it is global. */
1314 if ((type != NULL) && (type->flags & XML_SCHEMAS_TYPE_GLOBAL)) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00001315 msg = xmlStrcat(msg, BAD_CAST " [");
1316 msg = xmlStrcat(msg, xmlSchemaFormatItemForReport(&str, NULL, type, NULL, 0));
1317 msg = xmlStrcat(msg, BAD_CAST "]");
1318 }
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001319 msg = xmlStrcat(msg, BAD_CAST ": %s.\n");
1320 xmlSchemaVErr(ctxt, node, error, (const char *) msg,
William M. Brack2f2a6632004-08-20 23:09:47 +00001321 (const xmlChar *) message, NULL);
1322 FREE_AND_NULL(str)
1323 xmlFree(msg);
1324}
1325
1326/**
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001327 * xmlSchemaVComplexTypeElemErr:
1328 * @ctxt: the schema validation context
1329 * @error: the error code
1330 * @node: the node containing the validated value
1331 * @type: the complex type used for validation
1332 * @message: the error message
1333 *
1334 * Reports a complex type validation error.
1335 */
1336static void
1337xmlSchemaVComplexTypeElemErr(xmlSchemaValidCtxtPtr ctxt,
1338 xmlParserErrors error,
1339 xmlNodePtr node,
1340 xmlSchemaTypePtr type,
1341 const char *message,
1342 int nbval,
1343 int nbneg,
1344 xmlChar **values)
1345{
1346 xmlChar *str = NULL, *msg = NULL;
1347 xmlChar *localName, *nsName;
1348 const xmlChar *cur, *end;
1349 int i;
1350
1351 xmlSchemaFormatItemForReport(&msg, NULL, NULL, node, 0);
1352 /* Specify the complex type only if it is global. */
1353 if ((type != NULL) && (type->flags & XML_SCHEMAS_TYPE_GLOBAL)) {
1354 msg = xmlStrcat(msg, BAD_CAST " [");
1355 msg = xmlStrcat(msg, xmlSchemaFormatItemForReport(&str, NULL, type, NULL, 0));
1356 msg = xmlStrcat(msg, BAD_CAST "]");
1357 FREE_AND_NULL(str)
1358 }
1359 msg = xmlStrcat(msg, BAD_CAST ": ");
1360 msg = xmlStrcat(msg, (const xmlChar *) message);
1361 /*
1362 * Note that is does not make sense to report that we have a
1363 * wildcard here, since the wildcard might be unfolded into
1364 * multiple transitions.
1365 */
1366 if (nbval + nbneg > 0) {
1367 if (nbval + nbneg > 1) {
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00001368 str = xmlStrdup(BAD_CAST ". Expected is one of ( ");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001369 } else
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00001370 str = xmlStrdup(BAD_CAST ". Expected is ( ");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001371 nsName = NULL;
1372
1373 for (i = 0; i < nbval + nbneg; i++) {
1374 cur = values[i];
1375 /*
1376 * Get the local name.
1377 */
1378 localName = NULL;
1379
1380 end = cur;
1381 if (*end == '*') {
1382 localName = xmlStrdup(BAD_CAST "*");
1383 *end++;
1384 } else {
1385 while ((*end != 0) && (*end != '|'))
1386 end++;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001387 localName = xmlStrncat(localName, BAD_CAST cur, end - cur);
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001388 }
1389 if (*end != 0) {
1390 *end++;
1391 /*
1392 * Skip "*|*" if they come with negated expressions, since
1393 * they represent the same negated wildcard.
1394 */
1395 if ((nbneg == 0) || (*end != '*') || (*localName != '*')) {
1396 /*
1397 * Get the namespace name.
1398 */
1399 cur = end;
1400 if (*end == '*') {
1401 nsName = xmlStrdup(BAD_CAST "{*}");
1402 } else {
1403 while (*end != 0)
1404 end++;
1405
1406 if (i >= nbval)
1407 nsName = xmlStrdup(BAD_CAST "{##other:");
1408 else
1409 nsName = xmlStrdup(BAD_CAST "{");
1410
1411 nsName = xmlStrncat(nsName, BAD_CAST cur, end - cur);
1412 nsName = xmlStrcat(nsName, BAD_CAST "}");
1413 }
1414 str = xmlStrcat(str, BAD_CAST nsName);
1415 FREE_AND_NULL(nsName)
1416 } else {
1417 FREE_AND_NULL(localName);
1418 continue;
1419 }
1420 }
1421 str = xmlStrcat(str, BAD_CAST localName);
1422 FREE_AND_NULL(localName);
1423
1424 if (i < nbval + nbneg -1)
1425 str = xmlStrcat(str, BAD_CAST ", ");
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00001426 }
1427 str = xmlStrcat(str, BAD_CAST " )");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001428 msg = xmlStrcat(msg, BAD_CAST str);
1429 FREE_AND_NULL(str)
1430 }
1431 msg = xmlStrcat(msg, BAD_CAST ".\n");
1432 xmlSchemaVErr(ctxt, node, error, (const char *) msg, NULL, NULL);
1433 xmlFree(msg);
1434}
1435
1436/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00001437 * xmlSchemaPMissingAttrErr:
1438 * @ctxt: the schema validation context
1439 * @ownerDes: the designation of the owner
1440 * @ownerName: the name of the owner
1441 * @ownerItem: the owner as a schema object
1442 * @ownerElem: the owner as an element node
1443 * @node: the parent element node of the missing attribute node
1444 * @type: the corresponding type of the attribute node
1445 *
1446 * Reports an illegal attribute.
1447 */
1448static void
1449xmlSchemaPMissingAttrErr(xmlSchemaParserCtxtPtr ctxt,
1450 xmlParserErrors error,
1451 xmlChar **ownerDes,
1452 xmlSchemaTypePtr ownerItem,
1453 xmlNodePtr ownerElem,
1454 const char *name,
1455 const char *message)
1456{
1457 xmlChar *des = NULL;
1458
1459 if (ownerDes == NULL)
1460 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem, 1);
1461 else if (*ownerDes == NULL) {
1462 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, ownerElem, 1);
1463 des = *ownerDes;
1464 } else
1465 des = *ownerDes;
1466 if (message != NULL)
1467 xmlSchemaPErr(ctxt, ownerElem, error, "%s: %s.\n", BAD_CAST des, BAD_CAST message);
1468 else
1469 xmlSchemaPErr(ctxt, ownerElem, error,
1470 "%s: The attribute '%s' is required but missing.\n",
1471 BAD_CAST des, BAD_CAST name);
1472 if (ownerDes == NULL)
1473 FREE_AND_NULL(des);
1474}
1475
William M. Brack2f2a6632004-08-20 23:09:47 +00001476/**
1477 * xmlSchemaCompTypeToString:
1478 * @type: the type of the schema item
1479 *
1480 * Returns the component name of a schema item.
1481 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001482static const char *
1483xmlSchemaCompTypeToString(xmlSchemaTypeType type)
1484{
1485 switch (type) {
1486 case XML_SCHEMA_TYPE_SIMPLE:
1487 return("simple type definition");
1488 case XML_SCHEMA_TYPE_COMPLEX:
1489 return("complex type definition");
1490 case XML_SCHEMA_TYPE_ELEMENT:
1491 return("element declaration");
1492 case XML_SCHEMA_TYPE_ATTRIBUTE:
1493 return("attribute declaration");
1494 case XML_SCHEMA_TYPE_GROUP:
1495 return("model group definition");
1496 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1497 return("attribute group definition");
1498 case XML_SCHEMA_TYPE_NOTATION:
1499 return("notation declaration");
1500 default:
1501 return("Not a schema component");
1502 }
1503}
1504/**
1505 * xmlSchemaPResCompAttrErr:
1506 * @ctxt: the schema validation context
1507 * @error: the error code
1508 * @ownerDes: the designation of the owner
1509 * @ownerItem: the owner as a schema object
1510 * @ownerElem: the owner as an element node
1511 * @name: the name of the attribute holding the QName
1512 * @refName: the referenced local name
1513 * @refURI: the referenced namespace URI
1514 * @message: optional message
1515 *
1516 * Used to report QName attribute values that failed to resolve
1517 * to schema components.
1518 */
1519static void
1520xmlSchemaPResCompAttrErr(xmlSchemaParserCtxtPtr ctxt,
1521 xmlParserErrors error,
1522 xmlChar **ownerDes,
1523 xmlSchemaTypePtr ownerItem,
1524 xmlNodePtr ownerElem,
1525 const char *name,
1526 const xmlChar *refName,
1527 const xmlChar *refURI,
1528 xmlSchemaTypeType refType,
1529 const char *refTypeStr)
1530{
1531 xmlChar *des = NULL, *strA = NULL;
1532
1533 if (ownerDes == NULL)
1534 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem, 1);
1535 else if (*ownerDes == NULL) {
1536 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, ownerElem, 1);
1537 des = *ownerDes;
1538 } else
1539 des = *ownerDes;
Daniel Veillardc0826a72004-08-10 14:17:33 +00001540 if (refTypeStr == NULL)
1541 refTypeStr = xmlSchemaCompTypeToString(refType);
1542 xmlSchemaPErrExt(ctxt, ownerElem, error,
1543 NULL, NULL, NULL,
1544 "%s, attribute '%s': The QName value %s does not resolve to a(n) "
1545 "%s.\n", BAD_CAST des, BAD_CAST name,
1546 xmlSchemaFormatNsUriLocal(&strA, refURI, refName),
1547 BAD_CAST refTypeStr, NULL);
1548 if (ownerDes == NULL)
1549 FREE_AND_NULL(des)
1550 FREE_AND_NULL(strA)
1551}
1552
William M. Brack2f2a6632004-08-20 23:09:47 +00001553/**
1554 * xmlSchemaPCustomAttrErr:
1555 * @ctxt: the schema parser context
1556 * @error: the error code
1557 * @ownerDes: the designation of the owner
1558 * @ownerItem: the owner as a schema object
1559 * @attr: the illegal attribute node
1560 *
1561 * Reports an illegal attribute during the parse.
1562 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001563static void
1564xmlSchemaPCustomAttrErr(xmlSchemaParserCtxtPtr ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00001565 xmlParserErrors error,
1566 xmlChar **ownerDes,
1567 xmlSchemaTypePtr ownerItem,
1568 xmlAttrPtr attr,
1569 const char *msg)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001570{
1571 xmlChar *des = NULL;
1572
1573 if (ownerDes == NULL)
1574 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent, 1);
1575 else if (*ownerDes == NULL) {
1576 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent, 1);
1577 des = *ownerDes;
1578 } else
1579 des = *ownerDes;
1580 xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
1581 "%s, attribute '%s': %s.\n",
1582 BAD_CAST des, attr->name, (const xmlChar *) msg, NULL, NULL);
1583 if (ownerDes == NULL)
1584 FREE_AND_NULL(des);
1585}
1586
1587/**
1588 * xmlSchemaPIllegalAttrErr:
William M. Brack2f2a6632004-08-20 23:09:47 +00001589 * @ctxt: the schema parser context
Daniel Veillardc0826a72004-08-10 14:17:33 +00001590 * @error: the error code
William M. Brack2f2a6632004-08-20 23:09:47 +00001591 * @ownerDes: the designation of the attribute's owner
1592 * @ownerItem: the attribute's owner item
Daniel Veillardc0826a72004-08-10 14:17:33 +00001593 * @attr: the illegal attribute node
1594 *
William M. Brack2f2a6632004-08-20 23:09:47 +00001595 * Reports an illegal attribute during the parse.
Daniel Veillardc0826a72004-08-10 14:17:33 +00001596 */
1597static void
1598xmlSchemaPIllegalAttrErr(xmlSchemaParserCtxtPtr ctxt,
1599 xmlParserErrors error,
1600 xmlChar **ownerDes,
1601 xmlSchemaTypePtr ownerItem,
1602 xmlAttrPtr attr)
1603{
1604 xmlChar *des = NULL, *strA = NULL;
1605
1606 if (ownerDes == NULL)
1607 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent, 1);
1608 else if (*ownerDes == NULL) {
1609 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent, 1);
1610 des = *ownerDes;
1611 } else
1612 des = *ownerDes;
1613 xmlSchemaPErr(ctxt, (xmlNodePtr) attr, error,
1614 "%s: The attribute '%s' is not allowed.\n", BAD_CAST des,
1615 xmlSchemaFormatNsPrefixLocal(&strA, attr->ns, attr->name));
1616 if (ownerDes == NULL)
1617 FREE_AND_NULL(des);
1618 FREE_AND_NULL(strA);
1619}
1620
William M. Brack2f2a6632004-08-20 23:09:47 +00001621/**
1622 * xmlSchemaPAquireDes:
1623 * @des: the first designation
1624 * @itemDes: the second designation
1625 * @item: the schema item
1626 * @itemElem: the node of the schema item
1627 *
1628 * Creates a designation for an item.
1629 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001630static void
1631xmlSchemaPAquireDes(xmlChar **des,
1632 xmlChar **itemDes,
1633 xmlSchemaTypePtr item,
1634 xmlNodePtr itemElem)
1635{
1636 if (itemDes == NULL)
1637 xmlSchemaFormatItemForReport(des, NULL, item, itemElem, 1);
1638 else if (*itemDes == NULL) {
1639 xmlSchemaFormatItemForReport(itemDes, NULL, item, itemElem, 1);
1640 *des = *itemDes;
1641 } else
1642 *des = *itemDes;
1643}
1644
William M. Brack2f2a6632004-08-20 23:09:47 +00001645/**
1646 * xmlSchemaPCustomErr:
1647 * @ctxt: the schema parser context
1648 * @error: the error code
1649 * @itemDes: the designation of the schema item
1650 * @item: the schema item
1651 * @itemElem: the node of the schema item
1652 * @message: the error message
1653 * @str1: an optional param for the error message
1654 * @str2: an optional param for the error message
1655 * @str3: an optional param for the error message
1656 *
1657 * Reports an error during parsing.
1658 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001659static void
1660xmlSchemaPCustomErrExt(xmlSchemaParserCtxtPtr ctxt,
1661 xmlParserErrors error,
1662 xmlChar **itemDes,
1663 xmlSchemaTypePtr item,
1664 xmlNodePtr itemElem,
1665 const char *message,
1666 const xmlChar *str1,
1667 const xmlChar *str2,
1668 const xmlChar *str3)
1669{
1670 xmlChar *des = NULL, *msg = NULL;
1671
1672 xmlSchemaPAquireDes(&des, itemDes, item, itemElem);
1673 msg = xmlStrdup(BAD_CAST "%s: ");
1674 msg = xmlStrcat(msg, (const xmlChar *) message);
1675 msg = xmlStrcat(msg, BAD_CAST ".\n");
1676 if ((itemElem == NULL) && (item != NULL))
1677 itemElem = item->node;
1678 xmlSchemaPErrExt(ctxt, itemElem, error, NULL, NULL, NULL,
1679 (const char *) msg, BAD_CAST des, str1, str2, str3, NULL);
1680 if (itemDes == NULL)
1681 FREE_AND_NULL(des);
1682 FREE_AND_NULL(msg);
1683}
1684
William M. Brack2f2a6632004-08-20 23:09:47 +00001685/**
1686 * xmlSchemaPCustomErr:
1687 * @ctxt: the schema parser context
1688 * @error: the error code
1689 * @itemDes: the designation of the schema item
1690 * @item: the schema item
1691 * @itemElem: the node of the schema item
1692 * @message: the error message
1693 * @str1: the optional param for the error message
1694 *
1695 * Reports an error during parsing.
1696 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001697static void
1698xmlSchemaPCustomErr(xmlSchemaParserCtxtPtr ctxt,
1699 xmlParserErrors error,
1700 xmlChar **itemDes,
1701 xmlSchemaTypePtr item,
1702 xmlNodePtr itemElem,
1703 const char *message,
1704 const xmlChar *str1)
1705{
1706 xmlSchemaPCustomErrExt(ctxt, error, itemDes, item, itemElem, message,
1707 str1, NULL, NULL);
1708}
1709
William M. Brack2f2a6632004-08-20 23:09:47 +00001710/**
1711 * xmlSchemaPAttrUseErr:
1712 * @ctxt: the schema parser context
1713 * @error: the error code
1714 * @itemDes: the designation of the schema type
1715 * @item: the schema type
1716 * @itemElem: the node of the schema type
1717 * @attr: the invalid schema attribute
1718 * @message: the error message
1719 * @str1: the optional param for the error message
1720 *
1721 * Reports an attribute use error during parsing.
1722 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001723static void
1724xmlSchemaPAttrUseErr(xmlSchemaParserCtxtPtr ctxt,
1725 xmlParserErrors error,
1726 xmlChar **itemDes,
1727 xmlSchemaTypePtr item,
1728 xmlNodePtr itemElem,
1729 const xmlSchemaAttributePtr attr,
1730 const char *message,
1731 const xmlChar *str1)
1732{
1733 xmlChar *des = NULL, *strA = NULL, *msg = NULL;
1734
1735 xmlSchemaPAquireDes(&des, itemDes, item, itemElem);
1736 xmlSchemaFormatNsUriLocal(&strA, xmlSchemaGetAttrTargetNsURI(attr),
1737 xmlSchemaGetAttrName(attr));
1738 msg = xmlStrdup(BAD_CAST "%s, attr. use %s: ");
1739 msg = xmlStrcat(msg, (const xmlChar *) message);
1740 msg = xmlStrcat(msg, BAD_CAST ".\n");
1741 if ((itemElem == NULL) && (item != NULL))
1742 itemElem = item->node;
1743 xmlSchemaPErrExt(ctxt, itemElem, error, NULL, NULL, NULL,
1744 (const char *) msg, BAD_CAST des, BAD_CAST strA, str1, NULL, NULL);
1745 if (itemDes == NULL)
1746 FREE_AND_NULL(des);
1747 FREE_AND_NULL(strA);
1748 xmlFree(msg);
1749}
1750
William M. Brack2f2a6632004-08-20 23:09:47 +00001751/**
1752 * xmlSchemaPIllegalFacetAtomicErr:
1753 * @ctxt: the schema parser context
1754 * @error: the error code
1755 * @itemDes: the designation of the type
1756 * @item: the schema type
1757 * @baseItem: the base type of type
1758 * @facet: the illegal facet
1759 *
1760 * Reports an illegal facet for atomic simple types.
1761 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001762static void
1763xmlSchemaPIllegalFacetAtomicErr(xmlSchemaParserCtxtPtr ctxt,
1764 xmlParserErrors error,
1765 xmlChar **itemDes,
1766 xmlSchemaTypePtr item,
1767 xmlSchemaTypePtr baseItem,
1768 xmlSchemaFacetPtr facet)
1769{
1770 xmlChar *des = NULL, *strT = NULL;
1771
1772 xmlSchemaPAquireDes(&des, itemDes, item, item->node);
1773 xmlSchemaPErrExt(ctxt, item->node, error, NULL, NULL, NULL,
1774 "%s: The facet '%s' is not allowed on types derived from the "
1775 "type %s.\n",
1776 BAD_CAST des, BAD_CAST xmlSchemaFacetTypeToString(facet->type),
1777 xmlSchemaFormatItemForReport(&strT, NULL, baseItem, NULL, 1),
1778 NULL, NULL);
1779 if (itemDes == NULL)
1780 FREE_AND_NULL(des);
1781 FREE_AND_NULL(strT);
1782}
1783
William M. Brack2f2a6632004-08-20 23:09:47 +00001784/**
1785 * xmlSchemaPIllegalFacetListUnionErr:
1786 * @ctxt: the schema parser context
1787 * @error: the error code
1788 * @itemDes: the designation of the schema item involved
1789 * @item: the schema item involved
1790 * @facet: the illegal facet
1791 *
1792 * Reports an illegal facet for <list> and <union>.
1793 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001794static void
1795xmlSchemaPIllegalFacetListUnionErr(xmlSchemaParserCtxtPtr ctxt,
1796 xmlParserErrors error,
1797 xmlChar **itemDes,
1798 xmlSchemaTypePtr item,
1799 xmlSchemaFacetPtr facet)
1800{
1801 xmlChar *des = NULL, *strT = NULL;
1802
1803 xmlSchemaPAquireDes(&des, itemDes, item, item->node);
1804 xmlSchemaPErr(ctxt, item->node, error,
1805 "%s: The facet '%s' is not allowed.\n",
1806 BAD_CAST des, BAD_CAST xmlSchemaFacetTypeToString(facet->type));
1807 if (itemDes == NULL)
1808 FREE_AND_NULL(des);
1809 FREE_AND_NULL(strT);
1810}
1811
1812/**
1813 * xmlSchemaPMutualExclAttrErr:
1814 * @ctxt: the schema validation context
1815 * @error: the error code
1816 * @elemDes: the designation of the parent element node
1817 * @attr: the bad attribute node
1818 * @type: the corresponding type of the attribute node
1819 *
1820 * Reports an illegal attribute.
1821 */
1822static void
1823xmlSchemaPMutualExclAttrErr(xmlSchemaParserCtxtPtr ctxt,
1824 xmlParserErrors error,
1825 xmlChar **ownerDes,
1826 xmlSchemaTypePtr ownerItem,
1827 xmlAttrPtr attr,
1828 const char *name1,
1829 const char *name2)
1830{
1831 xmlChar *des = NULL;
1832
1833 if (ownerDes == NULL)
1834 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent, 1);
1835 else if (*ownerDes == NULL) {
1836 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent, 1);
1837 des = *ownerDes;
1838 } else
1839 des = *ownerDes;
1840 xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
1841 "%s: The attributes '%s' and '%s' are mutually exclusive.\n",
1842 BAD_CAST des, BAD_CAST name1, BAD_CAST name2, NULL, NULL);
1843 if (ownerDes == NULL)
1844 FREE_AND_NULL(des)
1845}
1846
1847/**
1848 * xmlSchemaPSimpleTypeErr:
1849 * @ctxt: the schema validation context
1850 * @error: the error code
William M. Brack2f2a6632004-08-20 23:09:47 +00001851 * @type: the type specifier
Daniel Veillardc0826a72004-08-10 14:17:33 +00001852 * @ownerDes: the designation of the owner
1853 * @ownerItem: the schema object if existent
1854 * @node: the validated node
1855 * @value: the validated value
1856 *
1857 * Reports a simple type validation error.
1858 * TODO: Should this report the value of an element as well?
1859 */
1860static void
1861xmlSchemaPSimpleTypeErr(xmlSchemaParserCtxtPtr ctxt,
1862 xmlParserErrors error,
1863 xmlChar **ownerDes,
1864 xmlSchemaTypePtr ownerItem,
1865 xmlNodePtr node,
William M. Brack2f2a6632004-08-20 23:09:47 +00001866 xmlSchemaTypePtr type,
Daniel Veillardc0826a72004-08-10 14:17:33 +00001867 const char *typeDes,
1868 const xmlChar *value,
1869 const char *message,
1870 const xmlChar *str1,
1871 const xmlChar *str2)
1872{
William M. Brack2f2a6632004-08-20 23:09:47 +00001873 xmlChar *des = NULL, *strA = NULL, *strT = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00001874
1875 if (ownerDes == NULL)
1876 xmlSchemaPRequestItemDes(&des, ownerItem, node);
1877 else if (*ownerDes == NULL) {
1878 xmlSchemaPRequestItemDes(ownerDes, ownerItem, node);
1879 des = *ownerDes;
1880 } else
1881 des = *ownerDes;
William M. Brack2f2a6632004-08-20 23:09:47 +00001882 if (type != NULL)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001883 typeDes = (const char *) xmlSchemaFormatItemForReport(&strT, NULL, type, NULL, 1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00001884 if (message == NULL) {
1885 /*
1886 * Use default messages.
1887 */
1888 if (node->type == XML_ATTRIBUTE_NODE) {
1889 xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL,
1890 "%s, attribute '%s' [%s]: The value '%s' is not "
1891 "valid.\n",
1892 BAD_CAST des, xmlSchemaFormatNsPrefixLocal(&strA, node->ns,
1893 node->name), BAD_CAST typeDes, value, NULL);
1894 } else {
1895 xmlSchemaPErr(ctxt, node, error,
1896 "%s [%s]: The character content is not valid.\n",
1897 BAD_CAST des, BAD_CAST typeDes);
1898 }
1899 } else {
1900 xmlChar *msg;
1901
1902 msg = xmlStrdup(BAD_CAST "%s");
1903 if (node->type == XML_ATTRIBUTE_NODE)
1904 msg = xmlStrcat(msg, BAD_CAST ", attribute '%s'");
1905 msg = xmlStrcat(msg, BAD_CAST " [%s]: ");
1906 msg = xmlStrcat(msg, (const xmlChar *) message);
1907 msg = xmlStrcat(msg, BAD_CAST ".\n");
1908 if (node->type == XML_ATTRIBUTE_NODE) {
1909 xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL,
1910 (const char *) msg,
1911 BAD_CAST des, xmlSchemaFormatNsPrefixLocal(&strA,
1912 node->ns, node->name), BAD_CAST typeDes, str1, str2);
1913 } else {
1914 xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL,
1915 (const char *) msg,
1916 BAD_CAST des, BAD_CAST typeDes, str1, str2, NULL);
1917 }
1918 xmlFree(msg);
1919 }
1920 /* Cleanup. */
1921 FREE_AND_NULL(strA)
1922 FREE_AND_NULL(strT)
1923 if (ownerDes == NULL)
1924 FREE_AND_NULL(des)
1925}
1926
William M. Brack2f2a6632004-08-20 23:09:47 +00001927/**
1928 * xmlSchemaPContentErr:
1929 * @ctxt: the schema parser context
1930 * @error: the error code
1931 * @onwerDes: the designation of the holder of the content
1932 * @ownerItem: the owner item of the holder of the content
1933 * @ownerElem: the node of the holder of the content
1934 * @child: the invalid child node
1935 * @message: the optional error message
1936 * @content: the optional string describing the correct content
1937 *
1938 * Reports an error concerning the content of a schema element.
1939 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001940static void
1941xmlSchemaPContentErr(xmlSchemaParserCtxtPtr ctxt,
1942 xmlParserErrors error,
1943 xmlChar **ownerDes,
1944 xmlSchemaTypePtr ownerItem,
1945 xmlNodePtr ownerElem,
1946 xmlNodePtr child,
1947 const char *message,
1948 const char *content)
1949{
1950 xmlChar *des = NULL;
1951
1952 if (ownerDes == NULL)
1953 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem, 1);
1954 else if (*ownerDes == NULL) {
1955 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, ownerElem, 1);
1956 des = *ownerDes;
1957 } else
1958 des = *ownerDes;
1959 if (message != NULL)
1960 xmlSchemaPErr2(ctxt, ownerElem, child, error,
1961 "%s: %s.\n",
1962 BAD_CAST des, BAD_CAST message);
1963 else {
1964 if (content != NULL) {
1965 xmlSchemaPErr2(ctxt, ownerElem, child, error,
1966 "%s: The content is not valid. Expected is %s.\n",
1967 BAD_CAST des, BAD_CAST content);
1968 } else {
1969 xmlSchemaPErr2(ctxt, ownerElem, child, error,
1970 "%s: The content is not valid.\n",
1971 BAD_CAST des, NULL);
1972 }
1973 }
1974 if (ownerDes == NULL)
1975 FREE_AND_NULL(des)
1976}
1977
1978/**
1979 * xmlSchemaVIllegalAttrErr:
1980 * @ctxt: the schema validation context
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00001981 * @error: the error code
Daniel Veillardc0826a72004-08-10 14:17:33 +00001982 * @attr: the illegal attribute node
1983 *
1984 * Reports an illegal attribute.
1985 */
1986static void
1987xmlSchemaVIllegalAttrErr(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00001988 xmlParserErrors error,
William M. Brack2f2a6632004-08-20 23:09:47 +00001989 xmlAttrPtr attr)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001990{
1991 xmlChar *strE = NULL, *strA = NULL;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00001992
1993 xmlSchemaVErr(ctxt, (xmlNodePtr) attr,
1994 error,
1995 /* XML_SCHEMAS_ERR_ATTRUNKNOWN, */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001996 "%s: The attribute '%s' is not allowed.\n",
1997 xmlSchemaFormatItemForReport(&strE, NULL, NULL, attr->parent, 0),
1998 xmlSchemaFormatNsPrefixLocal(&strA, attr->ns, attr->name));
1999 FREE_AND_NULL(strE)
2000 FREE_AND_NULL(strA)
2001}
2002
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +00002003
2004static int
2005xmlSchemaIsGlobalItem(xmlSchemaTypePtr item)
2006{
2007 switch (item->type) {
2008 case XML_SCHEMA_TYPE_COMPLEX:
2009 case XML_SCHEMA_TYPE_SIMPLE:
2010 case XML_SCHEMA_TYPE_GROUP:
2011 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL)
2012 return(1);
2013 break;
2014 case XML_SCHEMA_TYPE_ELEMENT:
2015 if ( ((xmlSchemaElementPtr) item)->flags &
2016 XML_SCHEMAS_ELEM_GLOBAL)
2017 return(1);
2018 break;
2019 case XML_SCHEMA_TYPE_ATTRIBUTE:
2020 if ( ((xmlSchemaAttributePtr) item)->flags &
2021 XML_SCHEMAS_ATTR_GLOBAL)
2022 return(1);
2023 break;
2024 /* Note that attribute groups are always global. */
2025 default:
2026 return(1);
2027 }
2028 return (0);
2029}
2030
William M. Brack2f2a6632004-08-20 23:09:47 +00002031/**
2032 * xmlSchemaVCustomErr:
2033 * @ctxt: the schema validation context
2034 * @error: the error code
2035 * @node: the validated node
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002036 * @type: the schema type of the validated node
William M. Brack2f2a6632004-08-20 23:09:47 +00002037 * @message: the error message
2038 * @str1: the optional param for the message
2039 *
2040 * Reports a validation error.
2041 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002042static void
2043xmlSchemaVCustomErr(xmlSchemaValidCtxtPtr ctxt,
2044 xmlParserErrors error,
2045 xmlNodePtr node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002046 xmlSchemaTypePtr type,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002047 const char *message,
2048 const xmlChar *str1)
2049{
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002050 xmlChar *msg = NULL, *str = NULL;
2051
2052 if (node == NULL) {
2053 xmlSchemaVErr(ctxt, NULL,
2054 XML_SCHEMAV_INTERNAL,
2055 "Internal error: xmlSchemaVCustomErr, no node "
2056 "given.\n", NULL, NULL);
2057 return;
2058 }
2059 /* TODO: Are the HTML and DOCB doc nodes expected here? */
2060 if (node->type != XML_DOCUMENT_NODE) {
2061 xmlSchemaFormatItemForReport(&msg, NULL, NULL, node, 0);
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +00002062 if ((type != NULL) && (xmlSchemaIsGlobalItem(type))) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002063 msg = xmlStrcat(msg, BAD_CAST " [");
2064 msg = xmlStrcat(msg, xmlSchemaFormatItemForReport(&str, NULL, type, NULL, 0));
2065 msg = xmlStrcat(msg, BAD_CAST "]");
2066 }
2067 msg = xmlStrcat(msg, BAD_CAST ": ");
2068 } else
2069 msg = xmlStrdup((const xmlChar *) "");
Daniel Veillardc0826a72004-08-10 14:17:33 +00002070 msg = xmlStrcat(msg, (const xmlChar *) message);
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002071 msg = xmlStrcat(msg, BAD_CAST ".\n");
2072 xmlSchemaVErr(ctxt, node, error, (const char *) msg, str1, NULL);
2073 FREE_AND_NULL(msg)
2074 FREE_AND_NULL(str)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002075}
2076
William M. Brack2f2a6632004-08-20 23:09:47 +00002077/**
2078 * xmlSchemaWildcardPCToString:
2079 * @pc: the type of processContents
2080 *
2081 * Returns a string representation of the type of
2082 * processContents.
2083 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002084static const char *
2085xmlSchemaWildcardPCToString(int pc)
2086{
2087 switch (pc) {
2088 case XML_SCHEMAS_ANY_SKIP:
2089 return ("skip");
2090 case XML_SCHEMAS_ANY_LAX:
2091 return ("lax");
2092 case XML_SCHEMAS_ANY_STRICT:
2093 return ("strict");
2094 default:
2095 return ("invalid process contents");
2096 }
2097}
2098
William M. Brack2f2a6632004-08-20 23:09:47 +00002099/**
2100 * xmlSchemaVWildcardErr:
2101 * @ctxt: the schema validation context
2102 * @error: the error code
2103 * @node: the validated node
2104 * @wild: the wildcard used
2105 * @message: the error message
2106 *
2107 * Reports an validation-by-wildcard error.
2108 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002109static void
2110xmlSchemaVWildcardErr(xmlSchemaValidCtxtPtr ctxt,
2111 xmlParserErrors error,
2112 xmlNodePtr node,
2113 xmlSchemaWildcardPtr wild,
2114 const char *message)
2115{
2116 xmlChar *des = NULL, *msg = NULL;
2117
2118 xmlSchemaFormatItemForReport(&des, NULL, NULL, node, 0);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00002119 msg = xmlStrdup(BAD_CAST "%s [");
Daniel Veillardc0826a72004-08-10 14:17:33 +00002120 msg = xmlStrcat(msg, BAD_CAST xmlSchemaWildcardPCToString(wild->processContents));
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +00002121 msg = xmlStrcat(msg, BAD_CAST " wildcard]: ");
Daniel Veillardc0826a72004-08-10 14:17:33 +00002122 msg = xmlStrcat(msg, (const xmlChar *) message);
2123 msg = xmlStrcat(msg, BAD_CAST ".\n");
2124 xmlSchemaVErr(ctxt, node, error, (const char *) msg, BAD_CAST des, NULL);
2125 FREE_AND_NULL(des);
2126 FREE_AND_NULL(msg);
2127}
2128
2129/**
2130 * xmlSchemaVMissingAttrErr:
2131 * @ctxt: the schema validation context
2132 * @node: the parent element node of the missing attribute node
2133 * @type: the corresponding type of the attribute node
2134 *
2135 * Reports an illegal attribute.
2136 */
2137static void
2138xmlSchemaVMissingAttrErr(xmlSchemaValidCtxtPtr ctxt,
2139 xmlNodePtr elem,
2140 xmlSchemaAttributePtr type)
2141{
2142 const xmlChar *name, *uri;
2143 xmlChar *strE = NULL, *strA = NULL;
2144
2145 if (type->ref != NULL) {
2146 name = type->ref;
2147 uri = type->refNs;
2148 } else {
2149 name = type->name;
2150 uri = type->targetNamespace;
2151 }
2152 xmlSchemaVErr(ctxt, elem,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002153 XML_SCHEMAV_CVC_COMPLEX_TYPE_4,
2154 /* XML_SCHEMAS_ERR_MISSING, */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002155 "%s: The attribute %s is required but missing.\n",
2156 xmlSchemaFormatItemForReport(&strE, NULL, NULL, elem, 0),
2157 xmlSchemaFormatNsUriLocal(&strA, uri, name));
2158 FREE_AND_NULL(strE)
2159 FREE_AND_NULL(strA)
2160}
2161
Daniel Veillard4255d502002-04-16 15:50:10 +00002162/************************************************************************
2163 * *
2164 * Allocation functions *
2165 * *
2166 ************************************************************************/
2167
2168/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00002169 * xmlSchemaNewSchemaForParserCtxt:
William M. Brack08171912003-12-29 02:52:11 +00002170 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00002171 *
2172 * Allocate a new Schema structure.
2173 *
2174 * Returns the newly allocated structure or NULL in case or error
2175 */
2176static xmlSchemaPtr
2177xmlSchemaNewSchema(xmlSchemaParserCtxtPtr ctxt)
2178{
2179 xmlSchemaPtr ret;
2180
2181 ret = (xmlSchemaPtr) xmlMalloc(sizeof(xmlSchema));
2182 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002183 xmlSchemaPErrMemory(ctxt, "allocating schema", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002184 return (NULL);
2185 }
2186 memset(ret, 0, sizeof(xmlSchema));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002187 ret->dict = ctxt->dict;
Daniel Veillard500a1de2004-03-22 15:22:58 +00002188 xmlDictReference(ret->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00002189
2190 return (ret);
2191}
2192
2193/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002194 * xmlSchemaNewSchema:
2195 * @ctxt: a schema validation context
2196 *
2197 * Allocate a new Schema structure.
2198 *
2199 * Returns the newly allocated structure or NULL in case or error
2200 */
2201static xmlSchemaAssemblePtr
2202xmlSchemaNewAssemble(void)
2203{
2204 xmlSchemaAssemblePtr ret;
2205
2206 ret = (xmlSchemaAssemblePtr) xmlMalloc(sizeof(xmlSchemaAssemble));
2207 if (ret == NULL) {
2208 /* xmlSchemaPErrMemory(ctxt, "allocating assemble info", NULL); */
2209 return (NULL);
2210 }
2211 memset(ret, 0, sizeof(xmlSchemaAssemble));
2212 ret->items = NULL;
2213 return (ret);
2214}
2215
2216/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002217 * xmlSchemaNewFacet:
Daniel Veillard4255d502002-04-16 15:50:10 +00002218 *
2219 * Allocate a new Facet structure.
2220 *
2221 * Returns the newly allocated structure or NULL in case or error
2222 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00002223xmlSchemaFacetPtr
2224xmlSchemaNewFacet(void)
Daniel Veillard4255d502002-04-16 15:50:10 +00002225{
2226 xmlSchemaFacetPtr ret;
2227
2228 ret = (xmlSchemaFacetPtr) xmlMalloc(sizeof(xmlSchemaFacet));
2229 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002230 return (NULL);
2231 }
2232 memset(ret, 0, sizeof(xmlSchemaFacet));
2233
2234 return (ret);
2235}
2236
2237/**
2238 * xmlSchemaNewAnnot:
William M. Brack08171912003-12-29 02:52:11 +00002239 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00002240 * @node: a node
2241 *
2242 * Allocate a new annotation structure.
2243 *
2244 * Returns the newly allocated structure or NULL in case or error
2245 */
2246static xmlSchemaAnnotPtr
2247xmlSchemaNewAnnot(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
2248{
2249 xmlSchemaAnnotPtr ret;
2250
2251 ret = (xmlSchemaAnnotPtr) xmlMalloc(sizeof(xmlSchemaAnnot));
2252 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002253 xmlSchemaPErrMemory(ctxt, "allocating annotation", node);
Daniel Veillard4255d502002-04-16 15:50:10 +00002254 return (NULL);
2255 }
2256 memset(ret, 0, sizeof(xmlSchemaAnnot));
2257 ret->content = node;
2258 return (ret);
2259}
2260
2261/**
Daniel Veillardfdc91562002-07-01 21:52:03 +00002262 * xmlSchemaFreeAnnot:
2263 * @annot: a schema type structure
2264 *
2265 * Deallocate a annotation structure
2266 */
2267static void
2268xmlSchemaFreeAnnot(xmlSchemaAnnotPtr annot)
2269{
2270 if (annot == NULL)
2271 return;
2272 xmlFree(annot);
2273}
2274
2275/**
Daniel Veillard1d913862003-11-21 00:28:39 +00002276 * xmlSchemaFreeImport:
2277 * @import: a schema import structure
2278 *
2279 * Deallocate an import structure
2280 */
2281static void
2282xmlSchemaFreeImport(xmlSchemaImportPtr import)
2283{
2284 if (import == NULL)
2285 return;
2286
2287 xmlSchemaFree(import->schema);
William M. Brack2f2a6632004-08-20 23:09:47 +00002288 xmlFreeDoc(import->doc);
Daniel Veillard1d913862003-11-21 00:28:39 +00002289 xmlFree(import);
2290}
2291
2292/**
Daniel Veillardbd2904b2003-11-25 15:38:59 +00002293 * xmlSchemaFreeInclude:
2294 * @include: a schema include structure
2295 *
2296 * Deallocate an include structure
2297 */
2298static void
2299xmlSchemaFreeInclude(xmlSchemaIncludePtr include)
2300{
2301 if (include == NULL)
2302 return;
2303
2304 xmlFreeDoc(include->doc);
2305 xmlFree(include);
2306}
2307
2308/**
2309 * xmlSchemaFreeIncludeList:
2310 * @includes: a schema include list
2311 *
2312 * Deallocate an include structure
2313 */
2314static void
2315xmlSchemaFreeIncludeList(xmlSchemaIncludePtr includes)
2316{
2317 xmlSchemaIncludePtr next;
2318
2319 while (includes != NULL) {
2320 next = includes->next;
2321 xmlSchemaFreeInclude(includes);
2322 includes = next;
2323 }
2324}
2325
2326/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002327 * xmlSchemaFreeNotation:
2328 * @schema: a schema notation structure
2329 *
2330 * Deallocate a Schema Notation structure.
2331 */
2332static void
2333xmlSchemaFreeNotation(xmlSchemaNotationPtr nota)
2334{
2335 if (nota == NULL)
2336 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00002337 xmlFree(nota);
2338}
2339
2340/**
2341 * xmlSchemaFreeAttribute:
2342 * @schema: a schema attribute structure
2343 *
2344 * Deallocate a Schema Attribute structure.
2345 */
2346static void
2347xmlSchemaFreeAttribute(xmlSchemaAttributePtr attr)
2348{
2349 if (attr == NULL)
2350 return;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002351 if (attr->annot != NULL)
2352 xmlSchemaFreeAnnot(attr->annot);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00002353 if (attr->defVal != NULL)
2354 xmlSchemaFreeValue(attr->defVal);
Daniel Veillard4255d502002-04-16 15:50:10 +00002355 xmlFree(attr);
2356}
2357
2358/**
Daniel Veillard3646d642004-06-02 19:19:14 +00002359 * xmlSchemaFreeWildcardNsSet:
2360 * set: a schema wildcard namespace
2361 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00002362 * Deallocates a list of wildcard constraint structures.
Daniel Veillard3646d642004-06-02 19:19:14 +00002363 */
2364static void
2365xmlSchemaFreeWildcardNsSet(xmlSchemaWildcardNsPtr set)
2366{
2367 xmlSchemaWildcardNsPtr next;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002368
Daniel Veillard3646d642004-06-02 19:19:14 +00002369 while (set != NULL) {
2370 next = set->next;
2371 xmlFree(set);
2372 set = next;
2373 }
2374}
2375
2376/**
2377 * xmlSchemaFreeWildcard:
Daniel Veillard01fa6152004-06-29 17:04:39 +00002378 * @wildcard: a wildcard structure
Daniel Veillard3646d642004-06-02 19:19:14 +00002379 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00002380 * Deallocates a wildcard structure.
Daniel Veillard3646d642004-06-02 19:19:14 +00002381 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00002382void
Daniel Veillard3646d642004-06-02 19:19:14 +00002383xmlSchemaFreeWildcard(xmlSchemaWildcardPtr wildcard)
2384{
2385 if (wildcard == NULL)
2386 return;
2387 if (wildcard->annot != NULL)
2388 xmlSchemaFreeAnnot(wildcard->annot);
2389 if (wildcard->nsSet != NULL)
2390 xmlSchemaFreeWildcardNsSet(wildcard->nsSet);
2391 if (wildcard->negNsSet != NULL)
2392 xmlFree(wildcard->negNsSet);
2393 xmlFree(wildcard);
2394}
2395
2396/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002397 * xmlSchemaFreeAttributeGroup:
2398 * @schema: a schema attribute group structure
2399 *
2400 * Deallocate a Schema Attribute Group structure.
2401 */
2402static void
2403xmlSchemaFreeAttributeGroup(xmlSchemaAttributeGroupPtr attr)
2404{
2405 if (attr == NULL)
2406 return;
Daniel Veillard3646d642004-06-02 19:19:14 +00002407 if (attr->annot != NULL)
2408 xmlSchemaFreeAnnot(attr->annot);
2409 if ((attr->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL) &&
2410 (attr->attributeWildcard != NULL))
2411 xmlSchemaFreeWildcard(attr->attributeWildcard);
2412
Daniel Veillard4255d502002-04-16 15:50:10 +00002413 xmlFree(attr);
2414}
2415
2416/**
Daniel Veillard3646d642004-06-02 19:19:14 +00002417 * xmlSchemaFreeAttributeUseList:
Daniel Veillard01fa6152004-06-29 17:04:39 +00002418 * @attrUse: an attribute link
Daniel Veillard3646d642004-06-02 19:19:14 +00002419 *
2420 * Deallocate a list of schema attribute uses.
2421 */
2422static void
2423xmlSchemaFreeAttributeUseList(xmlSchemaAttributeLinkPtr attrUse)
2424{
2425 xmlSchemaAttributeLinkPtr next;
2426
2427 while (attrUse != NULL) {
2428 next = attrUse->next;
2429 xmlFree(attrUse);
2430 attrUse = next;
2431 }
2432}
2433
2434/**
Daniel Veillard01fa6152004-06-29 17:04:39 +00002435 * xmlSchemaFreeTypeLinkList:
2436 * @alink: a type link
2437 *
2438 * Deallocate a list of types.
2439 */
2440static void
2441xmlSchemaFreeTypeLinkList(xmlSchemaTypeLinkPtr link)
2442{
2443 xmlSchemaTypeLinkPtr next;
2444
2445 while (link != NULL) {
2446 next = link->next;
2447 xmlFree(link);
2448 link = next;
2449 }
2450}
2451
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00002452#ifdef IDC_ENABLED
2453static void
2454xmlSchemaFreeIDCStateObjList(xmlSchemaIDCStateObjPtr sto)
2455{
2456 xmlSchemaIDCStateObjPtr next;
2457 while (sto != NULL) {
2458 next = sto->next;
2459 if (sto->history != NULL)
2460 xmlFree(sto->history);
2461 if (sto->xpathCtxt != NULL)
2462 xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
2463 xmlFree(sto);
2464 sto = next;
2465 }
2466}
2467
2468/**
2469 * xmlSchemaFreeIDC:
2470 * @idc: a identity-constraint definition
2471 *
2472 * Deallocates an identity-constraint definition.
2473 */
2474static void
2475xmlSchemaFreeIDC(xmlSchemaIDCPtr idcDef)
2476{
2477 xmlSchemaIDCSelectPtr cur, prev;
2478
2479 if (idcDef == NULL)
2480 return;
2481 if (idcDef->annot != NULL)
2482 xmlSchemaFreeAnnot(idcDef->annot);
2483 if (idcDef->ref != NULL)
2484 xmlFree(idcDef->ref);
2485 /* Selector */
2486 if (idcDef->selector != NULL) {
2487 if (idcDef->selector->xpathComp != NULL)
2488 xmlFreePattern((xmlPatternPtr) idcDef->selector->xpathComp);
2489 xmlFree(idcDef->selector);
2490 }
2491 /* Fields */
2492 if (idcDef->fields != NULL) {
2493 cur = idcDef->fields;
2494 do {
2495 prev = cur;
2496 cur = cur->next;
2497 if (prev->xpathComp != NULL)
2498 xmlFreePattern((xmlPatternPtr) prev->xpathComp);
2499 xmlFree(prev);
2500 } while (cur != NULL);
2501 }
2502 xmlFree(idcDef);
2503}
2504#endif /* IDC_ENABLED */
2505
Daniel Veillard01fa6152004-06-29 17:04:39 +00002506/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002507 * xmlSchemaFreeElement:
2508 * @schema: a schema element structure
2509 *
2510 * Deallocate a Schema Element structure.
2511 */
2512static void
2513xmlSchemaFreeElement(xmlSchemaElementPtr elem)
2514{
2515 if (elem == NULL)
2516 return;
Daniel Veillard32370232002-10-16 14:08:14 +00002517 if (elem->annot != NULL)
2518 xmlSchemaFreeAnnot(elem->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00002519 if (elem->contModel != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002520 xmlRegFreeRegexp(elem->contModel);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00002521 if (elem->defVal != NULL)
2522 xmlSchemaFreeValue(elem->defVal);
Daniel Veillard4255d502002-04-16 15:50:10 +00002523 xmlFree(elem);
2524}
2525
2526/**
2527 * xmlSchemaFreeFacet:
2528 * @facet: a schema facet structure
2529 *
2530 * Deallocate a Schema Facet structure.
2531 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00002532void
Daniel Veillard4255d502002-04-16 15:50:10 +00002533xmlSchemaFreeFacet(xmlSchemaFacetPtr facet)
2534{
2535 if (facet == NULL)
2536 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00002537 if (facet->val != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002538 xmlSchemaFreeValue(facet->val);
Daniel Veillard4255d502002-04-16 15:50:10 +00002539 if (facet->regexp != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002540 xmlRegFreeRegexp(facet->regexp);
Daniel Veillardfdc91562002-07-01 21:52:03 +00002541 if (facet->annot != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002542 xmlSchemaFreeAnnot(facet->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00002543 xmlFree(facet);
2544}
2545
2546/**
2547 * xmlSchemaFreeType:
2548 * @type: a schema type structure
2549 *
2550 * Deallocate a Schema Type structure.
2551 */
2552void
2553xmlSchemaFreeType(xmlSchemaTypePtr type)
2554{
2555 if (type == NULL)
2556 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00002557 if (type->annot != NULL)
Daniel Veillard32370232002-10-16 14:08:14 +00002558 xmlSchemaFreeAnnot(type->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00002559 if (type->facets != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002560 xmlSchemaFacetPtr facet, next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002561
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002562 facet = type->facets;
2563 while (facet != NULL) {
2564 next = facet->next;
2565 xmlSchemaFreeFacet(facet);
2566 facet = next;
2567 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002568 }
Daniel Veillard3646d642004-06-02 19:19:14 +00002569 if (type->type != XML_SCHEMA_TYPE_BASIC) {
2570 if (type->attributeUses != NULL)
2571 xmlSchemaFreeAttributeUseList(type->attributeUses);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002572 if ((type->attributeWildcard != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +00002573 ((type->type != XML_SCHEMA_TYPE_COMPLEX) ||
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002574 (type->flags & XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD))) {
2575 /*
2576 * NOTE: The only case where an attribute wildcard
2577 * is not owned, is if a complex type inherits it
2578 * from a base type.
2579 */
Daniel Veillard3646d642004-06-02 19:19:14 +00002580 xmlSchemaFreeWildcard(type->attributeWildcard);
2581 }
2582 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00002583 if (type->memberTypes != NULL)
2584 xmlSchemaFreeTypeLinkList(type->memberTypes);
2585 if (type->facetSet != NULL) {
2586 xmlSchemaFacetLinkPtr next, link;
2587
2588 link = type->facetSet;
2589 do {
2590 next = link->next;
2591 xmlFree(link);
2592 link = next;
2593 } while (link != NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002594 }
2595 if (type->contModel != NULL)
2596 xmlRegFreeRegexp(type->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +00002597 xmlFree(type);
2598}
2599
2600/**
Daniel Veillardb0f397e2003-12-23 23:30:53 +00002601 * xmlSchemaFreeTypeList:
2602 * @type: a schema type structure
2603 *
2604 * Deallocate a Schema Type structure.
2605 */
2606static void
2607xmlSchemaFreeTypeList(xmlSchemaTypePtr type)
2608{
2609 xmlSchemaTypePtr next;
2610
2611 while (type != NULL) {
2612 next = type->redef;
2613 xmlSchemaFreeType(type);
2614 type = next;
2615 }
2616}
2617
2618/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002619 * xmlSchemaFree:
2620 * @schema: a schema structure
2621 *
2622 * Deallocate a Schema structure.
2623 */
2624void
2625xmlSchemaFree(xmlSchemaPtr schema)
2626{
2627 if (schema == NULL)
2628 return;
2629
Daniel Veillard4255d502002-04-16 15:50:10 +00002630 if (schema->notaDecl != NULL)
2631 xmlHashFree(schema->notaDecl,
2632 (xmlHashDeallocator) xmlSchemaFreeNotation);
2633 if (schema->attrDecl != NULL)
2634 xmlHashFree(schema->attrDecl,
2635 (xmlHashDeallocator) xmlSchemaFreeAttribute);
2636 if (schema->attrgrpDecl != NULL)
2637 xmlHashFree(schema->attrgrpDecl,
2638 (xmlHashDeallocator) xmlSchemaFreeAttributeGroup);
2639 if (schema->elemDecl != NULL)
2640 xmlHashFree(schema->elemDecl,
2641 (xmlHashDeallocator) xmlSchemaFreeElement);
2642 if (schema->typeDecl != NULL)
2643 xmlHashFree(schema->typeDecl,
Daniel Veillardb0f397e2003-12-23 23:30:53 +00002644 (xmlHashDeallocator) xmlSchemaFreeTypeList);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00002645 if (schema->groupDecl != NULL)
2646 xmlHashFree(schema->groupDecl,
2647 (xmlHashDeallocator) xmlSchemaFreeType);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00002648#ifdef IDC_ENABLED
2649 if (schema->idcDef != NULL)
2650 xmlHashFree(schema->idcDef,
2651 (xmlHashDeallocator) xmlSchemaFreeIDC);
2652#endif
Daniel Veillard1d913862003-11-21 00:28:39 +00002653 if (schema->schemasImports != NULL)
2654 xmlHashFree(schema->schemasImports,
2655 (xmlHashDeallocator) xmlSchemaFreeImport);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00002656 if (schema->includes != NULL) {
2657 xmlSchemaFreeIncludeList((xmlSchemaIncludePtr) schema->includes);
2658 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002659 if (schema->annot != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002660 xmlSchemaFreeAnnot(schema->annot);
Daniel Veillarddda22c12004-01-24 08:31:30 +00002661 if (schema->doc != NULL && !schema->preserve)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002662 xmlFreeDoc(schema->doc);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002663 xmlDictFree(schema->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00002664 xmlFree(schema);
2665}
2666
2667/************************************************************************
2668 * *
Daniel Veillard4255d502002-04-16 15:50:10 +00002669 * Debug functions *
2670 * *
2671 ************************************************************************/
2672
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00002673#ifdef LIBXML_OUTPUT_ENABLED
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002674
Daniel Veillard4255d502002-04-16 15:50:10 +00002675/**
2676 * xmlSchemaElementDump:
2677 * @elem: an element
2678 * @output: the file output
2679 *
2680 * Dump the element
2681 */
2682static void
2683xmlSchemaElementDump(xmlSchemaElementPtr elem, FILE * output,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002684 const xmlChar * name ATTRIBUTE_UNUSED,
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002685 const xmlChar * namespace ATTRIBUTE_UNUSED,
2686 const xmlChar * context ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +00002687{
2688 if (elem == NULL)
2689 return;
2690
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002691 if (elem->flags & XML_SCHEMAS_ELEM_REF) {
2692 fprintf(output, "Particle: %s", name);
2693 fprintf(output, ", term element: %s", elem->ref);
2694 if (elem->refNs != NULL)
2695 fprintf(output, " ns %s", elem->refNs);
2696 } else {
2697 fprintf(output, "Element");
2698 if (elem->flags & XML_SCHEMAS_ELEM_GLOBAL)
2699 fprintf(output, " (global)");
2700 fprintf(output, ": %s ", elem->name);
2701 if (namespace != NULL)
2702 fprintf(output, "ns %s", namespace);
2703 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002704 fprintf(output, "\n");
2705 if ((elem->minOccurs != 1) || (elem->maxOccurs != 1)) {
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002706 fprintf(output, " min %d ", elem->minOccurs);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002707 if (elem->maxOccurs >= UNBOUNDED)
2708 fprintf(output, "max: unbounded\n");
2709 else if (elem->maxOccurs != 1)
2710 fprintf(output, "max: %d\n", elem->maxOccurs);
2711 else
2712 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00002713 }
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002714 /*
2715 * Misc other properties.
2716 */
2717 if ((elem->flags & XML_SCHEMAS_ELEM_NILLABLE) ||
2718 (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT) ||
2719 (elem->flags & XML_SCHEMAS_ELEM_FIXED) ||
2720 (elem->flags & XML_SCHEMAS_ELEM_DEFAULT) ||
2721 (elem->id != NULL)) {
2722 fprintf(output, " props: ");
2723 if (elem->flags & XML_SCHEMAS_ELEM_FIXED)
2724 fprintf(output, "[fixed] ");
2725 if (elem->flags & XML_SCHEMAS_ELEM_DEFAULT)
2726 fprintf(output, "[default] ");
2727 if (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT)
2728 fprintf(output, "[abstract] ");
2729 if (elem->flags & XML_SCHEMAS_ELEM_NILLABLE)
2730 fprintf(output, "[nillable] ");
2731 if (elem->id != NULL)
2732 fprintf(output, "[id: '%s'] ", elem->id);
2733 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00002734 }
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002735 /*
2736 * Default/fixed value.
2737 */
Daniel Veillard4255d502002-04-16 15:50:10 +00002738 if (elem->value != NULL)
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002739 fprintf(output, " value: '%s'\n", elem->value);
2740 /*
2741 * Type.
2742 */
2743 if (elem->namedType != NULL) {
2744 fprintf(output, " type: %s ", elem->namedType);
2745 if (elem->namedTypeNs != NULL)
2746 fprintf(output, "ns %s\n", elem->namedTypeNs);
2747 else
2748 fprintf(output, "\n");
2749 }
2750 /*
2751 * Substitution group.
2752 */
2753 if (elem->substGroup != NULL) {
2754 fprintf(output, " substitutionGroup: %s ", elem->substGroup);
2755 if (elem->substGroupNs != NULL)
2756 fprintf(output, "ns %s\n", elem->substGroupNs);
2757 else
2758 fprintf(output, "\n");
2759 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002760}
2761
2762/**
2763 * xmlSchemaAnnotDump:
2764 * @output: the file output
2765 * @annot: a annotation
2766 *
2767 * Dump the annotation
2768 */
2769static void
2770xmlSchemaAnnotDump(FILE * output, xmlSchemaAnnotPtr annot)
2771{
2772 xmlChar *content;
2773
2774 if (annot == NULL)
2775 return;
2776
2777 content = xmlNodeGetContent(annot->content);
2778 if (content != NULL) {
2779 fprintf(output, " Annot: %s\n", content);
2780 xmlFree(content);
2781 } else
2782 fprintf(output, " Annot: empty\n");
2783}
2784
2785/**
2786 * xmlSchemaTypeDump:
2787 * @output: the file output
2788 * @type: a type structure
2789 *
2790 * Dump a SchemaType structure
2791 */
2792static void
2793xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output)
2794{
2795 if (type == NULL) {
2796 fprintf(output, "Type: NULL\n");
2797 return;
2798 }
2799 fprintf(output, "Type: ");
2800 if (type->name != NULL)
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002801 fprintf(output, "%s ", type->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00002802 else
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002803 fprintf(output, "no name ");
2804 if (type->targetNamespace != NULL)
2805 fprintf(output, "ns %s ", type->targetNamespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00002806 switch (type->type) {
2807 case XML_SCHEMA_TYPE_BASIC:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002808 fprintf(output, "[basic] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002809 break;
2810 case XML_SCHEMA_TYPE_SIMPLE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002811 fprintf(output, "[simple] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002812 break;
2813 case XML_SCHEMA_TYPE_COMPLEX:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002814 fprintf(output, "[complex] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002815 break;
2816 case XML_SCHEMA_TYPE_SEQUENCE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002817 fprintf(output, "[sequence] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002818 break;
2819 case XML_SCHEMA_TYPE_CHOICE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002820 fprintf(output, "[choice] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002821 break;
2822 case XML_SCHEMA_TYPE_ALL:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002823 fprintf(output, "[all] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002824 break;
2825 case XML_SCHEMA_TYPE_UR:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002826 fprintf(output, "[ur] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002827 break;
2828 case XML_SCHEMA_TYPE_RESTRICTION:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002829 fprintf(output, "[restriction] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002830 break;
2831 case XML_SCHEMA_TYPE_EXTENSION:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002832 fprintf(output, "[extension] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002833 break;
2834 default:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002835 fprintf(output, "[unknown type %d] ", type->type);
Daniel Veillard4255d502002-04-16 15:50:10 +00002836 break;
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002837 }
2838 fprintf(output, "content: ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002839 switch (type->contentType) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002840 case XML_SCHEMA_CONTENT_UNKNOWN:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002841 fprintf(output, "[unknown] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002842 break;
2843 case XML_SCHEMA_CONTENT_EMPTY:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002844 fprintf(output, "[empty] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002845 break;
2846 case XML_SCHEMA_CONTENT_ELEMENTS:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002847 fprintf(output, "[element] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002848 break;
2849 case XML_SCHEMA_CONTENT_MIXED:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002850 fprintf(output, "[mixed] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002851 break;
2852 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00002853 /* not used. */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002854 break;
2855 case XML_SCHEMA_CONTENT_BASIC:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002856 fprintf(output, "[basic] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002857 break;
2858 case XML_SCHEMA_CONTENT_SIMPLE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002859 fprintf(output, "[simple] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002860 break;
2861 case XML_SCHEMA_CONTENT_ANY:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002862 fprintf(output, "[any] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002863 break;
Daniel Veillard4255d502002-04-16 15:50:10 +00002864 }
2865 fprintf(output, "\n");
2866 if ((type->minOccurs != 1) || (type->maxOccurs != 1)) {
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002867 fprintf(output, " min: %d ", type->minOccurs);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002868 if (type->maxOccurs >= UNBOUNDED)
2869 fprintf(output, "max: unbounded\n");
2870 else if (type->maxOccurs != 1)
2871 fprintf(output, "max: %d\n", type->maxOccurs);
2872 else
2873 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00002874 }
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002875 if (type->base != NULL) {
2876 fprintf(output, " base type: %s", type->base);
2877 if (type->baseNs != NULL)
2878 fprintf(output, " ns %s\n", type->baseNs);
2879 else
2880 fprintf(output, "\n");
2881 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002882 if (type->annot != NULL)
2883 xmlSchemaAnnotDump(output, type->annot);
2884 if (type->subtypes != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002885 xmlSchemaTypePtr sub = type->subtypes;
Daniel Veillard4255d502002-04-16 15:50:10 +00002886
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002887 fprintf(output, " subtypes: ");
2888 while (sub != NULL) {
2889 fprintf(output, "%s ", sub->name);
2890 sub = sub->next;
2891 }
2892 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00002893 }
2894
2895}
2896
2897/**
2898 * xmlSchemaDump:
2899 * @output: the file output
2900 * @schema: a schema structure
2901 *
2902 * Dump a Schema structure.
2903 */
2904void
2905xmlSchemaDump(FILE * output, xmlSchemaPtr schema)
2906{
Daniel Veillardce682bc2004-11-05 17:22:25 +00002907 if (output == NULL)
2908 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00002909 if (schema == NULL) {
2910 fprintf(output, "Schemas: NULL\n");
2911 return;
2912 }
2913 fprintf(output, "Schemas: ");
2914 if (schema->name != NULL)
2915 fprintf(output, "%s, ", schema->name);
2916 else
2917 fprintf(output, "no name, ");
2918 if (schema->targetNamespace != NULL)
Daniel Veillard580ced82003-03-21 21:22:48 +00002919 fprintf(output, "%s", (const char *) schema->targetNamespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00002920 else
2921 fprintf(output, "no target namespace");
2922 fprintf(output, "\n");
2923 if (schema->annot != NULL)
2924 xmlSchemaAnnotDump(output, schema->annot);
2925
2926 xmlHashScan(schema->typeDecl, (xmlHashScanner) xmlSchemaTypeDump,
2927 output);
2928 xmlHashScanFull(schema->elemDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002929 (xmlHashScannerFull) xmlSchemaElementDump, output);
Daniel Veillard4255d502002-04-16 15:50:10 +00002930}
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00002931
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00002932#ifdef IDC_ENABLED
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00002933/**
2934 * xmlSchemaDebugDumpIDCTable:
2935 * @vctxt: the WXS validation context
2936 *
2937 * Displays the current IDC table for debug purposes.
2938 */
2939static void
2940xmlSchemaDebugDumpIDCTable(FILE * output,
2941 const xmlChar *namespaceName,
2942 const xmlChar *localName,
2943 xmlSchemaPSVIIDCBindingPtr bind)
2944{
2945 xmlChar *str = NULL, *value;
2946 xmlSchemaPSVIIDCNodePtr tab;
2947 xmlSchemaPSVIIDCKeyPtr key;
2948 int i, j, res;
2949
2950 fprintf(output, "IDC: TABLES on %s\n",
2951 xmlSchemaFormatNsUriLocal(&str, namespaceName, localName));
2952 FREE_AND_NULL(str)
2953
2954 if (bind == NULL)
2955 return;
2956 do {
2957 fprintf(output, "IDC: BINDING %s\n",
2958 xmlSchemaFormatNsUriLocal(&str, bind->definition->targetNamespace,
2959 bind->definition->name));
2960 FREE_AND_NULL(str)
2961 for (i = 0; i < bind->nbNodes; i++) {
2962 tab = bind->nodeTable[i];
2963 fprintf(output, " ( ");
2964 for (j = 0; j < bind->definition->nbFields; j++) {
2965 key = tab->keys[j];
2966 if ((key != NULL) && (key->compValue != NULL)) {
2967#ifdef IDC_VALUE_SUPPORT
2968 res = xmlSchemaGetCanonValue(key->compValue, &value);
2969#else
2970 value = xmlStrdup(BAD_CAST "dummy-value");
2971 res = 0;
2972#endif
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00002973 if (res >= 0)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00002974 fprintf(output, "\"%s\" ", value);
2975 else
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00002976 fprintf(output, "CANON-VALUE-FAILED ");
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00002977 if (res == 0)
2978 FREE_AND_NULL(value)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00002979 } else if (key != NULL)
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00002980 fprintf(output, "(no val), ");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00002981 else
2982 fprintf(output, "(key missing), ");
2983 }
2984 fprintf(output, ")\n");
2985 }
2986 bind = bind->next;
2987 } while (bind != NULL);
2988}
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00002989#endif /* IDC_ENABLED */
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00002990#endif /* LIBXML_OUTPUT_ENABLED */
Daniel Veillard4255d502002-04-16 15:50:10 +00002991
2992/************************************************************************
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002993 * *
2994 * Utilities *
2995 * *
2996 ************************************************************************/
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002997
Daniel Veillardc0826a72004-08-10 14:17:33 +00002998/**
2999 * xmlSchemaGetPropNode:
3000 * @node: the element node
3001 * @name: the name of the attribute
3002 *
3003 * Seeks an attribute with a name of @name in
3004 * no namespace.
3005 *
3006 * Returns the attribute or NULL if not present.
3007 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00003008static xmlAttrPtr
Daniel Veillardc0826a72004-08-10 14:17:33 +00003009xmlSchemaGetPropNode(xmlNodePtr node, const char *name)
Daniel Veillard01fa6152004-06-29 17:04:39 +00003010{
3011 xmlAttrPtr prop;
3012
Daniel Veillardc0826a72004-08-10 14:17:33 +00003013 if ((node == NULL) || (name == NULL))
3014 return(NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00003015 prop = node->properties;
3016 while (prop != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00003017 if ((prop->ns == NULL) && xmlStrEqual(prop->name, BAD_CAST name))
3018 return(prop);
3019 prop = prop->next;
3020 }
3021 return (NULL);
3022}
3023
3024/**
3025 * xmlSchemaGetPropNodeNs:
3026 * @node: the element node
3027 * @uri: the uri
3028 * @name: the name of the attribute
3029 *
3030 * Seeks an attribute with a local name of @name and
3031 * a namespace URI of @uri.
3032 *
3033 * Returns the attribute or NULL if not present.
3034 */
3035static xmlAttrPtr
3036xmlSchemaGetPropNodeNs(xmlNodePtr node, const char *uri, const char *name)
3037{
3038 xmlAttrPtr prop;
3039
3040 if ((node == NULL) || (name == NULL))
3041 return(NULL);
3042 prop = node->properties;
3043 while (prop != NULL) {
3044 if ((prop->ns != NULL) &&
3045 xmlStrEqual(prop->name, BAD_CAST name) &&
3046 xmlStrEqual(prop->ns->href, BAD_CAST uri))
Daniel Veillard01fa6152004-06-29 17:04:39 +00003047 return(prop);
3048 prop = prop->next;
3049 }
3050 return (NULL);
3051}
3052
3053static const xmlChar *
3054xmlSchemaGetNodeContent(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
3055{
3056 xmlChar *val;
3057 const xmlChar *ret;
3058
3059 val = xmlNodeGetContent(node);
3060 if (val == NULL)
3061 return(NULL);
3062 ret = xmlDictLookup(ctxt->dict, val, -1);
3063 xmlFree(val);
3064 return(ret);
3065}
3066
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003067/**
3068 * xmlSchemaGetProp:
3069 * @ctxt: the parser context
3070 * @node: the node
3071 * @name: the property name
3072 *
3073 * Read a attribute value and internalize the string
3074 *
3075 * Returns the string or NULL if not present.
3076 */
3077static const xmlChar *
3078xmlSchemaGetProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
3079 const char *name)
3080{
3081 xmlChar *val;
3082 const xmlChar *ret;
3083
3084 val = xmlGetProp(node, BAD_CAST name);
3085 if (val == NULL)
3086 return(NULL);
3087 ret = xmlDictLookup(ctxt->dict, val, -1);
3088 xmlFree(val);
3089 return(ret);
3090}
3091
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003092/************************************************************************
Daniel Veillard4255d502002-04-16 15:50:10 +00003093 * *
3094 * Parsing functions *
3095 * *
3096 ************************************************************************/
3097
3098/**
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003099 * xmlSchemaGetElem:
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003100 * @schema: the schema context
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003101 * @name: the element name
3102 * @ns: the element namespace
3103 *
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003104 * Lookup a global element declaration in the schema.
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003105 *
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003106 * Returns the element declaration or NULL if not found.
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003107 */
3108static xmlSchemaElementPtr
3109xmlSchemaGetElem(xmlSchemaPtr schema, const xmlChar * name,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003110 const xmlChar * namespace)
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003111{
3112 xmlSchemaElementPtr ret;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003113
3114 if ((name == NULL) || (schema == NULL))
3115 return (NULL);
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003116
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003117 ret = xmlHashLookup2(schema->elemDecl, name, namespace);
Daniel Veillardf2a12832003-11-24 13:04:35 +00003118 if ((ret != NULL) &&
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003119 (ret->flags & XML_SCHEMAS_ELEM_GLOBAL)) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003120 return (ret);
Daniel Veillard3646d642004-06-02 19:19:14 +00003121 } else
3122 ret = NULL;
William M. Bracke7091952004-05-11 15:09:58 +00003123 /*
3124 * This one was removed, since top level element declarations have
3125 * the target namespace specified in targetNamespace of the <schema>
3126 * information element, even if elementFormDefault is "unqualified".
3127 */
3128
3129 /* else if ((schema->flags & XML_SCHEMAS_QUALIF_ELEM) == 0) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003130 if (xmlStrEqual(namespace, schema->targetNamespace))
3131 ret = xmlHashLookup2(schema->elemDecl, name, NULL);
3132 else
3133 ret = xmlHashLookup2(schema->elemDecl, name, namespace);
Daniel Veillardf2a12832003-11-24 13:04:35 +00003134 if ((ret != NULL) &&
3135 ((level == 0) || (ret->flags & XML_SCHEMAS_ELEM_TOPLEVEL))) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003136 return (ret);
Daniel Veillardf2a12832003-11-24 13:04:35 +00003137 }
William M. Bracke7091952004-05-11 15:09:58 +00003138 */
Daniel Veillard3646d642004-06-02 19:19:14 +00003139
William M. Brack2f2a6632004-08-20 23:09:47 +00003140 /*
3141 * Removed since imported components will be hold by the main schema only.
3142 *
Daniel Veillard3646d642004-06-02 19:19:14 +00003143 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00003144 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00003145 else
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003146 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00003147 if (import != NULL) {
Daniel Veillardf2a12832003-11-24 13:04:35 +00003148 ret = xmlSchemaGetElem(import->schema, name, namespace, level + 1);
Daniel Veillard3646d642004-06-02 19:19:14 +00003149 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ELEM_GLOBAL)) {
3150 return (ret);
3151 } else
3152 ret = NULL;
3153 }
William M. Brack2f2a6632004-08-20 23:09:47 +00003154 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003155#ifdef DEBUG
3156 if (ret == NULL) {
3157 if (namespace == NULL)
3158 fprintf(stderr, "Unable to lookup type %s", name);
3159 else
3160 fprintf(stderr, "Unable to lookup type %s:%s", name,
3161 namespace);
3162 }
3163#endif
3164 return (ret);
3165}
3166
3167/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003168 * xmlSchemaGetType:
3169 * @schema: the schemas context
3170 * @name: the type name
3171 * @ns: the type namespace
3172 *
3173 * Lookup a type in the schemas or the predefined types
3174 *
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003175 * Returns the group definition or NULL if not found.
Daniel Veillard4255d502002-04-16 15:50:10 +00003176 */
3177static xmlSchemaTypePtr
3178xmlSchemaGetType(xmlSchemaPtr schema, const xmlChar * name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003179 const xmlChar * namespace)
3180{
Daniel Veillard4255d502002-04-16 15:50:10 +00003181 xmlSchemaTypePtr ret;
3182
3183 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003184 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003185 if (schema != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003186 ret = xmlHashLookup2(schema->typeDecl, name, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00003187 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003188 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003189 }
3190 ret = xmlSchemaGetPredefinedType(name, namespace);
Daniel Veillard1d913862003-11-21 00:28:39 +00003191 if (ret != NULL)
3192 return (ret);
William M. Brack2f2a6632004-08-20 23:09:47 +00003193 /*
3194 * Removed, since the imported components will be grafted on the
3195 * main schema only.
Daniel Veillard3646d642004-06-02 19:19:14 +00003196 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00003197 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00003198 else
Daniel Veillard1d913862003-11-21 00:28:39 +00003199 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00003200 if (import != NULL) {
Daniel Veillard1d913862003-11-21 00:28:39 +00003201 ret = xmlSchemaGetType(import->schema, name, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00003202 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL)) {
3203 return (ret);
3204 } else
3205 ret = NULL;
3206 }
William M. Brack2f2a6632004-08-20 23:09:47 +00003207 */
Daniel Veillard4255d502002-04-16 15:50:10 +00003208#ifdef DEBUG
3209 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003210 if (namespace == NULL)
3211 fprintf(stderr, "Unable to lookup type %s", name);
3212 else
3213 fprintf(stderr, "Unable to lookup type %s:%s", name,
3214 namespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00003215 }
3216#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003217 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003218}
3219
Daniel Veillard3646d642004-06-02 19:19:14 +00003220/**
3221 * xmlSchemaGetAttribute:
3222 * @schema: the context of the schema
3223 * @name: the name of the attribute
3224 * @ns: the target namespace of the attribute
3225 *
3226 * Lookup a an attribute in the schema or imported schemas
3227 *
3228 * Returns the attribute declaration or NULL if not found.
3229 */
3230static xmlSchemaAttributePtr
3231xmlSchemaGetAttribute(xmlSchemaPtr schema, const xmlChar * name,
3232 const xmlChar * namespace)
3233{
3234 xmlSchemaAttributePtr ret;
Daniel Veillard3646d642004-06-02 19:19:14 +00003235
3236 if ((name == NULL) || (schema == NULL))
3237 return (NULL);
3238
3239
3240 ret = xmlHashLookup2(schema->attrDecl, name, namespace);
3241 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTR_GLOBAL))
3242 return (ret);
3243 else
3244 ret = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00003245 /*
3246 * Removed, since imported components will be hold by the main schema only.
3247 *
Daniel Veillard3646d642004-06-02 19:19:14 +00003248 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00003249 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00003250 else
3251 import = xmlHashLookup(schema->schemasImports, namespace);
3252 if (import != NULL) {
3253 ret = xmlSchemaGetAttribute(import->schema, name, namespace);
3254 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTR_GLOBAL)) {
3255 return (ret);
3256 } else
3257 ret = NULL;
3258 }
William M. Brack2f2a6632004-08-20 23:09:47 +00003259 */
Daniel Veillard3646d642004-06-02 19:19:14 +00003260#ifdef DEBUG
3261 if (ret == NULL) {
3262 if (namespace == NULL)
3263 fprintf(stderr, "Unable to lookup attribute %s", name);
3264 else
3265 fprintf(stderr, "Unable to lookup attribute %s:%s", name,
3266 namespace);
3267 }
3268#endif
3269 return (ret);
3270}
3271
3272/**
3273 * xmlSchemaGetAttributeGroup:
3274 * @schema: the context of the schema
3275 * @name: the name of the attribute group
3276 * @ns: the target namespace of the attribute group
3277 *
3278 * Lookup a an attribute group in the schema or imported schemas
3279 *
3280 * Returns the attribute group definition or NULL if not found.
3281 */
3282static xmlSchemaAttributeGroupPtr
3283xmlSchemaGetAttributeGroup(xmlSchemaPtr schema, const xmlChar * name,
3284 const xmlChar * namespace)
3285{
3286 xmlSchemaAttributeGroupPtr ret;
Daniel Veillard3646d642004-06-02 19:19:14 +00003287
3288 if ((name == NULL) || (schema == NULL))
3289 return (NULL);
3290
3291
3292 ret = xmlHashLookup2(schema->attrgrpDecl, name, namespace);
3293 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL))
3294 return (ret);
3295 else
3296 ret = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00003297 /*
3298 * Removed since imported components will be hold by the main schema only.
3299 *
Daniel Veillard3646d642004-06-02 19:19:14 +00003300 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00003301 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00003302 else
3303 import = xmlHashLookup(schema->schemasImports, namespace);
3304 if (import != NULL) {
3305 ret = xmlSchemaGetAttributeGroup(import->schema, name, namespace);
3306 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL))
3307 return (ret);
3308 else
3309 ret = NULL;
3310 }
William M. Brack2f2a6632004-08-20 23:09:47 +00003311 */
Daniel Veillard3646d642004-06-02 19:19:14 +00003312#ifdef DEBUG
3313 if (ret == NULL) {
3314 if (namespace == NULL)
3315 fprintf(stderr, "Unable to lookup attribute group %s", name);
3316 else
3317 fprintf(stderr, "Unable to lookup attribute group %s:%s", name,
3318 namespace);
3319 }
3320#endif
3321 return (ret);
3322}
3323
3324/**
3325 * xmlSchemaGetGroup:
3326 * @schema: the context of the schema
3327 * @name: the name of the group
3328 * @ns: the target namespace of the group
3329 *
3330 * Lookup a group in the schema or imported schemas
3331 *
3332 * Returns the group definition or NULL if not found.
3333 */
3334static xmlSchemaTypePtr
3335xmlSchemaGetGroup(xmlSchemaPtr schema, const xmlChar * name,
3336 const xmlChar * namespace)
3337{
3338 xmlSchemaTypePtr ret;
Daniel Veillard3646d642004-06-02 19:19:14 +00003339
3340 if ((name == NULL) || (schema == NULL))
3341 return (NULL);
3342
3343
3344 ret = xmlHashLookup2(schema->groupDecl, name, namespace);
3345 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL))
3346 return (ret);
3347 else
3348 ret = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00003349 /*
3350 * Removed since imported components will be hold by the main schema only.
3351 *
Daniel Veillard3646d642004-06-02 19:19:14 +00003352 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00003353 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00003354 else
3355 import = xmlHashLookup(schema->schemasImports, namespace);
3356 if (import != NULL) {
3357 ret = xmlSchemaGetGroup(import->schema, name, namespace);
3358 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL))
3359 return (ret);
3360 else
3361 ret = NULL;
3362 }
William M. Brack2f2a6632004-08-20 23:09:47 +00003363 */
Daniel Veillard3646d642004-06-02 19:19:14 +00003364#ifdef DEBUG
3365 if (ret == NULL) {
3366 if (namespace == NULL)
3367 fprintf(stderr, "Unable to lookup group %s", name);
3368 else
3369 fprintf(stderr, "Unable to lookup group %s:%s", name,
3370 namespace);
3371 }
3372#endif
3373 return (ret);
3374}
3375
Daniel Veillard4255d502002-04-16 15:50:10 +00003376/************************************************************************
3377 * *
3378 * Parsing functions *
3379 * *
3380 ************************************************************************/
3381
3382#define IS_BLANK_NODE(n) \
3383 (((n)->type == XML_TEXT_NODE) && (xmlSchemaIsBlank((n)->content)))
3384
3385/**
3386 * xmlSchemaIsBlank:
3387 * @str: a string
3388 *
3389 * Check if a string is ignorable
3390 *
3391 * Returns 1 if the string is NULL or made of blanks chars, 0 otherwise
3392 */
3393static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003394xmlSchemaIsBlank(xmlChar * str)
3395{
Daniel Veillard4255d502002-04-16 15:50:10 +00003396 if (str == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003397 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003398 while (*str != 0) {
William M. Brack76e95df2003-10-18 16:20:14 +00003399 if (!(IS_BLANK_CH(*str)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003400 return (0);
3401 str++;
Daniel Veillard4255d502002-04-16 15:50:10 +00003402 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003403 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003404}
3405
3406/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003407 * xmlSchemaAddAssembledItem:
3408 * @ctxt: a schema parser context
3409 * @schema: the schema being built
3410 * @item: the item
3411 *
3412 * Add a item to the schema's list of current items.
3413 * This is used if the schema was already constructed and
3414 * new schemata need to be added to it.
3415 * *WARNING* this interface is highly subject to change.
3416 *
3417 * Returns 0 if suceeds and -1 if an internal error occurs.
3418 */
3419static int
3420xmlSchemaAddAssembledItem(xmlSchemaParserCtxtPtr ctxt,
3421 xmlSchemaTypePtr item)
3422{
3423 static int growSize = 100;
3424 xmlSchemaAssemblePtr ass;
3425
3426 ass = ctxt->assemble;
3427 if (ass->sizeItems < 0) {
3428 /* If disabled. */
3429 return (0);
3430 }
3431 if (ass->sizeItems <= 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00003432 ass->items = (void **) xmlMalloc(growSize * sizeof(xmlSchemaTypePtr));
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003433 if (ass->items == NULL) {
3434 xmlSchemaPErrMemory(ctxt,
3435 "allocating new item buffer", NULL);
3436 return (-1);
3437 }
3438 ass->sizeItems = growSize;
3439 } else if (ass->sizeItems <= ass->nbItems) {
3440 ass->sizeItems *= 2;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00003441 ass->items = (void **) xmlRealloc(ass->items,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003442 ass->sizeItems * sizeof(xmlSchemaTypePtr));
3443 if (ass->items == NULL) {
3444 xmlSchemaPErrMemory(ctxt,
3445 "growing item buffer", NULL);
3446 ass->sizeItems = 0;
3447 return (-1);
3448 }
3449 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00003450 /* ass->items[ass->nbItems++] = (void *) item; */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003451 ((xmlSchemaTypePtr *) ass->items)[ass->nbItems++] = (void *) item;
3452 return (0);
3453}
3454
3455/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003456 * xmlSchemaAddNotation:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003457 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00003458 * @schema: the schema being built
3459 * @name: the item name
3460 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00003461 * Add an XML schema annotation declaration
Daniel Veillard4255d502002-04-16 15:50:10 +00003462 * *WARNING* this interface is highly subject to change
3463 *
3464 * Returns the new struture or NULL in case of error
3465 */
3466static xmlSchemaNotationPtr
3467xmlSchemaAddNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003468 const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +00003469{
3470 xmlSchemaNotationPtr ret = NULL;
3471 int val;
3472
3473 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
3474 return (NULL);
3475
3476 if (schema->notaDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00003477 schema->notaDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00003478 if (schema->notaDecl == NULL)
3479 return (NULL);
3480
3481 ret = (xmlSchemaNotationPtr) xmlMalloc(sizeof(xmlSchemaNotation));
3482 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003483 xmlSchemaPErrMemory(ctxt, "add annotation", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003484 return (NULL);
3485 }
3486 memset(ret, 0, sizeof(xmlSchemaNotation));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003487 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003488 val = xmlHashAddEntry2(schema->notaDecl, name, schema->targetNamespace,
3489 ret);
3490 if (val != 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00003491 /*
3492 * TODO: This should never happen, since a unique name will be computed.
3493 * If it fails, then an other internal error must have occured.
3494 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003495 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
3496 XML_SCHEMAP_REDEFINED_NOTATION,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003497 "Annotation declaration '%s' is already declared.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003498 name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003499 xmlFree(ret);
3500 return (NULL);
3501 }
3502 return (ret);
3503}
3504
3505
3506/**
3507 * xmlSchemaAddAttribute:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003508 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00003509 * @schema: the schema being built
3510 * @name: the item name
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003511 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00003512 *
3513 * Add an XML schema Attrribute declaration
3514 * *WARNING* this interface is highly subject to change
3515 *
3516 * Returns the new struture or NULL in case of error
3517 */
3518static xmlSchemaAttributePtr
3519xmlSchemaAddAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00003520 const xmlChar * name, const xmlChar * namespace,
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003521 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00003522{
3523 xmlSchemaAttributePtr ret = NULL;
3524 int val;
3525
3526 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
3527 return (NULL);
3528
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003529#ifdef DEBUG
3530 fprintf(stderr, "Adding attribute %s\n", name);
3531 if (namespace != NULL)
3532 fprintf(stderr, " target namespace %s\n", namespace);
3533#endif
3534
Daniel Veillard4255d502002-04-16 15:50:10 +00003535 if (schema->attrDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00003536 schema->attrDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00003537 if (schema->attrDecl == NULL)
3538 return (NULL);
3539
3540 ret = (xmlSchemaAttributePtr) xmlMalloc(sizeof(xmlSchemaAttribute));
3541 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003542 xmlSchemaPErrMemory(ctxt, "allocating attribute", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003543 return (NULL);
3544 }
3545 memset(ret, 0, sizeof(xmlSchemaAttribute));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003546 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00003547 ret->targetNamespace = namespace;
Daniel Veillard4255d502002-04-16 15:50:10 +00003548 val = xmlHashAddEntry3(schema->attrDecl, name,
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00003549 namespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003550 if (val != 0) {
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003551 if (topLevel) {
3552 xmlSchemaPCustomErr(ctxt,
3553 XML_SCHEMAP_REDEFINED_ATTR,
3554 NULL, NULL, node,
3555 "A global attribute declaration with the name '%s' does "
3556 "already exist", name);
3557 xmlFree(ret);
3558 return (NULL);
3559 } else {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003560 char buf[30];
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003561 /*
3562 * Using the ctxt->container for xmlHashAddEntry3 is ambigious
3563 * in the scenario:
3564 * 1. multiple top-level complex types have different target
3565 * namespaces but have the SAME NAME; this can happen if
3566 * schemata are imported
3567 * 2. those complex types contain attributes with an equal name
3568 * 3. those attributes are in no namespace
3569 * We will compute a new context string.
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003570 */
3571 snprintf(buf, 29, "#aCont%d", ctxt->counter++ + 1);
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003572 val = xmlHashAddEntry3(schema->attrDecl, name,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00003573 namespace, xmlDictLookup(ctxt->dict, BAD_CAST buf, -1), ret);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003574
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003575 if (val != 0) {
3576 xmlSchemaPCustomErr(ctxt,
3577 XML_SCHEMAP_INTERNAL,
3578 NULL, NULL, node,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003579 "Internal error: xmlSchemaAddAttribute, "
3580 "a dublicate attribute declaration with the name '%s' "
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003581 "could not be added to the hash.", name);
3582 xmlFree(ret);
3583 return (NULL);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003584 }
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003585 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003586 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003587 if (ctxt->assemble != NULL)
3588 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003589 return (ret);
3590}
3591
3592/**
3593 * xmlSchemaAddAttributeGroup:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003594 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00003595 * @schema: the schema being built
3596 * @name: the item name
3597 *
3598 * Add an XML schema Attrribute Group declaration
3599 *
3600 * Returns the new struture or NULL in case of error
3601 */
3602static xmlSchemaAttributeGroupPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003603xmlSchemaAddAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00003604 xmlSchemaPtr schema, const xmlChar * name,
3605 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00003606{
3607 xmlSchemaAttributeGroupPtr ret = NULL;
3608 int val;
3609
3610 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
3611 return (NULL);
3612
3613 if (schema->attrgrpDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00003614 schema->attrgrpDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00003615 if (schema->attrgrpDecl == NULL)
3616 return (NULL);
3617
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003618 ret =
3619 (xmlSchemaAttributeGroupPtr)
3620 xmlMalloc(sizeof(xmlSchemaAttributeGroup));
Daniel Veillard4255d502002-04-16 15:50:10 +00003621 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003622 xmlSchemaPErrMemory(ctxt, "allocating attribute group", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003623 return (NULL);
3624 }
3625 memset(ret, 0, sizeof(xmlSchemaAttributeGroup));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003626 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003627 val = xmlHashAddEntry3(schema->attrgrpDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003628 schema->targetNamespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003629 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00003630 xmlSchemaPCustomErr(ctxt,
3631 XML_SCHEMAP_REDEFINED_ATTRGROUP,
3632 NULL, NULL, node,
3633 "A global attribute group definition with the name '%s' does already exist", name);
Daniel Veillard4255d502002-04-16 15:50:10 +00003634 xmlFree(ret);
3635 return (NULL);
3636 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003637 if (ctxt->assemble != NULL)
3638 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003639 return (ret);
3640}
3641
3642/**
3643 * xmlSchemaAddElement:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003644 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00003645 * @schema: the schema being built
3646 * @name: the type name
3647 * @namespace: the type namespace
3648 *
3649 * Add an XML schema Element declaration
3650 * *WARNING* this interface is highly subject to change
3651 *
3652 * Returns the new struture or NULL in case of error
3653 */
3654static xmlSchemaElementPtr
3655xmlSchemaAddElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00003656 const xmlChar * name, const xmlChar * namespace,
3657 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00003658{
3659 xmlSchemaElementPtr ret = NULL;
3660 int val;
3661
3662 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
3663 return (NULL);
3664
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003665#ifdef DEBUG
3666 fprintf(stderr, "Adding element %s\n", name);
3667 if (namespace != NULL)
3668 fprintf(stderr, " target namespace %s\n", namespace);
3669#endif
3670
Daniel Veillard4255d502002-04-16 15:50:10 +00003671 if (schema->elemDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00003672 schema->elemDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00003673 if (schema->elemDecl == NULL)
3674 return (NULL);
3675
3676 ret = (xmlSchemaElementPtr) xmlMalloc(sizeof(xmlSchemaElement));
3677 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003678 xmlSchemaPErrMemory(ctxt, "allocating element", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003679 return (NULL);
3680 }
3681 memset(ret, 0, sizeof(xmlSchemaElement));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003682 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003683 val = xmlHashAddEntry3(schema->elemDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003684 namespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003685 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00003686 if (topLevel) {
3687 xmlSchemaPCustomErr(ctxt,
3688 XML_SCHEMAP_REDEFINED_ELEMENT,
3689 NULL, NULL, node,
3690 "A global element declaration with the name '%s' does "
3691 "already exist", name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003692 xmlFree(ret);
3693 return (NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +00003694 } else {
3695 char buf[30];
3696
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003697 snprintf(buf, 29, "#eCont%d", ctxt->counter++ + 1);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003698 val = xmlHashAddEntry3(schema->elemDecl, name,
3699 namespace, (xmlChar *) buf, ret);
William M. Brack2f2a6632004-08-20 23:09:47 +00003700 if (val != 0) {
3701 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003702 XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +00003703 NULL, NULL, node,
3704 "Internal error: xmlSchemaAddElement, "
3705 "a dublicate element declaration with the name '%s' "
3706 "could not be added to the hash.", name);
3707 xmlFree(ret);
3708 return (NULL);
3709 }
3710 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00003711
Daniel Veillard4255d502002-04-16 15:50:10 +00003712 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003713 if (ctxt->assemble != NULL)
3714 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003715 return (ret);
3716}
3717
3718/**
3719 * xmlSchemaAddType:
Daniel Veillard01fa6152004-06-29 17:04:39 +00003720 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00003721 * @schema: the schema being built
3722 * @name: the item name
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003723 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00003724 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00003725 * Add an XML schema item
Daniel Veillard4255d502002-04-16 15:50:10 +00003726 * *WARNING* this interface is highly subject to change
3727 *
3728 * Returns the new struture or NULL in case of error
3729 */
3730static xmlSchemaTypePtr
3731xmlSchemaAddType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00003732 const xmlChar * name, const xmlChar * namespace,
3733 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00003734{
3735 xmlSchemaTypePtr ret = NULL;
3736 int val;
3737
3738 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
3739 return (NULL);
3740
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003741#ifdef DEBUG
3742 fprintf(stderr, "Adding type %s\n", name);
3743 if (namespace != NULL)
3744 fprintf(stderr, " target namespace %s\n", namespace);
3745#endif
3746
Daniel Veillard4255d502002-04-16 15:50:10 +00003747 if (schema->typeDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00003748 schema->typeDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00003749 if (schema->typeDecl == NULL)
3750 return (NULL);
3751
3752 ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
3753 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003754 xmlSchemaPErrMemory(ctxt, "allocating type", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003755 return (NULL);
3756 }
3757 memset(ret, 0, sizeof(xmlSchemaType));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003758 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00003759 ret->redef = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003760 val = xmlHashAddEntry2(schema->typeDecl, name, namespace, ret);
William M. Brack2f2a6632004-08-20 23:09:47 +00003761 if (val != 0) {
3762 if (ctxt->includes == 0) {
3763 xmlSchemaPCustomErr(ctxt,
3764 XML_SCHEMAP_REDEFINED_TYPE,
3765 NULL, NULL, node,
3766 "A global type definition with the name '%s' does already exist", name);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00003767 xmlFree(ret);
3768 return (NULL);
3769 } else {
3770 xmlSchemaTypePtr prev;
3771
3772 prev = xmlHashLookup2(schema->typeDecl, name, namespace);
3773 if (prev == NULL) {
3774 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003775 XML_ERR_INTERNAL_ERROR,
3776 "Internal error: xmlSchemaAddType, on type "
3777 "'%s'.\n",
3778 name, NULL);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00003779 xmlFree(ret);
3780 return (NULL);
3781 }
3782 ret->redef = prev->redef;
3783 prev->redef = ret;
3784 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003785 }
3786 ret->minOccurs = 1;
3787 ret->maxOccurs = 1;
Daniel Veillard3646d642004-06-02 19:19:14 +00003788 ret->attributeUses = NULL;
3789 ret->attributeWildcard = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003790 if (ctxt->assemble != NULL)
3791 xmlSchemaAddAssembledItem(ctxt,ret);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003792 return (ret);
3793}
3794
3795/**
3796 * xmlSchemaAddGroup:
3797 * @ctxt: a schema validation context
3798 * @schema: the schema being built
3799 * @name: the group name
3800 *
3801 * Add an XML schema Group definition
3802 *
3803 * Returns the new struture or NULL in case of error
3804 */
3805static xmlSchemaTypePtr
3806xmlSchemaAddGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00003807 const xmlChar *name, const xmlChar *namespaceName,
3808 xmlNodePtr node)
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003809{
3810 xmlSchemaTypePtr ret = NULL;
3811 int val;
3812
3813 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
3814 return (NULL);
3815
3816 if (schema->groupDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00003817 schema->groupDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003818 if (schema->groupDecl == NULL)
3819 return (NULL);
3820
3821 ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
3822 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003823 xmlSchemaPErrMemory(ctxt, "adding group", NULL);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003824 return (NULL);
3825 }
3826 memset(ret, 0, sizeof(xmlSchemaType));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003827 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003828 val =
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00003829 xmlHashAddEntry2(schema->groupDecl, name, namespaceName,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003830 ret);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003831 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00003832 xmlSchemaPCustomErr(ctxt,
3833 XML_SCHEMAP_REDEFINED_GROUP,
3834 NULL, NULL, node,
3835 "A global model group definition with the name '%s' does already exist", name);
Daniel Veillard4255d502002-04-16 15:50:10 +00003836 xmlFree(ret);
3837 return (NULL);
3838 }
3839 ret->minOccurs = 1;
3840 ret->maxOccurs = 1;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003841 if (ctxt->assemble != NULL)
3842 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003843 return (ret);
3844}
3845
Daniel Veillard3646d642004-06-02 19:19:14 +00003846/**
3847 * xmlSchemaNewWildcardNs:
3848 * @ctxt: a schema validation context
3849 *
3850 * Creates a new wildcard namespace constraint.
3851 *
3852 * Returns the new struture or NULL in case of error
3853 */
3854static xmlSchemaWildcardNsPtr
3855xmlSchemaNewWildcardNsConstraint(xmlSchemaParserCtxtPtr ctxt)
3856{
3857 xmlSchemaWildcardNsPtr ret;
3858
3859 ret = (xmlSchemaWildcardNsPtr)
3860 xmlMalloc(sizeof(xmlSchemaWildcardNs));
3861 if (ret == NULL) {
3862 xmlSchemaPErrMemory(ctxt, "creating wildcard namespace constraint", NULL);
3863 return (NULL);
3864 }
3865 ret->value = NULL;
3866 ret->next = NULL;
3867 return (ret);
3868}
3869
3870/**
3871 * xmlSchemaAddWildcard:
3872 * @ctxt: a schema validation context
Daniel Veillardc0826a72004-08-10 14:17:33 +00003873 * Adds a wildcard. It corresponds to a
3874 * xsd:anyAttribute and is used as storage for namespace
3875 * constraints on a xsd:any.
Daniel Veillard3646d642004-06-02 19:19:14 +00003876 *
3877 * Returns the new struture or NULL in case of error
3878 */
3879static xmlSchemaWildcardPtr
3880xmlSchemaAddWildcard(xmlSchemaParserCtxtPtr ctxt)
3881{
3882 xmlSchemaWildcardPtr ret = NULL;
3883
3884 if (ctxt == NULL)
3885 return (NULL);
3886
3887 ret = (xmlSchemaWildcardPtr) xmlMalloc(sizeof(xmlSchemaWildcard));
3888 if (ret == NULL) {
3889 xmlSchemaPErrMemory(ctxt, "adding wildcard", NULL);
3890 return (NULL);
3891 }
3892 memset(ret, 0, sizeof(xmlSchemaWildcard));
3893 ret->minOccurs = 1;
3894 ret->maxOccurs = 1;
3895
3896 return (ret);
3897}
3898
Daniel Veillard4255d502002-04-16 15:50:10 +00003899/************************************************************************
3900 * *
3901 * Utilities for parsing *
3902 * *
3903 ************************************************************************/
3904
3905/**
3906 * xmlGetQNameProp:
3907 * @ctxt: a schema validation context
3908 * @node: a subtree containing XML Schema informations
3909 * @name: the attribute name
3910 * @namespace: the result namespace if any
3911 *
3912 * Extract a QName Attribute value
3913 *
3914 * Returns the NCName or NULL if not found, and also update @namespace
3915 * with the namespace URI
3916 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003917static const xmlChar *
Daniel Veillard4255d502002-04-16 15:50:10 +00003918xmlGetQNameProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003919 const char *name, const xmlChar ** namespace)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003920{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003921 const xmlChar *val;
Daniel Veillard4255d502002-04-16 15:50:10 +00003922 xmlNsPtr ns;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003923 const xmlChar *ret, *prefix;
3924 int len;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00003925 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00003926
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003927 *namespace = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00003928 attr = xmlSchemaGetPropNode(node, name);
3929 if (attr == NULL)
3930 return (NULL);
3931 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00003932
Daniel Veillard4255d502002-04-16 15:50:10 +00003933 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003934 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003935
Daniel Veillardba0153a2004-04-01 10:42:31 +00003936 if (!strchr((char *) val, ':')) {
Daniel Veillardebcdebd2004-03-05 00:15:50 +00003937 ns = xmlSearchNs(node->doc, node, 0);
3938 if (ns) {
3939 *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
3940 return (val);
3941 }
3942 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003943 ret = xmlSplitQName3(val, &len);
3944 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003945 return (val);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003946 }
3947 ret = xmlDictLookup(ctxt->dict, ret, -1);
3948 prefix = xmlDictLookup(ctxt->dict, val, len);
Daniel Veillard4255d502002-04-16 15:50:10 +00003949
3950 ns = xmlSearchNs(node->doc, node, prefix);
3951 if (ns == NULL) {
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00003952 xmlSchemaPSimpleTypeErr(ctxt, XML_SCHEMAP_PREFIX_UNDEFINED,
3953 NULL, NULL, (xmlNodePtr) attr,
3954 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), NULL, val,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003955 "The QName value '%s' has no corresponding namespace "
3956 "declaration in scope", val, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003957 } else {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003958 *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003959 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003960 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003961}
3962
3963/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00003964 * xmlSchemaPValAttrNodeQNameValue:
3965 * @ctxt: a schema parser context
3966 * @schema: the schema context
3967 * @ownerDes: the designation of the parent element
3968 * @ownerItem: the parent as a schema object
3969 * @value: the QName value
3970 * @local: the resulting local part if found, the attribute value otherwise
3971 * @uri: the resulting namespace URI if found
3972 *
3973 * Extracts the local name and the URI of a QName value and validates it.
3974 * This one is intended to be used on attribute values that
3975 * should resolve to schema components.
3976 *
3977 * Returns 0, in case the QName is valid, a positive error code
3978 * if not valid and -1 if an internal error occurs.
3979 */
3980static int
3981xmlSchemaPValAttrNodeQNameValue(xmlSchemaParserCtxtPtr ctxt,
3982 xmlSchemaPtr schema,
3983 xmlChar **ownerDes,
3984 xmlSchemaTypePtr ownerItem,
3985 xmlAttrPtr attr,
3986 const xmlChar *value,
3987 const xmlChar **uri,
3988 const xmlChar **prefix,
3989 const xmlChar **local)
3990{
3991 const xmlChar *pref;
3992 xmlNsPtr ns;
3993 int len, ret;
3994
3995 *uri = NULL;
3996 *local = NULL;
3997 if (prefix != 0)
3998 *prefix = NULL;
3999 ret = xmlValidateQName(value, 1);
4000 if (ret > 0) {
4001 xmlSchemaPSimpleTypeErr(ctxt,
4002 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
4003 ownerDes, ownerItem, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00004004 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
4005 "QName", value,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004006 NULL, NULL, NULL);
4007 *local = value;
4008 return (ctxt->err);
4009 } else if (ret < 0)
4010 return (-1);
4011
4012 if (!strchr((char *) value, ':')) {
4013 ns = xmlSearchNs(attr->doc, attr->parent, 0);
4014 if (ns)
4015 *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
4016 else if (schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) {
4017 /*
4018 * This one takes care of included schemas with no
4019 * target namespace.
4020 */
4021 *uri = schema->targetNamespace;
4022 }
4023 *local = value;
4024 return (0);
4025 }
4026 /*
4027 * At this point xmlSplitQName3 has to return a local name.
4028 */
4029 *local = xmlSplitQName3(value, &len);
4030 *local = xmlDictLookup(ctxt->dict, *local, -1);
4031 pref = xmlDictLookup(ctxt->dict, value, len);
4032 if (prefix != 0)
4033 *prefix = pref;
4034 ns = xmlSearchNs(attr->doc, attr->parent, pref);
4035 if (ns == NULL) {
4036 xmlSchemaPSimpleTypeErr(ctxt,
4037 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
4038 ownerDes, ownerItem, (xmlNodePtr) attr,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004039 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), "QName", value,
4040 "The QName value '%s' has no corresponding namespace "
4041 "declaration in scope", value, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004042 return (ctxt->err);
4043 } else {
4044 *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
4045 }
4046 return (0);
4047}
4048
4049/**
4050 * xmlSchemaPValAttrNodeQName:
4051 * @ctxt: a schema parser context
4052 * @schema: the schema context
4053 * @ownerDes: the designation of the owner element
4054 * @ownerItem: the owner as a schema object
4055 * @attr: the attribute node
4056 * @local: the resulting local part if found, the attribute value otherwise
4057 * @uri: the resulting namespace URI if found
4058 *
4059 * Extracts and validates the QName of an attribute value.
4060 * This one is intended to be used on attribute values that
4061 * should resolve to schema components.
4062 *
4063 * Returns 0, in case the QName is valid, a positive error code
4064 * if not valid and -1 if an internal error occurs.
4065 */
4066static int
4067xmlSchemaPValAttrNodeQName(xmlSchemaParserCtxtPtr ctxt,
4068 xmlSchemaPtr schema,
4069 xmlChar **ownerDes,
4070 xmlSchemaTypePtr ownerItem,
4071 xmlAttrPtr attr,
4072 const xmlChar **uri,
4073 const xmlChar **prefix,
4074 const xmlChar **local)
4075{
4076 const xmlChar *value;
4077
4078 value = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
4079 return (xmlSchemaPValAttrNodeQNameValue(ctxt, schema,
4080 ownerDes, ownerItem, attr, value, uri, prefix, local));
4081}
4082
4083/**
4084 * xmlSchemaPValAttrQName:
4085 * @ctxt: a schema parser context
4086 * @schema: the schema context
4087 * @ownerDes: the designation of the parent element
4088 * @ownerItem: the owner as a schema object
4089 * @ownerElem: the parent node of the attribute
4090 * @name: the name of the attribute
4091 * @local: the resulting local part if found, the attribute value otherwise
4092 * @uri: the resulting namespace URI if found
4093 *
4094 * Extracts and validates the QName of an attribute value.
4095 *
4096 * Returns 0, in case the QName is valid, a positive error code
4097 * if not valid and -1 if an internal error occurs.
4098 */
4099static int
4100xmlSchemaPValAttrQName(xmlSchemaParserCtxtPtr ctxt,
4101 xmlSchemaPtr schema,
4102 xmlChar **ownerDes,
4103 xmlSchemaTypePtr ownerItem,
4104 xmlNodePtr ownerElem,
4105 const char *name,
4106 const xmlChar **uri,
4107 const xmlChar **prefix,
4108 const xmlChar **local)
4109{
4110 xmlAttrPtr attr;
4111
4112 attr = xmlSchemaGetPropNode(ownerElem, name);
4113 if (attr == NULL) {
4114 *local = NULL;
4115 *uri = NULL;
4116 return (0);
4117 }
4118 return (xmlSchemaPValAttrNodeQName(ctxt, schema,
4119 ownerDes, ownerItem, attr, uri, prefix, local));
4120}
4121
4122/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004123 * xmlGetMaxOccurs:
4124 * @ctxt: a schema validation context
4125 * @node: a subtree containing XML Schema informations
4126 *
4127 * Get the maxOccurs property
4128 *
4129 * Returns the default if not found, or the value
4130 */
4131static int
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004132xmlGetMaxOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
4133 int min, int max, int def, const char *expected)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004134{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004135 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00004136 int ret = 0;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004137 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00004138
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004139 attr = xmlSchemaGetPropNode(node, "maxOccurs");
4140 if (attr == NULL)
4141 return (def);
4142 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Daniel Veillard4255d502002-04-16 15:50:10 +00004143
4144 if (xmlStrEqual(val, (const xmlChar *) "unbounded")) {
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004145 if (max != UNBOUNDED) {
4146 xmlSchemaPSimpleTypeErr(ctxt,
4147 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
4148 /* XML_SCHEMAP_INVALID_MINOCCURS, */
4149 NULL, NULL, (xmlNodePtr) attr, NULL, expected,
4150 val, NULL, NULL, NULL);
4151 return (def);
4152 } else
4153 return (UNBOUNDED); /* encoding it with -1 might be another option */
Daniel Veillard4255d502002-04-16 15:50:10 +00004154 }
4155
4156 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00004157 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004158 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004159 if (*cur == 0) {
4160 xmlSchemaPSimpleTypeErr(ctxt,
4161 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
4162 /* XML_SCHEMAP_INVALID_MINOCCURS, */
4163 NULL, NULL, (xmlNodePtr) attr, NULL, expected,
4164 val, NULL, NULL, NULL);
4165 return (def);
4166 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004167 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004168 ret = ret * 10 + (*cur - '0');
4169 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00004170 }
William M. Brack76e95df2003-10-18 16:20:14 +00004171 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004172 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004173 /*
4174 * TODO: Restrict the maximal value to Integer.
4175 */
4176 if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
4177 xmlSchemaPSimpleTypeErr(ctxt,
4178 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
4179 /* XML_SCHEMAP_INVALID_MINOCCURS, */
4180 NULL, NULL, (xmlNodePtr) attr, NULL, expected,
4181 val, NULL, NULL, NULL);
4182 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00004183 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004184 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004185}
4186
4187/**
4188 * xmlGetMinOccurs:
4189 * @ctxt: a schema validation context
4190 * @node: a subtree containing XML Schema informations
4191 *
4192 * Get the minOccurs property
4193 *
4194 * Returns the default if not found, or the value
4195 */
4196static int
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004197xmlGetMinOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
4198 int min, int max, int def, const char *expected)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004199{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004200 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00004201 int ret = 0;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004202 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00004203
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004204 attr = xmlSchemaGetPropNode(node, "minOccurs");
4205 if (attr == NULL)
4206 return (def);
4207 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Daniel Veillard4255d502002-04-16 15:50:10 +00004208 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00004209 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004210 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004211 if (*cur == 0) {
4212 xmlSchemaPSimpleTypeErr(ctxt,
4213 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
4214 /* XML_SCHEMAP_INVALID_MINOCCURS, */
4215 NULL, NULL, (xmlNodePtr) attr, NULL, expected,
4216 val, NULL, NULL, NULL);
4217 return (def);
4218 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004219 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004220 ret = ret * 10 + (*cur - '0');
4221 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00004222 }
William M. Brack76e95df2003-10-18 16:20:14 +00004223 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004224 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004225 /*
4226 * TODO: Restrict the maximal value to Integer.
4227 */
4228 if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
4229 xmlSchemaPSimpleTypeErr(ctxt,
4230 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
4231 /* XML_SCHEMAP_INVALID_MINOCCURS, */
4232 NULL, NULL, (xmlNodePtr) attr, NULL, expected,
4233 val, NULL, NULL, NULL);
4234 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00004235 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004236 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004237}
4238
4239/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00004240 * xmlSchemaPGetBoolNodeValue:
4241 * @ctxt: a schema validation context
4242 * @ownerDes: owner designation
4243 * @ownerItem: the owner as a schema item
4244 * @node: the node holding the value
4245 *
4246 * Converts a boolean string value into 1 or 0.
4247 *
4248 * Returns 0 or 1.
4249 */
4250static int
4251xmlSchemaPGetBoolNodeValue(xmlSchemaParserCtxtPtr ctxt,
4252 xmlChar **ownerDes,
4253 xmlSchemaTypePtr ownerItem,
4254 xmlNodePtr node)
4255{
4256 xmlChar *value = NULL;
4257 int res = 0;
4258
4259 value = xmlNodeGetContent(node);
4260 /*
4261 * 3.2.2.1 Lexical representation
4262 * An instance of a datatype that is defined as ·boolean·
4263 * can have the following legal literals {true, false, 1, 0}.
4264 */
4265 if (xmlStrEqual(BAD_CAST value, BAD_CAST "true"))
4266 res = 1;
4267 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "false"))
4268 res = 0;
4269 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "1"))
4270 res = 1;
4271 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "0"))
4272 res = 0;
4273 else {
4274 xmlSchemaPSimpleTypeErr(ctxt,
4275 XML_SCHEMAP_INVALID_BOOLEAN,
4276 ownerDes, ownerItem, node,
4277 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
4278 "(1 | 0 | true | false)", BAD_CAST value,
4279 NULL, NULL, NULL);
4280 }
4281 if (value != NULL)
4282 xmlFree(value);
4283 return (res);
4284}
4285
4286/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004287 * xmlGetBooleanProp:
4288 * @ctxt: a schema validation context
4289 * @node: a subtree containing XML Schema informations
4290 * @name: the attribute name
4291 * @def: the default value
4292 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00004293 * Evaluate if a boolean property is set
Daniel Veillard4255d502002-04-16 15:50:10 +00004294 *
4295 * Returns the default if not found, 0 if found to be false,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004296 * 1 if found to be true
Daniel Veillard4255d502002-04-16 15:50:10 +00004297 */
4298static int
Daniel Veillardc0826a72004-08-10 14:17:33 +00004299xmlGetBooleanProp(xmlSchemaParserCtxtPtr ctxt,
4300 xmlChar **ownerDes,
4301 xmlSchemaTypePtr ownerItem,
4302 xmlNodePtr node,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004303 const char *name, int def)
4304{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004305 const xmlChar *val;
Daniel Veillard4255d502002-04-16 15:50:10 +00004306
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004307 val = xmlSchemaGetProp(ctxt, node, name);
Daniel Veillard4255d502002-04-16 15:50:10 +00004308 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004309 return (def);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004310 /*
4311 * 3.2.2.1 Lexical representation
4312 * An instance of a datatype that is defined as ·boolean·
4313 * can have the following legal literals {true, false, 1, 0}.
4314 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004315 if (xmlStrEqual(val, BAD_CAST "true"))
4316 def = 1;
4317 else if (xmlStrEqual(val, BAD_CAST "false"))
4318 def = 0;
Daniel Veillardc0826a72004-08-10 14:17:33 +00004319 else if (xmlStrEqual(val, BAD_CAST "1"))
4320 def = 1;
4321 else if (xmlStrEqual(val, BAD_CAST "0"))
4322 def = 0;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00004323 else {
Daniel Veillardc0826a72004-08-10 14:17:33 +00004324 xmlSchemaPSimpleTypeErr(ctxt,
4325 XML_SCHEMAP_INVALID_BOOLEAN,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00004326 ownerDes, ownerItem,
4327 (xmlNodePtr) xmlSchemaGetPropNode(node, name),
William M. Brack2f2a6632004-08-20 23:09:47 +00004328 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
4329 "(1 | 0 | true | false)", val, NULL, NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004330 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004331 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00004332}
4333
4334/************************************************************************
4335 * *
4336 * Shema extraction from an Infoset *
4337 * *
4338 ************************************************************************/
4339static xmlSchemaTypePtr xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr
4340 ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00004341 xmlNodePtr node,
4342 int topLevel);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004343static xmlSchemaTypePtr xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr
4344 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00004345 xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00004346 xmlNodePtr node,
4347 int topLevel);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004348static xmlSchemaTypePtr xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr
4349 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00004350 xmlSchemaPtr schema,
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00004351 xmlNodePtr node);
Daniel Veillard4255d502002-04-16 15:50:10 +00004352static xmlSchemaTypePtr xmlSchemaParseSequence(xmlSchemaParserCtxtPtr ctxt,
4353 xmlSchemaPtr schema,
4354 xmlNodePtr node);
4355static xmlSchemaTypePtr xmlSchemaParseAll(xmlSchemaParserCtxtPtr ctxt,
4356 xmlSchemaPtr schema,
4357 xmlNodePtr node);
4358static xmlSchemaAttributePtr xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr
4359 ctxt,
4360 xmlSchemaPtr schema,
William M. Bracke7091952004-05-11 15:09:58 +00004361 xmlNodePtr node,
4362 int topLevel);
Daniel Veillard4255d502002-04-16 15:50:10 +00004363static xmlSchemaAttributeGroupPtr
4364xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +00004365 xmlSchemaPtr schema, xmlNodePtr node,
4366 int topLevel);
Daniel Veillard4255d502002-04-16 15:50:10 +00004367static xmlSchemaTypePtr xmlSchemaParseChoice(xmlSchemaParserCtxtPtr ctxt,
4368 xmlSchemaPtr schema,
4369 xmlNodePtr node);
4370static xmlSchemaTypePtr xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt,
4371 xmlSchemaPtr schema,
4372 xmlNodePtr node);
Daniel Veillard3646d642004-06-02 19:19:14 +00004373static xmlSchemaWildcardPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004374xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
4375 xmlSchemaPtr schema, xmlNodePtr node);
Daniel Veillard4255d502002-04-16 15:50:10 +00004376
4377/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004378 * xmlSchemaPValAttrNodeValue:
Daniel Veillard01fa6152004-06-29 17:04:39 +00004379 *
4380 * @ctxt: a schema parser context
Daniel Veillardc0826a72004-08-10 14:17:33 +00004381 * @ownerDes: the designation of the parent element
4382 * @ownerItem: the schema object owner if existent
4383 * @attr: the schema attribute node being validated
4384 * @value: the value
4385 * @type: the built-in type to be validated against
Daniel Veillard01fa6152004-06-29 17:04:39 +00004386 *
4387 * Validates a value against the given built-in type.
4388 * This one is intended to be used internally for validation
4389 * of schema attribute values during parsing of the schema.
4390 *
4391 * Returns 0 if the value is valid, a positive error code
4392 * number otherwise and -1 in case of an internal or API error.
4393 */
4394static int
Daniel Veillardc0826a72004-08-10 14:17:33 +00004395xmlSchemaPValAttrNodeValue(xmlSchemaParserCtxtPtr ctxt,
4396 xmlChar **ownerDes,
4397 xmlSchemaTypePtr ownerItem,
4398 xmlAttrPtr attr,
4399 const xmlChar *value,
4400 xmlSchemaTypePtr type)
Daniel Veillard01fa6152004-06-29 17:04:39 +00004401{
Daniel Veillard01fa6152004-06-29 17:04:39 +00004402
Daniel Veillardc0826a72004-08-10 14:17:33 +00004403 int ret = 0;
4404
4405 /*
4406 * NOTE: Should we move this to xmlschematypes.c? Hmm, but this
4407 * one is really meant to be used internally, so better not.
4408 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00004409 if ((ctxt == NULL) || (type == NULL) || (attr == NULL))
Daniel Veillardc0826a72004-08-10 14:17:33 +00004410 return (-1);
4411 if (type->type != XML_SCHEMA_TYPE_BASIC) {
4412 xmlSchemaPErr(ctxt, (xmlNodePtr) attr,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00004413 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00004414 "Internal error: xmlSchemaPValAttrNodeValue, the given "
Daniel Veillardc0826a72004-08-10 14:17:33 +00004415 "type '%s' is not a built-in type.\n",
4416 type->name, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00004417 return (-1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004418 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00004419 switch (type->builtInType) {
4420 case XML_SCHEMAS_NCNAME:
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00004421 case XML_SCHEMAS_QNAME:
4422 case XML_SCHEMAS_ANYURI:
4423 case XML_SCHEMAS_TOKEN:
4424 case XML_SCHEMAS_LANGUAGE:
4425 ret = xmlSchemaValPredefTypeNode(type, value, NULL, (xmlNodePtr) attr);
4426 break;
4427
4428 /*
4429 case XML_SCHEMAS_NCNAME:
Daniel Veillard01fa6152004-06-29 17:04:39 +00004430 ret = xmlValidateNCName(value, 1);
4431 break;
4432 case XML_SCHEMAS_QNAME:
Daniel Veillardc0826a72004-08-10 14:17:33 +00004433 xmlSchemaPErr(ctxt, (xmlNodePtr) attr,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00004434 XML_SCHEMAP_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004435 "Internal error: xmlSchemaPvalueAttrNode, use "
4436 "the function xmlSchemaExtractSchemaQNamePropvalueidated "
4437 "for extracting QName valueues instead.\n",
4438 NULL, NULL);
4439 return (-1);
4440 case XML_SCHEMAS_ANYURI:
4441 if (value != NULL) {
4442 xmlURIPtr uri = xmlParseURI((const char *) value);
4443 if (uri == NULL)
4444 ret = 1;
4445 else
4446 xmlFreeURI(uri);
Daniel Veillard01fa6152004-06-29 17:04:39 +00004447 }
4448 break;
Daniel Veillardc0826a72004-08-10 14:17:33 +00004449 case XML_SCHEMAS_TOKEN: {
4450 const xmlChar *cur = value;
4451
4452 if (IS_BLANK_CH(*cur)) {
4453 ret = 1;
4454 } else while (*cur != 0) {
4455 if ((*cur == 0xd) || (*cur == 0xa) || (*cur == 0x9)) {
4456 ret = 1;
4457 break;
4458 } else if (*cur == ' ') {
4459 cur++;
4460 if ((*cur == 0) || (*cur == ' ')) {
4461 ret = 1;
4462 break;
4463 }
4464 } else {
4465 cur++;
4466 }
4467 }
4468 }
4469 break;
4470 case XML_SCHEMAS_LANGUAGE:
4471 if (xmlCheckLanguageID(value) != 1)
4472 ret = 1;
4473 break;
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00004474 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00004475 default: {
4476 xmlSchemaPErr(ctxt, (xmlNodePtr) attr,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00004477 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00004478 "Internal error: xmlSchemaPValAttrNodeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +00004479 "valueidation using the type '%s' is not implemented "
4480 "yet.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +00004481 type->name, NULL);
4482 return (-1);
4483 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00004484 }
4485 /*
4486 * TODO: Should we use the S4S error codes instead?
4487 */
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00004488 if (ret < 0) {
4489 xmlSchemaPErr(ctxt, (xmlNodePtr) attr,
4490 XML_SCHEMAP_INTERNAL,
4491 "Internal error: xmlSchemaPValAttrNodeValue, "
4492 "failed to validate a schema attribute value.\n",
4493 NULL, NULL);
4494 return (-1);
4495 } else if (ret > 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00004496 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
4497 xmlSchemaPSimpleTypeErr(ctxt,
4498 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2,
4499 ownerDes, ownerItem, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00004500 type, NULL, value,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004501 NULL, NULL, NULL);
4502 return(XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2);
4503 } else {
4504 xmlSchemaPSimpleTypeErr(ctxt,
4505 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1,
4506 ownerDes, ownerItem, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00004507 type, NULL, value,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004508 NULL, NULL, NULL);
4509 return(XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1);
4510 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00004511 }
4512 return (ret);
4513}
4514
4515/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00004516 * xmlSchemaPValAttrNode:
4517 *
4518 * @ctxt: a schema parser context
4519 * @ownerDes: the designation of the parent element
4520 * @ownerItem: the schema object owner if existent
4521 * @attr: the schema attribute node being validated
4522 * @type: the built-in type to be validated against
4523 * @value: the resulting value if any
4524 *
4525 * Extracts and validates a value against the given built-in type.
4526 * This one is intended to be used internally for validation
4527 * of schema attribute values during parsing of the schema.
4528 *
4529 * Returns 0 if the value is valid, a positive error code
4530 * number otherwise and -1 in case of an internal or API error.
4531 */
4532static int
4533xmlSchemaPValAttrNode(xmlSchemaParserCtxtPtr ctxt,
4534 xmlChar **ownerDes,
4535 xmlSchemaTypePtr ownerItem,
4536 xmlAttrPtr attr,
4537 xmlSchemaTypePtr type,
4538 const xmlChar **value)
4539{
4540 const xmlChar *val;
4541
4542 if ((ctxt == NULL) || (type == NULL) || (attr == NULL))
4543 return (-1);
4544
4545 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
4546 if (value != NULL)
4547 *value = val;
4548
4549 return (xmlSchemaPValAttrNodeValue(ctxt, ownerDes, ownerItem, attr,
4550 val, type));
4551}
4552
4553/**
4554 * xmlSchemaPValAttr:
4555 *
4556 * @ctxt: a schema parser context
4557 * @node: the element node of the attribute
4558 * @ownerDes: the designation of the parent element
4559 * @ownerItem: the schema object owner if existent
4560 * @ownerElem: the owner element node
4561 * @name: the name of the schema attribute node
4562 * @type: the built-in type to be validated against
4563 * @value: the resulting value if any
4564 *
4565 * Extracts and validates a value against the given built-in type.
4566 * This one is intended to be used internally for validation
4567 * of schema attribute values during parsing of the schema.
4568 *
4569 * Returns 0 if the value is valid, a positive error code
4570 * number otherwise and -1 in case of an internal or API error.
4571 */
4572static int
4573xmlSchemaPValAttr(xmlSchemaParserCtxtPtr ctxt,
4574 xmlChar **ownerDes,
4575 xmlSchemaTypePtr ownerItem,
4576 xmlNodePtr ownerElem,
4577 const char *name,
4578 xmlSchemaTypePtr type,
4579 const xmlChar **value)
4580{
4581 xmlAttrPtr attr;
4582
4583 if ((ctxt == NULL) || (type == NULL)) {
4584 if (value != NULL)
4585 *value = NULL;
4586 return (-1);
4587 }
4588 if (type->type != XML_SCHEMA_TYPE_BASIC) {
4589 if (value != NULL)
4590 *value = NULL;
4591 xmlSchemaPErr(ctxt, ownerElem,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00004592 XML_SCHEMAP_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004593 "Internal error: xmlSchemaPValAttr, the given "
4594 "type '%s' is not a built-in type.\n",
4595 type->name, NULL);
4596 return (-1);
4597 }
4598 attr = xmlSchemaGetPropNode(ownerElem, name);
4599 if (attr == NULL) {
4600 if (value != NULL)
4601 *value = NULL;
4602 return (0);
4603 }
4604 return (xmlSchemaPValAttrNode(ctxt, ownerDes, ownerItem, attr,
4605 type, value));
4606}
4607/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004608 * xmlSchemaParseAttrDecls:
4609 * @ctxt: a schema validation context
4610 * @schema: the schema being built
4611 * @node: a subtree containing XML Schema informations
4612 * @type: the hosting type
4613 *
4614 * parse a XML schema attrDecls declaration corresponding to
4615 * <!ENTITY % attrDecls
4616 * '((%attribute;| %attributeGroup;)*,(%anyAttribute;)?)'>
4617 */
4618static xmlNodePtr
4619xmlSchemaParseAttrDecls(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
4620 xmlNodePtr child, xmlSchemaTypePtr type)
4621{
4622 xmlSchemaAttributePtr lastattr, attr;
4623
4624 lastattr = NULL;
4625 while ((IS_SCHEMA(child, "attribute")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004626 (IS_SCHEMA(child, "attributeGroup"))) {
4627 attr = NULL;
4628 if (IS_SCHEMA(child, "attribute")) {
William M. Bracke7091952004-05-11 15:09:58 +00004629 attr = xmlSchemaParseAttribute(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004630 } else if (IS_SCHEMA(child, "attributeGroup")) {
4631 attr = (xmlSchemaAttributePtr)
Daniel Veillard3646d642004-06-02 19:19:14 +00004632 xmlSchemaParseAttributeGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004633 }
4634 if (attr != NULL) {
4635 if (lastattr == NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +00004636 if (type->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP)
4637 ((xmlSchemaAttributeGroupPtr) type)->attributes = attr;
4638 else
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004639 type->attributes = attr;
4640 lastattr = attr;
4641 } else {
4642 lastattr->next = attr;
4643 lastattr = attr;
4644 }
4645 }
4646 child = child->next;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004647 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004648 return (child);
Daniel Veillard4255d502002-04-16 15:50:10 +00004649}
4650
4651/**
4652 * xmlSchemaParseAnnotation:
4653 * @ctxt: a schema validation context
4654 * @schema: the schema being built
4655 * @node: a subtree containing XML Schema informations
4656 *
4657 * parse a XML schema Attrribute declaration
4658 * *WARNING* this interface is highly subject to change
4659 *
William M. Bracke7091952004-05-11 15:09:58 +00004660 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00004661 * 1 in case of success.
4662 */
4663static xmlSchemaAnnotPtr
4664xmlSchemaParseAnnotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
4665 xmlNodePtr node)
4666{
4667 xmlSchemaAnnotPtr ret;
Daniel Veillardc0826a72004-08-10 14:17:33 +00004668 xmlNodePtr child = NULL;
4669 xmlAttrPtr attr;
4670 int barked = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00004671
Daniel Veillardc0826a72004-08-10 14:17:33 +00004672 /*
4673 * INFO: S4S completed.
4674 */
4675 /*
4676 * id = ID
4677 * {any attributes with non-schema namespace . . .}>
4678 * Content: (appinfo | documentation)*
4679 */
Daniel Veillard4255d502002-04-16 15:50:10 +00004680 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
4681 return (NULL);
4682 ret = xmlSchemaNewAnnot(ctxt, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004683 attr = node->properties;
4684 while (attr != NULL) {
4685 if (((attr->ns == NULL) &&
4686 (!xmlStrEqual(attr->name, BAD_CAST "id"))) ||
4687 ((attr->ns != NULL) &&
4688 xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
4689
4690 xmlSchemaPIllegalAttrErr(ctxt,
4691 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4692 NULL, NULL, attr);
4693 }
4694 attr = attr->next;
4695 }
4696 /* TODO: Check id. */
4697
4698 /*
4699 * And now for the children...
4700 */
4701 child = node->children;
4702 while (child != NULL) {
4703 if (IS_SCHEMA(child, "appinfo")) {
4704 /* TODO: make available the content of "appinfo". */
4705 /*
4706 * source = anyURI
4707 * {any attributes with non-schema namespace . . .}>
4708 * Content: ({any})*
4709 */
4710 attr = child->properties;
4711 while (attr != NULL) {
4712 if (((attr->ns == NULL) &&
4713 (!xmlStrEqual(attr->name, BAD_CAST "source"))) ||
4714 ((attr->ns != NULL) &&
4715 xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004716
Daniel Veillardc0826a72004-08-10 14:17:33 +00004717 xmlSchemaPIllegalAttrErr(ctxt,
4718 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4719 NULL, NULL, attr);
4720 }
4721 attr = attr->next;
4722 }
4723 xmlSchemaPValAttr(ctxt, NULL, NULL, child, "source",
4724 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), NULL);
4725 child = child->next;
4726 } else if (IS_SCHEMA(child, "documentation")) {
4727 /* TODO: make available the content of "documentation". */
4728 /*
4729 * source = anyURI
4730 * {any attributes with non-schema namespace . . .}>
4731 * Content: ({any})*
4732 */
4733 attr = child->properties;
4734 while (attr != NULL) {
4735 if (attr->ns == NULL) {
4736 if (!xmlStrEqual(attr->name, BAD_CAST "source")) {
4737 xmlSchemaPIllegalAttrErr(ctxt,
4738 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4739 NULL, NULL, attr);
4740 }
4741 } else {
4742 if (xmlStrEqual(attr->ns->href, xmlSchemaNs) ||
4743 (xmlStrEqual(attr->name, BAD_CAST "lang") &&
4744 (!xmlStrEqual(attr->ns->href, XML_XML_NAMESPACE)))) {
4745
4746 xmlSchemaPIllegalAttrErr(ctxt,
4747 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4748 NULL, NULL, attr);
4749 }
4750 }
4751 attr = attr->next;
4752 }
4753 /*
4754 * Attribute "xml:lang".
4755 */
4756 attr = xmlSchemaGetPropNodeNs(child, (const char *) XML_XML_NAMESPACE, "lang");
4757 if (attr != NULL)
4758 xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
4759 xmlSchemaGetBuiltInType(XML_SCHEMAS_LANGUAGE), NULL);
4760 child = child->next;
4761 } else {
4762 if (!barked)
4763 xmlSchemaPContentErr(ctxt,
4764 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
4765 NULL, NULL, node, child, NULL, "(appinfo | documentation)*");
4766 barked = 1;
4767 child = child->next;
4768 }
4769 }
4770
Daniel Veillard4255d502002-04-16 15:50:10 +00004771 return (ret);
4772}
4773
4774/**
4775 * xmlSchemaParseFacet:
4776 * @ctxt: a schema validation context
4777 * @schema: the schema being built
4778 * @node: a subtree containing XML Schema informations
4779 *
4780 * parse a XML schema Facet declaration
4781 * *WARNING* this interface is highly subject to change
4782 *
4783 * Returns the new type structure or NULL in case of error
4784 */
4785static xmlSchemaFacetPtr
4786xmlSchemaParseFacet(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004787 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00004788{
4789 xmlSchemaFacetPtr facet;
4790 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004791 const xmlChar *value;
Daniel Veillard4255d502002-04-16 15:50:10 +00004792
4793 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
4794 return (NULL);
4795
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00004796 facet = xmlSchemaNewFacet();
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004797 if (facet == NULL) {
4798 xmlSchemaPErrMemory(ctxt, "allocating facet", node);
4799 return (NULL);
4800 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004801 facet->node = node;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004802 value = xmlSchemaGetProp(ctxt, node, "value");
Daniel Veillard4255d502002-04-16 15:50:10 +00004803 if (value == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004804 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_FACET_NO_VALUE,
4805 "Facet %s has no value\n", node->name, NULL);
4806 xmlSchemaFreeFacet(facet);
Daniel Veillard4255d502002-04-16 15:50:10 +00004807 return (NULL);
4808 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004809 if (IS_SCHEMA(node, "minInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004810 facet->type = XML_SCHEMA_FACET_MININCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004811 } else if (IS_SCHEMA(node, "minExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004812 facet->type = XML_SCHEMA_FACET_MINEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004813 } else if (IS_SCHEMA(node, "maxInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004814 facet->type = XML_SCHEMA_FACET_MAXINCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004815 } else if (IS_SCHEMA(node, "maxExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004816 facet->type = XML_SCHEMA_FACET_MAXEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004817 } else if (IS_SCHEMA(node, "totalDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004818 facet->type = XML_SCHEMA_FACET_TOTALDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004819 } else if (IS_SCHEMA(node, "fractionDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004820 facet->type = XML_SCHEMA_FACET_FRACTIONDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004821 } else if (IS_SCHEMA(node, "pattern")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004822 facet->type = XML_SCHEMA_FACET_PATTERN;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004823 } else if (IS_SCHEMA(node, "enumeration")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004824 facet->type = XML_SCHEMA_FACET_ENUMERATION;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004825 } else if (IS_SCHEMA(node, "whiteSpace")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004826 facet->type = XML_SCHEMA_FACET_WHITESPACE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004827 } else if (IS_SCHEMA(node, "length")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004828 facet->type = XML_SCHEMA_FACET_LENGTH;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004829 } else if (IS_SCHEMA(node, "maxLength")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004830 facet->type = XML_SCHEMA_FACET_MAXLENGTH;
4831 } else if (IS_SCHEMA(node, "minLength")) {
4832 facet->type = XML_SCHEMA_FACET_MINLENGTH;
4833 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004834 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_TYPE,
4835 "Unknown facet type %s\n", node->name, NULL);
4836 xmlSchemaFreeFacet(facet);
4837 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004838 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004839 facet->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00004840 facet->value = value;
Daniel Veillard01fa6152004-06-29 17:04:39 +00004841 if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
4842 (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
4843 const xmlChar *fixed;
4844
4845 fixed = xmlSchemaGetProp(ctxt, node, "fixed");
4846 if (fixed != NULL) {
4847 if (xmlStrEqual(fixed, BAD_CAST "true"))
4848 facet->fixed = 1;
4849 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004850 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004851 child = node->children;
4852
4853 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004854 facet->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
4855 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004856 }
4857 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004858 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_CHILD,
4859 "Facet %s has unexpected child content\n",
4860 node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004861 }
4862 return (facet);
4863}
4864
4865/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00004866 * xmlSchemaParseWildcardNs:
4867 * @ctxt: a schema parser context
4868 * @wildc: the wildcard, already created
4869 * @node: a subtree containing XML Schema informations
4870 *
4871 * Parses the attribute "processContents" and "namespace"
4872 * of a xsd:anyAttribute and xsd:any.
4873 * *WARNING* this interface is highly subject to change
4874 *
4875 * Returns 0 if everything goes fine, a positive error code
4876 * if something is not valid and -1 if an internal error occurs.
4877 */
4878static int
4879xmlSchemaParseWildcardNs(xmlSchemaParserCtxtPtr ctxt,
4880 xmlSchemaPtr schema,
4881 xmlSchemaWildcardPtr wildc,
4882 xmlNodePtr node)
4883{
4884 const xmlChar *pc, *ns, *dictnsItem;
4885 int ret = 0;
4886 xmlChar *nsItem;
4887 xmlSchemaWildcardNsPtr tmp, lastNs = NULL;
4888 xmlAttrPtr attr;
4889
4890 pc = xmlSchemaGetProp(ctxt, node, "processContents");
4891 if ((pc == NULL)
4892 || (xmlStrEqual(pc, (const xmlChar *) "strict"))) {
4893 wildc->processContents = XML_SCHEMAS_ANY_STRICT;
4894 } else if (xmlStrEqual(pc, (const xmlChar *) "skip")) {
4895 wildc->processContents = XML_SCHEMAS_ANY_SKIP;
4896 } else if (xmlStrEqual(pc, (const xmlChar *) "lax")) {
4897 wildc->processContents = XML_SCHEMAS_ANY_LAX;
4898 } else {
4899 xmlSchemaPSimpleTypeErr(ctxt,
4900 XML_SCHEMAP_UNKNOWN_PROCESSCONTENT_CHILD,
4901 NULL, NULL, node,
William M. Brack2f2a6632004-08-20 23:09:47 +00004902 NULL, "(strict | skip | lax)", pc,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004903 NULL, NULL, NULL);
4904 wildc->processContents = XML_SCHEMAS_ANY_STRICT;
4905 ret = XML_SCHEMAP_UNKNOWN_PROCESSCONTENT_CHILD;
4906 }
4907 /*
4908 * Build the namespace constraints.
4909 */
4910 attr = xmlSchemaGetPropNode(node, "namespace");
4911 ns = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
4912 if ((ns == NULL) || (xmlStrEqual(ns, BAD_CAST "##any")))
4913 wildc->any = 1;
4914 else if (xmlStrEqual(ns, BAD_CAST "##other")) {
4915 wildc->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
4916 if (wildc->negNsSet == NULL) {
4917 return (-1);
4918 }
4919 wildc->negNsSet->value = schema->targetNamespace;
4920 } else {
4921 const xmlChar *end, *cur;
4922
4923 cur = ns;
4924 do {
4925 while (IS_BLANK_CH(*cur))
4926 cur++;
4927 end = cur;
4928 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
4929 end++;
4930 if (end == cur)
4931 break;
4932 nsItem = xmlStrndup(cur, end - cur);
4933 if ((xmlStrEqual(nsItem, BAD_CAST "##other")) ||
4934 (xmlStrEqual(nsItem, BAD_CAST "##any"))) {
4935 xmlSchemaPSimpleTypeErr(ctxt,
4936 XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER,
4937 NULL, NULL, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00004938 NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004939 "((##any | ##other) | List of (anyURI | "
4940 "(##targetNamespace | ##local)))",
4941 nsItem, NULL, NULL, NULL);
4942 ret = XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER;
4943 } else {
4944 if (xmlStrEqual(nsItem, BAD_CAST "##targetNamespace")) {
4945 dictnsItem = schema->targetNamespace;
4946 } else if (xmlStrEqual(nsItem, BAD_CAST "##local")) {
4947 dictnsItem = NULL;
4948 } else {
4949 /*
4950 * Validate the item (anyURI).
4951 */
4952 xmlSchemaPValAttrNodeValue(ctxt, NULL, NULL, attr,
4953 nsItem, xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI));
4954 dictnsItem = xmlDictLookup(ctxt->dict, nsItem, -1);
4955 }
4956 /*
4957 * Avoid dublicate namespaces.
4958 */
4959 tmp = wildc->nsSet;
4960 while (tmp != NULL) {
4961 if (dictnsItem == tmp->value)
4962 break;
4963 tmp = tmp->next;
4964 }
4965 if (tmp == NULL) {
4966 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
4967 if (tmp == NULL) {
4968 xmlFree(nsItem);
4969 return (-1);
4970 }
4971 tmp->value = dictnsItem;
4972 tmp->next = NULL;
4973 if (wildc->nsSet == NULL)
4974 wildc->nsSet = tmp;
4975 else
4976 lastNs->next = tmp;
4977 lastNs = tmp;
4978 }
4979
4980 }
4981 xmlFree(nsItem);
4982 cur = end;
4983 } while (*cur != 0);
4984 }
4985 return (ret);
4986}
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004987
4988static int
4989xmlSchemaPCheckParticleCorrect_2(xmlSchemaParserCtxtPtr ctxt,
4990 xmlSchemaTypePtr item,
4991 xmlNodePtr node,
4992 int minOccurs,
4993 int maxOccurs) {
4994
4995 if (maxOccurs != UNBOUNDED) {
4996 /*
4997 * TODO: Maby we should better not create the particle,
4998 * if min/max is invalid, since it could confuse the build of the
4999 * content model.
5000 */
5001 /*
5002 * 3.9.6 Schema Component Constraint: Particle Correct
5003 *
5004 */
5005 if (maxOccurs < 1) {
5006 /*
5007 * 2.2 {max occurs} must be greater than or equal to 1.
5008 */
5009 xmlSchemaPCustomAttrErr(ctxt,
5010 XML_SCHEMAP_P_PROPS_CORRECT_2_2,
5011 NULL, item, xmlSchemaGetPropNode(node, "maxOccurs"),
5012 "The value must be greater than or equal to 1");
5013 return (XML_SCHEMAP_P_PROPS_CORRECT_2_2);
5014 } else if (minOccurs > maxOccurs) {
5015 /*
5016 * 2.1 {min occurs} must not be greater than {max occurs}.
5017 */
5018 xmlSchemaPCustomAttrErr(ctxt,
5019 XML_SCHEMAP_P_PROPS_CORRECT_2_1,
5020 NULL, item, xmlSchemaGetPropNode(node, "minOccurs"),
5021 "The value must not be greater than the value of 'maxOccurs'");
5022 return (XML_SCHEMAP_P_PROPS_CORRECT_2_1);
5023 }
5024 }
5025 return (0);
5026}
5027
Daniel Veillardc0826a72004-08-10 14:17:33 +00005028/**
Daniel Veillard4255d502002-04-16 15:50:10 +00005029 * xmlSchemaParseAny:
5030 * @ctxt: a schema validation context
5031 * @schema: the schema being built
5032 * @node: a subtree containing XML Schema informations
5033 *
5034 * parse a XML schema Any declaration
5035 * *WARNING* this interface is highly subject to change
5036 *
5037 * Returns the new type structure or NULL in case of error
5038 */
5039static xmlSchemaTypePtr
5040xmlSchemaParseAny(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5041 xmlNodePtr node)
5042{
5043 xmlSchemaTypePtr type;
5044 xmlNodePtr child = NULL;
5045 xmlChar name[30];
Daniel Veillardc0826a72004-08-10 14:17:33 +00005046 xmlSchemaWildcardPtr wildc;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005047 int minOccurs, maxOccurs;
Daniel Veillard4255d502002-04-16 15:50:10 +00005048
5049 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5050 return (NULL);
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005051 maxOccurs = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
5052 "(nonNegativeInteger | unbounded)");
5053 minOccurs = xmlGetMinOccurs(ctxt, node, 0, -1, 1,
5054 "nonNegativeInteger");
5055 if ((minOccurs == 0) && (maxOccurs == 0))
5056 return (NULL);
5057
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00005058 snprintf((char *) name, 30, "#any%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00005059 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00005060 if (type == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005061 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005062 type->node = node;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005063 type->type = XML_SCHEMA_TYPE_ANY;
5064
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00005065 /*
5066 * TODO: Use a particle component here.
5067 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00005068 wildc = xmlSchemaAddWildcard(ctxt);
5069 /*
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005070 * Check min/max sanity.
5071 */
5072 type->maxOccurs = maxOccurs;
5073 type->minOccurs = minOccurs;
5074 xmlSchemaPCheckParticleCorrect_2(ctxt, type,
5075 node, type->minOccurs, type->maxOccurs);
5076 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00005077 * This is not nice, since it is won't be used as a attribute wildcard,
5078 * but better than adding a field to the structure.
5079 */
5080 type->attributeWildcard = wildc;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005081 xmlSchemaParseWildcardNs(ctxt, schema, wildc, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005082 child = node->children;
Daniel Veillard4255d502002-04-16 15:50:10 +00005083 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005084 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5085 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005086 }
5087 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005088 xmlSchemaPErr2(ctxt, node, child,
5089 XML_SCHEMAP_UNKNOWN_SEQUENCE_CHILD,
5090 "Sequence %s has unexpected content\n", type->name,
5091 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005092 }
5093
5094 return (type);
5095}
5096
5097/**
5098 * xmlSchemaParseNotation:
5099 * @ctxt: a schema validation context
5100 * @schema: the schema being built
5101 * @node: a subtree containing XML Schema informations
5102 *
5103 * parse a XML schema Notation declaration
5104 *
5105 * Returns the new structure or NULL in case of error
5106 */
5107static xmlSchemaNotationPtr
5108xmlSchemaParseNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005109 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00005110{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005111 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00005112 xmlSchemaNotationPtr ret;
5113 xmlNodePtr child = NULL;
5114
5115 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5116 return (NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005117 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00005118 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005119 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_NOTATION_NO_NAME,
5120 "Notation has no name\n", NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005121 return (NULL);
5122 }
5123 ret = xmlSchemaAddNotation(ctxt, schema, name);
5124 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005125 return (NULL);
5126 }
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00005127 ret->targetNamespace = schema->targetNamespace;
Daniel Veillard4255d502002-04-16 15:50:10 +00005128 child = node->children;
5129 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005130 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5131 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005132 }
5133 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005134 xmlSchemaPErr2(ctxt, node, child,
5135 XML_SCHEMAP_UNKNOWN_NOTATION_CHILD,
5136 "notation %s has unexpected content\n", name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005137 }
5138
5139 return (ret);
5140}
5141
5142/**
5143 * xmlSchemaParseAnyAttribute:
5144 * @ctxt: a schema validation context
5145 * @schema: the schema being built
5146 * @node: a subtree containing XML Schema informations
5147 *
5148 * parse a XML schema AnyAttrribute declaration
5149 * *WARNING* this interface is highly subject to change
5150 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005151 * Returns a wildcard or NULL.
Daniel Veillard4255d502002-04-16 15:50:10 +00005152 */
Daniel Veillard3646d642004-06-02 19:19:14 +00005153static xmlSchemaWildcardPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005154xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
5155 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00005156{
Daniel Veillard3646d642004-06-02 19:19:14 +00005157 xmlSchemaWildcardPtr ret;
Daniel Veillard4255d502002-04-16 15:50:10 +00005158 xmlNodePtr child = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005159 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005160
5161 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5162 return (NULL);
5163
Daniel Veillard3646d642004-06-02 19:19:14 +00005164 ret = xmlSchemaAddWildcard(ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +00005165 if (ret == NULL) {
5166 return (NULL);
5167 }
William M. Bracke7091952004-05-11 15:09:58 +00005168 ret->type = XML_SCHEMA_TYPE_ANY_ATTRIBUTE;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005169 /*
5170 * Check for illegal attributes.
5171 */
5172 attr = node->properties;
5173 while (attr != NULL) {
5174 if (attr->ns == NULL) {
5175 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
5176 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
5177 (!xmlStrEqual(attr->name, BAD_CAST "processContents"))) {
5178 xmlSchemaPIllegalAttrErr(ctxt,
5179 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5180 NULL, NULL, attr);
5181 }
5182 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5183 xmlSchemaPIllegalAttrErr(ctxt,
5184 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5185 NULL, NULL, attr);
5186 }
5187 attr = attr->next;
5188 }
5189 /* ret->id = xmlSchemaGetProp(ctxt, node, "id"); */
5190 /*
5191 * Parse the namespace list.
5192 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00005193 if (xmlSchemaParseWildcardNs(ctxt, schema, ret, node) != 0) {
5194 xmlSchemaFreeWildcard(ret);
5195 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005196 }
5197 /*
5198 * And now for the children...
5199 */
Daniel Veillard4255d502002-04-16 15:50:10 +00005200 child = node->children;
5201 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005202 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5203 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005204 }
5205 if (child != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005206 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005207 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
5208 NULL, NULL, node, child,
5209 NULL, "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00005210 }
5211
5212 return (ret);
5213}
5214
5215
5216/**
5217 * xmlSchemaParseAttribute:
5218 * @ctxt: a schema validation context
5219 * @schema: the schema being built
5220 * @node: a subtree containing XML Schema informations
5221 *
5222 * parse a XML schema Attrribute declaration
5223 * *WARNING* this interface is highly subject to change
5224 *
William M. Bracke7091952004-05-11 15:09:58 +00005225 * Returns the attribute declaration.
Daniel Veillard4255d502002-04-16 15:50:10 +00005226 */
5227static xmlSchemaAttributePtr
5228xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Bracke7091952004-05-11 15:09:58 +00005229 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00005230{
Daniel Veillardc0826a72004-08-10 14:17:33 +00005231 const xmlChar *name, *attrValue;
5232 xmlChar *repName = NULL; /* The reported designation. */
Daniel Veillard4255d502002-04-16 15:50:10 +00005233 xmlSchemaAttributePtr ret;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005234 xmlNodePtr child = NULL;
5235 xmlAttrPtr attr, nameAttr;
5236 int isRef = 0;
William M. Bracke7091952004-05-11 15:09:58 +00005237
5238 /*
5239 * Note that the w3c spec assumes the schema to be validated with schema
5240 * for schemas beforehand.
5241 *
5242 * 3.2.3 Constraints on XML Representations of Attribute Declarations
William M. Bracke7091952004-05-11 15:09:58 +00005243 */
Daniel Veillard4255d502002-04-16 15:50:10 +00005244
5245 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5246 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005247 attr = xmlSchemaGetPropNode(node, "ref");
5248 nameAttr = xmlSchemaGetPropNode(node, "name");
5249
5250 if ((attr == NULL) && (nameAttr == NULL)) {
5251 /*
5252 * 3.2.3 : 3.1
5253 * One of ref or name must be present, but not both
5254 */
5255 xmlSchemaPMissingAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_1,
5256 (xmlChar **) &xmlSchemaElemDesAttrDecl, NULL, node, NULL,
5257 "One of the attributes 'ref' or 'name' must be present");
5258 return (NULL);
5259 }
5260 if ((topLevel) || (attr == NULL)) {
5261 if (nameAttr == NULL) {
5262 xmlSchemaPMissingAttrErr(ctxt, XML_SCHEMAP_S4S_ATTR_MISSING,
5263 (xmlChar **) &xmlSchemaElemDesAttrDecl, NULL, node,
5264 "name", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00005265 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005266 }
5267 } else
5268 isRef = 1;
5269
5270 if (isRef) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005271 char buf[50];
Daniel Veillardc0826a72004-08-10 14:17:33 +00005272 const xmlChar *refNs = NULL, *ref = NULL, *refPrefix = NULL;
5273
5274 /*
5275 * Parse as attribute reference.
5276 */
5277 if (xmlSchemaPValAttrNodeQName(ctxt, schema,
5278 (xmlChar **) &xmlSchemaElemDesAttrRef, NULL, attr, &refNs,
5279 &refPrefix, &ref) != 0) {
5280 return (NULL);
5281 }
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00005282 snprintf(buf, 49, "#aRef%d", ctxt->counter++ + 1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005283 name = (const xmlChar *) buf;
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00005284 ret = xmlSchemaAddAttribute(ctxt, schema, name, NULL, node, 0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005285 if (ret == NULL) {
5286 if (repName != NULL)
5287 xmlFree(repName);
5288 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00005289 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005290 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
5291 ret->node = node;
5292 ret->refNs = refNs;
5293 ret->refPrefix = refPrefix;
5294 ret->ref = ref;
5295 /*
5296 xmlSchemaFormatTypeRep(&repName, (xmlSchemaTypePtr) ret, NULL, NULL);
5297 */
5298 if (nameAttr != NULL)
5299 xmlSchemaPMutualExclAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_1,
5300 &repName, (xmlSchemaTypePtr) ret, nameAttr,
5301 "ref", "name");
5302 /*
5303 * Check for illegal attributes.
5304 */
5305 attr = node->properties;
5306 while (attr != NULL) {
5307 if (attr->ns == NULL) {
5308 if (xmlStrEqual(attr->name, BAD_CAST "type") ||
5309 xmlStrEqual(attr->name, BAD_CAST "form")) {
5310 /*
5311 * 3.2.3 : 3.2
5312 * If ref is present, then all of <simpleType>,
5313 * form and type must be absent.
5314 */
5315 xmlSchemaPIllegalAttrErr(ctxt,
5316 XML_SCHEMAP_SRC_ATTRIBUTE_3_2, &repName,
5317 (xmlSchemaTypePtr) ret, attr);
5318 } else if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
5319 (!xmlStrEqual(attr->name, BAD_CAST "use")) &&
5320 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
5321 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
5322 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
5323 (!xmlStrEqual(attr->name, BAD_CAST "default"))) {
5324 xmlSchemaPIllegalAttrErr(ctxt,
5325 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5326 &repName, (xmlSchemaTypePtr) ret, attr);
5327 }
5328 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5329 xmlSchemaPIllegalAttrErr(ctxt,
5330 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5331 &repName, (xmlSchemaTypePtr) ret, attr);
5332 }
5333 attr = attr->next;
5334 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005335 } else {
William M. Bracke7091952004-05-11 15:09:58 +00005336 const xmlChar *ns = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005337
5338 /*
5339 * Parse as attribute declaration.
5340 */
5341 if (xmlSchemaPValAttrNode(ctxt,
5342 (xmlChar **) &xmlSchemaElemDesAttrDecl, NULL, nameAttr,
5343 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
5344 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00005345 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005346 /*
5347 xmlSchemaFormatTypeRep(&repName, NULL, xmlSchemaElemDesAttrDecl, name);
5348 */
5349 /*
5350 * 3.2.6 Schema Component Constraint: xmlns Not Allowed
5351 */
5352 if (xmlStrEqual(name, BAD_CAST "xmlns")) {
5353 xmlSchemaPSimpleTypeErr(ctxt,
5354 XML_SCHEMAP_NO_XMLNS,
5355 &repName, NULL, (xmlNodePtr) nameAttr,
William M. Brack2f2a6632004-08-20 23:09:47 +00005356 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), "NCName", NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005357 "The value must not match 'xmlns'",
5358 NULL, NULL);
5359 if (repName != NULL)
5360 xmlFree(repName);
5361 return (NULL);
5362 }
5363 /*
5364 * Evaluate the target namespace
5365 */
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005366 if (topLevel) {
5367 ns = schema->targetNamespace;
5368 } else {
5369 attr = xmlSchemaGetPropNode(node, "form");
5370 if (attr != NULL) {
5371 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5372 if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
5373 ns = schema->targetNamespace;
5374 } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) {
5375 xmlSchemaPSimpleTypeErr(ctxt,
5376 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5377 &repName, NULL, (xmlNodePtr) attr,
5378 NULL, "(qualified | unqualified)",
5379 attrValue, NULL, NULL, NULL);
5380 }
5381 } else if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
5382 ns = schema->targetNamespace;
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00005383 }
5384 ret = xmlSchemaAddAttribute(ctxt, schema, name, ns, node, topLevel);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005385 if (ret == NULL) {
5386 if (repName != NULL)
5387 xmlFree(repName);
Daniel Veillard3646d642004-06-02 19:19:14 +00005388 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00005389 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005390 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00005391 ret->node = node;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005392 if (topLevel)
5393 ret->flags |= XML_SCHEMAS_ATTR_GLOBAL;
5394 /*
5395 * 3.2.6 Schema Component Constraint: xsi: Not Allowed
5396 */
5397 if (xmlStrEqual(ret->targetNamespace, xmlSchemaInstanceNs)) {
5398 xmlSchemaPCustomErr(ctxt,
5399 XML_SCHEMAP_NO_XSI,
5400 &repName, (xmlSchemaTypePtr) ret, node,
5401 "The target namespace must not match '%s'",
5402 xmlSchemaInstanceNs);
5403 }
5404 /*
5405 * Check for illegal attributes.
5406 */
5407 attr = node->properties;
5408 while (attr != NULL) {
5409 if (attr->ns == NULL) {
5410 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
5411 (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
5412 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
5413 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
5414 (!xmlStrEqual(attr->name, BAD_CAST "type"))) {
5415 if ((topLevel) ||
5416 ((!xmlStrEqual(attr->name, BAD_CAST "form")) &&
5417 (!xmlStrEqual(attr->name, BAD_CAST "use")))) {
5418 xmlSchemaPIllegalAttrErr(ctxt,
5419 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5420 &repName, (xmlSchemaTypePtr) ret, attr);
5421 }
5422 }
5423 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5424 xmlSchemaPIllegalAttrErr(ctxt, XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5425 &repName, (xmlSchemaTypePtr) ret, attr);
5426 }
5427 attr = attr->next;
5428 }
5429 xmlSchemaPValAttrQName(ctxt, schema, &repName, (xmlSchemaTypePtr) ret,
5430 node, "type", &ret->typeNs, NULL, &ret->typeName);
William M. Bracke7091952004-05-11 15:09:58 +00005431 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005432 /* TODO: Check ID. */
5433 ret->id = xmlSchemaGetProp(ctxt, node, "id");
William M. Bracke7091952004-05-11 15:09:58 +00005434 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00005435 * Attribute "fixed".
William M. Bracke7091952004-05-11 15:09:58 +00005436 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00005437 ret->defValue = xmlSchemaGetProp(ctxt, node, "fixed");
5438 if (ret->defValue != NULL)
5439 ret->flags |= XML_SCHEMAS_ATTR_FIXED;
5440 /*
5441 * Attribute "default".
5442 */
5443 attr = xmlSchemaGetPropNode(node, "default");
5444 if (attr != NULL) {
5445 /*
5446 * 3.2.3 : 1
5447 * default and fixed must not both be present.
5448 */
5449 if (ret->flags & XML_SCHEMAS_ATTR_FIXED) {
5450 xmlSchemaPMutualExclAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_1,
5451 &repName, (xmlSchemaTypePtr) ret, attr, "default", "fixed");
5452 } else
5453 ret->defValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5454 }
5455 if (topLevel == 0) {
5456 /*
5457 * Attribute "use".
5458 */
5459 attr = xmlSchemaGetPropNode(node, "use");
5460 if (attr != NULL) {
5461 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5462 if (xmlStrEqual(attrValue, BAD_CAST "optional"))
5463 ret->occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
5464 else if (xmlStrEqual(attrValue, BAD_CAST "prohibited"))
5465 ret->occurs = XML_SCHEMAS_ATTR_USE_PROHIBITED;
5466 else if (xmlStrEqual(attrValue, BAD_CAST "required"))
5467 ret->occurs = XML_SCHEMAS_ATTR_USE_REQUIRED;
5468 else
5469 xmlSchemaPSimpleTypeErr(ctxt,
5470 XML_SCHEMAP_INVALID_ATTR_USE,
5471 &repName, (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00005472 NULL, "(optional | prohibited | required)",
Daniel Veillardc0826a72004-08-10 14:17:33 +00005473 attrValue, NULL, NULL, NULL);
5474 } else
5475 ret->occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
5476 /*
5477 * 3.2.3 : 2
5478 * If default and use are both present, use must have
5479 * the actual value optional.
5480 */
5481 if ((ret->occurs != XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
5482 (ret->defValue != NULL) &&
5483 ((ret->flags & XML_SCHEMAS_ATTR_FIXED) == 0)) {
5484 xmlSchemaPSimpleTypeErr(ctxt,
5485 XML_SCHEMAP_SRC_ATTRIBUTE_2,
5486 &repName, (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00005487 NULL, "(optional | prohibited | required)", NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005488 "The value must be 'optional' if the attribute "
5489 "'default' is present as well", NULL, NULL);
5490 }
5491 }
5492 /*
5493 * And now for the children...
5494 */
Daniel Veillard4255d502002-04-16 15:50:10 +00005495 child = node->children;
5496 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005497 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5498 child = child->next;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005499 }
5500 if (isRef) {
5501 if (child != NULL) {
5502 if (IS_SCHEMA(child, "simpleType"))
5503 /*
5504 * 3.2.3 : 3.2
5505 * If ref is present, then all of <simpleType>,
5506 * form and type must be absent.
5507 */
5508 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_2,
5509 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
5510 "(annotation?)");
5511 else
5512 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
5513 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
5514 "(annotation?)");
5515 }
5516 } else {
5517 if (IS_SCHEMA(child, "simpleType")) {
5518 if (ret->typeName != NULL) {
5519 /*
5520 * 3.2.3 : 4
5521 * type and <simpleType> must not both be present.
5522 */
5523 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_4,
5524 &repName, (xmlSchemaTypePtr) ret, node, child,
5525 "The attribute 'type' and the <simpleType> child "
5526 "are mutually exclusive", NULL);
5527 } else
5528 ret->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
5529 child = child->next;
5530 }
5531 if (child != NULL)
5532 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
5533 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
5534 "(annotation?, simpleType?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00005535 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005536 /*
5537 * Cleanup.
5538 */
5539 if (repName != NULL)
5540 xmlFree(repName);
Daniel Veillard4255d502002-04-16 15:50:10 +00005541 return (ret);
5542}
5543
5544/**
5545 * xmlSchemaParseAttributeGroup:
5546 * @ctxt: a schema validation context
5547 * @schema: the schema being built
5548 * @node: a subtree containing XML Schema informations
5549 *
5550 * parse a XML schema Attribute Group declaration
5551 * *WARNING* this interface is highly subject to change
5552 *
5553 * Returns the attribute group or NULL in case of error.
5554 */
5555static xmlSchemaAttributeGroupPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005556xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +00005557 xmlSchemaPtr schema, xmlNodePtr node,
5558 int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00005559{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005560 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00005561 xmlSchemaAttributeGroupPtr ret;
Daniel Veillard4255d502002-04-16 15:50:10 +00005562 xmlNodePtr child = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005563 const xmlChar *oldcontainer;
5564 xmlAttrPtr attr, nameAttr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005565
5566 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5567 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005568
5569 nameAttr = xmlSchemaGetPropNode(node, "name");
5570 attr = xmlSchemaGetPropNode(node, "ref");
5571 if ((topLevel) || (attr == NULL)) {
5572 /*
5573 * Parse as an attribute group definition.
5574 * Note that those are allowed at top level only.
5575 */
5576 if (nameAttr == NULL) {
5577 xmlSchemaPMissingAttrErr(ctxt,
5578 XML_SCHEMAP_S4S_ATTR_MISSING,
5579 NULL, NULL, node, "name", NULL);
5580 return (NULL);
5581 }
5582 name = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) nameAttr);
5583 /*
5584 * The name is crucial, exit if invalid.
5585 */
5586 if (xmlSchemaPValAttrNode(ctxt,
5587 NULL, NULL, nameAttr,
5588 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
5589 return (NULL);
5590 }
5591 ret = xmlSchemaAddAttributeGroup(ctxt, schema, name, node);
5592 if (ret == NULL)
5593 return (NULL);
5594 ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
5595 ret->flags |= XML_SCHEMAS_ATTRGROUP_GLOBAL;
5596 ret->node = node;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00005597 ret->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005598 } else {
5599 char buf[50];
5600 const xmlChar *refNs = NULL, *ref = NULL, *refPrefix;
5601
5602 /*
5603 * Parse as an attribute group definition reference.
5604 */
5605 if (attr == NULL) {
5606 xmlSchemaPMissingAttrErr(ctxt,
5607 XML_SCHEMAP_S4S_ATTR_MISSING,
5608 NULL, NULL, node, "ref", NULL);
5609 }
5610 xmlSchemaPValAttrNodeQName(ctxt, schema,
5611 NULL, NULL, attr, &refNs, &refPrefix, &ref);
5612
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00005613 snprintf(buf, 49, "#agRef%d", ctxt->counter++ + 1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005614 name = (const xmlChar *) buf;
5615 if (name == NULL) {
5616 xmlSchemaPErrMemory(ctxt, "creating internal name for an "
5617 "attribute group definition reference", node);
5618 return (NULL);
5619 }
5620 ret = xmlSchemaAddAttributeGroup(ctxt, schema, name, node);
5621 if (ret == NULL)
5622 return (NULL);
5623 ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
5624 ret->ref = ref;
5625 ret->refNs = refNs;
5626 /* TODO: Is @refPrefix currently used? */
5627 ret->refPrefix = refPrefix;
5628 ret->node = node;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00005629 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005630 /*
5631 * Check for illegal attributes.
5632 */
5633 attr = node->properties;
5634 while (attr != NULL) {
5635 if (attr->ns == NULL) {
5636 if ((((topLevel == 0) && (!xmlStrEqual(attr->name, BAD_CAST "ref"))) ||
5637 (topLevel && (!xmlStrEqual(attr->name, BAD_CAST "name")))) &&
5638 (!xmlStrEqual(attr->name, BAD_CAST "id")))
5639 {
5640 xmlSchemaPIllegalAttrErr(ctxt,
5641 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5642 NULL, NULL, attr);
5643 }
5644 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5645 xmlSchemaPIllegalAttrErr(ctxt,
5646 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5647 NULL, NULL, attr);
5648 }
5649 attr = attr->next;
5650 }
5651 /* TODO: Validate "id" ? */
5652 /*
5653 * And now for the children...
5654 */
Daniel Veillard4255d502002-04-16 15:50:10 +00005655 oldcontainer = ctxt->container;
Daniel Veillard4255d502002-04-16 15:50:10 +00005656 ctxt->container = name;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005657 child = node->children;
Daniel Veillard4255d502002-04-16 15:50:10 +00005658 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005659 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5660 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005661 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005662 if (topLevel) {
5663 child = xmlSchemaParseAttrDecls(ctxt, schema, child, (xmlSchemaTypePtr) ret);
5664 if (IS_SCHEMA(child, "anyAttribute")) {
5665 ret->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
5666 child = child->next;
5667 }
5668 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005669 if (child != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005670 xmlSchemaPContentErr(ctxt,
5671 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
5672 NULL, NULL, node, child, NULL,
5673 "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00005674 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005675 ctxt->container = oldcontainer;
5676 return (ret);
5677}
5678
5679/**
William M. Brack2f2a6632004-08-20 23:09:47 +00005680 * xmlSchemaPValAttrFormDefault:
5681 * @value: the value
5682 * @flags: the flags to be modified
5683 * @flagQualified: the specific flag for "qualified"
5684 *
5685 * Returns 0 if the value is valid, 1 otherwise.
5686 */
5687static int
5688xmlSchemaPValAttrFormDefault(const xmlChar *value,
5689 int *flags,
5690 int flagQualified)
5691{
5692 if (xmlStrEqual(value, BAD_CAST "qualified")) {
5693 if ((*flags & flagQualified) == 0)
5694 *flags |= flagQualified;
5695 } else if (!xmlStrEqual(value, BAD_CAST "unqualified"))
5696 return (1);
5697
5698 return (0);
5699}
5700
5701/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00005702 * xmlSchemaPValAttrBlockFinal:
5703 * @value: the value
5704 * @flags: the flags to be modified
5705 * @flagAll: the specific flag for "#all"
5706 * @flagExtension: the specific flag for "extension"
5707 * @flagRestriction: the specific flag for "restriction"
5708 * @flagSubstitution: the specific flag for "substitution"
5709 * @flagList: the specific flag for "list"
5710 * @flagUnion: the specific flag for "union"
5711 *
5712 * Validates the value of the attribute "final" and "block". The value
5713 * is converted into the specified flag values and returned in @flags.
5714 *
5715 * Returns 0 if the value is valid, 1 otherwise.
5716 */
5717
5718static int
5719xmlSchemaPValAttrBlockFinal(const xmlChar *value,
5720 int *flags,
5721 int flagAll,
5722 int flagExtension,
5723 int flagRestriction,
5724 int flagSubstitution,
5725 int flagList,
5726 int flagUnion)
5727{
5728 int ret = 0;
5729
5730 /*
5731 * TODO: This does not check for dublicate entries.
5732 */
William M. Brack2f2a6632004-08-20 23:09:47 +00005733 if (value == NULL)
5734 return (1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005735 if (xmlStrEqual(value, BAD_CAST "#all")) {
5736 if (flagAll != -1)
5737 *flags |= flagAll;
5738 else {
5739 if (flagExtension != -1)
5740 *flags |= flagExtension;
5741 if (flagRestriction != -1)
5742 *flags |= flagRestriction;
5743 if (flagSubstitution != -1)
5744 *flags |= flagSubstitution;
5745 if (flagList != -1)
5746 *flags |= flagList;
5747 if (flagUnion != -1)
5748 *flags |= flagUnion;
5749 }
5750 } else {
5751 const xmlChar *end, *cur = value;
5752 xmlChar *item;
5753
5754 do {
5755 while (IS_BLANK_CH(*cur))
5756 cur++;
5757 end = cur;
5758 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
5759 end++;
5760 if (end == cur)
5761 break;
5762 item = xmlStrndup(cur, end - cur);
5763 if (xmlStrEqual(item, BAD_CAST "extension")) {
5764 if (flagExtension != -1) {
5765 if ((*flags & flagExtension) == 0)
5766 *flags |= flagExtension;
5767 } else
5768 ret = 1;
5769 } else if (xmlStrEqual(item, BAD_CAST "restriction")) {
5770 if (flagRestriction != -1) {
5771 if ((*flags & flagRestriction) == 0)
5772 *flags |= flagRestriction;
5773 } else
5774 ret = 1;
5775 } else if (xmlStrEqual(item, BAD_CAST "substitution")) {
5776 if (flagSubstitution != -1) {
5777 if ((*flags & flagSubstitution) == 0)
5778 *flags |= flagSubstitution;
5779 } else
5780 ret = 1;
5781 } else if (xmlStrEqual(item, BAD_CAST "list")) {
5782 if (flagList != -1) {
5783 if ((*flags & flagList) == 0)
5784 *flags |= flagList;
5785 } else
5786 ret = 1;
5787 } else if (xmlStrEqual(item, BAD_CAST "union")) {
5788 if (flagUnion != -1) {
5789 if ((*flags & flagUnion) == 0)
5790 *flags |= flagUnion;
5791 } else
5792 ret = 1;
5793 } else
5794 ret = 1;
5795 if (item != NULL)
5796 xmlFree(item);
5797 cur = end;
5798 } while ((ret == 0) && (*cur != 0));
5799 }
5800
5801 return (ret);
5802}
5803
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00005804#ifdef IDC_ENABLED
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00005805static int
5806xmlSchemaCheckCSelectorXPath(xmlSchemaParserCtxtPtr ctxt,
5807 xmlSchemaPtr schema,
5808 xmlSchemaIDCPtr idc,
5809 xmlSchemaIDCSelectPtr selector,
5810 xmlNodePtr parNode,
5811 xmlAttrPtr attr,
5812 int isField)
5813{
5814 xmlNodePtr node;
5815
5816 /*
5817 * c-selector-xpath:
5818 * Schema Component Constraint: Selector Value OK
5819 *
5820 * TODO: 1 The {selector} must be a valid XPath expression, as defined
5821 * in [XPath].
5822 */
5823 if (selector == NULL) {
5824 xmlSchemaPErr(ctxt, idc->node,
5825 XML_SCHEMAP_INTERNAL,
5826 "Internal error: xmlSchemaCheckCSelectorXPath, "
5827 "the selector is not specified.\n", NULL, NULL);
5828 return (-1);
5829 }
5830 if (attr == NULL)
5831 node = idc->node;
5832 else
5833 node = (xmlNodePtr) attr;
5834 if (selector->xpath == NULL) {
5835 xmlSchemaPCustomErr(ctxt,
5836 /* TODO: Adjust error code. */
5837 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5838 NULL, NULL, node,
5839 "The XPath expression of the selector is not valid", NULL);
5840 return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE);
5841 } else {
5842 /*
5843 * Compile the XPath expression.
5844 */
5845 /*
5846 * TODO: We need the array of in-scope namespaces for compilation.
5847 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00005848 selector->xpathComp = (void *) xmlPatterncompile(selector->xpath,
5849 NULL, 0, NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00005850#ifdef IDC_XPATH_SUPPORT
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00005851 if (selector->xpathComp == NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00005852 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00005853 /* TODO: Adjust error code? */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00005854 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5855 NULL, NULL, node,
5856 "The XPath expression '%s' could not be "
5857 "compiled", selector->xpath);
5858 return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE);
5859 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00005860#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00005861 }
5862 return (0);
5863}
5864
5865/**
5866 * xmlSchemaAssignAnnotation:
5867 * @item: the schema component
5868 * @annot: the annotation
5869 *
5870 * Adds the annotation to the given schema component.
5871 *
5872 * Returns the given annotaion.
5873 */
5874static xmlSchemaAnnotPtr
5875xmlSchemaAssignAnnotation(xmlSchemaBasicItemPtr item,
5876 xmlSchemaAnnotPtr annot)
5877{
5878 xmlSchemaAnnotPtr cur = item->annot;
5879
5880 if (item->annot == NULL) {
5881 item->annot = annot;
5882 return (annot);
5883 }
5884 cur = item->annot;
5885 if (cur->next != NULL) {
5886 cur = cur->next;
5887 }
5888 cur->next = annot;
5889 return (annot);
5890}
5891
5892/**
5893 * xmlSchemaParseIDCSelectorAndField:
5894 * @ctxt: a schema validation context
5895 * @schema: the schema being built
5896 * @node: a subtree containing XML Schema informations
5897 *
5898 * Parses a XML Schema identity-contraint definition's
5899 * <selector> and <field> elements.
5900 *
5901 * Returns the parsed identity-constraint definition.
5902 */
5903static xmlSchemaIDCSelectPtr
5904xmlSchemaParseIDCSelectorAndField(xmlSchemaParserCtxtPtr ctxt,
5905 xmlSchemaPtr schema,
5906 xmlSchemaIDCPtr idc,
5907 xmlNodePtr node,
5908 int isField)
5909{
5910 xmlSchemaIDCSelectPtr item;
5911 xmlNodePtr child = NULL;
5912 xmlAttrPtr attr;
5913
5914 /*
5915 * Check for illegal attributes.
5916 */
5917 attr = node->properties;
5918 while (attr != NULL) {
5919 if (attr->ns == NULL) {
5920 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
5921 (!xmlStrEqual(attr->name, BAD_CAST "xpath"))) {
5922 xmlSchemaPIllegalAttrErr(ctxt,
5923 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5924 NULL, NULL, attr);
5925 }
5926 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5927 xmlSchemaPIllegalAttrErr(ctxt,
5928 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5929 NULL, NULL, attr);
5930 }
5931 attr = attr->next;
5932 }
5933 /*
5934 * Create the item.
5935 */
5936 item = (xmlSchemaIDCSelectPtr) xmlMalloc(sizeof(xmlSchemaIDCSelect));
5937 if (item == NULL) {
5938 xmlSchemaPErrMemory(ctxt,
5939 "allocating a 'selector' of an identity-constraint definition",
5940 NULL);
5941 return (NULL);
5942 }
5943 memset(item, 0, sizeof(xmlSchemaIDCSelect));
5944 /*
5945 * Attribute "xpath" (mandatory).
5946 */
5947 attr = xmlSchemaGetPropNode(node, "xpath");
5948 if (attr == NULL) {
5949 xmlSchemaPMissingAttrErr(ctxt,
5950 XML_SCHEMAP_S4S_ATTR_MISSING,
5951 NULL, NULL, node,
5952 "name", NULL);
5953 } else {
5954 item->xpath = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5955 /*
5956 * URGENT TODO: "field"s have an other syntax than "selector"s.
5957 */
5958
5959 if (xmlSchemaCheckCSelectorXPath(ctxt, schema,
5960 idc, item, node, attr, isField) == -1)
5961 {
5962 xmlSchemaPErr(ctxt,
5963 (xmlNodePtr) attr,
5964 XML_SCHEMAP_INTERNAL,
5965 "Internal error: xmlSchemaParseIDCSelectorAndField, "
5966 "validating the XPath expression of a IDC selector.\n",
5967 NULL, NULL);
5968 }
5969
5970 }
5971 /*
5972 * And now for the children...
5973 */
5974 child = node->children;
5975 if (IS_SCHEMA(child, "annotation")) {
5976 /*
5977 * Add the annotation to the parent IDC.
5978 */
5979 xmlSchemaAssignAnnotation((xmlSchemaBasicItemPtr) idc,
5980 xmlSchemaParseAnnotation(ctxt, schema, child));
5981 child = child->next;
5982 }
5983 if (child != NULL) {
5984 xmlSchemaPContentErr(ctxt,
5985 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
5986 NULL, NULL, node, child,
5987 NULL, "(annotation?)");
5988 }
5989
5990 return (item);
5991}
5992
5993/**
5994 * xmlSchemaParseIDC:
5995 * @ctxt: a schema validation context
5996 * @schema: the schema being built
5997 * @node: a subtree containing XML Schema informations
5998 *
5999 * Parses a XML Schema identity-contraint definition.
6000 *
6001 * Returns the parsed identity-constraint definition.
6002 */
6003static xmlSchemaIDCPtr
6004xmlSchemaParseIDC(xmlSchemaParserCtxtPtr ctxt,
6005 xmlSchemaPtr schema,
6006 xmlNodePtr node,
6007 xmlSchemaTypeType idcCategory,
6008 const xmlChar *targetNamespace)
6009{
6010 xmlSchemaIDCPtr item = NULL;
6011 xmlNodePtr child = NULL;
6012 xmlAttrPtr attr;
6013 const xmlChar *name = NULL;
6014 xmlSchemaIDCSelectPtr field = NULL, lastField = NULL;
6015 int resAdd;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00006016
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006017 /*
6018 * Check for illegal attributes.
6019 */
6020 attr = node->properties;
6021 while (attr != NULL) {
6022 if (attr->ns == NULL) {
6023 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6024 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
6025 ((idcCategory != XML_SCHEMA_TYPE_IDC_KEYREF) ||
6026 (!xmlStrEqual(attr->name, BAD_CAST "refer")))) {
6027 xmlSchemaPIllegalAttrErr(ctxt,
6028 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6029 NULL, NULL, attr);
6030 }
6031 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6032 xmlSchemaPIllegalAttrErr(ctxt,
6033 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6034 NULL, NULL, attr);
6035 }
6036 attr = attr->next;
6037 }
6038 /*
6039 * Attribute "name" (mandatory).
6040 */
6041 attr = xmlSchemaGetPropNode(node, "name");
6042 if (attr == NULL) {
6043 xmlSchemaPMissingAttrErr(ctxt,
6044 XML_SCHEMAP_S4S_ATTR_MISSING,
6045 NULL, NULL, node,
6046 "name", NULL);
6047 return (NULL);
6048 } else if (xmlSchemaPValAttrNode(ctxt,
6049 NULL, NULL, attr,
6050 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
6051 return (NULL);
6052 }
6053 /*
6054 * Create the component.
6055 */
6056 if (schema->idcDef == NULL)
6057 schema->idcDef = xmlHashCreateDict(10, ctxt->dict);
6058 if (schema->idcDef == NULL)
6059 return (NULL);
6060
6061 item = (xmlSchemaIDCPtr) xmlMalloc(sizeof(xmlSchemaIDC));
6062 if (item == NULL) {
6063 xmlSchemaPErrMemory(ctxt,
6064 "allocating an identity-constraint definition", NULL);
6065 return (NULL);
6066 }
6067 /*
6068 * Add the IDC to the list of IDCs on the schema component.
6069 */
6070 resAdd = xmlHashAddEntry2(schema->idcDef, name, targetNamespace, item);
6071 if (resAdd != 0) {
6072 xmlSchemaPCustomErrExt(ctxt,
6073 XML_SCHEMAP_REDEFINED_TYPE,
6074 NULL, NULL, node,
6075 "An identity-constraint definition with the name '%s' "
6076 "and targetNamespace '%s' does already exist",
6077 name, targetNamespace, NULL);
6078 xmlFree(item);
6079 return (NULL);
6080 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006081 memset(item, 0, sizeof(xmlSchemaIDC));
6082 item->name = name;
6083 item->type = idcCategory;
6084 item->node = node;
6085 /*
6086 * The target namespace of the parent element declaration.
6087 */
6088 item->targetNamespace = targetNamespace;
6089 /* TODO: Handle attribute "id". */
6090 if (idcCategory == XML_SCHEMA_TYPE_IDC_KEYREF) {
6091 /*
6092 * Attribute "refer" (mandatory).
6093 */
6094 attr = xmlSchemaGetPropNode(node, "refer");
6095 if (attr == NULL) {
6096 xmlSchemaPMissingAttrErr(ctxt,
6097 XML_SCHEMAP_S4S_ATTR_MISSING,
6098 NULL, NULL, node,
6099 "refer", NULL);
6100 } else {
6101 /*
6102 * Create a reference item.
6103 */
6104 item->ref = (xmlSchemaItemQNRefPtr) xmlMalloc(
6105 sizeof(xmlSchemaItemQNRef));
6106 if (item->ref == NULL) {
6107 xmlSchemaPErrMemory(ctxt,
6108 "allocating a QName reference item", NULL);
6109 return (NULL);
6110 }
6111 memset(item->ref, 0, sizeof(xmlSchemaItemQNRef));
6112 xmlSchemaPValAttrNodeQName(ctxt, schema,
6113 NULL, NULL, attr,
6114 &(item->ref->targetNamespace), 0,
6115 &(item->ref->name));
6116 }
6117 }
6118 /*
6119 * And now for the children...
6120 */
6121 child = node->children;
6122 if (IS_SCHEMA(child, "annotation")) {
6123 item->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6124 child = child->next;
6125 }
6126 /*
6127 * Child element <selector>.
6128 */
6129 if (IS_SCHEMA(child, "selector")) {
6130 item->selector = xmlSchemaParseIDCSelectorAndField(ctxt, schema,
6131 item, child, 0);
6132 child = child->next;
6133 /*
6134 * Child elements <field>.
6135 */
6136 if (IS_SCHEMA(child, "field")) {
6137 do {
6138 field = xmlSchemaParseIDCSelectorAndField(ctxt, schema,
6139 item, child, 1);
6140 if (field != NULL) {
6141 field->index = item->nbFields;
6142 item->nbFields++;
6143 if (lastField != NULL)
6144 lastField->next = field;
6145 else
6146 item->fields = field;
6147 lastField = field;
6148 }
6149 child = child->next;
6150 } while (IS_SCHEMA(child, "field"));
6151 } else {
6152 xmlSchemaPContentErr(ctxt,
6153 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6154 NULL, NULL, node, child,
6155 NULL, "(annotation?, (selector, field+))");
6156 }
6157 }
6158 if (child != NULL) {
6159 xmlSchemaPContentErr(ctxt,
6160 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6161 NULL, NULL, node, child,
6162 NULL, "(annotation?, (selector, field+))");
6163 }
6164
6165 return (item);
6166}
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006167#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006168
Daniel Veillardc0826a72004-08-10 14:17:33 +00006169/**
Daniel Veillard4255d502002-04-16 15:50:10 +00006170 * xmlSchemaParseElement:
6171 * @ctxt: a schema validation context
6172 * @schema: the schema being built
6173 * @node: a subtree containing XML Schema informations
6174 *
6175 * parse a XML schema Element declaration
6176 * *WARNING* this interface is highly subject to change
6177 *
William M. Bracke7091952004-05-11 15:09:58 +00006178 * Returns the parsed element declaration.
Daniel Veillard4255d502002-04-16 15:50:10 +00006179 */
6180static xmlSchemaElementPtr
6181xmlSchemaParseElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00006182 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00006183{
Daniel Veillardc0826a72004-08-10 14:17:33 +00006184 const xmlChar *name = NULL;
6185 const xmlChar *attrValue;
6186 xmlChar *repName = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00006187 xmlSchemaElementPtr ret;
6188 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006189 const xmlChar *oldcontainer;
6190 xmlAttrPtr attr, nameAttr;
6191 int minOccurs, maxOccurs;
6192 int isRef = 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006193#ifdef IDC_ENABLED
6194 xmlSchemaIDCPtr curIDC, lastIDC = NULL;
6195#endif
William M. Bracke7091952004-05-11 15:09:58 +00006196
6197 /* 3.3.3 Constraints on XML Representations of Element Declarations */
6198 /* TODO: Complete implementation of 3.3.6 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00006199
Daniel Veillard4255d502002-04-16 15:50:10 +00006200 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6201 return (NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006202
Daniel Veillardc0826a72004-08-10 14:17:33 +00006203 oldcontainer = ctxt->container;
6204
6205 nameAttr = xmlSchemaGetPropNode(node, "name");
6206 attr = xmlSchemaGetPropNode(node, "ref");
6207 if ((topLevel) || (attr == NULL)) {
6208 if (nameAttr == NULL) {
6209 xmlSchemaPMissingAttrErr(ctxt,
6210 XML_SCHEMAP_S4S_ATTR_MISSING,
6211 (xmlChar **) &xmlSchemaElemDesElemDecl, NULL, node,
6212 "name", NULL);
6213 return (NULL);
6214 }
6215 name = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) nameAttr);
6216 } else {
6217 isRef = 1;
6218
6219 }
6220 /*
6221 * ... unless minOccurs=maxOccurs=0, in which case the item corresponds
6222 * to no component at all
6223 * TODO: It might be better to validate the element, even if it won't be
6224 * used.
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006225 */
6226 minOccurs = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "nonNegativeInteger");
6227 maxOccurs = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1, "(nonNegativeInteger | unbounded)");
Daniel Veillardc0826a72004-08-10 14:17:33 +00006228 if ((minOccurs == 0) && (maxOccurs == 0))
6229 return (NULL);
6230 /*
6231 * If we get a "ref" attribute on a local <element> we will assume it's
6232 * a reference - even if there's a "name" attribute; this seems to be more
6233 * robust.
6234 */
6235 if (isRef) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006236 char buf[50];
Daniel Veillardc0826a72004-08-10 14:17:33 +00006237 const xmlChar *refNs = NULL, *ref = NULL, *refPrefix;
6238
6239 /*
6240 * Parse as a particle.
6241 */
6242 xmlSchemaPValAttrNodeQName(ctxt, schema,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006243 (xmlChar **) &xmlSchemaElemDesElemRef,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006244 NULL, attr, &refNs, &refPrefix, &ref);
6245
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006246 snprintf(buf, 49, "#eRef%d", ctxt->counter++ + 1);
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00006247 ret = xmlSchemaAddElement(ctxt, schema, (const xmlChar *) buf, NULL, node, 0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006248 if (ret == NULL) {
6249 if (repName != NULL)
6250 xmlFree(repName);
6251 return (NULL);
6252 }
6253 ret->type = XML_SCHEMA_TYPE_ELEMENT;
6254 ret->node = node;
6255 ret->ref = ref;
6256 ret->refNs = refNs;
6257 ret->refPrefix = refPrefix;
6258 ret->flags |= XML_SCHEMAS_ELEM_REF;
6259 /*
6260 * Check for illegal attributes.
6261 */
6262 /*
6263 * 3.3.3 : 2.1
6264 * One of ref or name must be present, but not both
6265 */
6266 if (nameAttr != NULL) {
6267 xmlSchemaPMutualExclAttrErr(ctxt,
6268 XML_SCHEMAP_SRC_ELEMENT_2_1,
6269 &repName, (xmlSchemaTypePtr) ret, nameAttr,
6270 "ref", "name");
6271 }
6272 /* 3.3.3 : 2.2 */
6273 attr = node->properties;
6274 while (attr != NULL) {
6275 if (attr->ns == NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006276 if (xmlStrEqual(attr->name, BAD_CAST "ref") ||
6277 xmlStrEqual(attr->name, BAD_CAST "name") ||
6278 xmlStrEqual(attr->name, BAD_CAST "id") ||
6279 xmlStrEqual(attr->name, BAD_CAST "maxOccurs") ||
6280 xmlStrEqual(attr->name, BAD_CAST "minOccurs"))
6281 {
6282 attr = attr->next;
6283 continue;
6284 } else {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006285 xmlSchemaPCustomAttrErr(ctxt,
6286 XML_SCHEMAP_SRC_ELEMENT_2_2,
6287 &repName, (xmlSchemaTypePtr) ret, attr,
6288 "Only the attributes 'minOccurs', 'maxOccurs' and "
6289 "'id' are allowed in addition to 'ref'");
6290 break;
6291 }
6292 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6293 xmlSchemaPIllegalAttrErr(ctxt,
6294 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6295 &repName, (xmlSchemaTypePtr) ret, attr);
6296 }
6297 attr = attr->next;
6298 }
6299 } else {
6300 const xmlChar *ns = NULL, *fixed;
6301
6302 /*
6303 * Parse as an element declaration.
6304 */
6305 if (xmlSchemaPValAttrNode(ctxt,
6306 (xmlChar **) &xmlSchemaElemDesElemDecl, NULL, nameAttr,
6307 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0)
6308 return (NULL);
6309 /*
6310 * Evaluate the target namespace.
6311 */
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006312 if (topLevel) {
6313 ns = schema->targetNamespace;
6314 } else {
6315 attr = xmlSchemaGetPropNode(node, "form");
6316 if (attr != NULL) {
6317 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6318 if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
William M. Bracke7091952004-05-11 15:09:58 +00006319 ns = schema->targetNamespace;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006320 } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) {
6321 xmlSchemaPSimpleTypeErr(ctxt,
6322 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6323 &repName, NULL, (xmlNodePtr) attr,
6324 NULL, "(qualified | unqualified)",
6325 attrValue, NULL, NULL, NULL);
6326 }
6327 } else if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
6328 ns = schema->targetNamespace;
William M. Brack2f2a6632004-08-20 23:09:47 +00006329 }
6330 ret = xmlSchemaAddElement(ctxt, schema, name, ns, node, topLevel);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006331 if (ret == NULL) {
6332 if (repName != NULL)
6333 xmlFree(repName);
6334 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00006335 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006336 ret->type = XML_SCHEMA_TYPE_ELEMENT;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006337 ret->node = node;
6338 ret->targetNamespace = ns;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006339 /*
6340 * Check for illegal attributes.
6341 */
William M. Bracke7091952004-05-11 15:09:58 +00006342 attr = node->properties;
6343 while (attr != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006344 if (attr->ns == NULL) {
6345 if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
6346 (!xmlStrEqual(attr->name, BAD_CAST "type")) &&
6347 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6348 (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
6349 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
6350 (!xmlStrEqual(attr->name, BAD_CAST "block")) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006351 (!xmlStrEqual(attr->name, BAD_CAST "nillable")))
6352 {
6353 if (topLevel == 0) {
6354 if ((!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00006355 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006356 (!xmlStrEqual(attr->name, BAD_CAST "form")))
6357 {
6358 if (xmlStrEqual(attr->name, BAD_CAST "substitutionGroup")) {
6359 /*
6360 * 3.3.6 : 3 If there is a non-·absent· {substitution
6361 * group affiliation}, then {scope} must be global.
6362 * TODO: This one is redundant, since the S4S does
6363 * prohibit this attribute on local declarations already;
6364 * so why an explicit error code? Weird spec.
6365 * TODO: Move this to the proper constraint layer.
6366 * TODO: Or better wait for spec 1.1 to come.
6367 */
6368 xmlSchemaPIllegalAttrErr(ctxt,
6369 XML_SCHEMAP_E_PROPS_CORRECT_3,
6370 &repName, (xmlSchemaTypePtr) ret, attr);
6371 } else {
6372 xmlSchemaPIllegalAttrErr(ctxt,
6373 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6374 &repName, (xmlSchemaTypePtr) ret, attr);
6375 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006376 }
6377 } else if ((!xmlStrEqual(attr->name, BAD_CAST "final")) &&
6378 (!xmlStrEqual(attr->name, BAD_CAST "abstract")) &&
6379 (!xmlStrEqual(attr->name, BAD_CAST "substitutionGroup"))) {
6380
6381 xmlSchemaPIllegalAttrErr(ctxt,
6382 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6383 &repName, (xmlSchemaTypePtr) ret, attr);
6384 }
6385 }
6386 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6387
6388 xmlSchemaPIllegalAttrErr(ctxt,
6389 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6390 &repName, (xmlSchemaTypePtr) ret, attr);
William M. Bracke7091952004-05-11 15:09:58 +00006391 }
6392 attr = attr->next;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006393 }
William M. Bracke7091952004-05-11 15:09:58 +00006394 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006395 * Extract/validate attributes.
6396 */
6397 if (topLevel) {
6398 /*
6399 * Process top attributes of global element declarations here.
6400 */
6401 ret->flags |= XML_SCHEMAS_ELEM_GLOBAL;
6402 ret->flags |= XML_SCHEMAS_ELEM_TOPLEVEL;
6403 xmlSchemaPValAttrQName(ctxt, schema, &repName,
6404 (xmlSchemaTypePtr) ret, node, "substitutionGroup",
6405 &(ret->substGroupNs), NULL, &(ret->substGroup));
6406 if (xmlGetBooleanProp(ctxt, &repName, (xmlSchemaTypePtr) ret,
6407 node, "abstract", 0))
6408 ret->flags |= XML_SCHEMAS_ELEM_ABSTRACT;
6409 /*
6410 * Attribute "final".
6411 */
6412 attr = xmlSchemaGetPropNode(node, "final");
6413 if (attr == NULL) {
6414 ret->flags |= XML_SCHEMAS_ELEM_FINAL_ABSENT;
6415 } else {
6416 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6417 if (xmlSchemaPValAttrBlockFinal(attrValue, &(ret->flags),
6418 -1,
6419 XML_SCHEMAS_ELEM_FINAL_EXTENSION,
6420 XML_SCHEMAS_ELEM_FINAL_RESTRICTION, -1, -1, -1) != 0) {
6421 xmlSchemaPSimpleTypeErr(ctxt,
6422 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6423 &repName, (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00006424 NULL, "(#all | List of (extension | restriction))",
Daniel Veillardc0826a72004-08-10 14:17:33 +00006425 attrValue, NULL, NULL, NULL);
6426 }
6427 }
6428 }
6429 /*
6430 * Attribute "block".
6431 */
6432 attr = xmlSchemaGetPropNode(node, "block");
6433 if (attr == NULL) {
6434 ret->flags |= XML_SCHEMAS_ELEM_BLOCK_ABSENT;
6435 } else {
6436 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6437 if (xmlSchemaPValAttrBlockFinal(attrValue, &(ret->flags),
6438 -1,
6439 XML_SCHEMAS_ELEM_BLOCK_EXTENSION,
6440 XML_SCHEMAS_ELEM_BLOCK_RESTRICTION,
6441 XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION, -1, -1) != 0) {
6442 xmlSchemaPSimpleTypeErr(ctxt,
6443 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6444 &repName, (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00006445 NULL, "(#all | List of (extension | "
Daniel Veillardc0826a72004-08-10 14:17:33 +00006446 "restriction | substitution))", attrValue,
6447 NULL, NULL, NULL);
6448 }
6449 }
6450 if (xmlGetBooleanProp(ctxt, &repName, (xmlSchemaTypePtr) ret,
6451 node, "nillable", 0))
6452 ret->flags |= XML_SCHEMAS_ELEM_NILLABLE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006453
Daniel Veillardc0826a72004-08-10 14:17:33 +00006454 xmlSchemaPValAttrQName(ctxt, schema,
6455 &repName, (xmlSchemaTypePtr) ret, node,
6456 "type", &(ret->namedTypeNs), NULL, &(ret->namedType));
Daniel Veillard4255d502002-04-16 15:50:10 +00006457
Daniel Veillardc0826a72004-08-10 14:17:33 +00006458 ret->value = xmlSchemaGetProp(ctxt, node, "default");
6459 attr = xmlSchemaGetPropNode(node, "fixed");
6460 if (attr != NULL) {
6461 fixed = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6462 if (ret->value != NULL) {
6463 /*
6464 * 3.3.3 : 1
6465 * default and fixed must not both be present.
6466 */
6467 xmlSchemaPMutualExclAttrErr(ctxt,
6468 XML_SCHEMAP_SRC_ELEMENT_1,
6469 &repName, (xmlSchemaTypePtr) ret, attr,
6470 "default", "fixed");
6471 } else {
6472 ret->flags |= XML_SCHEMAS_ELEM_FIXED;
6473 ret->value = fixed;
6474 }
6475 }
6476 }
6477 /*
6478 * Extract/validate common attributes.
6479 */
6480 /* TODO: Check ID: */
6481 ret->id = xmlSchemaGetProp(ctxt, node, "id");
6482 ret->minOccurs = minOccurs;
6483 ret->maxOccurs = maxOccurs;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006484 if (topLevel != 1)
6485 xmlSchemaPCheckParticleCorrect_2(ctxt, (xmlSchemaTypePtr) ret,
6486 node, minOccurs, maxOccurs);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006487 /*
6488 * And now for the children...
6489 */
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00006490 ctxt->container = ret->name;
Daniel Veillard4255d502002-04-16 15:50:10 +00006491 child = node->children;
6492 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006493 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6494 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006495 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006496 if (isRef) {
6497 if (child != NULL) {
6498 xmlSchemaPContentErr(ctxt,
6499 XML_SCHEMAP_SRC_ELEMENT_2_2,
6500 &repName, (xmlSchemaTypePtr) ret, node, child,
6501 NULL, "(annotation?)");
William M. Bracke7091952004-05-11 15:09:58 +00006502 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006503 } else {
William M. Bracke7091952004-05-11 15:09:58 +00006504 if (IS_SCHEMA(child, "complexType")) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006505 /*
6506 * 3.3.3 : 3
6507 * "type" and either <simpleType> or <complexType> are mutually
6508 * exclusive
6509 */
William M. Bracke7091952004-05-11 15:09:58 +00006510 if (ret->namedType != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006511 xmlSchemaPContentErr(ctxt,
6512 XML_SCHEMAP_SRC_ELEMENT_3,
6513 &repName, (xmlSchemaTypePtr) ret, node, child,
6514 "The attribute 'type' and the <complexType> child are "
6515 "mutually exclusive", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00006516 } else
Daniel Veillard3646d642004-06-02 19:19:14 +00006517 ret->subtypes = xmlSchemaParseComplexType(ctxt, schema, child, 0);
William M. Bracke7091952004-05-11 15:09:58 +00006518 child = child->next;
6519 } else if (IS_SCHEMA(child, "simpleType")) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006520 /*
6521 * 3.3.3 : 3
6522 * "type" and either <simpleType> or <complexType> are
6523 * mutually exclusive
6524 */
William M. Bracke7091952004-05-11 15:09:58 +00006525 if (ret->namedType != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006526 xmlSchemaPContentErr(ctxt,
6527 XML_SCHEMAP_SRC_ELEMENT_3,
6528 &repName, (xmlSchemaTypePtr) ret, node, child,
6529 "The attribute 'type' and the <simpleType> child are "
6530 "mutually exclusive", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00006531 } else
Daniel Veillard3646d642004-06-02 19:19:14 +00006532 ret->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
William M. Bracke7091952004-05-11 15:09:58 +00006533 child = child->next;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006534 }
William M. Bracke7091952004-05-11 15:09:58 +00006535 while ((IS_SCHEMA(child, "unique")) ||
Daniel Veillardc0826a72004-08-10 14:17:33 +00006536 (IS_SCHEMA(child, "key")) || (IS_SCHEMA(child, "keyref"))) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006537#ifdef IDC_ENABLED
6538 if (IS_SCHEMA(child, "unique")) {
6539 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
6540 XML_SCHEMA_TYPE_IDC_UNIQUE, ret->targetNamespace);
6541 } else if (IS_SCHEMA(child, "key")) {
6542 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
6543 XML_SCHEMA_TYPE_IDC_KEY, ret->targetNamespace);
6544 } else if (IS_SCHEMA(child, "keyref")) {
6545 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
6546 XML_SCHEMA_TYPE_IDC_KEYREF, ret->targetNamespace);
6547 }
6548 if (lastIDC != NULL)
6549 lastIDC->next = curIDC;
6550 else
6551 (xmlSchemaIDCPtr) ret->idcs = curIDC;
6552 lastIDC = curIDC;
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006553#else
6554 TODO
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006555#endif
6556 child = child->next;
William M. Bracke7091952004-05-11 15:09:58 +00006557 }
6558 if (child != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006559 xmlSchemaPContentErr(ctxt,
6560 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6561 &repName, (xmlSchemaTypePtr) ret, node, child,
6562 NULL, "(annotation?, ((simpleType | complexType)?, "
6563 "(unique | key | keyref)*))");
6564 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006565
Daniel Veillardc0826a72004-08-10 14:17:33 +00006566 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006567 ctxt->container = oldcontainer;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006568 /*
6569 * Cleanup.
6570 */
6571 if (repName != NULL)
6572 xmlFree(repName);
6573 /*
6574 * NOTE: Element Declaration Representation OK 4. will be checked at a
6575 * different layer.
6576 */
Daniel Veillard4255d502002-04-16 15:50:10 +00006577 return (ret);
6578}
6579
6580/**
6581 * xmlSchemaParseUnion:
6582 * @ctxt: a schema validation context
6583 * @schema: the schema being built
6584 * @node: a subtree containing XML Schema informations
6585 *
6586 * parse a XML schema Union definition
6587 * *WARNING* this interface is highly subject to change
6588 *
William M. Bracke7091952004-05-11 15:09:58 +00006589 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00006590 * 1 in case of success.
6591 */
6592static xmlSchemaTypePtr
6593xmlSchemaParseUnion(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006594 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00006595{
6596 xmlSchemaTypePtr type, subtype, last = NULL;
6597 xmlNodePtr child = NULL;
6598 xmlChar name[30];
William M. Brack2f2a6632004-08-20 23:09:47 +00006599 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00006600
6601 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6602 return (NULL);
6603
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006604 snprintf((char *) name, 30, "#union%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00006605 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00006606 if (type == NULL)
6607 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00006608 type->type = XML_SCHEMA_TYPE_UNION;
Daniel Veillard4255d502002-04-16 15:50:10 +00006609 type->node = node;
William M. Brack2f2a6632004-08-20 23:09:47 +00006610 /*
6611 * Check for illegal attributes.
6612 */
6613 attr = node->properties;
6614 while (attr != NULL) {
6615 if (attr->ns == NULL) {
6616 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6617 (!xmlStrEqual(attr->name, BAD_CAST "memberTypes"))) {
6618 xmlSchemaPIllegalAttrErr(ctxt,
6619 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6620 NULL, type, attr);
6621 }
6622 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6623 xmlSchemaPIllegalAttrErr(ctxt,
6624 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6625 NULL, type, attr);
6626 }
6627 attr = attr->next;
6628 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006629 type->id = xmlSchemaGetProp(ctxt, node, "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00006630 /*
6631 * Attribute "memberTypes". This is a list of QNames.
6632 * TODO: Validate the QNames.
6633 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00006634 type->base = xmlSchemaGetProp(ctxt, node, "memberTypes");
William M. Brack2f2a6632004-08-20 23:09:47 +00006635 /*
6636 * And now for the children...
6637 */
Daniel Veillard4255d502002-04-16 15:50:10 +00006638 child = node->children;
6639 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006640 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6641 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006642 }
William M. Brack2f2a6632004-08-20 23:09:47 +00006643 while (IS_SCHEMA(child, "simpleType")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006644 subtype = (xmlSchemaTypePtr)
Daniel Veillard3646d642004-06-02 19:19:14 +00006645 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006646 if (subtype != NULL) {
6647 if (last == NULL) {
6648 type->subtypes = subtype;
6649 last = subtype;
6650 } else {
6651 last->next = subtype;
6652 last = subtype;
6653 }
6654 last->next = NULL;
6655 }
6656 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006657 }
6658 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00006659 /* TODO: Think about the error code. */
6660 xmlSchemaPContentErr(ctxt,
6661 XML_SCHEMAP_UNKNOWN_UNION_CHILD,
6662 NULL, type, node, child, NULL, "(annotation?, simpleType*)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006663 }
6664 return (type);
6665}
6666
6667/**
6668 * xmlSchemaParseList:
6669 * @ctxt: a schema validation context
6670 * @schema: the schema being built
6671 * @node: a subtree containing XML Schema informations
6672 *
6673 * parse a XML schema List definition
6674 * *WARNING* this interface is highly subject to change
6675 *
William M. Bracke7091952004-05-11 15:09:58 +00006676 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00006677 * 1 in case of success.
6678 */
6679static xmlSchemaTypePtr
6680xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006681 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00006682{
6683 xmlSchemaTypePtr type, subtype;
6684 xmlNodePtr child = NULL;
6685 xmlChar name[30];
William M. Brack2f2a6632004-08-20 23:09:47 +00006686 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00006687
6688 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6689 return (NULL);
6690
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006691 snprintf((char *) name, 30, "#list%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00006692 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00006693 if (type == NULL)
6694 return (NULL);
6695 type->node = node;
6696 type->type = XML_SCHEMA_TYPE_LIST;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006697 type->id = xmlSchemaGetProp(ctxt, node, "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00006698 /*
6699 * Check for illegal attributes.
6700 */
6701 attr = node->properties;
6702 while (attr != NULL) {
6703 if (attr->ns == NULL) {
6704 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6705 (!xmlStrEqual(attr->name, BAD_CAST "itemType"))) {
6706 xmlSchemaPIllegalAttrErr(ctxt,
6707 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6708 NULL, type, attr);
6709 }
6710 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6711 xmlSchemaPIllegalAttrErr(ctxt,
6712 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6713 NULL, type, attr);
6714 }
6715 attr = attr->next;
6716 }
6717 /*
6718 * Attribute "itemType".
6719 */
6720 xmlSchemaPValAttrQName(ctxt, schema, NULL, NULL,
6721 node, "itemType", &(type->baseNs), NULL, &(type->base));
6722 /*
6723 * And now for the children...
6724 */
Daniel Veillard4255d502002-04-16 15:50:10 +00006725 child = node->children;
6726 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006727 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6728 child = child->next;
William M. Brack2f2a6632004-08-20 23:09:47 +00006729 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006730 subtype = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00006731 if (IS_SCHEMA(child, "simpleType")) {
6732 if (type->base != NULL) {
6733 xmlSchemaPCustomErr(ctxt,
6734 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
6735 NULL, type, node,
6736 "The attribute 'itemType' and the <simpleType> child "
6737 "are mutually exclusive", NULL);
6738 } else {
6739 subtype = (xmlSchemaTypePtr)
6740 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
6741 type->subtypes = subtype;
6742 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00006743 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006744 }
6745 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00006746 /* TODO: Think about the error code. */
6747 xmlSchemaPContentErr(ctxt,
6748 XML_SCHEMAP_UNKNOWN_LIST_CHILD,
6749 NULL, type, node, child, NULL, "(annotation?, simpleType?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006750 }
6751 return (type);
6752}
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006753
Daniel Veillard4255d502002-04-16 15:50:10 +00006754/**
6755 * xmlSchemaParseSimpleType:
6756 * @ctxt: a schema validation context
6757 * @schema: the schema being built
6758 * @node: a subtree containing XML Schema informations
6759 *
6760 * parse a XML schema Simple Type definition
6761 * *WARNING* this interface is highly subject to change
6762 *
William M. Bracke7091952004-05-11 15:09:58 +00006763 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillardc0826a72004-08-10 14:17:33 +00006764 * 1 in case of success.
Daniel Veillard4255d502002-04-16 15:50:10 +00006765 */
6766static xmlSchemaTypePtr
6767xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00006768 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00006769{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006770 xmlSchemaTypePtr type, subtype, oldCtxtType, oldParentItem;
Daniel Veillard4255d502002-04-16 15:50:10 +00006771 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006772 const xmlChar *attrValue = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006773 xmlChar *des = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006774 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00006775
6776 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6777 return (NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006778
Daniel Veillardc0826a72004-08-10 14:17:33 +00006779 if (topLevel) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006780 attr = xmlSchemaGetPropNode(node, "name");
Daniel Veillardc0826a72004-08-10 14:17:33 +00006781 if (attr == NULL) {
6782 xmlSchemaPMissingAttrErr(ctxt,
6783 XML_SCHEMAP_S4S_ATTR_MISSING,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006784 (xmlChar **) &xmlSchemaElemDesST, NULL, node,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006785 "name", NULL);
6786 return (NULL);
6787 } else if (xmlSchemaPValAttrNode(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006788 (xmlChar **) &xmlSchemaElemDesST, NULL, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006789 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &attrValue) != 0) {
Daniel Veillard01fa6152004-06-29 17:04:39 +00006790 return (NULL);
6791 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006792 }
6793
6794 if (topLevel == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006795 char buf[40];
Daniel Veillardc0826a72004-08-10 14:17:33 +00006796
Daniel Veillard01fa6152004-06-29 17:04:39 +00006797 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006798 * Parse as local simple type definition.
Daniel Veillard01fa6152004-06-29 17:04:39 +00006799 */
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006800 snprintf(buf, 39, "#ST%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00006801 type = xmlSchemaAddType(ctxt, schema, (const xmlChar *)buf, NULL, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006802 if (type == NULL)
6803 return (NULL);
6804 type->node = node;
6805 type->type = XML_SCHEMA_TYPE_SIMPLE;
6806 /*
6807 * Check for illegal attributes.
6808 */
6809 attr = node->properties;
6810 while (attr != NULL) {
6811 if (attr->ns == NULL) {
6812 if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
6813 xmlSchemaPIllegalAttrErr(ctxt,
6814 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006815 &des, type, attr);
Daniel Veillard01fa6152004-06-29 17:04:39 +00006816 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006817 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6818 xmlSchemaPIllegalAttrErr(ctxt,
6819 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006820 &des, type, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006821 }
6822 attr = attr->next;
Daniel Veillard01fa6152004-06-29 17:04:39 +00006823 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006824 } else {
6825 /*
6826 * Parse as global simple type definition.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006827 *
6828 * Note that attrValue is the value of the attribute "name" here.
Daniel Veillardc0826a72004-08-10 14:17:33 +00006829 */
William M. Brack2f2a6632004-08-20 23:09:47 +00006830 type = xmlSchemaAddType(ctxt, schema, attrValue, schema->targetNamespace, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006831 if (type == NULL)
6832 return (NULL);
6833 type->node = node;
6834 type->type = XML_SCHEMA_TYPE_SIMPLE;
6835 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
6836 /*
6837 * Check for illegal attributes.
6838 */
6839 attr = node->properties;
6840 while (attr != NULL) {
6841 if (attr->ns == NULL) {
6842 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6843 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006844 (!xmlStrEqual(attr->name, BAD_CAST "final"))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006845 xmlSchemaPIllegalAttrErr(ctxt,
6846 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006847 &des, type, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006848 }
6849 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6850 xmlSchemaPIllegalAttrErr(ctxt,
6851 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006852 &des, type, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006853 }
6854 attr = attr->next;
6855 }
6856 /*
6857 * Attribute "final".
6858 */
6859 attr = xmlSchemaGetPropNode(node, "final");
6860 if (attr == NULL) {
6861 type->flags |= XML_SCHEMAS_TYPE_FINAL_DEFAULT;
6862 } else {
6863 attrValue = xmlSchemaGetProp(ctxt, node, "final");
6864 if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
6865 -1, -1, XML_SCHEMAS_TYPE_FINAL_RESTRICTION, -1,
6866 XML_SCHEMAS_TYPE_FINAL_LIST,
6867 XML_SCHEMAS_TYPE_FINAL_UNION) != 0) {
6868
6869 xmlSchemaPSimpleTypeErr(ctxt,
6870 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006871 &des, type, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00006872 NULL, "(#all | List of (list | union | restriction)",
Daniel Veillardc0826a72004-08-10 14:17:33 +00006873 attrValue, NULL, NULL, NULL);
6874 }
6875 }
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006876 }
6877 type->targetNamespace = schema->targetNamespace;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006878 /* TODO: Check id. */
6879 type->id = xmlSchemaGetProp(ctxt, node, "id");
6880 /*
6881 * And now for the children...
6882 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006883 oldCtxtType = ctxt->ctxtType;
6884 oldParentItem = ctxt->parentItem;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006885 ctxt->ctxtType = type;
6886 ctxt->parentItem = type;
Daniel Veillard4255d502002-04-16 15:50:10 +00006887 child = node->children;
6888 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006889 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6890 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006891 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006892 subtype = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00006893 if (IS_SCHEMA(child, "restriction")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006894 subtype = (xmlSchemaTypePtr)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00006895 xmlSchemaParseRestriction(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006896 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006897 } else if (IS_SCHEMA(child, "list")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006898 subtype = (xmlSchemaTypePtr)
6899 xmlSchemaParseList(ctxt, schema, child);
6900 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006901 } else if (IS_SCHEMA(child, "union")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006902 subtype = (xmlSchemaTypePtr)
6903 xmlSchemaParseUnion(ctxt, schema, child);
6904 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006905 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006906 type->subtypes = subtype;
6907 if ((child != NULL) || (subtype == NULL)) {
6908 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006909 &des, type, node, child, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006910 "(annotation?, (restriction | list | union))");
Daniel Veillard4255d502002-04-16 15:50:10 +00006911 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006912 ctxt->parentItem = oldParentItem;
6913 ctxt->ctxtType = oldCtxtType;
6914 FREE_AND_NULL(des)
Daniel Veillard01fa6152004-06-29 17:04:39 +00006915
Daniel Veillard4255d502002-04-16 15:50:10 +00006916 return (type);
6917}
6918
6919
6920/**
6921 * xmlSchemaParseGroup:
6922 * @ctxt: a schema validation context
6923 * @schema: the schema being built
6924 * @node: a subtree containing XML Schema informations
6925 *
6926 * parse a XML schema Group definition
6927 * *WARNING* this interface is highly subject to change
6928 *
William M. Bracke7091952004-05-11 15:09:58 +00006929 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00006930 * 1 in case of success.
6931 */
6932static xmlSchemaTypePtr
6933xmlSchemaParseGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00006934 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00006935{
6936 xmlSchemaTypePtr type, subtype;
6937 xmlNodePtr child = NULL;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006938 const xmlChar *name, *ns = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006939 const xmlChar *ref = NULL, *refNs = NULL;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006940 char buf[50];
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00006941 int minOccurs, maxOccurs;
Daniel Veillard4255d502002-04-16 15:50:10 +00006942
6943 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6944 return (NULL);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00006945 /*
6946 * TODO: Validate the element even if no item is created
6947 * (i.e. min/maxOccurs == 0).
6948 */
6949 minOccurs = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "nonNegativeInteger");
6950 maxOccurs = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1, "(nonNegativeInteger | unbounded)");
6951 if ((minOccurs == 0) && (maxOccurs == 0)) {
6952 return (NULL);
6953 }
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006954 if (topLevel)
6955 ns = schema->targetNamespace;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006956 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00006957 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006958 ref = xmlGetQNameProp(ctxt, node, "ref", &refNs);
6959 if (ref == NULL) {
6960 xmlSchemaPErr2(ctxt, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006961 XML_SCHEMAP_GROUP_NONAME_NOREF,
6962 "Group definition or particle: One of the attributes \"name\" "
6963 "or \"ref\" must be present.\n", NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006964 return (NULL);
6965 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006966 if (refNs == NULL)
6967 refNs = schema->targetNamespace;
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006968 snprintf(buf, 49, "#grRef%d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006969 name = (const xmlChar *) buf;
Daniel Veillard4255d502002-04-16 15:50:10 +00006970 }
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006971 type = xmlSchemaAddGroup(ctxt, schema, name, ns, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00006972 if (type == NULL)
6973 return (NULL);
6974 type->node = node;
6975 type->type = XML_SCHEMA_TYPE_GROUP;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006976 if (topLevel)
6977 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006978 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00006979 type->ref = ref;
6980 type->refNs = refNs;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00006981 type->minOccurs = minOccurs;
6982 type->maxOccurs = maxOccurs;
6983 xmlSchemaPCheckParticleCorrect_2(ctxt, type,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006984 node, type->minOccurs, type->maxOccurs);
Daniel Veillard4255d502002-04-16 15:50:10 +00006985
6986 child = node->children;
6987 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006988 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6989 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006990 }
6991 subtype = NULL;
6992 if (IS_SCHEMA(child, "all")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006993 subtype = (xmlSchemaTypePtr)
6994 xmlSchemaParseAll(ctxt, schema, child);
6995 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006996 } else if (IS_SCHEMA(child, "choice")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006997 subtype = xmlSchemaParseChoice(ctxt, schema, child);
6998 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006999 } else if (IS_SCHEMA(child, "sequence")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007000 subtype = (xmlSchemaTypePtr)
7001 xmlSchemaParseSequence(ctxt, schema, child);
7002 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007003 }
7004 if (subtype != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007005 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00007006 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007007 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_GROUP_CHILD,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007008 "Group definition \"%s\" has unexpected content.\n", type->name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007009 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007010 }
7011
7012 return (type);
7013}
7014
7015/**
7016 * xmlSchemaParseAll:
7017 * @ctxt: a schema validation context
7018 * @schema: the schema being built
7019 * @node: a subtree containing XML Schema informations
7020 *
7021 * parse a XML schema All definition
7022 * *WARNING* this interface is highly subject to change
7023 *
William M. Bracke7091952004-05-11 15:09:58 +00007024 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00007025 * 1 in case of success.
7026 */
7027static xmlSchemaTypePtr
7028xmlSchemaParseAll(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007029 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00007030{
7031 xmlSchemaTypePtr type, subtype, last = NULL;
7032 xmlNodePtr child = NULL;
7033 xmlChar name[30];
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00007034 const xmlChar *oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00007035
7036 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7037 return (NULL);
7038
7039
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00007040 snprintf((char *) name, 30, "#all%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00007041 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00007042 if (type == NULL)
7043 return (NULL);
7044 type->node = node;
Daniel Veillard7646b182002-04-20 06:41:40 +00007045 type->type = XML_SCHEMA_TYPE_ALL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007046 type->id = xmlSchemaGetProp(ctxt, node, "id");
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00007047
7048 type->minOccurs = xmlGetMinOccurs(ctxt, node, 0, 1, 1, "(0 | 1)");
7049 type->maxOccurs = xmlGetMaxOccurs(ctxt, node, 1, 1, 1, "1");
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00007050
7051 oldcontainer = ctxt->container;
7052 ctxt->container = (const xmlChar *) name;
Daniel Veillard4255d502002-04-16 15:50:10 +00007053 child = node->children;
7054 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007055 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7056 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007057 }
7058 while (IS_SCHEMA(child, "element")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007059 subtype = (xmlSchemaTypePtr)
7060 xmlSchemaParseElement(ctxt, schema, child, 0);
7061 if (subtype != NULL) {
William M. Brackb15351e2003-12-27 04:34:42 +00007062 if (subtype->minOccurs > 1)
7063 xmlSchemaPErr(ctxt, child, XML_SCHEMAP_INVALID_MINOCCURS,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007064 "invalid value for minOccurs (must be 0 or 1).\n",
William M. Brackb15351e2003-12-27 04:34:42 +00007065 NULL, NULL);
7066 if (subtype->maxOccurs > 1)
7067 xmlSchemaPErr(ctxt, child, XML_SCHEMAP_INVALID_MAXOCCURS,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007068 "invalid value for maxOccurs (must be 0 or 1).\n",
William M. Brackb15351e2003-12-27 04:34:42 +00007069 NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007070 if (last == NULL) {
7071 type->subtypes = subtype;
7072 last = subtype;
7073 } else {
7074 last->next = subtype;
7075 last = subtype;
7076 }
7077 last->next = NULL;
7078 }
7079 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007080 }
7081 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007082 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_ALL_CHILD,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007083 "<all> has unexpected content.\n", type->name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007084 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007085 }
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00007086 ctxt->container = oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00007087 return (type);
7088}
7089
7090/**
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007091 * xmlSchemaCleanupDoc:
7092 * @ctxt: a schema validation context
7093 * @node: the root of the document.
7094 *
7095 * removes unwanted nodes in a schemas document tree
7096 */
7097static void
7098xmlSchemaCleanupDoc(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr root)
7099{
7100 xmlNodePtr delete, cur;
7101
7102 if ((ctxt == NULL) || (root == NULL)) return;
7103
7104 /*
7105 * Remove all the blank text nodes
7106 */
7107 delete = NULL;
7108 cur = root;
7109 while (cur != NULL) {
7110 if (delete != NULL) {
7111 xmlUnlinkNode(delete);
7112 xmlFreeNode(delete);
7113 delete = NULL;
7114 }
7115 if (cur->type == XML_TEXT_NODE) {
7116 if (IS_BLANK_NODE(cur)) {
7117 if (xmlNodeGetSpacePreserve(cur) != 1) {
7118 delete = cur;
7119 }
7120 }
7121 } else if ((cur->type != XML_ELEMENT_NODE) &&
7122 (cur->type != XML_CDATA_SECTION_NODE)) {
7123 delete = cur;
7124 goto skip_children;
7125 }
7126
7127 /*
7128 * Skip to next node
7129 */
7130 if (cur->children != NULL) {
7131 if ((cur->children->type != XML_ENTITY_DECL) &&
7132 (cur->children->type != XML_ENTITY_REF_NODE) &&
7133 (cur->children->type != XML_ENTITY_NODE)) {
7134 cur = cur->children;
7135 continue;
7136 }
7137 }
7138 skip_children:
7139 if (cur->next != NULL) {
7140 cur = cur->next;
7141 continue;
7142 }
7143
7144 do {
7145 cur = cur->parent;
7146 if (cur == NULL)
7147 break;
7148 if (cur == root) {
7149 cur = NULL;
7150 break;
7151 }
7152 if (cur->next != NULL) {
7153 cur = cur->next;
7154 break;
7155 }
7156 } while (cur != NULL);
7157 }
7158 if (delete != NULL) {
7159 xmlUnlinkNode(delete);
7160 xmlFreeNode(delete);
7161 delete = NULL;
7162 }
7163}
7164
William M. Brack2f2a6632004-08-20 23:09:47 +00007165
7166/**
7167 * xmlSchemaImportSchema
7168 *
7169 * @ctxt: a schema validation context
7170 * @schemaLocation: an URI defining where to find the imported schema
7171 *
7172 * import a XML schema
7173 * *WARNING* this interface is highly subject to change
7174 *
7175 * Returns -1 in case of error and 1 in case of success.
7176 */
7177#if 0
7178static xmlSchemaImportPtr
7179xmlSchemaImportSchema(xmlSchemaParserCtxtPtr ctxt,
7180 const xmlChar *schemaLocation)
7181{
7182 xmlSchemaImportPtr import;
7183 xmlSchemaParserCtxtPtr newctxt;
7184
7185 newctxt = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
7186 if (newctxt == NULL) {
7187 xmlSchemaPErrMemory(ctxt, "allocating schema parser context",
7188 NULL);
7189 return (NULL);
7190 }
7191 memset(newctxt, 0, sizeof(xmlSchemaParserCtxt));
7192 /* Keep the same dictionnary for parsing, really */
7193 xmlDictReference(ctxt->dict);
7194 newctxt->dict = ctxt->dict;
7195 newctxt->includes = 0;
7196 newctxt->URL = xmlDictLookup(newctxt->dict, schemaLocation, -1);
7197
7198 xmlSchemaSetParserErrors(newctxt, ctxt->error, ctxt->warning,
7199 ctxt->userData);
7200
7201 import = (xmlSchemaImport*) xmlMalloc(sizeof(xmlSchemaImport));
7202 if (import == NULL) {
7203 xmlSchemaPErrMemory(NULL, "allocating imported schema",
7204 NULL);
7205 xmlSchemaFreeParserCtxt(newctxt);
7206 return (NULL);
7207 }
7208
7209 memset(import, 0, sizeof(xmlSchemaImport));
7210 import->schemaLocation = xmlDictLookup(ctxt->dict, schemaLocation, -1);
7211 import->schema = xmlSchemaParse(newctxt);
7212
7213 if (import->schema == NULL) {
7214 /* FIXME use another error enum here ? */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00007215 xmlSchemaPErr(ctxt, NULL, XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +00007216 "Failed to import schema from location \"%s\".\n",
7217 schemaLocation, NULL);
7218
7219 xmlSchemaFreeParserCtxt(newctxt);
7220 /* The schemaLocation is held by the dictionary.
7221 if (import->schemaLocation != NULL)
7222 xmlFree((xmlChar *)import->schemaLocation);
7223 */
7224 xmlFree(import);
7225 return NULL;
7226 }
7227
7228 xmlSchemaFreeParserCtxt(newctxt);
7229 return import;
7230}
7231#endif
7232
7233static void
7234xmlSchemaClearSchemaDefaults(xmlSchemaPtr schema)
7235{
7236 if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
7237 schema->flags ^= XML_SCHEMAS_QUALIF_ELEM;
7238
7239 if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
7240 schema->flags ^= XML_SCHEMAS_QUALIF_ATTR;
7241
7242 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
7243 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_EXTENSION;
7244 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
7245 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION;
7246 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST)
7247 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_LIST;
7248 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION)
7249 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_UNION;
7250
7251 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
7252 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION;
7253 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
7254 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION;
7255 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
7256 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION;
7257}
7258
7259static void
7260xmlSchemaParseSchemaDefaults(xmlSchemaParserCtxtPtr ctxt,
7261 xmlSchemaPtr schema,
7262 xmlNodePtr node)
7263{
7264 xmlAttrPtr attr;
7265 const xmlChar *val;
7266
7267 attr = xmlSchemaGetPropNode(node, "elementFormDefault");
7268 if (attr != NULL) {
7269 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
7270 if (xmlSchemaPValAttrFormDefault(val, &schema->flags,
7271 XML_SCHEMAS_QUALIF_ELEM) != 0) {
7272 xmlSchemaPSimpleTypeErr(ctxt,
7273 XML_SCHEMAP_ELEMFORMDEFAULT_VALUE,
7274 NULL, NULL, (xmlNodePtr) attr, NULL,
7275 "(qualified | unqualified)", val, NULL, NULL, NULL);
7276 }
7277 }
7278
7279 attr = xmlSchemaGetPropNode(node, "attributeFormDefault");
7280 if (attr != NULL) {
7281 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
7282 if (xmlSchemaPValAttrFormDefault(val, &schema->flags,
7283 XML_SCHEMAS_QUALIF_ATTR) != 0) {
7284 xmlSchemaPSimpleTypeErr(ctxt,
7285 XML_SCHEMAP_ATTRFORMDEFAULT_VALUE,
7286 NULL, NULL, (xmlNodePtr) attr, NULL,
7287 "(qualified | unqualified)", val, NULL, NULL, NULL);
7288 }
7289 }
7290
7291 attr = xmlSchemaGetPropNode(node, "finalDefault");
7292 if (attr != NULL) {
7293 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
7294 if (xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
7295 XML_SCHEMAS_FINAL_DEFAULT_EXTENSION,
7296 XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION,
7297 -1,
7298 XML_SCHEMAS_FINAL_DEFAULT_LIST,
7299 XML_SCHEMAS_FINAL_DEFAULT_UNION) != 0) {
7300 xmlSchemaPSimpleTypeErr(ctxt,
7301 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
7302 NULL, NULL, (xmlNodePtr) attr, NULL,
7303 "(#all | List of (extension | restriction | list | union))",
7304 val, NULL, NULL, NULL);
7305 }
7306 }
7307
7308 attr = xmlSchemaGetPropNode(node, "blockDefault");
7309 if (attr != NULL) {
7310 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
7311 if (xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
7312 XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION,
7313 XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION,
7314 XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION, -1, -1) != 0) {
7315 xmlSchemaPSimpleTypeErr(ctxt,
7316 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
7317 NULL, NULL, (xmlNodePtr) attr, NULL,
7318 "(#all | List of (extension | restriction | substitution))",
7319 val, NULL, NULL, NULL);
7320 }
7321 }
7322}
7323
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007324/**
7325 * xmlSchemaParseSchemaTopLevel:
7326 * @ctxt: a schema validation context
7327 * @schema: the schemas
7328 * @nodes: the list of top level nodes
7329 *
7330 * Returns the internal XML Schema structure built from the resource or
7331 * NULL in case of error
7332 */
7333static void
7334xmlSchemaParseSchemaTopLevel(xmlSchemaParserCtxtPtr ctxt,
7335 xmlSchemaPtr schema, xmlNodePtr nodes)
7336{
7337 xmlNodePtr child;
7338 xmlSchemaAnnotPtr annot;
7339
7340 if ((ctxt == NULL) || (schema == NULL) || (nodes == NULL))
7341 return;
7342
7343 child = nodes;
7344 while ((IS_SCHEMA(child, "include")) ||
7345 (IS_SCHEMA(child, "import")) ||
7346 (IS_SCHEMA(child, "redefine")) ||
7347 (IS_SCHEMA(child, "annotation"))) {
7348 if (IS_SCHEMA(child, "annotation")) {
7349 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7350 if (schema->annot == NULL)
7351 schema->annot = annot;
7352 else
7353 xmlSchemaFreeAnnot(annot);
7354 } else if (IS_SCHEMA(child, "import")) {
7355 xmlSchemaParseImport(ctxt, schema, child);
7356 } else if (IS_SCHEMA(child, "include")) {
Daniel Veillardb0f397e2003-12-23 23:30:53 +00007357 ctxt->includes++;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007358 xmlSchemaParseInclude(ctxt, schema, child);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00007359 ctxt->includes--;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007360 } else if (IS_SCHEMA(child, "redefine")) {
7361 TODO
7362 }
7363 child = child->next;
7364 }
7365 while (child != NULL) {
7366 if (IS_SCHEMA(child, "complexType")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00007367 xmlSchemaParseComplexType(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007368 child = child->next;
7369 } else if (IS_SCHEMA(child, "simpleType")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00007370 xmlSchemaParseSimpleType(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007371 child = child->next;
7372 } else if (IS_SCHEMA(child, "element")) {
7373 xmlSchemaParseElement(ctxt, schema, child, 1);
7374 child = child->next;
7375 } else if (IS_SCHEMA(child, "attribute")) {
William M. Bracke7091952004-05-11 15:09:58 +00007376 xmlSchemaParseAttribute(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007377 child = child->next;
7378 } else if (IS_SCHEMA(child, "attributeGroup")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00007379 xmlSchemaParseAttributeGroup(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007380 child = child->next;
7381 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00007382 xmlSchemaParseGroup(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007383 child = child->next;
7384 } else if (IS_SCHEMA(child, "notation")) {
7385 xmlSchemaParseNotation(ctxt, schema, child);
7386 child = child->next;
7387 } else {
7388 xmlSchemaPErr2(ctxt, NULL, child,
7389 XML_SCHEMAP_UNKNOWN_SCHEMAS_CHILD,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007390 "Unexpected element \"%s\" as child of <schema>.\n",
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007391 child->name, NULL);
7392 child = child->next;
7393 }
7394 while (IS_SCHEMA(child, "annotation")) {
7395 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7396 if (schema->annot == NULL)
7397 schema->annot = annot;
7398 else
7399 xmlSchemaFreeAnnot(annot);
7400 child = child->next;
7401 }
7402 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00007403 ctxt->parentItem = NULL;
7404 ctxt->ctxtType = NULL;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007405}
7406
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007407static xmlSchemaImportPtr
7408xmlSchemaAddImport(xmlSchemaParserCtxtPtr ctxt,
7409 xmlHashTablePtr *imports,
7410 const xmlChar *nsName)
7411{
7412 xmlSchemaImportPtr ret;
7413
7414 if (*imports == NULL) {
Daniel Veillardb9e2f262005-01-23 23:48:34 +00007415 *imports = xmlHashCreateDict(10, ctxt->dict);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007416 if (*imports == NULL) {
7417 xmlSchemaPCustomErr(ctxt,
7418 XML_SCHEMAP_FAILED_BUILD_IMPORT,
7419 NULL, NULL, (xmlNodePtr) ctxt->doc,
7420 "Internal error: failed to build the import table",
7421 NULL);
7422 return (NULL);
7423 }
7424 }
7425 ret = (xmlSchemaImport*) xmlMalloc(sizeof(xmlSchemaImport));
7426 if (ret == NULL) {
7427 xmlSchemaPErrMemory(NULL, "allocating import struct", NULL);
7428 return (NULL);
7429 }
7430 memset(ret, 0, sizeof(xmlSchemaImport));
7431 if (nsName == NULL)
7432 nsName = XML_SCHEMAS_NO_NAMESPACE;
7433 xmlHashAddEntry(*imports, nsName, ret);
7434
7435 return (ret);
7436}
7437
7438static int
7439xmlSchemaAcquireSchemaDoc(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007440 xmlSchemaPtr schema,
7441 xmlNodePtr node,
7442 const xmlChar *nsName,
7443 const xmlChar *location,
7444 xmlDocPtr *doc,
7445 const xmlChar **targetNamespace,
7446 int absolute)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007447{
7448 xmlParserCtxtPtr parserCtxt;
7449 xmlSchemaImportPtr import;
7450 const xmlChar *ns;
7451 xmlNodePtr root;
7452
7453 /*
7454 * NOTE: This will be used for <import>, <xsi:schemaLocation> and
7455 * <xsi:noNamespaceSchemaLocation>.
7456 */
7457 *doc = NULL;
7458 /*
7459 * Given that the schemaLocation [attribute] is only a hint, it is open
7460 * to applications to ignore all but the first <import> for a given
7461 * namespace, regardless of the ·actual value· of schemaLocation, but
7462 * such a strategy risks missing useful information when new
7463 * schemaLocations are offered.
7464 *
7465 * XSV (ver 2.5-2) does use the first <import> which resolves to a valid schema.
7466 * Xerces-J (ver 2.5.1) ignores all but the first given <import> - regardless if
7467 * valid or not.
7468 * We will follow XSV here.
7469 */
7470 if (location == NULL) {
7471 /*
7472 * Schema Document Location Strategy:
7473 *
7474 * 3 Based on the namespace name, identify an existing schema document,
7475 * either as a resource which is an XML document or a <schema> element
7476 * information item, in some local schema repository;
7477 *
7478 * 5 Attempt to resolve the namespace name to locate such a resource.
7479 *
7480 * NOTE: Those stategies are not supported, so we will skip.
7481 */
7482 return (0);
7483 }
7484 if (nsName == NULL)
7485 ns = XML_SCHEMAS_NO_NAMESPACE;
7486 else
7487 ns = nsName;
7488
7489 import = xmlHashLookup(schema->schemasImports, ns);
7490 if (import != NULL) {
7491 /*
7492 * There was a valid resource for the specified namespace already
7493 * defined, so skip.
7494 * TODO: This might be changed someday to allow import of
7495 * components from multiple documents for a single target namespace.
7496 */
7497 return (0);
7498 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007499
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007500 /*
7501 * Schema Document Location Strategy:
7502 *
7503 * 2 Based on the location URI, identify an existing schema document,
7504 * either as a resource which is an XML document or a <schema> element
7505 * information item, in some local schema repository;
7506 *
7507 * 4 Attempt to resolve the location URI, to locate a resource on the
7508 * web which is or contains or references a <schema> element;
7509 * TODO: Hmm, I don't know if the reference stuff in 4. will work.
7510 *
7511 */
7512 if ((absolute == 0) && (node != NULL)) {
7513 xmlChar *base, *URI;
7514
7515 base = xmlNodeGetBase(node->doc, node);
7516 if (base == NULL) {
7517 URI = xmlBuildURI(location, node->doc->URL);
7518 } else {
7519 URI = xmlBuildURI(location, base);
7520 xmlFree(base);
7521 }
7522 if (URI != NULL) {
7523 location = xmlDictLookup(ctxt->dict, URI, -1);
7524 xmlFree(URI);
7525 }
7526 }
7527 parserCtxt = xmlNewParserCtxt();
7528 if (parserCtxt == NULL) {
7529 xmlSchemaPErrMemory(NULL, "xmlSchemaParseImport: "
7530 "allocating a parser context", NULL);
7531 return(-1);
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00007532 }
7533
7534 if ((ctxt->dict != NULL) && (parserCtxt->dict != NULL)) {
7535 xmlDictFree(parserCtxt->dict);
7536 parserCtxt->dict = ctxt->dict;
7537 xmlDictReference(parserCtxt->dict);
7538 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007539
7540 *doc = xmlCtxtReadFile(parserCtxt, (const char *) location,
7541 NULL, SCHEMAS_PARSE_OPTIONS);
7542
7543 /*
7544 * 2.1 The referent is (a fragment of) a resource which is an
7545 * XML document (see clause 1.1), which in turn corresponds to
7546 * a <schema> element information item in a well-formed information
7547 * set, which in turn corresponds to a valid schema.
7548 * TODO: What to do with the "fragment" stuff?
7549 *
7550 * 2.2 The referent is a <schema> element information item in
7551 * a well-formed information set, which in turn corresponds
7552 * to a valid schema.
7553 * NOTE: 2.2 won't apply, since only XML documents will be processed
7554 * here.
7555 */
7556 if (*doc == NULL) {
7557 xmlErrorPtr lerr;
7558 /*
7559 * It is *not* an error for the application schema reference
7560 * strategy to fail.
7561 *
7562 * If the doc is NULL and the parser error is an IO error we
7563 * will assume that the resource could not be located or accessed.
7564 *
7565 * TODO: Try to find specific error codes to react only on
7566 * localisation failures.
7567 *
7568 * TODO, FIXME: Check the spec: is a namespace added to the imported
7569 * namespaces, even if the schemaLocation did not provide
7570 * a resource? I guess so, since omitting the "schemaLocation"
7571 * attribute, imports a namespace as well.
7572 */
7573 lerr = xmlGetLastError();
7574 if ((lerr != NULL) && (lerr->domain == XML_FROM_IO)) {
7575 xmlFreeParserCtxt(parserCtxt);
7576 return(0);
7577 }
7578
7579 xmlSchemaPCustomErr(ctxt,
7580 XML_SCHEMAP_SRC_IMPORT_2_1,
7581 NULL, NULL, node,
7582 "Failed to parse the resource '%s' for import",
7583 location);
7584 xmlFreeParserCtxt(parserCtxt);
7585 return(XML_SCHEMAP_SRC_IMPORT_2_1);
7586 }
7587 xmlFreeParserCtxt(parserCtxt);
7588
7589 root = xmlDocGetRootElement(*doc);
7590 if (root == NULL) {
7591 xmlSchemaPCustomErr(ctxt,
7592 XML_SCHEMAP_SRC_IMPORT_2_1,
7593 NULL, NULL, node,
7594 "The XML document '%s' to be imported has no document "
7595 "element", location);
7596 xmlFreeDoc(*doc);
7597 *doc = NULL;
7598 return (XML_SCHEMAP_SRC_IMPORT_2_1);
7599 }
7600
7601 xmlSchemaCleanupDoc(ctxt, root);
7602
7603 if (!IS_SCHEMA(root, "schema")) {
7604 xmlSchemaPCustomErr(ctxt,
7605 XML_SCHEMAP_SRC_IMPORT_2_1,
7606 NULL, NULL, node,
7607 "The XML document '%s' to be imported is not a XML schema document",
7608 location);
7609 xmlFreeDoc(*doc);
7610 *doc = NULL;
7611 return (XML_SCHEMAP_SRC_IMPORT_2_1);
7612 }
7613 *targetNamespace = xmlSchemaGetProp(ctxt, root, "targetNamespace");
7614 /*
7615 * Schema Representation Constraint: Import Constraints and Semantics
7616 */
7617 if (nsName == NULL) {
7618 if (*targetNamespace != NULL) {
7619 xmlSchemaPCustomErr(ctxt,
7620 XML_SCHEMAP_SRC_IMPORT_3_2,
7621 NULL, NULL, node,
7622 "The XML schema to be imported is not expected "
7623 "to have a target namespace; this differs from "
7624 "its target namespace of '%s'", *targetNamespace);
7625 xmlFreeDoc(*doc);
7626 *doc = NULL;
7627 return (XML_SCHEMAP_SRC_IMPORT_3_2);
7628 }
7629 } else {
7630 if (*targetNamespace == NULL) {
7631 xmlSchemaPCustomErr(ctxt,
7632 XML_SCHEMAP_SRC_IMPORT_3_1,
7633 NULL, NULL, node,
7634 "The XML schema to be imported is expected to have a target "
7635 "namespace of '%s'", nsName);
7636 xmlFreeDoc(*doc);
7637 *doc = NULL;
7638 return (XML_SCHEMAP_SRC_IMPORT_3_1);
7639 } else if (!xmlStrEqual(*targetNamespace, nsName)) {
7640 xmlSchemaPCustomErrExt(ctxt,
7641 XML_SCHEMAP_SRC_IMPORT_3_1,
7642 NULL, NULL, node,
7643 "The XML schema to be imported is expected to have a "
7644 "target namespace of '%s'; this differs from "
7645 "its target namespace of '%s'",
7646 nsName, *targetNamespace, NULL);
7647 xmlFreeDoc(*doc);
7648 *doc = NULL;
7649 return (XML_SCHEMAP_SRC_IMPORT_3_1);
7650 }
7651 }
7652
7653 import = xmlSchemaAddImport(ctxt, &(schema->schemasImports), nsName);
7654 if (import == NULL) {
7655 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_FAILED_BUILD_IMPORT,
7656 NULL, NULL, NULL,
7657 "Internal error: xmlSchemaAcquireSchemaDoc, "
7658 "failed to build import table", NULL);
7659 xmlFreeDoc(*doc);
7660 *doc = NULL;
7661 return (-1);
7662 }
7663 import->schemaLocation = location;
7664 import->doc = *doc;
7665 return (0);
7666}
William M. Brack2f2a6632004-08-20 23:09:47 +00007667
7668/**
7669 * xmlSchemaParseImport:
7670 * @ctxt: a schema validation context
7671 * @schema: the schema being built
7672 * @node: a subtree containing XML Schema informations
7673 *
7674 * parse a XML schema Import definition
7675 * *WARNING* this interface is highly subject to change
7676 *
7677 * Returns 0 in case of success, a positive error code if
7678 * not valid and -1 in case of an internal error.
7679 */
7680static int
7681xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
7682 xmlNodePtr node)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007683{
7684 xmlNodePtr child;
7685 const xmlChar *namespace = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00007686 const xmlChar *schemaLocation = NULL;
7687 const xmlChar *targetNamespace, *oldTNS, *url;
7688 xmlAttrPtr attr;
7689 xmlDocPtr doc;
7690 xmlNodePtr root;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007691 int flags, ret = 0;
William M. Brack2f2a6632004-08-20 23:09:47 +00007692
7693
7694 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7695 return (-1);
7696
7697 /*
7698 * Check for illegal attributes.
7699 */
7700 attr = node->properties;
7701 while (attr != NULL) {
7702 if (attr->ns == NULL) {
7703 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7704 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
7705 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
7706 xmlSchemaPIllegalAttrErr(ctxt,
7707 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7708 NULL, NULL, attr);
7709 }
7710 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7711 xmlSchemaPIllegalAttrErr(ctxt,
7712 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7713 NULL, NULL, attr);
7714 }
7715 attr = attr->next;
7716 }
7717 /*
7718 * Extract and validate attributes.
7719 */
7720 if (xmlSchemaPValAttr(ctxt, NULL, NULL, node,
7721 "namespace", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
7722 &namespace) != 0) {
7723 xmlSchemaPSimpleTypeErr(ctxt,
7724 XML_SCHEMAP_IMPORT_NAMESPACE_NOT_URI,
7725 NULL, NULL, node,
7726 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
7727 NULL, namespace, NULL, NULL, NULL);
7728 return (XML_SCHEMAP_IMPORT_NAMESPACE_NOT_URI);
7729 }
7730
7731 if (xmlSchemaPValAttr(ctxt, NULL, NULL, node,
7732 "schemaLocation", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
7733 &schemaLocation) != 0) {
7734 xmlSchemaPSimpleTypeErr(ctxt,
7735 XML_SCHEMAP_IMPORT_SCHEMA_NOT_URI,
7736 NULL, NULL, node,
7737 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
7738 NULL, namespace, NULL, NULL, NULL);
7739 return (XML_SCHEMAP_IMPORT_SCHEMA_NOT_URI);
7740 }
7741 /*
7742 * And now for the children...
7743 */
7744 child = node->children;
7745 if (IS_SCHEMA(child, "annotation")) {
7746 /*
7747 * the annotation here is simply discarded ...
7748 */
7749 child = child->next;
7750 }
7751 if (child != NULL) {
7752 xmlSchemaPContentErr(ctxt,
7753 XML_SCHEMAP_UNKNOWN_IMPORT_CHILD,
7754 NULL, NULL, node, child, NULL,
7755 "(annotation?)");
7756 }
7757 /*
7758 * Apply additional constraints.
7759 */
7760 if (namespace != NULL) {
7761 /*
7762 * 1.1 If the namespace [attribute] is present, then its ·actual value·
7763 * must not match the ·actual value· of the enclosing <schema>'s
7764 * targetNamespace [attribute].
7765 */
7766 if (xmlStrEqual(schema->targetNamespace, namespace)) {
7767 xmlSchemaPCustomErr(ctxt,
7768 XML_SCHEMAP_SRC_IMPORT_1_1,
7769 NULL, NULL, node,
7770 "The value of the attribute 'namespace' must not match "
7771 "the target namespace '%s' of the importing schema",
7772 schema->targetNamespace);
7773 return (XML_SCHEMAP_SRC_IMPORT_1_1);
7774 }
7775 } else {
7776 /*
7777 * 1.2 If the namespace [attribute] is not present, then the enclosing
7778 * <schema> must have a targetNamespace [attribute].
7779 */
7780 if (schema->targetNamespace == NULL) {
7781 xmlSchemaPCustomErr(ctxt,
7782 XML_SCHEMAP_SRC_IMPORT_1_2,
7783 NULL, NULL, node,
7784 "The attribute 'namespace' must be existent if "
7785 "the importing schema has no target namespace",
7786 NULL);
7787 return (XML_SCHEMAP_SRC_IMPORT_1_2);
7788 }
7789 }
William M. Brack2f2a6632004-08-20 23:09:47 +00007790 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007791 * Locate and aquire the schema document.
William M. Brack2f2a6632004-08-20 23:09:47 +00007792 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007793 ret = xmlSchemaAcquireSchemaDoc(ctxt, schema, node, namespace,
7794 schemaLocation, &doc, &targetNamespace, 0);
7795 if (ret != 0) {
7796 if (doc != NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00007797 xmlFreeDoc(doc);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007798 return (ret);
7799 } else if (doc != NULL) {
7800 /*
7801 * Save and reset the context & schema.
7802 */
7803 url = ctxt->URL;
7804 /* TODO: Is using the doc->URL here correct? */
7805 ctxt->URL = doc->URL;
7806 flags = schema->flags;
7807 oldTNS = schema->targetNamespace;
7808 /*
7809 * Parse the schema.
7810 */
7811 root = xmlDocGetRootElement(doc);
7812 xmlSchemaClearSchemaDefaults(schema);
7813 xmlSchemaParseSchemaDefaults(ctxt, schema, root);
7814 schema->targetNamespace = targetNamespace;
7815 xmlSchemaParseSchemaTopLevel(ctxt, schema, root->children);
7816 /*
7817 * Restore the context & schema.
7818 */
7819 schema->flags = flags;
7820 schema->targetNamespace = oldTNS;
7821 ctxt->URL = url;
William M. Brack2f2a6632004-08-20 23:09:47 +00007822 }
William M. Brack2f2a6632004-08-20 23:09:47 +00007823
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007824 return (0);
William M. Brack2f2a6632004-08-20 23:09:47 +00007825}
7826
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007827/**
7828 * xmlSchemaParseInclude:
7829 * @ctxt: a schema validation context
7830 * @schema: the schema being built
7831 * @node: a subtree containing XML Schema informations
7832 *
7833 * parse a XML schema Include definition
7834 *
William M. Bracke7091952004-05-11 15:09:58 +00007835 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007836 * 1 in case of success.
7837 */
7838static int
7839xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
7840 xmlNodePtr node)
7841{
7842 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007843 const xmlChar *schemaLocation, *targetNamespace;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007844 xmlDocPtr doc;
7845 xmlNodePtr root;
7846 xmlSchemaIncludePtr include;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007847 int wasConvertingNs = 0;
William M. Brack2f2a6632004-08-20 23:09:47 +00007848 xmlAttrPtr attr;
7849 int saveFlags;
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00007850 xmlParserCtxtPtr parserCtxt;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007851
7852
7853 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7854 return (-1);
7855
7856 /*
William M. Brack2f2a6632004-08-20 23:09:47 +00007857 * Check for illegal attributes.
7858 */
7859 attr = node->properties;
7860 while (attr != NULL) {
7861 if (attr->ns == NULL) {
7862 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7863 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
7864 xmlSchemaPIllegalAttrErr(ctxt,
7865 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7866 NULL, NULL, attr);
7867 }
7868 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7869 xmlSchemaPIllegalAttrErr(ctxt,
7870 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7871 NULL, NULL, attr);
7872 }
7873 attr = attr->next;
7874 }
7875 /*
7876 * Extract and validate attributes.
7877 */
7878 /*
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007879 * Preliminary step, extract the URI-Reference for the include and
7880 * make an URI from the base.
7881 */
William M. Brack2f2a6632004-08-20 23:09:47 +00007882 attr = xmlSchemaGetPropNode(node, "schemaLocation");
7883 if (attr != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007884 xmlChar *base = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00007885 xmlChar *uri = NULL;
7886
7887 if (xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
7888 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), &schemaLocation) != 0)
7889 return (-1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007890 base = xmlNodeGetBase(node->doc, node);
7891 if (base == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00007892 uri = xmlBuildURI(schemaLocation, node->doc->URL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007893 } else {
William M. Brack2f2a6632004-08-20 23:09:47 +00007894 uri = xmlBuildURI(schemaLocation, base);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007895 xmlFree(base);
7896 }
William M. Brack2f2a6632004-08-20 23:09:47 +00007897 if (uri != NULL) {
7898 schemaLocation = xmlDictLookup(ctxt->dict, uri, -1);
7899 xmlFree(uri);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007900 }
7901 } else {
William M. Brack2f2a6632004-08-20 23:09:47 +00007902 xmlSchemaPMissingAttrErr(ctxt,
7903 XML_SCHEMAP_INCLUDE_SCHEMA_NO_URI,
7904 NULL, NULL, node, "schemaLocation", NULL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007905 return (-1);
7906 }
William M. Brack2f2a6632004-08-20 23:09:47 +00007907 /*
7908 * And now for the children...
7909 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007910 child = node->children;
7911 while (IS_SCHEMA(child, "annotation")) {
7912 /*
7913 * the annotations here are simply discarded ...
7914 */
7915 child = child->next;
7916 }
7917 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00007918 xmlSchemaPContentErr(ctxt,
7919 XML_SCHEMAP_UNKNOWN_INCLUDE_CHILD,
7920 NULL, NULL, node, child, NULL,
7921 "(annotation?)");
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007922 }
7923
7924 /*
7925 * First step is to parse the input document into an DOM/Infoset
7926 */
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00007927 /*
7928 * TODO: Use xmlCtxtReadFile to share the dictionary.
7929 */
7930 parserCtxt = xmlNewParserCtxt();
7931 if (parserCtxt == NULL) {
7932 xmlSchemaPErrMemory(NULL, "xmlSchemaParseInclude: "
7933 "allocating a parser context", NULL);
7934 return(-1);
7935 }
7936
7937 if ((ctxt->dict != NULL) && (parserCtxt->dict != NULL)) {
7938 xmlDictFree(parserCtxt->dict);
7939 parserCtxt->dict = ctxt->dict;
7940 xmlDictReference(parserCtxt->dict);
7941 }
7942
7943 doc = xmlCtxtReadFile(parserCtxt, (const char *) schemaLocation,
7944 NULL, SCHEMAS_PARSE_OPTIONS);
7945 xmlFreeParserCtxt(parserCtxt);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007946 if (doc == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00007947 /*
7948 * TODO: It is not an error for the ·actual value· of the
7949 * schemaLocation [attribute] to fail to resolve it all, in which
7950 * case no corresponding inclusion is performed.
7951 * So do we need a warning report here?
7952 */
7953 xmlSchemaPCustomErr(ctxt,
7954 XML_SCHEMAP_FAILED_LOAD,
7955 NULL, NULL, node,
7956 "Failed to load the document '%s' for inclusion", schemaLocation);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007957 return(-1);
7958 }
7959
7960 /*
7961 * Then extract the root of the schema
7962 */
7963 root = xmlDocGetRootElement(doc);
7964 if (root == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00007965 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007966 XML_SCHEMAP_NOROOT,
William M. Brack2f2a6632004-08-20 23:09:47 +00007967 NULL, NULL, node,
7968 "The included document '%s' has no document "
7969 "element", schemaLocation);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007970 xmlFreeDoc(doc);
7971 return (-1);
7972 }
7973
7974 /*
7975 * Remove all the blank text nodes
7976 */
7977 xmlSchemaCleanupDoc(ctxt, root);
7978
7979 /*
7980 * Check the schemas top level element
7981 */
7982 if (!IS_SCHEMA(root, "schema")) {
William M. Brack2f2a6632004-08-20 23:09:47 +00007983 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007984 XML_SCHEMAP_NOT_SCHEMA,
William M. Brack2f2a6632004-08-20 23:09:47 +00007985 NULL, NULL, node,
7986 "The document '%s' to be included is not a schema document",
7987 schemaLocation);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007988 xmlFreeDoc(doc);
7989 return (-1);
7990 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00007991
William M. Brack2f2a6632004-08-20 23:09:47 +00007992 targetNamespace = xmlSchemaGetProp(ctxt, root, "targetNamespace");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007993 /*
7994 * 2.1 SII has a targetNamespace [attribute], and its ·actual
7995 * value· is identical to the ·actual value· of the targetNamespace
7996 * [attribute] of SIIÂ’ (which must have such an [attribute]).
7997 */
7998 if (targetNamespace != NULL) {
7999 if (schema->targetNamespace == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008000 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008001 XML_SCHEMAP_SRC_INCLUDE,
William M. Brack2f2a6632004-08-20 23:09:47 +00008002 NULL, NULL, node,
8003 "The target namespace of the included schema "
8004 "'%s' has to be absent, since the including schema "
8005 "has no target namespace",
8006 schemaLocation);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008007 xmlFreeDoc(doc);
8008 return (-1);
William M. Brack2f2a6632004-08-20 23:09:47 +00008009 } else if (!xmlStrEqual(targetNamespace, schema->targetNamespace)) {
8010 xmlSchemaPCustomErrExt(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008011 XML_SCHEMAP_SRC_INCLUDE,
William M. Brack2f2a6632004-08-20 23:09:47 +00008012 NULL, NULL, node,
8013 "The target namespace '%s' of the included schema '%s' "
8014 "differs from '%s' of the including schema",
8015 targetNamespace, schemaLocation, schema->targetNamespace);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008016 xmlFreeDoc(doc);
8017 return (-1);
8018 }
8019 } else if (schema->targetNamespace != NULL) {
8020 if ((schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) == 0) {
8021 schema->flags |= XML_SCHEMAS_INCLUDING_CONVERT_NS;
8022 } else
8023 wasConvertingNs = 1;
8024 }
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008025 /*
8026 * register the include
8027 */
8028 include = (xmlSchemaIncludePtr) xmlMalloc(sizeof(xmlSchemaInclude));
8029 if (include == NULL) {
8030 xmlSchemaPErrMemory(ctxt, "allocating included schema", NULL);
8031 xmlFreeDoc(doc);
8032 return (-1);
8033 }
8034
8035 memset(include, 0, sizeof(xmlSchemaInclude));
8036 include->schemaLocation = xmlDictLookup(ctxt->dict, schemaLocation, -1);
8037 include->doc = doc;
8038 include->next = schema->includes;
8039 schema->includes = include;
8040
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008041 /*
8042 * parse the declarations in the included file like if they
8043 * were in the original file.
Daniel Veillardc0826a72004-08-10 14:17:33 +00008044 */
8045 /*
William M. Brack2f2a6632004-08-20 23:09:47 +00008046 * TODO: The complete validation of the <schema> element is not done.
Daniel Veillardc0826a72004-08-10 14:17:33 +00008047 */
William M. Brack2f2a6632004-08-20 23:09:47 +00008048 /*
8049 * The default values ("blockDefault", "elementFormDefault", etc.)
8050 * are set to the values of the included schema and restored afterwards.
8051 */
8052 saveFlags = schema->flags;
8053 xmlSchemaClearSchemaDefaults(schema);
8054 xmlSchemaParseSchemaDefaults(ctxt, schema, root);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008055 xmlSchemaParseSchemaTopLevel(ctxt, schema, root->children);
William M. Brack2f2a6632004-08-20 23:09:47 +00008056 schema->flags = saveFlags;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008057 /*
8058 * Remove the converting flag.
8059 */
William M. Brack2f2a6632004-08-20 23:09:47 +00008060 if ((wasConvertingNs == 0) &&
8061 (schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS))
Daniel Veillardc0826a72004-08-10 14:17:33 +00008062 schema->flags ^= XML_SCHEMAS_INCLUDING_CONVERT_NS;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008063 return (1);
8064}
8065
8066/**
Daniel Veillard4255d502002-04-16 15:50:10 +00008067 * xmlSchemaParseChoice:
8068 * @ctxt: a schema validation context
8069 * @schema: the schema being built
8070 * @node: a subtree containing XML Schema informations
8071 *
8072 * parse a XML schema Choice definition
8073 * *WARNING* this interface is highly subject to change
8074 *
William M. Bracke7091952004-05-11 15:09:58 +00008075 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00008076 * 1 in case of success.
8077 */
8078static xmlSchemaTypePtr
8079xmlSchemaParseChoice(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008080 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00008081{
8082 xmlSchemaTypePtr type, subtype, last = NULL;
8083 xmlNodePtr child = NULL;
8084 xmlChar name[30];
William M. Brack2f2a6632004-08-20 23:09:47 +00008085 xmlAttrPtr attr;
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00008086 const xmlChar *oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00008087
8088 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8089 return (NULL);
8090
8091
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00008092 snprintf((char *) name, 30, "#ch%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00008093 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00008094 if (type == NULL)
8095 return (NULL);
8096 type->node = node;
8097 type->type = XML_SCHEMA_TYPE_CHOICE;
William M. Brack2f2a6632004-08-20 23:09:47 +00008098 /*
8099 * Check for illegal attributes.
8100 */
8101 attr = node->properties;
8102 while (attr != NULL) {
8103 if (attr->ns == NULL) {
8104 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8105 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
8106 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs"))) {
8107 xmlSchemaPIllegalAttrErr(ctxt,
8108 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8109 NULL, type, attr);
8110 }
8111 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8112 xmlSchemaPIllegalAttrErr(ctxt,
8113 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8114 NULL, type, attr);
8115 }
8116 attr = attr->next;
8117 }
8118 /*
8119 * Extract and validate attributes.
8120 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008121 type->id = xmlSchemaGetProp(ctxt, node, "id");
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00008122 type->minOccurs = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "nonNegativeInteger");
8123 type->maxOccurs = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
8124 "(nonNegativeInteger | unbounded)");
William M. Brack2f2a6632004-08-20 23:09:47 +00008125 /*
8126 * And now for the children...
8127 */
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00008128 oldcontainer = ctxt->container;
8129 ctxt->container = (const xmlChar *) name;
Daniel Veillard4255d502002-04-16 15:50:10 +00008130 child = node->children;
8131 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008132 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8133 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008134 }
8135 while ((IS_SCHEMA(child, "element")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008136 (IS_SCHEMA(child, "group")) ||
8137 (IS_SCHEMA(child, "any")) ||
8138 (IS_SCHEMA(child, "choice")) ||
8139 (IS_SCHEMA(child, "sequence"))) {
8140 subtype = NULL;
8141 if (IS_SCHEMA(child, "element")) {
8142 subtype = (xmlSchemaTypePtr)
8143 xmlSchemaParseElement(ctxt, schema, child, 0);
8144 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00008145 subtype = xmlSchemaParseGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008146 } else if (IS_SCHEMA(child, "any")) {
8147 subtype = xmlSchemaParseAny(ctxt, schema, child);
8148 } else if (IS_SCHEMA(child, "sequence")) {
8149 subtype = xmlSchemaParseSequence(ctxt, schema, child);
8150 } else if (IS_SCHEMA(child, "choice")) {
8151 subtype = xmlSchemaParseChoice(ctxt, schema, child);
8152 }
8153 if (subtype != NULL) {
8154 if (last == NULL) {
8155 type->subtypes = subtype;
8156 last = subtype;
8157 } else {
8158 last->next = subtype;
8159 last = subtype;
8160 }
8161 last->next = NULL;
8162 }
8163 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008164 }
8165 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008166 /* TODO: error code. */
8167 xmlSchemaPContentErr(ctxt,
8168 XML_SCHEMAP_UNKNOWN_CHOICE_CHILD,
8169 NULL, type, node, child, NULL,
8170 "(annotation?, (element | group | choice | sequence | any)*)");
Daniel Veillard4255d502002-04-16 15:50:10 +00008171 }
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00008172 ctxt->container = oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00008173 return (type);
8174}
8175
8176/**
8177 * xmlSchemaParseSequence:
8178 * @ctxt: a schema validation context
8179 * @schema: the schema being built
8180 * @node: a subtree containing XML Schema informations
8181 *
8182 * parse a XML schema Sequence definition
8183 * *WARNING* this interface is highly subject to change
8184 *
William M. Bracke7091952004-05-11 15:09:58 +00008185 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00008186 * 1 in case of success.
8187 */
8188static xmlSchemaTypePtr
8189xmlSchemaParseSequence(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008190 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00008191{
8192 xmlSchemaTypePtr type, subtype, last = NULL;
8193 xmlNodePtr child = NULL;
8194 xmlChar name[30];
William M. Brack2f2a6632004-08-20 23:09:47 +00008195 xmlAttrPtr attr;
8196 const xmlChar *oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00008197
8198 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8199 return (NULL);
8200
William M. Brack2f2a6632004-08-20 23:09:47 +00008201 oldcontainer = ctxt->container;
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00008202 snprintf((char *) name, 30, "#seq%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00008203 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00008204 if (type == NULL)
8205 return (NULL);
8206 type->node = node;
8207 type->type = XML_SCHEMA_TYPE_SEQUENCE;
William M. Brack2f2a6632004-08-20 23:09:47 +00008208 /*
8209 * Check for illegal attributes.
8210 */
8211 attr = node->properties;
8212 while (attr != NULL) {
8213 if (attr->ns == NULL) {
8214 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8215 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
8216 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs"))) {
8217 xmlSchemaPIllegalAttrErr(ctxt,
8218 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8219 NULL, type, attr);
8220 }
8221 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8222 xmlSchemaPIllegalAttrErr(ctxt,
8223 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8224 NULL, type, attr);
8225 }
8226 attr = attr->next;
8227 }
8228 /*
8229 * Extract and validate attributes.
8230 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008231 type->id = xmlSchemaGetProp(ctxt, node, "id");
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00008232 type->minOccurs = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "nonNegativeInteger");
8233 type->maxOccurs = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
8234 "(nonNegativeInteger | unbounded)");
William M. Brack2f2a6632004-08-20 23:09:47 +00008235 /*
8236 * And now for the children...
8237 */
8238 ctxt->container = (const xmlChar *) name;
Daniel Veillard4255d502002-04-16 15:50:10 +00008239 child = node->children;
8240 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008241 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8242 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008243 }
8244 while ((IS_SCHEMA(child, "element")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008245 (IS_SCHEMA(child, "group")) ||
8246 (IS_SCHEMA(child, "any")) ||
8247 (IS_SCHEMA(child, "choice")) ||
8248 (IS_SCHEMA(child, "sequence"))) {
8249 subtype = NULL;
8250 if (IS_SCHEMA(child, "element")) {
8251 subtype = (xmlSchemaTypePtr)
8252 xmlSchemaParseElement(ctxt, schema, child, 0);
8253 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00008254 subtype = xmlSchemaParseGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008255 } else if (IS_SCHEMA(child, "any")) {
8256 subtype = xmlSchemaParseAny(ctxt, schema, child);
8257 } else if (IS_SCHEMA(child, "choice")) {
8258 subtype = xmlSchemaParseChoice(ctxt, schema, child);
8259 } else if (IS_SCHEMA(child, "sequence")) {
8260 subtype = xmlSchemaParseSequence(ctxt, schema, child);
8261 }
8262 if (subtype != NULL) {
8263 if (last == NULL) {
8264 type->subtypes = subtype;
8265 last = subtype;
8266 } else {
8267 last->next = subtype;
8268 last = subtype;
8269 }
8270 last->next = NULL;
8271 }
8272 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008273 }
8274 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008275 xmlSchemaPContentErr(ctxt,
8276 XML_SCHEMAP_UNKNOWN_SEQUENCE_CHILD,
8277 NULL, type, node, child, NULL,
8278 "(annotation?, (element | group | choice | sequence | any)*)");
Daniel Veillard4255d502002-04-16 15:50:10 +00008279 }
William M. Brack2f2a6632004-08-20 23:09:47 +00008280 ctxt->container = oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00008281
8282 return (type);
8283}
8284
8285/**
8286 * xmlSchemaParseRestriction:
8287 * @ctxt: a schema validation context
8288 * @schema: the schema being built
8289 * @node: a subtree containing XML Schema informations
Daniel Veillard4255d502002-04-16 15:50:10 +00008290 *
8291 * parse a XML schema Restriction definition
8292 * *WARNING* this interface is highly subject to change
8293 *
8294 * Returns the type definition or NULL in case of error
8295 */
8296static xmlSchemaTypePtr
8297xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00008298 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00008299{
Daniel Veillard01fa6152004-06-29 17:04:39 +00008300 xmlSchemaTypePtr type, subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00008301 xmlNodePtr child = NULL;
8302 xmlChar name[30];
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008303 const xmlChar *oldcontainer;
William M. Brack2f2a6632004-08-20 23:09:47 +00008304 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00008305
8306 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8307 return (NULL);
8308
8309 oldcontainer = ctxt->container;
8310
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00008311 snprintf((char *) name, 30, "#restr%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00008312 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00008313 if (type == NULL)
8314 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00008315 type->type = XML_SCHEMA_TYPE_RESTRICTION;
Daniel Veillard4255d502002-04-16 15:50:10 +00008316 type->node = node;
William M. Brack2f2a6632004-08-20 23:09:47 +00008317 /*
8318 * Check for illegal attributes.
8319 */
8320 attr = node->properties;
8321 while (attr != NULL) {
8322 if (attr->ns == NULL) {
8323 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8324 (!xmlStrEqual(attr->name, BAD_CAST "base"))) {
8325 xmlSchemaPIllegalAttrErr(ctxt,
8326 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8327 NULL, type, attr);
8328 }
8329 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8330 xmlSchemaPIllegalAttrErr(ctxt,
8331 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8332 NULL, type, attr);
8333 }
8334 attr = attr->next;
8335 }
8336 /*
8337 * Extract and validate attributes.
8338 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008339 type->id = xmlSchemaGetProp(ctxt, node, "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00008340 /*
8341 * Attribute "base".
8342 */
Daniel Veillard4255d502002-04-16 15:50:10 +00008343 type->base = xmlGetQNameProp(ctxt, node, "base", &(type->baseNs));
Daniel Veillard01fa6152004-06-29 17:04:39 +00008344 if ((type->base == NULL) &&
William M. Brack2f2a6632004-08-20 23:09:47 +00008345 (ctxt->ctxtType->type == XML_SCHEMA_TYPE_COMPLEX)) {
8346 /* TODO: Think about the error code. */
8347 xmlSchemaPMissingAttrErr(ctxt,
8348 XML_SCHEMAP_RESTRICTION_NONAME_NOREF,
8349 NULL, type, node, "base", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00008350 }
William M. Brack2f2a6632004-08-20 23:09:47 +00008351 /*
8352 * And now for the children...
8353 */
Daniel Veillard4255d502002-04-16 15:50:10 +00008354 ctxt->container = name;
Daniel Veillard4255d502002-04-16 15:50:10 +00008355 child = node->children;
8356 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008357 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8358 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008359 }
8360 subtype = NULL;
Daniel Veillard01fa6152004-06-29 17:04:39 +00008361 if (ctxt->parentItem->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
8362 if (IS_SCHEMA(child, "all")) {
8363 subtype = (xmlSchemaTypePtr)
8364 xmlSchemaParseAll(ctxt, schema, child);
8365 child = child->next;
8366 type->subtypes = subtype;
8367 } else if (IS_SCHEMA(child, "choice")) {
8368 subtype = xmlSchemaParseChoice(ctxt, schema, child);
8369 child = child->next;
8370 type->subtypes = subtype;
8371 } else if (IS_SCHEMA(child, "sequence")) {
8372 subtype = (xmlSchemaTypePtr)
8373 xmlSchemaParseSequence(ctxt, schema, child);
8374 child = child->next;
8375 type->subtypes = subtype;
8376 } else if (IS_SCHEMA(child, "group")) {
8377 subtype = (xmlSchemaTypePtr)
8378 xmlSchemaParseGroup(ctxt, schema, child, 0);
8379 child = child->next;
8380 type->subtypes = subtype;
8381 }
William M. Brack2f2a6632004-08-20 23:09:47 +00008382 } else if (ctxt->ctxtType->type == XML_SCHEMA_TYPE_SIMPLE) {
8383 if (IS_SCHEMA(child, "simpleType")) {
8384 if (type->base != NULL) {
8385 /*
8386 * src-restriction-base-or-simpleType
8387 * Either the base [attribute] or the simpleType [child] of the
8388 * <restriction> element must be present, but not both.
8389 */
8390 xmlSchemaPContentErr(ctxt,
8391 XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
8392 NULL, NULL, type->node, child,
8393 "The attribute 'base' and the <simpleType> child are "
8394 "mutually exclusive", NULL);
8395 } else {
8396 subtype = (xmlSchemaTypePtr)
8397 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
8398 type->baseType = subtype;
8399 }
8400 child = child->next;
8401 }
8402 } else if (ctxt->parentItem->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
Daniel Veillard01fa6152004-06-29 17:04:39 +00008403 if (IS_SCHEMA(child, "simpleType")) {
8404 subtype = (xmlSchemaTypePtr)
8405 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
Daniel Veillard01fa6152004-06-29 17:04:39 +00008406 type->subtypes = subtype;
8407 child = child->next;
William M. Brack2f2a6632004-08-20 23:09:47 +00008408 }
8409 }
8410 if ((ctxt->ctxtType->type == XML_SCHEMA_TYPE_SIMPLE) ||
8411 (ctxt->parentItem->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT)) {
8412 xmlSchemaFacetPtr facet, lastfacet = NULL;
8413
Daniel Veillard01fa6152004-06-29 17:04:39 +00008414 /*
8415 * Add the facets to the parent simpleType/complexType.
8416 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00008417 /*
8418 * TODO: Datatypes: 4.1.3 Constraints on XML Representation of
8419 * Simple Type Definition Schema Representation Constraint:
8420 * *Single Facet Value*
8421 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00008422 while ((IS_SCHEMA(child, "minInclusive")) ||
8423 (IS_SCHEMA(child, "minExclusive")) ||
8424 (IS_SCHEMA(child, "maxInclusive")) ||
8425 (IS_SCHEMA(child, "maxExclusive")) ||
8426 (IS_SCHEMA(child, "totalDigits")) ||
8427 (IS_SCHEMA(child, "fractionDigits")) ||
8428 (IS_SCHEMA(child, "pattern")) ||
8429 (IS_SCHEMA(child, "enumeration")) ||
8430 (IS_SCHEMA(child, "whiteSpace")) ||
8431 (IS_SCHEMA(child, "length")) ||
8432 (IS_SCHEMA(child, "maxLength")) ||
8433 (IS_SCHEMA(child, "minLength"))) {
8434 facet = xmlSchemaParseFacet(ctxt, schema, child);
8435 if (facet != NULL) {
8436 if (lastfacet == NULL)
8437 ctxt->ctxtType->facets = facet;
8438 else
8439 lastfacet->next = facet;
8440 lastfacet = facet;
8441 lastfacet->next = NULL;
8442 }
8443 child = child->next;
8444 }
8445 /*
8446 * Create links for derivation and validation.
8447 */
8448 if (lastfacet != NULL) {
8449 xmlSchemaFacetLinkPtr facetLink, lastFacetLink = NULL;
8450
8451 facet = ctxt->ctxtType->facets;
8452 do {
8453 facetLink = (xmlSchemaFacetLinkPtr) xmlMalloc(sizeof(xmlSchemaFacetLink));
8454 if (facetLink == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008455 xmlSchemaPErrMemory(ctxt, "allocating a facet link", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00008456 xmlFree(facetLink);
8457 return (NULL);
8458 }
8459 facetLink->facet = facet;
8460 facetLink->next = NULL;
8461 if (lastFacetLink == NULL)
8462 ctxt->ctxtType->facetSet = facetLink;
8463 else
8464 lastFacetLink->next = facetLink;
8465 lastFacetLink = facetLink;
8466 facet = facet->next;
8467 } while (facet != NULL);
8468 }
8469 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008470 if (ctxt->ctxtType->type == XML_SCHEMA_TYPE_COMPLEX) {
8471 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
8472 if (IS_SCHEMA(child, "anyAttribute")) {
8473 ctxt->ctxtType->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
8474 child = child->next;
8475 }
8476 }
Daniel Veillard4255d502002-04-16 15:50:10 +00008477 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008478 /* TODO: Think about the error code. */
8479 if (ctxt->parentItem->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
8480 xmlSchemaPContentErr(ctxt,
8481 XML_SCHEMAP_UNKNOWN_RESTRICTION_CHILD,
8482 NULL, type, node, child, NULL,
8483 "annotation?, (group | all | choice | sequence)?, "
8484 "((attribute | attributeGroup)*, anyAttribute?))");
8485 } else if (ctxt->parentItem->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
8486 xmlSchemaPContentErr(ctxt,
8487 XML_SCHEMAP_UNKNOWN_RESTRICTION_CHILD,
8488 NULL, type, node, child, NULL,
8489 "(annotation?, (simpleType?, (minExclusive | minInclusive | "
8490 "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
8491 "length | minLength | maxLength | enumeration | whiteSpace | "
8492 "pattern)*)?, ((attribute | attributeGroup)*, anyAttribute?))");
8493 } else {
8494 /* Simple type */
8495 xmlSchemaPContentErr(ctxt,
8496 XML_SCHEMAP_UNKNOWN_RESTRICTION_CHILD,
8497 NULL, type, node, child, NULL,
8498 "(annotation?, (simpleType?, (minExclusive | minInclusive | "
8499 "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
8500 "length | minLength | maxLength | enumeration | whiteSpace | "
8501 "pattern)*))");
8502 }
8503 }
Daniel Veillard4255d502002-04-16 15:50:10 +00008504 ctxt->container = oldcontainer;
8505 return (type);
8506}
8507
8508/**
8509 * xmlSchemaParseExtension:
8510 * @ctxt: a schema validation context
8511 * @schema: the schema being built
8512 * @node: a subtree containing XML Schema informations
8513 *
8514 * parse a XML schema Extension definition
8515 * *WARNING* this interface is highly subject to change
8516 *
8517 * Returns the type definition or NULL in case of error
8518 */
8519static xmlSchemaTypePtr
8520xmlSchemaParseExtension(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008521 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00008522{
8523 xmlSchemaTypePtr type, subtype;
8524 xmlNodePtr child = NULL;
8525 xmlChar name[30];
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008526 const xmlChar *oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00008527
8528 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8529 return (NULL);
8530
8531 oldcontainer = ctxt->container;
8532
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00008533 snprintf((char *) name, 30, "#ext%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00008534 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00008535 if (type == NULL)
8536 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00008537 type->type = XML_SCHEMA_TYPE_EXTENSION;
Daniel Veillard4255d502002-04-16 15:50:10 +00008538 type->node = node;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008539 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00008540 ctxt->container = name;
8541
8542 type->base = xmlGetQNameProp(ctxt, node, "base", &(type->baseNs));
8543 if (type->base == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008544 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_EXTENSION_NO_BASE,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008545 "<extension>: The attribute \"base\" is missing.\n",
8546 type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00008547 }
8548 child = node->children;
8549 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008550 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8551 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008552 }
8553 subtype = NULL;
8554
8555 if (IS_SCHEMA(child, "all")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008556 subtype = xmlSchemaParseAll(ctxt, schema, child);
8557 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008558 } else if (IS_SCHEMA(child, "choice")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008559 subtype = xmlSchemaParseChoice(ctxt, schema, child);
8560 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008561 } else if (IS_SCHEMA(child, "sequence")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008562 subtype = xmlSchemaParseSequence(ctxt, schema, child);
8563 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008564 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00008565 subtype = xmlSchemaParseGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008566 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008567 }
8568 if (subtype != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008569 type->subtypes = subtype;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008570 if ((ctxt->ctxtType != NULL) &&
8571 (ctxt->ctxtType->type == XML_SCHEMA_TYPE_COMPLEX)) {
8572 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
8573 if (IS_SCHEMA(child, "anyAttribute")) {
8574 ctxt->ctxtType->attributeWildcard =
8575 xmlSchemaParseAnyAttribute(ctxt, schema, child);
8576 child = child->next;
8577 }
8578 }
Daniel Veillard4255d502002-04-16 15:50:10 +00008579 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008580 xmlSchemaPErr2(ctxt, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008581 XML_SCHEMAP_UNKNOWN_EXTENSION_CHILD,
8582 "<extension> has unexpected content.\n", type->name,
8583 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00008584 }
8585 ctxt->container = oldcontainer;
8586 return (type);
8587}
8588
8589/**
8590 * xmlSchemaParseSimpleContent:
8591 * @ctxt: a schema validation context
8592 * @schema: the schema being built
8593 * @node: a subtree containing XML Schema informations
8594 *
8595 * parse a XML schema SimpleContent definition
8596 * *WARNING* this interface is highly subject to change
8597 *
8598 * Returns the type definition or NULL in case of error
8599 */
8600static xmlSchemaTypePtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008601xmlSchemaParseSimpleContent(xmlSchemaParserCtxtPtr ctxt,
8602 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00008603{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008604 xmlSchemaTypePtr type, subtype, oldParentItem;
Daniel Veillard4255d502002-04-16 15:50:10 +00008605 xmlNodePtr child = NULL;
8606 xmlChar name[30];
8607
8608 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8609 return (NULL);
8610
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00008611 snprintf((char *) name, 30, "#SC%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00008612 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00008613 if (type == NULL)
8614 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00008615 type->type = XML_SCHEMA_TYPE_SIMPLE_CONTENT;
Daniel Veillard4255d502002-04-16 15:50:10 +00008616 type->node = node;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008617 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00008618
8619 child = node->children;
8620 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008621 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8622 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008623 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008624 oldParentItem = ctxt->parentItem;
Daniel Veillard01fa6152004-06-29 17:04:39 +00008625 ctxt->parentItem = type;
8626 subtype = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00008627 if (IS_SCHEMA(child, "restriction")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008628 subtype = (xmlSchemaTypePtr)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00008629 xmlSchemaParseRestriction(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008630 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008631 } else if (IS_SCHEMA(child, "extension")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008632 subtype = (xmlSchemaTypePtr)
8633 xmlSchemaParseExtension(ctxt, schema, child);
8634 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008635 }
8636 type->subtypes = subtype;
8637 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008638 xmlSchemaPErr2(ctxt, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008639 XML_SCHEMAP_UNKNOWN_SIMPLECONTENT_CHILD,
8640 "<simpleContent> has unexpected content.\n",
8641 NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00008642 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008643 ctxt->parentItem = oldParentItem;
Daniel Veillard4255d502002-04-16 15:50:10 +00008644 return (type);
8645}
8646
8647/**
8648 * xmlSchemaParseComplexContent:
8649 * @ctxt: a schema validation context
8650 * @schema: the schema being built
8651 * @node: a subtree containing XML Schema informations
8652 *
8653 * parse a XML schema ComplexContent definition
8654 * *WARNING* this interface is highly subject to change
8655 *
8656 * Returns the type definition or NULL in case of error
8657 */
8658static xmlSchemaTypePtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008659xmlSchemaParseComplexContent(xmlSchemaParserCtxtPtr ctxt,
8660 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00008661{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008662 xmlSchemaTypePtr type, subtype, oldParentItem;
Daniel Veillard4255d502002-04-16 15:50:10 +00008663 xmlNodePtr child = NULL;
8664 xmlChar name[30];
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008665 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00008666
8667 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8668 return (NULL);
8669
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00008670 snprintf((char *) name, 30, "#CC%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00008671 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00008672 if (type == NULL)
8673 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00008674 type->type = XML_SCHEMA_TYPE_COMPLEX_CONTENT;
Daniel Veillard01fa6152004-06-29 17:04:39 +00008675 type->node = node;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008676 /*
8677 * Check for illegal attributes.
8678 */
8679 attr = node->properties;
8680 while (attr != NULL) {
8681 if (attr->ns == NULL) {
8682 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8683 (!xmlStrEqual(attr->name, BAD_CAST "mixed")))
8684 {
8685 xmlSchemaPIllegalAttrErr(ctxt,
8686 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8687 NULL, NULL, attr);
8688 }
8689 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8690 xmlSchemaPIllegalAttrErr(ctxt,
8691 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8692 NULL, NULL, attr);
8693 }
8694 attr = attr->next;
8695 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008696 type->id = xmlSchemaGetProp(ctxt, node, "id");
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008697 /*
8698 * Handle attribute 'mixed'.
8699 */
8700 if (xmlGetBooleanProp(ctxt, NULL, type, node, "mixed", 0)) {
8701 if ((ctxt->ctxtType->flags & XML_SCHEMAS_TYPE_MIXED) == 0)
8702 ctxt->ctxtType->flags |= XML_SCHEMAS_TYPE_MIXED;
8703 }
Daniel Veillard4255d502002-04-16 15:50:10 +00008704 child = node->children;
8705 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008706 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8707 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008708 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008709 oldParentItem = ctxt->parentItem;
Daniel Veillard01fa6152004-06-29 17:04:39 +00008710 ctxt->parentItem = type;
Daniel Veillard4255d502002-04-16 15:50:10 +00008711 subtype = NULL;
8712 if (IS_SCHEMA(child, "restriction")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008713 subtype = (xmlSchemaTypePtr)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00008714 xmlSchemaParseRestriction(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008715 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008716 } else if (IS_SCHEMA(child, "extension")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008717 subtype = (xmlSchemaTypePtr)
8718 xmlSchemaParseExtension(ctxt, schema, child);
8719 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008720 }
8721 type->subtypes = subtype;
8722 if (child != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008723 xmlSchemaPContentErr(ctxt,
8724 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8725 NULL, NULL, node, child,
8726 NULL, "(annotation?, (restriction | extension))");
Daniel Veillard4255d502002-04-16 15:50:10 +00008727 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008728 ctxt->parentItem = oldParentItem;
Daniel Veillard4255d502002-04-16 15:50:10 +00008729 return (type);
8730}
8731
8732/**
8733 * xmlSchemaParseComplexType:
8734 * @ctxt: a schema validation context
8735 * @schema: the schema being built
8736 * @node: a subtree containing XML Schema informations
8737 *
8738 * parse a XML schema Complex Type definition
8739 * *WARNING* this interface is highly subject to change
8740 *
8741 * Returns the type definition or NULL in case of error
8742 */
8743static xmlSchemaTypePtr
8744xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00008745 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00008746{
Daniel Veillard01fa6152004-06-29 17:04:39 +00008747 xmlSchemaTypePtr type, subtype, ctxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +00008748 xmlNodePtr child = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008749 const xmlChar *name = NULL;
William M. Bracke7091952004-05-11 15:09:58 +00008750 const xmlChar *oldcontainer;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008751 xmlAttrPtr attr;
8752 const xmlChar *attrValue;
8753 xmlChar *des = NULL; /* The reported designation. */
Daniel Veillard1a380b82004-10-21 16:00:06 +00008754 char buf[40];
8755
Daniel Veillard4255d502002-04-16 15:50:10 +00008756
8757 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8758 return (NULL);
8759
Daniel Veillard01fa6152004-06-29 17:04:39 +00008760 ctxtType = ctxt->ctxtType;
8761
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008762 if (topLevel) {
8763 attr = xmlSchemaGetPropNode(node, "name");
8764 if (attr == NULL) {
8765 xmlSchemaPMissingAttrErr(ctxt,
8766 XML_SCHEMAP_S4S_ATTR_MISSING,
8767 (xmlChar **) &xmlSchemaElemDesCT, NULL, node,
8768 "name", NULL);
8769 return (NULL);
8770 } else if (xmlSchemaPValAttrNode(ctxt,
8771 (xmlChar **) &xmlSchemaElemDesCT, NULL, attr,
8772 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
8773 return (NULL);
8774 }
8775 }
8776
8777 if (topLevel == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008778 /*
8779 * Parse as local complex type definition.
8780 */
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00008781 snprintf(buf, 39, "#CT%d", ctxt->counter++ + 1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008782 type = xmlSchemaAddType(ctxt, schema, (const xmlChar *)buf, NULL, node);
8783 if (type == NULL)
8784 return (NULL);
8785 name = (const xmlChar *) buf;
8786 type->node = node;
8787 type->type = XML_SCHEMA_TYPE_COMPLEX;
8788 /*
8789 * TODO: We need the target namespace.
8790 */
8791 } else {
8792 /*
8793 * Parse as global complex type definition.
8794 */
William M. Brack2f2a6632004-08-20 23:09:47 +00008795 type = xmlSchemaAddType(ctxt, schema, name, schema->targetNamespace, node);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008796 if (type == NULL)
8797 return (NULL);
8798 type->node = node;
8799 type->type = XML_SCHEMA_TYPE_COMPLEX;
8800 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
8801 /*
8802 * Set defaults.
8803 */
8804 type->flags |= XML_SCHEMAS_TYPE_FINAL_DEFAULT;
8805 type->flags |= XML_SCHEMAS_TYPE_BLOCK_DEFAULT;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00008806 }
8807 type->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008808 /*
8809 * Handle attributes.
8810 */
8811 attr = node->properties;
8812 while (attr != NULL) {
8813 if (attr->ns == NULL) {
8814 if (xmlStrEqual(attr->name, BAD_CAST "id")) {
8815 /*
8816 * Attribute "id".
8817 */
8818 type->id = xmlSchemaGetProp(ctxt, node, "id");
8819 } else if (xmlStrEqual(attr->name, BAD_CAST "mixed")) {
8820 /*
8821 * Attribute "mixed".
8822 */
8823 if (xmlSchemaPGetBoolNodeValue(ctxt, &des, type,
8824 (xmlNodePtr) attr))
8825 type->flags |= XML_SCHEMAS_TYPE_MIXED;
8826 } else if (topLevel) {
8827 /*
8828 * Attributes of global complex type definitions.
8829 */
8830 if (xmlStrEqual(attr->name, BAD_CAST "name")) {
8831 /* Pass. */
8832 } else if (xmlStrEqual(attr->name, BAD_CAST "abstract")) {
8833 /*
8834 * Attribute "abstract".
8835 */
8836 if (xmlSchemaPGetBoolNodeValue(ctxt, &des, type,
8837 (xmlNodePtr) attr))
8838 type->flags |= XML_SCHEMAS_TYPE_ABSTRACT;
8839 } else if (xmlStrEqual(attr->name, BAD_CAST "final")) {
8840 /*
8841 * Attribute "final".
8842 */
8843 attrValue = xmlSchemaGetNodeContent(ctxt,
8844 (xmlNodePtr) attr);
8845 if (xmlSchemaPValAttrBlockFinal(attrValue,
8846 &(type->flags),
8847 -1,
8848 XML_SCHEMAS_TYPE_FINAL_EXTENSION,
8849 XML_SCHEMAS_TYPE_FINAL_RESTRICTION,
8850 -1, -1, -1) != 0)
8851 {
8852 xmlSchemaPSimpleTypeErr(ctxt,
8853 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8854 &des, type, (xmlNodePtr) attr,
8855 NULL,
8856 "(#all | List of (extension | restriction))",
8857 attrValue, NULL, NULL, NULL);
8858 }
8859 } else if (xmlStrEqual(attr->name, BAD_CAST "block")) {
8860 /*
8861 * Attribute "block".
8862 */
8863 attrValue = xmlSchemaGetNodeContent(ctxt,
8864 (xmlNodePtr) attr);
8865 if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
8866 -1,
8867 XML_SCHEMAS_TYPE_BLOCK_EXTENSION,
8868 XML_SCHEMAS_TYPE_BLOCK_RESTRICTION,
8869 -1, -1, -1) != 0) {
8870 xmlSchemaPSimpleTypeErr(ctxt,
8871 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8872 &des, type, (xmlNodePtr) attr,
8873 NULL,
8874 "(#all | List of (extension | restriction)) ",
8875 attrValue, NULL, NULL, NULL);
8876 }
8877 } else {
8878 xmlSchemaPIllegalAttrErr(ctxt,
8879 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8880 &des, type, attr);
8881 }
8882 } else {
8883 xmlSchemaPIllegalAttrErr(ctxt,
8884 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8885 &des, type, attr);
8886 }
8887 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8888 xmlSchemaPIllegalAttrErr(ctxt,
8889 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8890 &des, type, attr);
8891 }
8892 attr = attr->next;
8893 }
8894 /*
8895 * Set as default for attribute wildcards.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008896 * This will be only changed if a complex type
8897 * inherits an attribute wildcard from a base type.
8898 */
8899 type->flags |= XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008900 /*
8901 * And now for the children...
8902 */
8903 oldcontainer = ctxt->container;
8904 ctxt->container = name;
Daniel Veillard4255d502002-04-16 15:50:10 +00008905 child = node->children;
8906 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008907 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8908 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008909 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00008910 ctxt->ctxtType = type;
Daniel Veillard4255d502002-04-16 15:50:10 +00008911 if (IS_SCHEMA(child, "simpleContent")) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008912 /*
8913 * 3.4.3 : 2.2
8914 * Specifying mixed='true' when the <simpleContent>
8915 * alternative is chosen has no effect
8916 */
William M. Bracke7091952004-05-11 15:09:58 +00008917 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
8918 type->flags ^= XML_SCHEMAS_TYPE_MIXED;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008919 type->subtypes = xmlSchemaParseSimpleContent(ctxt, schema, child);
8920 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008921 } else if (IS_SCHEMA(child, "complexContent")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008922 type->subtypes = xmlSchemaParseComplexContent(ctxt, schema, child);
8923 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008924 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008925 subtype = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008926 /*
8927 * Parse model groups.
8928 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008929 if (IS_SCHEMA(child, "all")) {
8930 subtype = xmlSchemaParseAll(ctxt, schema, child);
8931 child = child->next;
8932 } else if (IS_SCHEMA(child, "choice")) {
8933 subtype = xmlSchemaParseChoice(ctxt, schema, child);
8934 child = child->next;
8935 } else if (IS_SCHEMA(child, "sequence")) {
8936 subtype = xmlSchemaParseSequence(ctxt, schema, child);
8937 child = child->next;
8938 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00008939 subtype = xmlSchemaParseGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008940 child = child->next;
8941 }
8942 if (subtype != NULL)
8943 type->subtypes = subtype;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008944 /*
8945 * Parse attribute decls/refs.
8946 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008947 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008948 /*
8949 * Parse attribute wildcard.
8950 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008951 if (IS_SCHEMA(child, "anyAttribute")) {
8952 type->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
8953 child = child->next;
8954 }
Daniel Veillard4255d502002-04-16 15:50:10 +00008955 }
8956 if (child != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008957 xmlSchemaPContentErr(ctxt,
8958 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8959 &des, type, node, child,
8960 NULL, "(annotation?, (simpleContent | complexContent | "
8961 "((group | all | choice | sequence)?, ((attribute | "
8962 "attributeGroup)*, anyAttribute?))))");
Daniel Veillard4255d502002-04-16 15:50:10 +00008963 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008964 FREE_AND_NULL(des);
Daniel Veillard4255d502002-04-16 15:50:10 +00008965 ctxt->container = oldcontainer;
Daniel Veillard01fa6152004-06-29 17:04:39 +00008966 ctxt->ctxtType = ctxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +00008967 return (type);
8968}
8969
Daniel Veillard4255d502002-04-16 15:50:10 +00008970/**
8971 * xmlSchemaParseSchema:
8972 * @ctxt: a schema validation context
8973 * @node: a subtree containing XML Schema informations
8974 *
8975 * parse a XML schema definition from a node set
8976 * *WARNING* this interface is highly subject to change
8977 *
8978 * Returns the internal XML Schema structure built from the resource or
8979 * NULL in case of error
8980 */
8981static xmlSchemaPtr
8982xmlSchemaParseSchema(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
8983{
8984 xmlSchemaPtr schema = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008985 const xmlChar *val;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00008986 int nberrors;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008987 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00008988
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008989 /*
8990 * This one is called by xmlSchemaParse only and is used if
8991 * the schema to be parsed was specified via the API; i.e. not
8992 * automatically by the validated instance document.
8993 */
Daniel Veillard4255d502002-04-16 15:50:10 +00008994 if ((ctxt == NULL) || (node == NULL))
8995 return (NULL);
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00008996 nberrors = ctxt->nberrors;
8997 ctxt->nberrors = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00008998 if (IS_SCHEMA(node, "schema")) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008999 xmlSchemaImportPtr import;
9000
Daniel Veillard4255d502002-04-16 15:50:10 +00009001 schema = xmlSchemaNewSchema(ctxt);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009002 if (schema == NULL)
9003 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009004 /*
9005 * Disable build of list of items.
9006 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00009007 attr = xmlSchemaGetPropNode(node, "targetNamespace");
9008 if (attr != NULL) {
9009 xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
9010 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), &val);
9011 /*
9012 * TODO: Should we proceed with an invalid target namespace?
9013 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00009014 schema->targetNamespace = xmlDictLookup(ctxt->dict, val, -1);
9015 } else {
9016 schema->targetNamespace = NULL;
9017 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009018 /*
9019 * Add the current ns name and location to the import table;
9020 * this is needed to have a consistent mechanism, regardless
9021 * if all schemata are constructed dynamically fired by the
9022 * instance or if the schema to be used was specified via
9023 * the API.
9024 */
9025 import = xmlSchemaAddImport(ctxt, &(schema->schemasImports),
9026 schema->targetNamespace);
9027 if (import == NULL) {
9028 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_FAILED_BUILD_IMPORT,
9029 NULL, NULL, (xmlNodePtr) ctxt->doc,
9030 "Internal error: xmlSchemaParseSchema, "
9031 "failed to add an import entry", NULL);
9032 xmlSchemaFree(schema);
9033 schema = NULL;
9034 return (NULL);
9035 }
9036 import->schemaLocation = ctxt->URL;
9037 /*
9038 * NOTE: We won't set the doc here, otherwise it will be freed
9039 * if the import struct is freed.
9040 * import->doc = ctxt->doc;
9041 */
9042
Daniel Veillardc0826a72004-08-10 14:17:33 +00009043 /* TODO: Check id. */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00009044 schema->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillardc0826a72004-08-10 14:17:33 +00009045 xmlSchemaPValAttr(ctxt, NULL, NULL, node, "version",
9046 xmlSchemaGetBuiltInType(XML_SCHEMAS_TOKEN), &(schema->version));
9047
William M. Brack2f2a6632004-08-20 23:09:47 +00009048 xmlSchemaParseSchemaDefaults(ctxt, schema, node);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009049 xmlSchemaParseSchemaTopLevel(ctxt, schema, node->children);
9050 } else {
9051 xmlDocPtr doc;
9052
9053 doc = node->doc;
9054
9055 if ((doc != NULL) && (doc->URL != NULL)) {
9056 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
9057 XML_SCHEMAP_NOT_SCHEMA,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009058 "The file \"%s\" is not a XML schema.\n", doc->URL, NULL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009059 } else {
9060 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
9061 XML_SCHEMAP_NOT_SCHEMA,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009062 "The file is not a XML schema.\n", NULL, NULL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009063 }
9064 return(NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00009065 }
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00009066 if (ctxt->nberrors != 0) {
9067 if (schema != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009068 xmlSchemaFree(schema);
9069 schema = NULL;
9070 }
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00009071 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009072 if (schema != NULL)
9073 schema->counter = ctxt->counter;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00009074 ctxt->nberrors = nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +00009075#ifdef DEBUG
9076 if (schema == NULL)
9077 xmlGenericError(xmlGenericErrorContext,
9078 "xmlSchemaParse() failed\n");
9079#endif
Daniel Veillard4255d502002-04-16 15:50:10 +00009080 return (schema);
9081}
9082
9083/************************************************************************
9084 * *
9085 * Validating using Schemas *
9086 * *
9087 ************************************************************************/
9088
9089/************************************************************************
9090 * *
9091 * Reading/Writing Schemas *
9092 * *
9093 ************************************************************************/
9094
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009095#if 0 /* Will be enabled if it is clear what options are needed. */
9096/**
9097 * xmlSchemaParserCtxtSetOptions:
9098 * @ctxt: a schema parser context
9099 * @options: a combination of xmlSchemaParserOption
9100 *
9101 * Sets the options to be used during the parse.
9102 *
9103 * Returns 0 in case of success, -1 in case of an
9104 * API error.
9105 */
9106static int
9107xmlSchemaParserCtxtSetOptions(xmlSchemaParserCtxtPtr ctxt,
9108 int options)
9109
9110{
9111 int i;
9112
9113 if (ctxt == NULL)
9114 return (-1);
9115 /*
9116 * WARNING: Change the start value if adding to the
9117 * xmlSchemaParseOption.
9118 */
9119 for (i = 1; i < (int) sizeof(int) * 8; i++) {
9120 if (options & 1<<i) {
9121 return (-1);
9122 }
9123 }
9124 ctxt->options = options;
9125 return (0);
9126}
9127
9128/**
9129 * xmlSchemaValidCtxtGetOptions:
9130 * @ctxt: a schema parser context
9131 *
9132 * Returns the option combination of the parser context.
9133 */
9134static int
9135xmlSchemaParserCtxtGetOptions(xmlSchemaParserCtxtPtr ctxt)
9136
9137{
9138 if (ctxt == NULL)
9139 return (-1);
9140 else
9141 return (ctxt->options);
9142}
9143
9144 void *curItems; /* used for dynamic addition of schemata */
9145 int nbCurItems; /* used for dynamic addition of schemata */
9146 int sizeCurItems; /* used for dynamic addition of schemata */
9147
9148#endif
9149
Daniel Veillard4255d502002-04-16 15:50:10 +00009150/**
9151 * xmlSchemaNewParserCtxt:
9152 * @URL: the location of the schema
9153 *
9154 * Create an XML Schemas parse context for that file/resource expected
9155 * to contain an XML Schemas file.
9156 *
9157 * Returns the parser context or NULL in case of error
9158 */
9159xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009160xmlSchemaNewParserCtxt(const char *URL)
9161{
Daniel Veillard4255d502002-04-16 15:50:10 +00009162 xmlSchemaParserCtxtPtr ret;
9163
9164 if (URL == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009165 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00009166
9167 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
9168 if (ret == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009169 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009170 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00009171 return (NULL);
9172 }
9173 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00009174 ret->dict = xmlDictCreate();
9175 ret->URL = xmlDictLookup(ret->dict, (const xmlChar *) URL, -1);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00009176 ret->includes = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00009177 return (ret);
9178}
9179
9180/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009181 * xmlSchemaNewParserCtxtUseDict:
9182 * @URL: the location of the schema
9183 * @dict: the dictionary to be used
9184 *
9185 * Create an XML Schemas parse context for that file/resource expected
9186 * to contain an XML Schemas file.
9187 *
9188 * Returns the parser context or NULL in case of error
9189 */
9190static xmlSchemaParserCtxtPtr
9191xmlSchemaNewParserCtxtUseDict(const char *URL, xmlDictPtr dict)
9192{
9193 xmlSchemaParserCtxtPtr ret;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009194 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009195 if (URL == NULL)
9196 return (NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009197 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009198
9199 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
9200 if (ret == NULL) {
9201 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
9202 NULL);
9203 return (NULL);
9204 }
9205 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
9206 ret->dict = dict;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009207 xmlDictReference(dict);
9208 if (URL != NULL)
9209 ret->URL = xmlDictLookup(dict, (const xmlChar *) URL, -1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009210 ret->includes = 0;
9211 return (ret);
9212}
9213
9214
9215/**
Daniel Veillard6045c902002-10-09 21:13:59 +00009216 * xmlSchemaNewMemParserCtxt:
9217 * @buffer: a pointer to a char array containing the schemas
9218 * @size: the size of the array
9219 *
9220 * Create an XML Schemas parse context for that memory buffer expected
9221 * to contain an XML Schemas file.
9222 *
9223 * Returns the parser context or NULL in case of error
9224 */
9225xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009226xmlSchemaNewMemParserCtxt(const char *buffer, int size)
9227{
Daniel Veillard6045c902002-10-09 21:13:59 +00009228 xmlSchemaParserCtxtPtr ret;
9229
9230 if ((buffer == NULL) || (size <= 0))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009231 return (NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +00009232
9233 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
9234 if (ret == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009235 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009236 NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +00009237 return (NULL);
9238 }
9239 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
9240 ret->buffer = buffer;
9241 ret->size = size;
William M. Brackcf9eadf2003-12-25 13:24:05 +00009242 ret->dict = xmlDictCreate();
Daniel Veillard6045c902002-10-09 21:13:59 +00009243 return (ret);
9244}
9245
9246/**
Daniel Veillard9d751502003-10-29 13:21:47 +00009247 * xmlSchemaNewDocParserCtxt:
9248 * @doc: a preparsed document tree
9249 *
9250 * Create an XML Schemas parse context for that document.
9251 * NB. The document may be modified during the parsing process.
9252 *
9253 * Returns the parser context or NULL in case of error
9254 */
9255xmlSchemaParserCtxtPtr
9256xmlSchemaNewDocParserCtxt(xmlDocPtr doc)
9257{
9258 xmlSchemaParserCtxtPtr ret;
9259
9260 if (doc == NULL)
9261 return (NULL);
9262
9263 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
9264 if (ret == NULL) {
9265 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
9266 NULL);
9267 return (NULL);
9268 }
9269 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
9270 ret->doc = doc;
William M. Brackcf9eadf2003-12-25 13:24:05 +00009271 ret->dict = xmlDictCreate();
Daniel Veillarddda22c12004-01-24 08:31:30 +00009272 /* The application has responsibility for the document */
9273 ret->preserve = 1;
Daniel Veillard9d751502003-10-29 13:21:47 +00009274
9275 return (ret);
9276}
9277
9278/**
Daniel Veillard4255d502002-04-16 15:50:10 +00009279 * xmlSchemaFreeParserCtxt:
9280 * @ctxt: the schema parser context
9281 *
9282 * Free the resources associated to the schema parser context
9283 */
9284void
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009285xmlSchemaFreeParserCtxt(xmlSchemaParserCtxtPtr ctxt)
9286{
Daniel Veillard4255d502002-04-16 15:50:10 +00009287 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009288 return;
Daniel Veillarddda22c12004-01-24 08:31:30 +00009289 if (ctxt->doc != NULL && !ctxt->preserve)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009290 xmlFreeDoc(ctxt->doc);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009291 if (ctxt->assemble != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009292 xmlFree((xmlSchemaTypePtr *) ctxt->assemble->items);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009293 xmlFree(ctxt->assemble);
9294 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009295 if (ctxt->vctxt != NULL) {
9296 xmlSchemaFreeValidCtxt(ctxt->vctxt);
9297 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00009298 xmlDictFree(ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00009299 xmlFree(ctxt);
9300}
9301
9302/************************************************************************
9303 * *
9304 * Building the content models *
9305 * *
9306 ************************************************************************/
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009307
Daniel Veillard4255d502002-04-16 15:50:10 +00009308/**
9309 * xmlSchemaBuildAContentModel:
9310 * @type: the schema type definition
9311 * @ctxt: the schema parser context
9312 * @name: the element name whose content is being built
9313 *
9314 * Generate the automata sequence needed for that type
9315 */
9316static void
9317xmlSchemaBuildAContentModel(xmlSchemaTypePtr type,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009318 xmlSchemaParserCtxtPtr ctxt,
9319 const xmlChar * name)
9320{
Daniel Veillard4255d502002-04-16 15:50:10 +00009321 if (type == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009322 xmlGenericError(xmlGenericErrorContext,
9323 "Found unexpected type = NULL in %s content model\n",
9324 name);
9325 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00009326 }
9327 switch (type->type) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009328 case XML_SCHEMA_TYPE_ANY: {
9329 xmlAutomataStatePtr start, end;
9330 xmlSchemaWildcardPtr wild;
9331 xmlSchemaWildcardNsPtr ns;
Daniel Veillard32370232002-10-16 14:08:14 +00009332
Daniel Veillardc0826a72004-08-10 14:17:33 +00009333 wild = type->attributeWildcard;
9334
9335 if (wild == NULL) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00009336 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009337 "Internal error: xmlSchemaBuildAContentModel, "
9338 "no wildcard on xsd:any.\n", NULL, NULL);
9339 return;
9340 }
9341
9342 start = ctxt->state;
9343 end = xmlAutomataNewState(ctxt->am);
9344
9345 if (type->maxOccurs == 1) {
9346 if (wild->any == 1) {
9347 /*
9348 * We need to add both transitions:
9349 *
9350 * 1. the {"*", "*"} for elements in a namespace.
9351 */
9352 ctxt->state =
9353 xmlAutomataNewTransition2(ctxt->am,
9354 start, NULL, BAD_CAST "*", BAD_CAST "*", type);
9355 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
9356 /*
9357 * 2. the {"*"} for elements in no namespace.
9358 */
9359 ctxt->state =
9360 xmlAutomataNewTransition2(ctxt->am,
9361 start, NULL, BAD_CAST "*", NULL, type);
9362 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
9363
9364 } else if (wild->nsSet != NULL) {
9365 ns = wild->nsSet;
9366 do {
9367 ctxt->state = start;
9368 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
9369 ctxt->state, NULL, BAD_CAST "*", ns->value, type);
9370 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
9371 ns = ns->next;
9372 } while (ns != NULL);
9373
9374 } else if (wild->negNsSet != NULL) {
9375 xmlAutomataStatePtr deadEnd;
9376
9377 deadEnd = xmlAutomataNewState(ctxt->am);
9378 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
9379 start, deadEnd, BAD_CAST "*", wild->negNsSet->value, type);
9380 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
9381 start, NULL, BAD_CAST "*", BAD_CAST "*", type);
9382 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
9383 }
9384 } else {
9385 int counter;
9386 xmlAutomataStatePtr hop;
9387 int maxOccurs =
9388 type->maxOccurs == UNBOUNDED ? UNBOUNDED : type->maxOccurs - 1;
9389 int minOccurs =
9390 type->minOccurs < 1 ? 0 : type->minOccurs - 1;
9391
9392 counter = xmlAutomataNewCounter(ctxt->am, minOccurs, maxOccurs);
9393 hop = xmlAutomataNewState(ctxt->am);
9394 if (wild->any == 1) {
9395 ctxt->state =
9396 xmlAutomataNewTransition2(ctxt->am,
9397 start, NULL, BAD_CAST "*", BAD_CAST "*", type);
9398 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
9399 ctxt->state =
9400 xmlAutomataNewTransition2(ctxt->am,
9401 start, NULL, BAD_CAST "*", NULL, type);
9402 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
9403 } else if (wild->nsSet != NULL) {
9404 ns = wild->nsSet;
9405 do {
9406 ctxt->state =
9407 xmlAutomataNewTransition2(ctxt->am,
9408 start, NULL, BAD_CAST "*", ns->value, type);
9409 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
9410 ns = ns->next;
9411 } while (ns != NULL);
9412
9413 } else if (wild->negNsSet != NULL) {
9414 xmlAutomataStatePtr deadEnd;
9415
9416 deadEnd = xmlAutomataNewState(ctxt->am);
9417 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
9418 start, deadEnd, BAD_CAST "*", wild->negNsSet->value, type);
9419 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
9420 start, NULL, BAD_CAST "*", BAD_CAST "*", type);
9421 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
9422 }
9423 xmlAutomataNewCountedTrans(ctxt->am, hop, start, counter);
9424 xmlAutomataNewCounterTrans(ctxt->am, hop, end, counter);
9425 }
9426 if (type->minOccurs == 0) {
9427 xmlAutomataNewEpsilon(ctxt->am, start, end);
9428 }
9429 ctxt->state = end;
9430 break;
9431 }
9432 case XML_SCHEMA_TYPE_ELEMENT:{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009433 xmlAutomataStatePtr oldstate;
9434 xmlSchemaElementPtr particle, elemDecl;
Daniel Veillard32370232002-10-16 14:08:14 +00009435
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009436 /*
9437 * IMPORTANT: This puts element declarations
9438 * (and never element decl. references) into the
9439 * automaton. This is crucial and should not be changed,
9440 * since validating functions rely now on it.
9441 */
9442 particle = (xmlSchemaElementPtr) type;
9443 if (particle->ref != NULL) {
9444 if (particle->refDecl == NULL) {
9445 /*
9446 * Skip content model creation if the reference
9447 * did not resolve to a declaration.
9448 */
9449 break;
9450 } else {
9451 /*
9452 * Referenced global element declaration.
9453 */
9454 elemDecl = particle->refDecl;
9455 }
9456 } else {
9457 /*
9458 * Anonymous element declaration.
9459 */
9460 elemDecl = particle;
9461 }
9462
9463 oldstate = ctxt->state;
9464
9465 if (particle->maxOccurs >= UNBOUNDED) {
9466 if (particle->minOccurs > 1) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009467 xmlAutomataStatePtr tmp;
9468 int counter;
Daniel Veillard32370232002-10-16 14:08:14 +00009469
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009470 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009471 oldstate, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009472 oldstate = ctxt->state;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009473 counter = xmlAutomataNewCounter(ctxt->am,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009474 particle->minOccurs - 1, UNBOUNDED);
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00009475 ctxt->state =
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009476 xmlAutomataNewTransition2(ctxt->am,
9477 ctxt->state, NULL,
9478 elemDecl->name,
9479 elemDecl->targetNamespace,
9480 (xmlSchemaTypePtr) elemDecl);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009481 tmp = ctxt->state;
9482 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009483 counter);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009484 ctxt->state =
9485 xmlAutomataNewCounterTrans(ctxt->am, tmp, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009486 counter);
Daniel Veillard32370232002-10-16 14:08:14 +00009487
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009488 } else {
9489 ctxt->state =
9490 xmlAutomataNewTransition2(ctxt->am,
9491 ctxt->state, NULL,
9492 elemDecl->name,
9493 elemDecl->targetNamespace,
9494 (xmlSchemaTypePtr) elemDecl);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009495 xmlAutomataNewEpsilon(ctxt->am, ctxt->state,
9496 oldstate);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009497 if (particle->minOccurs == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009498 /* basically an elem* */
9499 xmlAutomataNewEpsilon(ctxt->am, oldstate,
9500 ctxt->state);
9501 }
9502 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009503 } else if ((particle->maxOccurs > 1) || (particle->minOccurs > 1)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009504 xmlAutomataStatePtr tmp;
9505 int counter;
Daniel Veillard32370232002-10-16 14:08:14 +00009506
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009507 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
9508 oldstate, NULL);
9509 oldstate = ctxt->state;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009510 counter = xmlAutomataNewCounter(ctxt->am,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009511 particle->minOccurs - 1,
9512 particle->maxOccurs - 1);
9513 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
9514 ctxt->state,
9515 NULL,
9516 elemDecl->name,
9517 elemDecl->targetNamespace,
9518 (xmlSchemaTypePtr) elemDecl);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009519 tmp = ctxt->state;
9520 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009521 counter);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009522 ctxt->state = xmlAutomataNewCounterTrans(ctxt->am, tmp,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009523 NULL, counter);
9524 if (particle->minOccurs == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009525 /* basically an elem? */
9526 xmlAutomataNewEpsilon(ctxt->am, oldstate,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009527 ctxt->state);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009528 }
Daniel Veillardb39bc392002-10-26 19:29:51 +00009529
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009530 } else {
9531 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
9532 ctxt->state,
9533 NULL,
9534 elemDecl->name,
9535 elemDecl->targetNamespace,
9536 (xmlSchemaTypePtr) elemDecl);
9537 if (particle->minOccurs == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009538 /* basically an elem? */
9539 xmlAutomataNewEpsilon(ctxt->am, oldstate,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009540 ctxt->state);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009541 }
9542 }
9543 break;
9544 }
9545 case XML_SCHEMA_TYPE_SEQUENCE:{
9546 xmlSchemaTypePtr subtypes;
Daniel Veillardb39bc392002-10-26 19:29:51 +00009547
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009548 /*
9549 * If max and min occurances are default (1) then
9550 * simply iterate over the subtypes
9551 */
9552 if ((type->minOccurs == 1) && (type->maxOccurs == 1)) {
9553 subtypes = type->subtypes;
9554 while (subtypes != NULL) {
9555 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
9556 subtypes = subtypes->next;
9557 }
9558 } else {
9559 xmlAutomataStatePtr oldstate = ctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +00009560
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009561 if (type->maxOccurs >= UNBOUNDED) {
9562 if (type->minOccurs > 1) {
9563 xmlAutomataStatePtr tmp;
9564 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +00009565
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009566 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
9567 oldstate,
9568 NULL);
9569 oldstate = ctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +00009570
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009571 counter = xmlAutomataNewCounter(ctxt->am,
9572 type->
9573 minOccurs - 1,
9574 UNBOUNDED);
Daniel Veillardb39bc392002-10-26 19:29:51 +00009575
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009576 subtypes = type->subtypes;
9577 while (subtypes != NULL) {
9578 xmlSchemaBuildAContentModel(subtypes, ctxt,
9579 name);
9580 subtypes = subtypes->next;
9581 }
9582 tmp = ctxt->state;
9583 xmlAutomataNewCountedTrans(ctxt->am, tmp,
9584 oldstate, counter);
9585 ctxt->state =
9586 xmlAutomataNewCounterTrans(ctxt->am, tmp,
9587 NULL, counter);
Daniel Veillardb39bc392002-10-26 19:29:51 +00009588
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009589 } else {
9590 subtypes = type->subtypes;
9591 while (subtypes != NULL) {
9592 xmlSchemaBuildAContentModel(subtypes, ctxt,
9593 name);
9594 subtypes = subtypes->next;
9595 }
9596 xmlAutomataNewEpsilon(ctxt->am, ctxt->state,
9597 oldstate);
9598 if (type->minOccurs == 0) {
9599 xmlAutomataNewEpsilon(ctxt->am, oldstate,
9600 ctxt->state);
9601 }
9602 }
9603 } else if ((type->maxOccurs > 1)
9604 || (type->minOccurs > 1)) {
9605 xmlAutomataStatePtr tmp;
9606 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +00009607
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009608 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
9609 oldstate,
9610 NULL);
9611 oldstate = ctxt->state;
Daniel Veillard4255d502002-04-16 15:50:10 +00009612
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009613 counter = xmlAutomataNewCounter(ctxt->am,
9614 type->minOccurs -
9615 1,
9616 type->maxOccurs -
9617 1);
Daniel Veillard4255d502002-04-16 15:50:10 +00009618
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009619 subtypes = type->subtypes;
9620 while (subtypes != NULL) {
9621 xmlSchemaBuildAContentModel(subtypes, ctxt,
9622 name);
9623 subtypes = subtypes->next;
9624 }
9625 tmp = ctxt->state;
9626 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
9627 counter);
9628 ctxt->state =
9629 xmlAutomataNewCounterTrans(ctxt->am, tmp, NULL,
9630 counter);
9631 if (type->minOccurs == 0) {
9632 xmlAutomataNewEpsilon(ctxt->am, oldstate,
9633 ctxt->state);
9634 }
Daniel Veillardb509f152002-04-17 16:28:10 +00009635
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009636 } else {
9637 subtypes = type->subtypes;
9638 while (subtypes != NULL) {
9639 xmlSchemaBuildAContentModel(subtypes, ctxt,
9640 name);
9641 subtypes = subtypes->next;
9642 }
9643 if (type->minOccurs == 0) {
9644 xmlAutomataNewEpsilon(ctxt->am, oldstate,
9645 ctxt->state);
9646 }
9647 }
9648 }
9649 break;
9650 }
9651 case XML_SCHEMA_TYPE_CHOICE:{
9652 xmlSchemaTypePtr subtypes;
9653 xmlAutomataStatePtr start, end;
Daniel Veillardb509f152002-04-17 16:28:10 +00009654
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009655 start = ctxt->state;
9656 end = xmlAutomataNewState(ctxt->am);
Daniel Veillard7646b182002-04-20 06:41:40 +00009657
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009658 /*
9659 * iterate over the subtypes and remerge the end with an
9660 * epsilon transition
9661 */
9662 if (type->maxOccurs == 1) {
9663 subtypes = type->subtypes;
9664 while (subtypes != NULL) {
9665 ctxt->state = start;
9666 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
9667 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
9668 subtypes = subtypes->next;
9669 }
9670 } else {
9671 int counter;
9672 xmlAutomataStatePtr hop;
9673 int maxOccurs = type->maxOccurs == UNBOUNDED ?
9674 UNBOUNDED : type->maxOccurs - 1;
9675 int minOccurs =
9676 type->minOccurs < 1 ? 0 : type->minOccurs - 1;
Daniel Veillard7646b182002-04-20 06:41:40 +00009677
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009678 /*
9679 * use a counter to keep track of the number of transtions
9680 * which went through the choice.
9681 */
9682 counter =
9683 xmlAutomataNewCounter(ctxt->am, minOccurs,
9684 maxOccurs);
9685 hop = xmlAutomataNewState(ctxt->am);
Daniel Veillard6231e842002-04-18 11:54:04 +00009686
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009687 subtypes = type->subtypes;
9688 while (subtypes != NULL) {
9689 ctxt->state = start;
9690 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
9691 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
9692 subtypes = subtypes->next;
9693 }
9694 xmlAutomataNewCountedTrans(ctxt->am, hop, start,
9695 counter);
9696 xmlAutomataNewCounterTrans(ctxt->am, hop, end,
9697 counter);
9698 }
9699 if (type->minOccurs == 0) {
9700 xmlAutomataNewEpsilon(ctxt->am, start, end);
9701 }
9702 ctxt->state = end;
9703 break;
9704 }
9705 case XML_SCHEMA_TYPE_ALL:{
9706 xmlAutomataStatePtr start;
9707 xmlSchemaTypePtr subtypes;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009708
Daniel Veillard3646d642004-06-02 19:19:14 +00009709 xmlSchemaElementPtr elem;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009710 int lax;
9711
9712 subtypes = type->subtypes;
9713 if (subtypes == NULL)
9714 break;
9715 start = ctxt->state;
9716 while (subtypes != NULL) {
9717 ctxt->state = start;
William M. Brack9989c7d2004-05-12 14:39:38 +00009718 /*
9719 * the following 'if' was needed to fix bug 139897
9720 * not quite sure why it only needs to be done for
9721 * elements with a 'ref', but it seems to work ok.
9722 */
9723 if (subtypes->ref != NULL)
9724 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009725 elem = (xmlSchemaElementPtr) subtypes;
9726 /*
9727 * NOTE: The {max occurs} of all the particles in the
9728 * {particles} of the group must be 0 or 1.
9729 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009730 if ((elem->minOccurs == 1) && (elem->maxOccurs == 1)) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009731 xmlAutomataNewOnceTrans2(ctxt->am, ctxt->state,
9732 ctxt->state,
9733 elem->name,
9734 elem->targetNamespace,
9735 1, 1, subtypes);
9736 } else if ((elem->minOccurs == 0) &&
9737 (elem->maxOccurs == 1)) {
9738
9739 xmlAutomataNewCountTrans2(ctxt->am, ctxt->state,
9740 ctxt->state,
9741 elem->name,
9742 elem->targetNamespace,
9743 0,
9744 1,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009745 subtypes);
9746 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009747 /*
9748 * NOTE: if maxOccurs == 0 then no transition will be
9749 * created.
9750 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009751 subtypes = subtypes->next;
9752 }
9753 lax = type->minOccurs == 0;
9754 ctxt->state =
9755 xmlAutomataNewAllTrans(ctxt->am, ctxt->state, NULL,
9756 lax);
9757 break;
9758 }
9759 case XML_SCHEMA_TYPE_RESTRICTION:
9760 if (type->subtypes != NULL)
9761 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
9762 break;
9763 case XML_SCHEMA_TYPE_EXTENSION:
9764 if (type->baseType != NULL) {
9765 xmlSchemaTypePtr subtypes;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009766
9767 /*
9768 * TODO: Circular definitions will be checked at the
9769 * constraint level. So remove this when the complex type
9770 * constraints are implemented.
9771 */
Daniel Veillardf7627552004-04-22 07:15:40 +00009772 if (type->recurse) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009773 /* TODO: Change the error code. */
9774 xmlSchemaPCustomErr(ctxt,
9775 XML_SCHEMAP_UNKNOWN_BASE_TYPE,
9776 NULL, type, type->node,
9777 "This item is circular", NULL);
Daniel Veillardf7627552004-04-22 07:15:40 +00009778 return;
9779 }
9780 type->recurse = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009781 xmlSchemaBuildAContentModel(type->baseType, ctxt, name);
Daniel Veillardf7627552004-04-22 07:15:40 +00009782 type->recurse = 0;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009783 subtypes = type->subtypes;
9784 while (subtypes != NULL) {
9785 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
9786 subtypes = subtypes->next;
9787 }
9788 } else if (type->subtypes != NULL)
9789 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
9790 break;
9791 case XML_SCHEMA_TYPE_GROUP:
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00009792 /*
9793 * Handle model group definition references.
9794 * NOTE: type->subtypes is the referenced model grop definition;
9795 * and type->subtypes->subtypes is the model group (i.e. <all> or
9796 * <choice> or <sequence>).
9797 */
9798 if ((type->ref != NULL) && (type->subtypes != NULL) &&
9799 (type->subtypes->subtypes != NULL)) {
9800 xmlSchemaTypePtr modelGr;
9801 xmlAutomataStatePtr start, end;
9802
9803 modelGr = type->subtypes->subtypes;
9804 start = ctxt->state;
9805 end = xmlAutomataNewState(ctxt->am);
9806 if (type->maxOccurs == 1) {
9807 ctxt->state = start;
9808 xmlSchemaBuildAContentModel(modelGr, ctxt, name);
9809 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
9810 } else {
9811 int counter;
9812 xmlAutomataStatePtr hop;
9813 int maxOccurs = type->maxOccurs == UNBOUNDED ?
9814 UNBOUNDED : type->maxOccurs - 1;
9815 int minOccurs =
9816 type->minOccurs < 1 ? 0 : type->minOccurs - 1;
9817
9818 counter =
9819 xmlAutomataNewCounter(ctxt->am, minOccurs, maxOccurs);
9820 hop = xmlAutomataNewState(ctxt->am);
9821 ctxt->state = start;
9822 xmlSchemaBuildAContentModel(modelGr, ctxt, name);
9823 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
9824 xmlAutomataNewCountedTrans(ctxt->am, hop, start,
9825 counter);
9826 xmlAutomataNewCounterTrans(ctxt->am, hop, end,
9827 counter);
9828 }
9829 if (type->minOccurs == 0) {
9830 xmlAutomataNewEpsilon(ctxt->am, start, end);
9831 }
9832 ctxt->state = end;
9833 break;
9834 }
9835 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009836 case XML_SCHEMA_TYPE_COMPLEX:
9837 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:
9838 if (type->subtypes != NULL)
9839 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
9840 break;
William M. Brack2f2a6632004-08-20 23:09:47 +00009841 case XML_SCHEMA_TYPE_SIMPLE_CONTENT:
9842 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009843 default:
9844 xmlGenericError(xmlGenericErrorContext,
9845 "Found unexpected type %d in %s content model\n",
9846 type->type, name);
9847 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00009848 }
9849}
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009850
Daniel Veillard4255d502002-04-16 15:50:10 +00009851/**
9852 * xmlSchemaBuildContentModel:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009853 * @type: the type definition (or reference)
Daniel Veillard4255d502002-04-16 15:50:10 +00009854 * @ctxt: the schema parser context
Daniel Veillarda84c0b32003-06-02 16:58:46 +00009855 * @name: the element name
Daniel Veillard4255d502002-04-16 15:50:10 +00009856 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009857 * Builds the content model of the complex type.
Daniel Veillard4255d502002-04-16 15:50:10 +00009858 */
9859static void
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009860xmlSchemaBuildContentModel(xmlSchemaTypePtr type,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009861 xmlSchemaParserCtxtPtr ctxt,
9862 const xmlChar * name)
9863{
Daniel Veillard4255d502002-04-16 15:50:10 +00009864 xmlAutomataStatePtr start;
9865
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009866 if ((type->type != XML_SCHEMA_TYPE_COMPLEX) || (type->ref != NULL) ||
9867 (type->contentType == XML_SCHEMA_CONTENT_BASIC) ||
9868 (type->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
9869 (type->contModel != NULL))
9870 return;
Daniel Veillarddecd64d2002-04-18 14:41:51 +00009871
9872#ifdef DEBUG_CONTENT
9873 xmlGenericError(xmlGenericErrorContext,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009874 "Building content model for %s\n", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +00009875#endif
9876
Daniel Veillard4255d502002-04-16 15:50:10 +00009877 ctxt->am = xmlNewAutomata();
9878 if (ctxt->am == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009879 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009880 "Cannot create automata for complex tpye %s\n", name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009881 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00009882 }
9883 start = ctxt->state = xmlAutomataGetInitState(ctxt->am);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009884 xmlSchemaBuildAContentModel(type, ctxt, name);
Daniel Veillard4255d502002-04-16 15:50:10 +00009885 xmlAutomataSetFinalState(ctxt->am, ctxt->state);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009886 type->contModel = xmlAutomataCompile(ctxt->am);
9887 if (type->contModel == NULL) {
9888 xmlSchemaPCustomErr(ctxt,
9889 XML_SCHEMAP_INTERNAL,
9890 NULL, type, type->node,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009891 "Failed to compile the content model", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009892 } else if (xmlRegexpIsDeterminist(type->contModel) != 1) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00009893 xmlSchemaPCustomErr(ctxt,
9894 XML_SCHEMAP_NOT_DETERMINISTIC,
9895 /* XML_SCHEMAS_ERR_NOTDETERMINIST, */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009896 NULL, type, type->node,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009897 "The content model is not determinist", NULL);
Daniel Veillarde19fc232002-04-22 16:01:24 +00009898 } else {
Daniel Veillard118aed72002-09-24 14:13:13 +00009899#ifdef DEBUG_CONTENT_REGEXP
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009900 xmlGenericError(xmlGenericErrorContext,
9901 "Content model of %s:\n", name);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009902 xmlRegexpPrint(stderr, type->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +00009903#endif
Daniel Veillarde19fc232002-04-22 16:01:24 +00009904 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +00009905 ctxt->state = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00009906 xmlFreeAutomata(ctxt->am);
9907 ctxt->am = NULL;
9908}
9909
9910/**
9911 * xmlSchemaRefFixupCallback:
9912 * @elem: the schema element context
9913 * @ctxt: the schema parser context
9914 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00009915 * Resolves the references of an element declaration
9916 * or particle, which has an element declaration as it's
9917 * term.
Daniel Veillard4255d502002-04-16 15:50:10 +00009918 */
9919static void
9920xmlSchemaRefFixupCallback(xmlSchemaElementPtr elem,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009921 xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009922 const xmlChar * name ATTRIBUTE_UNUSED,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009923 const xmlChar * context ATTRIBUTE_UNUSED,
9924 const xmlChar * namespace ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +00009925{
Daniel Veillardc0826a72004-08-10 14:17:33 +00009926 if ((ctxt == NULL) || (elem == NULL) ||
9927 ((elem != NULL) && (elem->flags & XML_SCHEMAS_ELEM_INTERNAL_RESOLVED)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009928 return;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009929 elem->flags |= XML_SCHEMAS_ELEM_INTERNAL_RESOLVED;
Daniel Veillard4255d502002-04-16 15:50:10 +00009930 if (elem->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009931 xmlSchemaElementPtr elemDecl;
Daniel Veillard4255d502002-04-16 15:50:10 +00009932
Daniel Veillardc0826a72004-08-10 14:17:33 +00009933 /*
9934 * TODO: Evaluate, what errors could occur if the declaration is not
9935 * found. It might be possible that the "typefixup" might crash if
9936 * no ref declaration was found.
9937 */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00009938 elemDecl = xmlSchemaGetElem(ctxt->schema, elem->ref, elem->refNs);
Daniel Veillardc0826a72004-08-10 14:17:33 +00009939 if (elemDecl == NULL) {
9940 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +00009941 XML_SCHEMAP_SRC_RESOLVE,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009942 NULL, (xmlSchemaTypePtr) elem, elem->node,
9943 "ref", elem->ref, elem->refNs,
9944 XML_SCHEMA_TYPE_ELEMENT, NULL);
9945 } else
9946 elem->refDecl = elemDecl;
9947 } else {
9948 if ((elem->subtypes == NULL) && (elem->namedType != NULL)) {
9949 xmlSchemaTypePtr type;
9950
9951 /* (type definition) ... otherwise the type definition ·resolved·
9952 * to by the ·actual value· of the type [attribute] ...
9953 */
9954 type = xmlSchemaGetType(ctxt->schema, elem->namedType,
9955 elem->namedTypeNs);
9956 if (type == NULL) {
9957 xmlSchemaPResCompAttrErr(ctxt,
9958 XML_SCHEMAP_SRC_RESOLVE,
9959 NULL, (xmlSchemaTypePtr) elem, elem->node,
9960 "type", elem->namedType, elem->namedTypeNs,
9961 XML_SCHEMA_TYPE_BASIC, "type definition");
9962 } else
9963 elem->subtypes = type;
9964 }
9965 if (elem->substGroup != NULL) {
9966 xmlSchemaElementPtr substHead;
9967
9968 /*
9969 * FIXME TODO: Do we need a new field in _xmlSchemaElement for
9970 * substitutionGroup?
9971 */
9972 substHead = xmlSchemaGetElem(ctxt->schema, elem->substGroup,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00009973 elem->substGroupNs);
Daniel Veillardc0826a72004-08-10 14:17:33 +00009974 if (substHead == NULL) {
9975 xmlSchemaPResCompAttrErr(ctxt,
9976 XML_SCHEMAP_SRC_RESOLVE,
9977 NULL, (xmlSchemaTypePtr) elem, NULL,
9978 "substitutionGroup", elem->substGroup, elem->substGroupNs,
9979 XML_SCHEMA_TYPE_ELEMENT, NULL);
9980 } else {
9981 xmlSchemaRefFixupCallback(substHead, ctxt, NULL, NULL, NULL);
9982 /*
9983 * (type definition)...otherwise the {type definition} of the
9984 * element declaration ·resolved· to by the ·actual value· of
9985 * the substitutionGroup [attribute], if present
9986 */
9987 if (elem->subtypes == NULL)
9988 elem->subtypes = substHead->subtypes;
9989 }
9990 }
9991 if ((elem->subtypes == NULL) && (elem->namedType == NULL) &&
9992 (elem->substGroup == NULL))
9993 elem->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
9994 }
Daniel Veillard4255d502002-04-16 15:50:10 +00009995}
9996
William M. Bracke7091952004-05-11 15:09:58 +00009997/**
9998 * xmlSchemaParseListRefFixup:
9999 * @type: the schema type definition
10000 * @ctxt: the schema parser context
10001 *
10002 * Fixup of the itemType reference of the list type.
10003 */
Daniel Veillard377e1a92004-04-16 16:30:05 +000010004static void
William M. Bracke7091952004-05-11 15:09:58 +000010005xmlSchemaParseListRefFixup(xmlSchemaTypePtr type, xmlSchemaParserCtxtPtr ctxt)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010006{
Daniel Veillardc0826a72004-08-10 14:17:33 +000010007
Daniel Veillard01fa6152004-06-29 17:04:39 +000010008 if (((type->base == NULL) &&
10009 (type->subtypes == NULL)) ||
10010 ((type->base != NULL) &&
10011 (type->subtypes != NULL))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010012 /*
10013 * src-list-itemType-or-simpleType
10014 * Either the itemType [attribute] or the <simpleType> [child] of
10015 * the <list> element must be present, but not both.
Daniel Veillard01fa6152004-06-29 17:04:39 +000010016 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000010017 /*
10018 * TODO: Move this to the parse function.
10019 */
10020 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010021 XML_SCHEMAP_SRC_LIST_ITEMTYPE_OR_SIMPLETYPE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010022 NULL, type, type->node,
10023 "The attribute 'itemType' and the <simpleType> child "
10024 "are mutually exclusive", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010025 } else if (type->base!= NULL) {
10026 type->subtypes = xmlSchemaGetType(ctxt->schema, type->base, type->baseNs);
10027 if (type->subtypes == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010028 xmlSchemaPResCompAttrErr(ctxt,
10029 XML_SCHEMAP_SRC_RESOLVE,
10030 NULL, type, type->node,
10031 "itemType", type->base, type->baseNs,
10032 XML_SCHEMA_TYPE_SIMPLE, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010033 }
10034 }
10035 if ((type->subtypes != NULL) &&
10036 (type->subtypes->contentType == XML_SCHEMA_CONTENT_UNKNOWN))
10037 xmlSchemaTypeFixup(type->subtypes, ctxt, NULL);
William M. Bracke7091952004-05-11 15:09:58 +000010038}
10039
10040/**
10041 * xmlSchemaParseUnionRefCheck:
10042 * @typeDecl: the schema type definition
10043 * @ctxt: the schema parser context
10044 *
Daniel Veillard01fa6152004-06-29 17:04:39 +000010045 * Checks and builds the memberTypes of the union type.
10046 * Returns -1 in case of an internal error, 0 otherwise.
William M. Bracke7091952004-05-11 15:09:58 +000010047 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000010048static int
William M. Bracke7091952004-05-11 15:09:58 +000010049xmlSchemaParseUnionRefCheck(xmlSchemaTypePtr type,
Daniel Veillard377e1a92004-04-16 16:30:05 +000010050 xmlSchemaParserCtxtPtr ctxt)
10051{
Daniel Veillardc0826a72004-08-10 14:17:33 +000010052
Daniel Veillard01fa6152004-06-29 17:04:39 +000010053 xmlSchemaTypeLinkPtr link, lastLink = NULL, prevLink, subLink, newLink;
10054 xmlSchemaTypePtr memberType, ctxtType;
Daniel Veillard377e1a92004-04-16 16:30:05 +000010055
Daniel Veillard01fa6152004-06-29 17:04:39 +000010056 /* 1 If the <union> alternative is chosen, then [Definition:]
10057 * define the explicit members as the type definitions ·resolved·
10058 * to by the items in the ·actual value· of the memberTypes [attribute],
10059 * if any, followed by the type definitions corresponding to the
10060 * <simpleType>s among the [children] of <union>, if any.
10061 */
Daniel Veillard377e1a92004-04-16 16:30:05 +000010062
Daniel Veillard01fa6152004-06-29 17:04:39 +000010063 if (type->type != XML_SCHEMA_TYPE_UNION)
10064 return (-1);
10065 if (ctxt->ctxtType == NULL) {
10066 xmlSchemaPErr(ctxt, type->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000010067 XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010068 "Internal error: xmlSchemaParseUnionRefCheck, no parent type "
10069 "available", NULL, NULL);
10070 return (-1);
10071 }
10072 /*
10073 * src-union-memberTypes-or-simpleTypes
10074 * Either the memberTypes [attribute] of the <union> element must
10075 * be non-empty or there must be at least one simpleType [child].
10076 */
10077 if ((type->base == NULL) &&
10078 (type->subtypes == NULL)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010079 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010080 XML_SCHEMAP_SRC_UNION_MEMBERTYPES_OR_SIMPLETYPES,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010081 NULL, NULL, type->node,
10082 "Either the attribute 'memberTypes' must be non-empty "
10083 "or there must be at least one <simpleType> child", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010084 }
10085
10086 ctxtType = ctxt->ctxtType;
10087 if (type->base != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010088 xmlAttrPtr attr;
10089 const xmlChar *cur, *end;
10090 xmlChar *tmp;
10091 const xmlChar *localName, *uri;
10092
10093 attr = xmlSchemaGetPropNode(type->node, "memberTypes");
Daniel Veillard01fa6152004-06-29 17:04:39 +000010094 cur = type->base;
10095 do {
10096 while (IS_BLANK_CH(*cur))
10097 cur++;
10098 end = cur;
10099 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
10100 end++;
10101 if (end == cur)
10102 break;
10103 tmp = xmlStrndup(cur, end - cur);
Daniel Veillardc0826a72004-08-10 14:17:33 +000010104 xmlSchemaPValAttrNodeQNameValue(ctxt, ctxt->schema, NULL,
10105 NULL, attr, BAD_CAST tmp, &uri, NULL, &localName);
10106 memberType = xmlSchemaGetType(ctxt->schema, localName, uri);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010107 if (memberType == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010108 xmlSchemaPResCompAttrErr(ctxt,
10109 XML_SCHEMAP_UNKNOWN_MEMBER_TYPE,
10110 NULL, NULL, type->node, "memberTypes", localName, uri,
10111 XML_SCHEMA_TYPE_SIMPLE, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010112 } else {
10113 if (memberType->contentType == XML_SCHEMA_CONTENT_UNKNOWN)
10114 xmlSchemaTypeFixup(memberType, ctxt, NULL);
10115 link = (xmlSchemaTypeLinkPtr) xmlMalloc(sizeof(xmlSchemaTypeLink));
10116 if (link == NULL) {
10117 xmlSchemaPErrMemory(ctxt, "allocating a type link", NULL);
10118 return (-1);
10119 }
10120 link->type = memberType;
10121 link->next = NULL;
10122 if (lastLink == NULL)
10123 ctxtType->memberTypes = link;
10124 else
10125 lastLink->next = link;
10126 lastLink = link;
10127 }
10128 xmlFree(tmp);
10129 cur = end;
10130 } while (*cur != 0);
10131 }
10132 /*
10133 * Add local simple types,
10134 */
10135 memberType = type->subtypes;
10136 while (memberType != NULL) {
10137 if (memberType->contentType == XML_SCHEMA_CONTENT_UNKNOWN)
10138 xmlSchemaTypeFixup(memberType, ctxt, NULL);
10139 link = (xmlSchemaTypeLinkPtr) xmlMalloc(sizeof(xmlSchemaTypeLink));
10140 if (link == NULL) {
10141 xmlSchemaPErrMemory(ctxt, "allocating a type link", NULL);
10142 return (-1);
10143 }
10144 link->type = memberType;
10145 link->next = NULL;
10146 if (lastLink == NULL)
10147 ctxtType->memberTypes = link;
10148 else
10149 lastLink->next = link;
10150 lastLink = link;
10151 memberType = memberType->next;
10152 }
10153 /*
10154 * The actual value is then formed by replacing any union type
10155 * definition in the ·explicit members· with the members of their
10156 * {member type definitions}, in order.
10157 */
10158 link = ctxtType->memberTypes;
10159 while (link != NULL) {
10160 if (link->type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
10161 subLink = link->type->memberTypes;
10162 if (subLink != NULL) {
10163 link->type = subLink->type;
10164 if (subLink->next != NULL) {
10165 lastLink = link->next;
10166 subLink = subLink->next;
10167 prevLink = link;
10168 while (subLink != NULL) {
10169 newLink = (xmlSchemaTypeLinkPtr)
10170 xmlMalloc(sizeof(xmlSchemaTypeLink));
10171 if (newLink == NULL) {
10172 xmlSchemaPErrMemory(ctxt, "allocating a type link",
10173 NULL);
10174 return (-1);
10175 }
10176 newLink->type = memberType;
10177 prevLink->next = newLink;
10178 prevLink = newLink;
10179 newLink->next = lastLink;
10180
10181 subLink = subLink->next;
10182 }
10183 }
10184 }
10185 }
10186 link = link->next;
10187 }
10188
10189 return (0);
Daniel Veillard377e1a92004-04-16 16:30:05 +000010190}
10191
Daniel Veillard4255d502002-04-16 15:50:10 +000010192/**
Daniel Veillard3646d642004-06-02 19:19:14 +000010193 * xmlSchemaIsDerivedFromBuiltInType:
10194 * @ctxt: the schema parser context
10195 * @type: the type definition
10196 * @valType: the value type
10197 *
10198 *
10199 * Returns 1 if the type has the given value type, or
10200 * is derived from such a type.
10201 */
William M. Brack803812b2004-06-03 02:11:24 +000010202static int
Daniel Veillard3646d642004-06-02 19:19:14 +000010203xmlSchemaIsDerivedFromBuiltInType(xmlSchemaParserCtxtPtr ctxt,
10204 xmlSchemaTypePtr type, int valType)
10205{
10206 /* TODO: Check if this works in every case. */
Daniel Veillard01fa6152004-06-29 17:04:39 +000010207 if ((type->type == XML_SCHEMA_TYPE_BASIC) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000010208 (type->contentType == XML_SCHEMA_CONTENT_BASIC)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000010209 if (type->builtInType == valType)
Daniel Veillard3646d642004-06-02 19:19:14 +000010210 return(1);
10211 } else if (type->type == XML_SCHEMA_TYPE_ATTRIBUTE) {
10212 if (((xmlSchemaAttributePtr) type)->subtypes != NULL)
10213 return(xmlSchemaIsDerivedFromBuiltInType(ctxt,
10214 ((xmlSchemaAttributePtr) type)->subtypes, valType));
10215 } else if ((type->type == XML_SCHEMA_TYPE_RESTRICTION) ||
10216 (type->type == XML_SCHEMA_TYPE_EXTENSION)) {
10217 if (type->baseType != NULL)
10218 return(xmlSchemaIsDerivedFromBuiltInType(ctxt, type->baseType,
10219 valType));
10220 } else if ((type->subtypes != NULL) &&
10221 ((type->subtypes->type == XML_SCHEMA_TYPE_COMPLEX) ||
10222 (type->subtypes->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) ||
10223 (type->subtypes->type == XML_SCHEMA_TYPE_SIMPLE) ||
10224 (type->subtypes->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT))) {
10225 return(xmlSchemaIsDerivedFromBuiltInType(ctxt, type->subtypes,
10226 valType));
10227 }
10228
10229 return (0);
10230}
10231
10232/**
Daniel Veillard01fa6152004-06-29 17:04:39 +000010233 * xmlSchemaIsDerivedFromBuiltInType:
10234 * @type: the simpleType definition
10235 *
10236 * Returns the primitive type of the given type or
10237 * NULL in case of error.
10238 */
10239static xmlSchemaTypePtr
10240xmlSchemaGetPrimitiveType(xmlSchemaTypePtr type)
10241{
10242 while (type != NULL) {
10243 if (type->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE)
10244 return (type);
10245 type = type->baseType;
10246 }
10247
10248 return (NULL);
10249}
10250
10251
10252/**
Daniel Veillard3646d642004-06-02 19:19:14 +000010253 * xmlSchemaBuildAttributeUsesOwned:
10254 * @ctxt: the schema parser context
10255 * @type: the complex type definition
10256 * @cur: the attribute declaration list
10257 * @lastUse: the top of the attribute use list
10258 *
10259 * Builds the attribute uses list on the given complex type.
10260 * This one is supposed to be called by
10261 * xmlSchemaBuildAttributeValidation only.
10262 */
10263static int
10264xmlSchemaBuildAttributeUsesOwned(xmlSchemaParserCtxtPtr ctxt,
10265 xmlSchemaAttributePtr cur,
10266 xmlSchemaAttributeLinkPtr *uses,
10267 xmlSchemaAttributeLinkPtr *lastUse)
10268{
10269 xmlSchemaAttributeLinkPtr tmp;
10270 while (cur != NULL) {
10271 if (cur->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
10272 /*
10273 * W3C: "2 The {attribute uses} of the attribute groups ·resolved·
10274 * to by the ·actual value·s of the ref [attribute] of the
10275 * <attributeGroup> [children], if any."
10276 */
10277 if (xmlSchemaBuildAttributeUsesOwned(ctxt,
10278 ((xmlSchemaAttributeGroupPtr) cur)->attributes, uses,
10279 lastUse) == -1) {
10280 return (-1);
10281 }
10282 } else {
10283 /* W3C: "1 The set of attribute uses corresponding to the
10284 * <attribute> [children], if any."
10285 */
10286 tmp = (xmlSchemaAttributeLinkPtr)
10287 xmlMalloc(sizeof(xmlSchemaAttributeLink));
10288 if (tmp == NULL) {
10289 xmlSchemaPErrMemory(ctxt, "building attribute uses", NULL);
10290 return (-1);
10291 }
10292 tmp->attr = cur;
10293 tmp->next = NULL;
10294 if (*uses == NULL)
10295 *uses = tmp;
10296 else
10297 (*lastUse)->next = tmp;
10298 *lastUse = tmp;
10299 }
10300 cur = cur->next;
10301 }
10302 return (0);
10303}
10304
Daniel Veillard50355f02004-06-08 17:52:16 +000010305/**
10306 * xmlSchemaCloneWildcardNsConstraints:
10307 * @ctxt: the schema parser context
10308 * @dest: the destination wildcard
10309 * @source: the source wildcard
10310 *
10311 * Clones the namespace constraints of source
10312 * and assignes them to dest.
10313 * Returns -1 on internal error, 0 otherwise.
10314 */
Daniel Veillard3646d642004-06-02 19:19:14 +000010315static int
10316xmlSchemaCloneWildcardNsConstraints(xmlSchemaParserCtxtPtr ctxt,
10317 xmlSchemaWildcardPtr *dest,
10318 xmlSchemaWildcardPtr source)
10319{
10320 xmlSchemaWildcardNsPtr cur, tmp, last;
10321
10322 if ((source == NULL) || (*dest == NULL))
10323 return(-1);
10324 (*dest)->any = source->any;
10325 cur = source->nsSet;
10326 last = NULL;
10327 while (cur != NULL) {
10328 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
10329 if (tmp == NULL)
10330 return(-1);
10331 tmp->value = cur->value;
10332 if (last == NULL)
10333 (*dest)->nsSet = tmp;
10334 else
10335 last->next = tmp;
10336 last = tmp;
10337 cur = cur->next;
10338 }
10339 if ((*dest)->negNsSet != NULL)
10340 xmlSchemaFreeWildcardNsSet((*dest)->negNsSet);
10341 if (source->negNsSet != NULL) {
10342 (*dest)->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
10343 if ((*dest)->negNsSet == NULL)
10344 return(-1);
10345 (*dest)->negNsSet->value = source->negNsSet->value;
10346 } else
10347 (*dest)->negNsSet = NULL;
10348 return(0);
10349}
10350
Daniel Veillard50355f02004-06-08 17:52:16 +000010351/**
10352 * xmlSchemaUnionWildcards:
10353 * @ctxt: the schema parser context
10354 * @completeWild: the first wildcard
10355 * @curWild: the second wildcard
10356 *
10357 * Unions the namespace constraints of the given wildcards.
10358 * @completeWild will hold the resulting union.
10359 * Returns a positive error code on failure, -1 in case of an
10360 * internal error, 0 otherwise.
10361 */
Daniel Veillard3646d642004-06-02 19:19:14 +000010362static int
10363xmlSchemaUnionWildcards(xmlSchemaParserCtxtPtr ctxt,
10364 xmlSchemaWildcardPtr completeWild,
10365 xmlSchemaWildcardPtr curWild)
10366{
10367 xmlSchemaWildcardNsPtr cur, curB, tmp;
10368
10369 /*
10370 * 1 If O1 and O2 are the same value, then that value must be the
10371 * value.
10372 */
10373 if ((completeWild->any == curWild->any) &&
10374 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
10375 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
10376
10377 if ((completeWild->negNsSet == NULL) ||
10378 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
10379
10380 if (completeWild->nsSet != NULL) {
William M. Brack803812b2004-06-03 02:11:24 +000010381 int found = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000010382
10383 /*
10384 * Check equality of sets.
10385 */
10386 cur = completeWild->nsSet;
10387 while (cur != NULL) {
10388 found = 0;
10389 curB = curWild->nsSet;
10390 while (curB != NULL) {
10391 if (cur->value == curB->value) {
10392 found = 1;
10393 break;
10394 }
10395 curB = curB->next;
10396 }
10397 if (!found)
10398 break;
10399 cur = cur->next;
10400 }
10401 if (found)
10402 return(0);
10403 } else
10404 return(0);
10405 }
10406 }
10407 /*
10408 * 2 If either O1 or O2 is any, then any must be the value
10409 */
Daniel Veillard50355f02004-06-08 17:52:16 +000010410 if (completeWild->any != curWild->any) {
Daniel Veillard3646d642004-06-02 19:19:14 +000010411 if (completeWild->any == 0) {
10412 completeWild->any = 1;
10413 if (completeWild->nsSet != NULL) {
10414 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
10415 completeWild->nsSet = NULL;
10416 }
10417 if (completeWild->negNsSet != NULL) {
10418 xmlFree(completeWild->negNsSet);
10419 completeWild->negNsSet = NULL;
10420 }
10421 }
Daniel Veillard50355f02004-06-08 17:52:16 +000010422 return (0);
Daniel Veillard3646d642004-06-02 19:19:14 +000010423 }
10424 /*
10425 * 3 If both O1 and O2 are sets of (namespace names or ·absent·),
10426 * then the union of those sets must be the value.
10427 */
10428 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
10429 int found;
10430 xmlSchemaWildcardNsPtr start;
10431
10432 cur = curWild->nsSet;
10433 start = completeWild->nsSet;
10434 while (cur != NULL) {
10435 found = 0;
10436 curB = start;
10437 while (curB != NULL) {
10438 if (cur->value == curB->value) {
10439 found = 1;
10440 break;
10441 }
10442 curB = curB->next;
10443 }
10444 if (!found) {
10445 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
10446 if (tmp == NULL)
10447 return (-1);
10448 tmp->value = cur->value;
10449 tmp->next = completeWild->nsSet;
10450 completeWild->nsSet = tmp;
10451 }
10452 cur = cur->next;
10453 }
10454
10455 return(0);
10456 }
10457 /*
10458 * 4 If the two are negations of different values (namespace names
10459 * or ·absent·), then a pair of not and ·absent· must be the value.
10460 */
10461 if ((completeWild->negNsSet != NULL) &&
10462 (curWild->negNsSet != NULL) &&
10463 (completeWild->negNsSet->value != curWild->negNsSet->value)) {
10464 completeWild->negNsSet->value = NULL;
Daniel Veillard50355f02004-06-08 17:52:16 +000010465
10466 return(0);
Daniel Veillard3646d642004-06-02 19:19:14 +000010467 }
10468 /*
10469 * 5.
10470 */
10471 if (((completeWild->negNsSet != NULL) &&
10472 (completeWild->negNsSet->value != NULL) &&
10473 (curWild->nsSet != NULL)) ||
10474 ((curWild->negNsSet != NULL) &&
10475 (curWild->negNsSet->value != NULL) &&
10476 (completeWild->nsSet != NULL))) {
10477
10478 int nsFound, absentFound = 0;
10479
10480 if (completeWild->nsSet != NULL) {
10481 cur = completeWild->nsSet;
10482 curB = curWild->negNsSet;
10483 } else {
10484 cur = curWild->nsSet;
10485 curB = completeWild->negNsSet;
10486 }
10487 nsFound = 0;
10488 while (cur != NULL) {
10489 if (cur->value == NULL)
10490 absentFound = 1;
10491 else if (cur->value == curB->value)
10492 nsFound = 1;
10493 if (nsFound && absentFound)
10494 break;
10495 cur = cur->next;
10496 }
10497
10498 if (nsFound && absentFound) {
10499 /*
10500 * 5.1 If the set S includes both the negated namespace
10501 * name and ·absent·, then any must be the value.
10502 */
10503 completeWild->any = 1;
10504 if (completeWild->nsSet != NULL) {
10505 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
10506 completeWild->nsSet = NULL;
10507 }
10508 if (completeWild->negNsSet != NULL) {
10509 xmlFree(completeWild->negNsSet);
10510 completeWild->negNsSet = NULL;
10511 }
10512 } else if (nsFound && (!absentFound)) {
10513 /*
10514 * 5.2 If the set S includes the negated namespace name
10515 * but not ·absent·, then a pair of not and ·absent· must
10516 * be the value.
10517 */
10518 if (completeWild->nsSet != NULL) {
10519 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
10520 completeWild->nsSet = NULL;
10521 }
10522 if (completeWild->negNsSet == NULL) {
10523 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
10524 if (completeWild->negNsSet == NULL)
10525 return (-1);
10526 }
10527 completeWild->negNsSet->value = NULL;
10528 } else if ((!nsFound) && absentFound) {
10529 /*
10530 * 5.3 If the set S includes ·absent· but not the negated
10531 * namespace name, then the union is not expressible.
10532 */
10533 xmlSchemaPErr(ctxt, completeWild->node,
10534 XML_SCHEMAP_UNION_NOT_EXPRESSIBLE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010535 "The union of the wilcard is not expressible.\n",
Daniel Veillard3646d642004-06-02 19:19:14 +000010536 NULL, NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +000010537 return(XML_SCHEMAP_UNION_NOT_EXPRESSIBLE);
Daniel Veillard3646d642004-06-02 19:19:14 +000010538 } else if ((!nsFound) && (!absentFound)) {
10539 /*
10540 * 5.4 If the set S does not include either the negated namespace
10541 * name or ·absent·, then whichever of O1 or O2 is a pair of not
10542 * and a namespace name must be the value.
10543 */
10544 if (completeWild->negNsSet == NULL) {
10545 if (completeWild->nsSet != NULL) {
10546 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
10547 completeWild->nsSet = NULL;
10548 }
10549 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
10550 if (completeWild->negNsSet == NULL)
10551 return (-1);
10552 completeWild->negNsSet->value = curWild->negNsSet->value;
10553 }
10554 }
10555 return (0);
10556 }
10557 /*
10558 * 6.
10559 */
10560 if (((completeWild->negNsSet != NULL) &&
10561 (completeWild->negNsSet->value == NULL) &&
10562 (curWild->nsSet != NULL)) ||
10563 ((curWild->negNsSet != NULL) &&
10564 (curWild->negNsSet->value == NULL) &&
10565 (completeWild->nsSet != NULL))) {
10566
10567 if (completeWild->nsSet != NULL) {
10568 cur = completeWild->nsSet;
10569 } else {
10570 cur = curWild->nsSet;
10571 }
10572 while (cur != NULL) {
10573 if (cur->value == NULL) {
10574 /*
10575 * 6.1 If the set S includes ·absent·, then any must be the
10576 * value.
10577 */
10578 completeWild->any = 1;
10579 if (completeWild->nsSet != NULL) {
10580 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
10581 completeWild->nsSet = NULL;
10582 }
10583 if (completeWild->negNsSet != NULL) {
10584 xmlFree(completeWild->negNsSet);
10585 completeWild->negNsSet = NULL;
10586 }
10587 return (0);
10588 }
10589 cur = cur->next;
10590 }
10591 if (completeWild->negNsSet == NULL) {
10592 /*
10593 * 6.2 If the set S does not include ·absent·, then a pair of not
10594 * and ·absent· must be the value.
10595 */
10596 if (completeWild->nsSet != NULL) {
10597 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
10598 completeWild->nsSet = NULL;
10599 }
10600 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
10601 if (completeWild->negNsSet == NULL)
10602 return (-1);
10603 completeWild->negNsSet->value = NULL;
10604 }
10605 return (0);
10606 }
10607 return (0);
10608
10609}
10610
Daniel Veillard50355f02004-06-08 17:52:16 +000010611/**
10612 * xmlSchemaIntersectWildcards:
10613 * @ctxt: the schema parser context
10614 * @completeWild: the first wildcard
10615 * @curWild: the second wildcard
10616 *
10617 * Intersects the namespace constraints of the given wildcards.
10618 * @completeWild will hold the resulting intersection.
10619 * Returns a positive error code on failure, -1 in case of an
10620 * internal error, 0 otherwise.
10621 */
Daniel Veillard3646d642004-06-02 19:19:14 +000010622static int
10623xmlSchemaIntersectWildcards(xmlSchemaParserCtxtPtr ctxt,
10624 xmlSchemaWildcardPtr completeWild,
10625 xmlSchemaWildcardPtr curWild)
10626{
William M. Brack803812b2004-06-03 02:11:24 +000010627 xmlSchemaWildcardNsPtr cur, curB, prev, tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000010628
10629 /*
10630 * 1 If O1 and O2 are the same value, then that value must be the
10631 * value.
10632 */
10633 if ((completeWild->any == curWild->any) &&
10634 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
10635 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
10636
10637 if ((completeWild->negNsSet == NULL) ||
10638 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
10639
10640 if (completeWild->nsSet != NULL) {
William M. Brack803812b2004-06-03 02:11:24 +000010641 int found = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000010642
10643 /*
10644 * Check equality of sets.
10645 */
10646 cur = completeWild->nsSet;
10647 while (cur != NULL) {
10648 found = 0;
10649 curB = curWild->nsSet;
10650 while (curB != NULL) {
10651 if (cur->value == curB->value) {
10652 found = 1;
10653 break;
10654 }
10655 curB = curB->next;
10656 }
10657 if (!found)
10658 break;
10659 cur = cur->next;
10660 }
10661 if (found)
10662 return(0);
10663 } else
10664 return(0);
10665 }
10666 }
10667 /*
10668 * 2 If either O1 or O2 is any, then the other must be the value.
10669 */
10670 if ((completeWild->any != curWild->any) && (completeWild->any)) {
10671 if (xmlSchemaCloneWildcardNsConstraints(ctxt, &completeWild, curWild) == -1)
10672 return(-1);
10673 return(0);
10674 }
10675 /*
10676 * 3 If either O1 or O2 is a pair of not and a value (a namespace
10677 * name or ·absent·) and the other is a set of (namespace names or
10678 * ·absent·), then that set, minus the negated value if it was in
10679 * the set, minus ·absent· if it was in the set, must be the value.
10680 */
10681 if (((completeWild->negNsSet != NULL) && (curWild->nsSet != NULL)) ||
10682 ((curWild->negNsSet != NULL) && (completeWild->nsSet != NULL))) {
10683 const xmlChar *neg;
10684
10685 if (completeWild->nsSet == NULL) {
10686 neg = completeWild->negNsSet->value;
10687 if (xmlSchemaCloneWildcardNsConstraints(ctxt, &completeWild, curWild) == -1)
10688 return(-1);
10689 } else
10690 neg = curWild->negNsSet->value;
10691 /*
10692 * Remove absent and negated.
10693 */
10694 prev = NULL;
10695 cur = completeWild->nsSet;
10696 while (cur != NULL) {
10697 if (cur->value == NULL) {
10698 if (prev == NULL)
10699 completeWild->nsSet = cur->next;
10700 else
10701 prev->next = cur->next;
10702 xmlFree(cur);
10703 break;
10704 }
10705 prev = cur;
10706 cur = cur->next;
10707 }
10708 if (neg != NULL) {
10709 prev = NULL;
10710 cur = completeWild->nsSet;
10711 while (cur != NULL) {
10712 if (cur->value == neg) {
10713 if (prev == NULL)
10714 completeWild->nsSet = cur->next;
10715 else
10716 prev->next = cur->next;
10717 xmlFree(cur);
10718 break;
10719 }
10720 prev = cur;
10721 cur = cur->next;
10722 }
10723 }
10724
10725 return(0);
10726 }
10727 /*
10728 * 4 If both O1 and O2 are sets of (namespace names or ·absent·),
10729 * then the intersection of those sets must be the value.
10730 */
10731 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
10732 int found;
10733
10734 cur = completeWild->nsSet;
10735 prev = NULL;
10736 while (cur != NULL) {
10737 found = 0;
10738 curB = curWild->nsSet;
10739 while (curB != NULL) {
10740 if (cur->value == curB->value) {
10741 found = 1;
10742 break;
10743 }
10744 curB = curB->next;
10745 }
10746 if (!found) {
10747 if (prev == NULL)
10748 completeWild->nsSet = cur->next;
10749 else
10750 prev->next = cur->next;
10751 tmp = cur->next;
10752 xmlFree(cur);
10753 cur = tmp;
10754 continue;
10755 }
10756 prev = cur;
10757 cur = cur->next;
10758 }
10759
10760 return(0);
10761 }
10762 /* 5 If the two are negations of different namespace names,
10763 * then the intersection is not expressible
10764 */
10765 if ((completeWild->negNsSet != NULL) &&
10766 (curWild->negNsSet != NULL) &&
10767 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
10768 (completeWild->negNsSet->value != NULL) &&
10769 (curWild->negNsSet->value != NULL)) {
10770
10771 xmlSchemaPErr(ctxt, completeWild->node, XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010772 "The intersection of the wilcard is not expressible.\n",
Daniel Veillard3646d642004-06-02 19:19:14 +000010773 NULL, NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +000010774 return(XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE);
Daniel Veillard3646d642004-06-02 19:19:14 +000010775 }
10776 /*
10777 * 6 If the one is a negation of a namespace name and the other
10778 * is a negation of ·absent·, then the one which is the negation
10779 * of a namespace name must be the value.
10780 */
10781 if ((completeWild->negNsSet != NULL) && (curWild->negNsSet != NULL) &&
10782 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
10783 (completeWild->negNsSet->value == NULL)) {
10784 completeWild->negNsSet->value = curWild->negNsSet->value;
10785 }
10786 return(0);
10787}
10788
Daniel Veillard50355f02004-06-08 17:52:16 +000010789/**
10790 * xmlSchemaIsWildcardNsConstraintSubset:
10791 * @ctxt: the schema parser context
10792 * @wildA: the first wildcard
10793 * @wildB: the second wildcard
10794 *
10795 * Returns 1 if the namespace constraint of @wildA is an intensional
10796 * subset of @wildB, 0 otherwise.
10797 */
10798static int
Daniel Veillardc0826a72004-08-10 14:17:33 +000010799xmlSchemaIsWildcardNsConstraintSubset(xmlSchemaWildcardPtr wildA,
10800 xmlSchemaWildcardPtr wildB)
Daniel Veillard50355f02004-06-08 17:52:16 +000010801{
Daniel Veillard3646d642004-06-02 19:19:14 +000010802
Daniel Veillard50355f02004-06-08 17:52:16 +000010803 /*
10804 * Schema Component Constraint: Wildcard Subset
10805 */
10806 /*
10807 * 1 super must be any.
10808 */
10809 if (wildB->any)
10810 return (1);
10811 /*
10812 * 2.1 sub must be a pair of not and a namespace name or ·absent·.
10813 * 2.2 super must be a pair of not and the same value.
10814 */
10815 if ((wildA->negNsSet != NULL) &&
10816 (wildB->negNsSet != NULL) &&
10817 (wildA->negNsSet->value == wildA->negNsSet->value))
10818 return (1);
10819 /*
10820 * 3.1 sub must be a set whose members are either namespace names or ·absent·.
10821 */
10822 if (wildA->nsSet != NULL) {
10823 /*
10824 * 3.2.1 super must be the same set or a superset thereof.
10825 */
10826 if (wildB->nsSet != NULL) {
10827 xmlSchemaWildcardNsPtr cur, curB;
10828 int found = 0;
10829
10830 cur = wildA->nsSet;
10831 while (cur != NULL) {
10832 found = 0;
10833 curB = wildB->nsSet;
10834 while (curB != NULL) {
10835 if (cur->value == curB->value) {
10836 found = 1;
10837 break;
10838 }
10839 curB = curB->next;
10840 }
10841 if (!found)
10842 return (0);
10843 cur = cur->next;
10844 }
10845 if (found)
10846 return (1);
10847 } else if (wildB->negNsSet != NULL) {
10848 xmlSchemaWildcardNsPtr cur;
10849 /*
10850 * 3.2.2 super must be a pair of not and a namespace name or
10851 * ·absent· and that value must not be in sub's set.
10852 */
10853 cur = wildA->nsSet;
10854 while (cur != NULL) {
10855 if (cur->value == wildB->negNsSet->value)
10856 return (0);
10857 cur = cur->next;
10858 }
10859 return (1);
10860 }
10861 }
10862 return (0);
10863}
10864
10865/**
10866 * xmlSchemaBuildCompleteAttributeWildcard:
10867 * @ctxt: the schema parser context
10868 * @attrs: the attribute list
10869 * @completeWild: the resulting complete wildcard
10870 *
10871 * Returns -1 in case of an internal error, 0 otherwise.
10872 */
10873static int
10874xmlSchemaBuildCompleteAttributeWildcard(xmlSchemaParserCtxtPtr ctxt,
10875 xmlSchemaAttributePtr attrs,
10876 xmlSchemaWildcardPtr *completeWild)
Daniel Veillard3646d642004-06-02 19:19:14 +000010877{
10878 while (attrs != NULL) {
10879 if (attrs->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
10880 xmlSchemaAttributeGroupPtr group;
10881
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010882 group = (xmlSchemaAttributeGroupPtr) attrs;
10883 /*
10884 * Handle attribute group references.
10885 */
10886 if (group->ref != NULL) {
10887 if (group->refItem == NULL) {
10888 /*
10889 * TODO: Should we raise a warning here?
10890 */
10891 /*
10892 * The referenced attribute group definition could not
10893 * be resolved beforehand, so skip.
10894 */
10895 attrs = attrs->next;
10896 continue;
10897 } else
10898 group = group->refItem;
10899 }
10900 /*
10901 * For every attribute group definition, an intersected wildcard
10902 * will be created (assumed that a wildcard exists on the
10903 * particular attr. gr. def. or on any contained attr. gr. def
10904 * at all).
10905 * The flag XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED ensures
10906 * that the intersection will be performed only once.
10907 */
Daniel Veillard3646d642004-06-02 19:19:14 +000010908 if ((group->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED) == 0) {
10909 if (group->attributes != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000010910 if (xmlSchemaBuildCompleteAttributeWildcard(ctxt,
10911 group->attributes, &group->attributeWildcard) == -1)
10912 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000010913 }
10914 group->flags |= XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED;
10915 }
10916 if (group->attributeWildcard != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000010917 if (*completeWild == NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +000010918 /*
10919 * Copy the first encountered wildcard as context, except for the annotation.
10920 */
Daniel Veillard50355f02004-06-08 17:52:16 +000010921 *completeWild = xmlSchemaAddWildcard(ctxt);
10922 (*completeWild)->type = XML_SCHEMA_TYPE_ANY_ATTRIBUTE;
10923 if (xmlSchemaCloneWildcardNsConstraints(ctxt,
10924 completeWild, group->attributeWildcard) == -1)
10925 return (-1);
10926 (*completeWild)->processContents = group->attributeWildcard->processContents;
Daniel Veillard3646d642004-06-02 19:19:14 +000010927 /*
10928 * Although the complete wildcard might not correspond to any
10929 * node in the schema, we will save this context node.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010930 * TODO: Hmm, is this sane?
Daniel Veillard3646d642004-06-02 19:19:14 +000010931 */
Daniel Veillard50355f02004-06-08 17:52:16 +000010932 (*completeWild)->node = group->attributeWildcard->node;
10933
10934 } else if (xmlSchemaIntersectWildcards(ctxt, *completeWild, group->attributeWildcard) == -1) {
10935 xmlSchemaFreeWildcard(*completeWild);
10936 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000010937 }
10938 }
10939 }
10940 attrs = attrs->next;
10941 }
10942
Daniel Veillard50355f02004-06-08 17:52:16 +000010943 return (0);
Daniel Veillard3646d642004-06-02 19:19:14 +000010944}
10945
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010946static int
10947xmlSchemaGetEffectiveValueConstraint(xmlSchemaAttributePtr item,
10948 int *fixed,
10949 const xmlChar **value,
10950 xmlSchemaValPtr *val)
10951{
10952 *fixed = 0;
10953 *value = NULL;
10954 if (val != 0)
10955 *val = NULL;
10956
10957 if (item->defValue == NULL)
10958 item = item->refDecl;
10959
10960 if (item == NULL)
10961 return (0);
10962
10963 if (item->defValue != NULL) {
10964 *value = item->defValue;
10965 if (val != 0)
10966 *val = item->defVal;
10967 if (item->flags & XML_SCHEMAS_ATTR_FIXED)
10968 *fixed = 1;
10969 return (1);
10970 }
10971 return (0);
10972}
Daniel Veillard3646d642004-06-02 19:19:14 +000010973/**
10974 * xmlSchemaMatchesWildcardNs:
10975 * @wild: the wildcard
10976 * @ns: the namespace
10977 *
10978 *
10979 * Returns 1 if the given namespace matches the wildcard,
10980 * 0 otherwise.
10981 */
10982static int
10983xmlSchemaMatchesWildcardNs(xmlSchemaWildcardPtr wild, const xmlChar* ns)
10984{
10985 if (wild == NULL)
10986 return(0);
10987
10988 if (wild->any)
10989 return(1);
10990 else if (wild->nsSet != NULL) {
10991 xmlSchemaWildcardNsPtr cur;
10992
10993 cur = wild->nsSet;
10994 while (cur != NULL) {
10995 if (xmlStrEqual(cur->value, ns))
10996 return(1);
10997 cur = cur->next;
10998 }
10999 } else if ((wild->negNsSet != NULL) && (ns != NULL) &&
11000 (!xmlStrEqual(wild->negNsSet->value, ns)))
11001 return(1);
11002
11003 return(0);
11004}
11005
11006/**
11007 * xmlSchemaBuildAttributeValidation:
11008 * @ctxt: the schema parser context
11009 * @type: the complex type definition
11010 *
11011 *
11012 * Builds the wildcard and the attribute uses on the given complex type.
11013 * Returns -1 if an internal error occurs, 0 otherwise.
11014 */
11015static int
11016xmlSchemaBuildAttributeValidation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaTypePtr type)
11017{
11018 xmlSchemaTypePtr baseType = NULL;
11019 xmlSchemaAttributeLinkPtr cur, base, tmp, id = NULL, prev = NULL, uses = NULL,
William M. Brack803812b2004-06-03 02:11:24 +000011020 lastUse = NULL, lastBaseUse = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000011021 xmlSchemaAttributePtr attrs;
Daniel Veillard01fa6152004-06-29 17:04:39 +000011022 xmlSchemaTypePtr anyType;
Daniel Veillard50355f02004-06-08 17:52:16 +000011023 int baseIsAnyType = 0;
Daniel Veillardc0826a72004-08-10 14:17:33 +000011024 xmlChar *str = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000011025 int err = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000011026
Daniel Veillard01fa6152004-06-29 17:04:39 +000011027 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
Daniel Veillard3646d642004-06-02 19:19:14 +000011028 /*
11029 * Complex Type Definition with complex content Schema Component.
11030 *
11031 * Attribute uses.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011032 * TODO: Add checks for absent referenced attribute declarations and
11033 * simple types.
Daniel Veillard3646d642004-06-02 19:19:14 +000011034 */
11035 if (type->attributeUses != NULL) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000011036 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011037 "Internal error: xmlSchemaBuildAttributeValidation: "
Daniel Veillard3646d642004-06-02 19:19:14 +000011038 "attribute uses already builded.\n",
11039 NULL, NULL);
11040 return (-1);
11041 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000011042 if (type->baseType == NULL) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000011043 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011044 "Internal error: xmlSchemaBuildAttributeValidation: "
Daniel Veillardc0826a72004-08-10 14:17:33 +000011045 "complex type '%s' has no base type.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000011046 type->name, NULL);
11047 return (-1);
11048 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011049 baseType = type->baseType;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011050 if (baseType == anyType)
11051 baseIsAnyType = 1;
11052 /*
11053 * Inherit the attribute uses of the base type.
11054 */
11055 /*
11056 * NOTE: It is allowed to "extend" the anyType complex type.
11057 */
11058 if (!baseIsAnyType) {
11059 if (baseType != NULL) {
11060 for (cur = baseType->attributeUses; cur != NULL; cur = cur->next) {
11061 tmp = (xmlSchemaAttributeLinkPtr)
11062 xmlMalloc(sizeof(xmlSchemaAttributeLink));
11063 if (tmp == NULL) {
11064 xmlSchemaPErrMemory(ctxt,
11065 "building attribute uses of complexType", NULL);
11066 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000011067 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011068 tmp->attr = cur->attr;
11069 tmp->next = NULL;
11070 if (type->attributeUses == NULL) {
11071 type->attributeUses = tmp;
11072 } else
11073 lastBaseUse->next = tmp;
11074 lastBaseUse = tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000011075 }
11076 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011077 }
11078 if ((type->subtypes != NULL) &&
11079 ((type->subtypes->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) ||
11080 (type->subtypes->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT))) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011081 /*
11082 * type --> (<simpleContent>|<complexContent>)
11083 * --> (<restriction>|<extension>) --> attributes
11084 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011085 attrs = type->subtypes->subtypes->attributes;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011086 } else {
11087 /* Short hand form of the complexType. */
11088 attrs = type->attributes;
11089 }
11090 /*
11091 * Handle attribute wildcards.
11092 */
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000011093 err = xmlSchemaBuildCompleteAttributeWildcard(ctxt,
11094 attrs, &type->attributeWildcard);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011095 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011096 * NOTE: During the parse time, the wildcard is created on the complexType
11097 * directly, if encountered in a <restriction> or <extension> element.
Daniel Veillard01fa6152004-06-29 17:04:39 +000011098 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011099 if (err == -1) {
11100 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_INTERNAL,
11101 "Internal error: xmlSchemaBuildAttributeValidation: "
11102 "failed to build an intersected attribute wildcard.\n",
11103 NULL, NULL);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000011104 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011105 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011106
11107 if ((type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) &&
11108 ((baseIsAnyType) ||
11109 ((baseType != NULL) &&
11110 (baseType->type == XML_SCHEMA_TYPE_COMPLEX) &&
11111 (baseType->attributeWildcard != NULL)))) {
11112 if (type->attributeWildcard != NULL) {
11113 /*
11114 * Union the complete wildcard with the base wildcard.
11115 */
11116 if (xmlSchemaUnionWildcards(ctxt, type->attributeWildcard,
11117 baseType->attributeWildcard) == -1)
11118 return (-1);
11119 } else {
11120 /*
11121 * Just inherit the wildcard.
11122 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011123 /*
11124 * NOTE: This is the only case where an attribute
11125 * wildcard is shared.
11126 */
11127 if (type->flags & XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD)
11128 type->flags ^= XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011129 type->attributeWildcard = baseType->attributeWildcard;
Daniel Veillard50355f02004-06-08 17:52:16 +000011130 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011131 }
11132
11133 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
11134 if (type->attributeWildcard != NULL) {
11135 /*
11136 * Derivation Valid (Restriction, Complex)
11137 * 4.1 The {base type definition} must also have one.
11138 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000011139 if (baseType->attributeWildcard == NULL) {
11140 xmlSchemaPCustomErr(ctxt,
11141 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_1,
11142 NULL, type, NULL,
11143 "The type has an attribute wildcard, "
11144 "but the base type %s does not have one",
11145 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
11146 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011147 return (1);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011148 } else if (xmlSchemaIsWildcardNsConstraintSubset(
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011149 type->attributeWildcard, baseType->attributeWildcard) == 0) {
11150 /* 4.2 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000011151 xmlSchemaPCustomErr(ctxt,
11152 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_2,
11153 NULL, type, NULL,
11154 "The attribute wildcard is not a valid "
11155 "subset of the wildcard in the base type %s",
11156 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
11157 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011158 return (1);
11159 }
11160 /* 4.3 Unless the {base type definition} is the ·ur-type
11161 * definition·, the complex type definition's {attribute
11162 * wildcard}'s {process contents} must be identical to or
11163 * stronger than the {base type definition}'s {attribute
11164 * wildcard}'s {process contents}, where strict is stronger
11165 * than lax is stronger than skip.
11166 */
11167 if ((type->baseType != anyType) &&
11168 (type->attributeWildcard->processContents <
11169 baseType->attributeWildcard->processContents)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011170 xmlSchemaPCustomErr(ctxt,
11171 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_3,
11172 NULL, type, NULL,
11173 "The 'process contents' of the attribute wildcard is weaker than "
11174 "the one in the base type %s",
11175 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
11176 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011177 return (1);
11178 }
11179 }
11180 } else if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
11181 /*
11182 * Derivation Valid (Extension)
11183 * At this point the type and the base have both, either
11184 * no wildcard or a wildcard.
11185 */
11186 if ((baseType->attributeWildcard != NULL) &&
11187 (baseType->attributeWildcard != type->attributeWildcard)) {
11188 /* 1.3 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000011189 if (xmlSchemaIsWildcardNsConstraintSubset(
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011190 baseType->attributeWildcard, type->attributeWildcard) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011191 xmlSchemaPCustomErr(ctxt,
11192 XML_SCHEMAP_COS_CT_EXTENDS_1_3,
11193 NULL, type, NULL,
11194 "The attribute wildcard is not a valid "
11195 "superset of the one in the base type %s",
11196 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
11197 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011198 return (1);
11199 }
11200 }
11201 }
11202
Daniel Veillard3646d642004-06-02 19:19:14 +000011203 /*
11204 * Gather attribute uses defined by this type.
11205 */
11206 if (attrs != NULL) {
11207 if (xmlSchemaBuildAttributeUsesOwned(ctxt, attrs,
11208 &uses, &lastUse) == -1) {
11209 return (-1);
11210 }
11211 }
11212 /* 3.4.6 -> Complex Type Definition Properties Correct 4.
11213 * "Two distinct attribute declarations in the {attribute uses} must
11214 * not have identical {name}s and {target namespace}s."
11215 *
11216 * For "extension" this is done further down.
11217 */
11218 if ((uses != NULL) && ((type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) == 0)) {
11219 cur = uses;
11220 while (cur != NULL) {
11221 tmp = cur->next;
11222 while (tmp != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011223 if ((xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
11224 xmlSchemaGetAttrName(tmp->attr))) &&
11225 (xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr ),
11226 xmlSchemaGetAttrTargetNsURI(tmp->attr)))) {
11227
11228 xmlSchemaPAttrUseErr(ctxt,
11229 XML_SCHEMAP_CT_PROPS_CORRECT_4,
11230 NULL, type, NULL, cur->attr,
11231 "Duplicate attribute use %s specified",
11232 xmlSchemaFormatNsUriLocal(&str,
11233 xmlSchemaGetAttrTargetNsURI(tmp->attr),
11234 xmlSchemaGetAttrName(tmp->attr))
11235 );
11236 FREE_AND_NULL(str)
Daniel Veillard3646d642004-06-02 19:19:14 +000011237 break;
11238 }
11239 tmp = tmp->next;
11240 }
11241 cur = cur->next;
11242 }
11243 }
11244 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
11245 /*
11246 * Derive by restriction.
11247 */
11248 if (baseIsAnyType) {
11249 type->attributeUses = uses;
11250 } else {
11251 int found;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011252 const xmlChar *bEffValue;
11253 int effFixed;
Daniel Veillard3646d642004-06-02 19:19:14 +000011254
11255 cur = uses;
11256 while (cur != NULL) {
11257 found = 0;
11258 base = type->attributeUses;
11259 while (base != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011260 if (xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
11261 xmlSchemaGetAttrName(base->attr)) &&
11262 xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr),
11263 xmlSchemaGetAttrTargetNsURI(base->attr))) {
Daniel Veillard3646d642004-06-02 19:19:14 +000011264
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011265 found = 1;
11266
Daniel Veillard3646d642004-06-02 19:19:14 +000011267 if ((cur->attr->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
11268 (base->attr->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED)) {
11269 /*
11270 * derivation-ok-restriction 2.1.1
Daniel Veillardc0826a72004-08-10 14:17:33 +000011271 */
11272 xmlSchemaPAttrUseErr(ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +000011273 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011274 NULL, type, NULL, cur->attr,
11275 "The 'optional' use is inconsistent with a matching "
11276 "'required' use of the base type", NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +000011277 } else if ((cur->attr->occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) &&
11278 (base->attr->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED)) {
11279 /*
11280 * derivation-ok-restriction 3
11281 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000011282 xmlSchemaPCustomErr(ctxt,
11283 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_3,
11284 NULL, type, NULL,
11285 "A matching attribute use for the 'required' "
11286 "attribute use %s of the base type is missing",
11287 xmlSchemaFormatNsUriLocal(&str,
11288 xmlSchemaGetAttrTargetNsURI(base->attr),
11289 xmlSchemaGetAttrName(base->attr)));
11290 FREE_AND_NULL(str)
Daniel Veillard3646d642004-06-02 19:19:14 +000011291 } else {
11292 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011293 * 2.1.3 [Definition:] Let the effective value
11294 * constraint of an attribute use be its {value
11295 * constraint}, if present, otherwise its {attribute
11296 * declaration}'s {value constraint} .
11297 */
11298 xmlSchemaGetEffectiveValueConstraint(base->attr, &effFixed,
11299 &bEffValue, 0);
11300 /*
11301 * 2.1.3 ... one of the following must be true
11302 *
11303 * 2.1.3.1 B's ·effective value constraint· is
11304 * ·absent· or default.
11305 */
11306 if ((bEffValue != NULL) &&
11307 (effFixed == 1)) {
11308 const xmlChar *rEffValue = NULL;
11309
11310 xmlSchemaGetEffectiveValueConstraint(base->attr, &effFixed,
11311 &rEffValue, 0);
11312 /*
11313 * 2.1.3.2 R's ·effective value constraint· is
11314 * fixed with the same string as B's.
11315 */
11316 if ((effFixed == 0) ||
11317 (! xmlStrEqual(rEffValue, bEffValue))) {
11318 xmlSchemaPAttrUseErr(ctxt,
11319 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_3,
11320 NULL, type, NULL, cur->attr,
11321 "The effective value constraint of the "
11322 "attribute use is inconsistent with "
11323 "its correspondent of the base type",
11324 NULL);
11325 }
11326 }
11327 /*
11328 * TODO: derivation-ok-restriction 2.1.2 ({type definition} must be validly derived)
11329 */
11330 /*
Daniel Veillard3646d642004-06-02 19:19:14 +000011331 * Override the attribute use.
11332 */
11333 base->attr = cur->attr;
11334 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011335
Daniel Veillard3646d642004-06-02 19:19:14 +000011336 break;
11337 }
11338 base = base->next;
11339 }
11340
11341 if (!found) {
11342 if (cur->attr->occurs != XML_SCHEMAS_ATTR_USE_PROHIBITED) {
11343 /*
11344 * derivation-ok-restriction 2.2
11345 */
11346 if ((type->attributeWildcard != NULL) &&
11347 xmlSchemaMatchesWildcardNs(type->attributeWildcard,
11348 cur->attr->targetNamespace))
11349 found = 1;
11350
11351 if (!found) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011352 xmlSchemaPAttrUseErr(ctxt,
11353 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_2,
11354 NULL, type, NULL, cur->attr,
11355 "Neither a matching attribute use, "
11356 "nor a matching wildcard in the base type does exist",
11357 NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +000011358 } else {
11359 /*
11360 * Add the attribute use.
11361 *
11362 * Note that this may lead to funny derivation error reports, if
11363 * multiple equal attribute uses exist; but this is not
11364 * allowed anyway, and it will be reported beforehand.
11365 */
11366 tmp = cur;
11367 if (prev != NULL)
11368 prev->next = cur->next;
11369 else
11370 uses = cur->next;
11371 cur = cur->next;
11372 if (type->attributeUses == NULL) {
11373 type->attributeUses = tmp;
11374 } else
11375 lastBaseUse->next = tmp;
11376 lastBaseUse = tmp;
11377
11378 continue;
11379 }
11380 }
11381 }
11382 prev = cur;
11383 cur = cur->next;
11384 }
11385 if (uses != NULL)
11386 xmlSchemaFreeAttributeUseList(uses);
11387 }
11388 } else if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
11389 /*
11390 * The spec allows only appending, and not other kinds of extensions.
11391 *
11392 * This ensures: Schema Component Constraint: Derivation Valid (Extension) : 1.2
11393 */
11394 if (uses != NULL) {
11395 if (type->attributeUses == NULL) {
11396 type->attributeUses = uses;
11397 } else
11398 lastBaseUse->next = uses;
Daniel Veillard50355f02004-06-08 17:52:16 +000011399 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011400 } else {
11401 /*
Daniel Veillard50355f02004-06-08 17:52:16 +000011402 * Derive implicitely from the ur-type.
11403 */
Daniel Veillard3646d642004-06-02 19:19:14 +000011404 type->attributeUses = uses;
Daniel Veillard50355f02004-06-08 17:52:16 +000011405 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011406 /*
11407 * 3.4.6 -> Complex Type Definition Properties Correct
11408 */
11409 if (type->attributeUses != NULL) {
11410 cur = type->attributeUses;
11411 prev = NULL;
11412 while (cur != NULL) {
11413 /*
11414 * 4. Two distinct attribute declarations in the {attribute uses} must
11415 * not have identical {name}s and {target namespace}s.
Daniel Veillard50355f02004-06-08 17:52:16 +000011416 *
Daniel Veillard3646d642004-06-02 19:19:14 +000011417 * Note that this was already done for "restriction" and types derived from
11418 * the ur-type.
Daniel Veillard50355f02004-06-08 17:52:16 +000011419 */
Daniel Veillard3646d642004-06-02 19:19:14 +000011420 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
11421 tmp = cur->next;
11422 while (tmp != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011423 if ((xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
11424 xmlSchemaGetAttrName(tmp->attr))) &&
11425 (xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr ),
11426 xmlSchemaGetAttrTargetNsURI(tmp->attr)))) {
Daniel Veillard3646d642004-06-02 19:19:14 +000011427
Daniel Veillardc0826a72004-08-10 14:17:33 +000011428 xmlSchemaPAttrUseErr(ctxt,
11429 XML_SCHEMAP_CT_PROPS_CORRECT_4,
11430 NULL, type, NULL, tmp->attr,
11431 "Duplicate attribute use specified", NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +000011432 break;
11433 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011434 tmp = tmp->next;
Daniel Veillard50355f02004-06-08 17:52:16 +000011435 }
11436 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011437 /*
11438 * 5. Two distinct attribute declarations in the {attribute uses} must
11439 * not have {type definition}s which are or are derived from ID.
11440 */
11441 if ((cur->attr->subtypes != NULL) &&
Daniel Veillard01fa6152004-06-29 17:04:39 +000011442 (xmlSchemaIsDerivedFromBuiltInType(ctxt, (xmlSchemaTypePtr) cur->attr, XML_SCHEMAS_ID))) {
Daniel Veillard3646d642004-06-02 19:19:14 +000011443 if (id != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011444 xmlSchemaPAttrUseErr(ctxt,
11445 XML_SCHEMAP_CT_PROPS_CORRECT_5,
11446 NULL, type, NULL, cur->attr,
11447 "There must not exist more than one attribute use, "
11448 "declared of type 'ID' or derived from it",
11449 NULL);
11450 FREE_AND_NULL(str)
Daniel Veillard50355f02004-06-08 17:52:16 +000011451 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011452 id = cur;
11453 }
11454 /*
11455 * Remove "prohibited" attribute uses. The reason this is done at this late
11456 * stage is to be able to catch dublicate attribute uses. So we had to keep
11457 * prohibited uses in the list as well.
11458 */
11459 if (cur->attr->occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) {
11460 tmp = cur;
11461 if (prev == NULL)
11462 type->attributeUses = cur->next;
11463 else
11464 prev->next = cur->next;
11465 cur = cur->next;
Daniel Veillard50355f02004-06-08 17:52:16 +000011466 xmlFree(tmp);
Daniel Veillard3646d642004-06-02 19:19:14 +000011467 } else {
11468 prev = cur;
11469 cur = cur->next;
11470 }
11471 }
11472 }
11473 /*
11474 * TODO: This check should be removed if we are 100% sure of
11475 * the base type attribute uses already being built.
11476 */
11477 if ((baseType != NULL) && (!baseIsAnyType) &&
11478 (baseType->type == XML_SCHEMA_TYPE_COMPLEX) &&
11479 (baseType->contentType == XML_SCHEMA_CONTENT_UNKNOWN)) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000011480 xmlSchemaPErr(ctxt, baseType->node, XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011481 "Internal error: xmlSchemaBuildAttributeValidation: "
Daniel Veillardc0826a72004-08-10 14:17:33 +000011482 "attribute uses not builded on base type '%s'.\n",
Daniel Veillard3646d642004-06-02 19:19:14 +000011483 baseType->name, NULL);
11484 }
11485 return (0);
11486}
11487
11488/**
Daniel Veillard01fa6152004-06-29 17:04:39 +000011489 * xmlSchemaTypeFinalContains:
11490 * @schema: the schema
11491 * @type: the type definition
11492 * @final: the final
11493 *
11494 * Evaluates if a type definition contains the given "final".
11495 * This does take "finalDefault" into account as well.
11496 *
11497 * Returns 1 if the type does containt the given "final",
11498 * 0 otherwise.
11499 */
11500static int
11501xmlSchemaTypeFinalContains(xmlSchemaPtr schema, xmlSchemaTypePtr type, int final)
11502{
11503 int tfinal = final, tflags = type->flags;
11504
11505 if (type == NULL)
11506 return (0);
11507 if (type->flags & XML_SCHEMAS_TYPE_FINAL_DEFAULT) {
11508 switch (final) {
11509 case XML_SCHEMAS_TYPE_FINAL_RESTRICTION:
11510 tfinal = XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION;
11511 break;
11512 case XML_SCHEMAS_TYPE_FINAL_EXTENSION:
11513 tfinal = XML_SCHEMAS_FINAL_DEFAULT_EXTENSION;
11514 break;
11515 case XML_SCHEMAS_TYPE_FINAL_LIST:
11516 tfinal = XML_SCHEMAS_FINAL_DEFAULT_LIST;
11517 break;
11518 case XML_SCHEMAS_TYPE_FINAL_UNION:
11519 tfinal = XML_SCHEMAS_FINAL_DEFAULT_UNION;
11520 break;
11521 }
11522 tflags = schema->flags;
11523 }
11524 if (tflags & tfinal)
11525 return (1);
11526 else
11527 return (0);
11528
11529}
11530
11531/**
11532 * xmlSchemaGetUnionSimpleTypeMemberTypes:
11533 * @type: the Union Simple Type
11534 *
11535 * Returns a list of member types of @type if existing,
11536 * returns NULL otherwise.
11537 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011538static xmlSchemaTypeLinkPtr
Daniel Veillard01fa6152004-06-29 17:04:39 +000011539xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type)
11540{
11541 while (type != NULL) {
11542 if (type->memberTypes != NULL)
11543 return (type->memberTypes);
11544 else
11545 type = type->baseType;
11546 }
11547 return (NULL);
11548}
11549
11550/**
11551 * xmlSchemaGetListSimpleTypeItemType:
11552 * @type: the simple type definition
11553 *
11554 * Returns the item type definition of the list simple type.
11555 */
11556static xmlSchemaTypePtr
11557xmlSchemaGetListSimpleTypeItemType(xmlSchemaTypePtr type)
11558{
11559 if ((type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) == 0)
11560 return (NULL);
11561 /*
11562 * Note: In libxml2, the built-in types do not reflect
11563 * the datatype hierarchy (yet?) - we have to treat them
11564 * in a special way.
11565 */
11566 if (type->type == XML_SCHEMA_TYPE_BASIC)
11567 return (xmlSchemaGetBuiltInListSimpleTypeItemType(type));
11568 if (type->subtypes->type == XML_SCHEMA_TYPE_LIST)
11569 /* 1 If the <list> alternative is chosen, then the type
11570 * definition ·resolved· to by the ·actual value· of the
11571 * itemType [attribute] of <list>, if present, otherwise
11572 * the type definition corresponding to the <simpleType>
11573 * among the [children] of <list>.
11574 */
11575 return (type->subtypes->subtypes);
11576 else {
11577 /* 2 If the <restriction> option is chosen, then the
11578 * {item type definition} of the {base type definition}.
11579 */
11580 return (xmlSchemaGetListSimpleTypeItemType(type->baseType));
11581 }
11582}
11583
11584/**
11585 * xmlSchemaCheckCOSSTDerivedOK:
11586 * @type: the derived simple type definition
11587 * @baseType: the base type definition
11588 *
11589 * Checks wheter @type can be validly
11590 * derived from @baseType.
11591 *
11592 * Returns 0 on success, an positive error code otherwise.
11593 */
11594static int
11595xmlSchemaCheckCOSSTDerivedOK(xmlSchemaPtr schema,
11596 xmlSchemaTypePtr type,
11597 xmlSchemaTypePtr baseType,
11598 int subset)
11599{
11600 /*
11601 * Schema Component Constraint: Type Derivation OK (Simple)
11602 *
11603 *
11604 * 1 They are the same type definition.
11605 * TODO: The identy check might have to be more complex than this.
11606 */
11607 if (type == baseType)
11608 return (0);
11609 /*
11610 * 2.1 restriction is not in the subset, or in the {final}
11611 * of its own {base type definition};
11612 */
11613 if ((subset & XML_SCHEMAS_TYPE_FINAL_RESTRICTION) ||
11614 (xmlSchemaTypeFinalContains(schema,
11615 type->baseType, XML_SCHEMAS_TYPE_FINAL_RESTRICTION))) {
11616 return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_1);
11617 }
11618 /* 2.2 */
11619 if (type->baseType == baseType) {
11620 /*
11621 * 2.2.1 D's ·base type definition· is B.
11622 */
11623 return (0);
11624 }
11625 /*
11626 * 2.2.2 D's ·base type definition· is not the ·ur-type definition·
11627 * and is validly derived from B given the subset, as defined by this
11628 * constraint.
11629 */
11630 if ((type->baseType != xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE)) &&
11631 (xmlSchemaCheckCOSSTDerivedOK(schema, type->baseType, baseType, subset) == 0)) {
11632 return (0);
11633 }
11634 /*
11635 * 2.2.3 D's {variety} is list or union and B is the ·simple ur-type
11636 * definition·.
11637 */
11638 if (((type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) ||
11639 (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION)) &&
11640 (baseType == xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE))) {
11641 return (0);
11642 }
11643 /*
11644 * 2.2.4 B's {variety} is union and D is validly derived from a type
11645 * definition in B's {member type definitions} given the subset, as
11646 * defined by this constraint.
11647 *
11648 * NOTE: This seems not to involve built-in types, since there is no
11649 * built-in Union Simple Type.
11650 */
11651 if (baseType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
11652 xmlSchemaTypeLinkPtr cur;
11653
11654 cur = baseType->memberTypes;
11655 while (cur != NULL) {
11656 if (xmlSchemaCheckCOSSTDerivedOK(schema, type,
11657 cur->type, subset) == 0)
11658 return (0);
11659 cur = cur->next;
11660 }
11661 }
11662
11663 return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_2);
11664}
11665
11666
11667/**
11668 * xmlSchemaCheckSTPropsCorrect:
11669 * @ctxt: the schema parser context
11670 * @type: the simple type definition
11671 *
11672 * Checks st-props-correct.
11673 *
11674 * Returns 0 if the properties are correct,
11675 * if not, a positive error code and -1 on internal
11676 * errors.
11677 */
11678static int
11679xmlSchemaCheckSTPropsCorrect(xmlSchemaParserCtxtPtr ctxt,
11680 xmlSchemaTypePtr type)
11681{
11682 xmlSchemaTypePtr baseType = type->baseType, anySimpleType,
11683 anyType;
Daniel Veillardc0826a72004-08-10 14:17:33 +000011684 xmlChar *str = NULL;
Daniel Veillard01fa6152004-06-29 17:04:39 +000011685
Daniel Veillardc0826a72004-08-10 14:17:33 +000011686 /* STATE: error funcs converted. */
Daniel Veillard01fa6152004-06-29 17:04:39 +000011687 /*
11688 * Schema Component Constraint: Simple Type Definition Properties Correct
11689 *
11690 * NOTE: This is somehow redundant, since we actually built a simple type
11691 * to have all the needed information; this acts as an self test.
11692 */
11693 anySimpleType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
11694 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
11695 /*
11696 * TODO: 1 The values of the properties of a simple type definition must be as
11697 * described in the property tableau in Datatype definition, modulo the
11698 * impact of Missing Sub-components (§5.3).
11699 */
11700 /* Base type: If the datatype has been ·derived· by ·restriction·
11701 * then the Simple Type Definition component from which it is ·derived·,
11702 * otherwise the Simple Type Definition for anySimpleType (§4.1.6).
11703 */
11704 if (baseType == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011705 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011706 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011707 NULL, type, NULL,
11708 "No base type existent", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011709 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
11710 }
11711 if ((baseType->type != XML_SCHEMA_TYPE_SIMPLE) &&
11712 ((baseType->type != XML_SCHEMA_TYPE_BASIC) ||
11713 (baseType == anyType))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011714 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011715 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011716 NULL, type, NULL,
11717 "The base type %s is not a simple type",
11718 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
11719 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011720 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
11721 }
11722 if ((baseType != anySimpleType) &&
11723 (type->subtypes->type != XML_SCHEMA_TYPE_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011724 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011725 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011726 NULL, type, NULL,
11727 "A type, derived by list or union, must have"
11728 "the simple ur-type definition as base type, not %s",
11729 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
11730 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011731 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
11732 }
11733 /*
11734 * Variety: One of {atomic, list, union}.
11735 */
11736 if (((type->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) &&
11737 ((type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) == 0) &&
11738 ((type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) == 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011739 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011740 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011741 NULL, type, NULL,
11742 "The variety is absent", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011743 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
11744 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000011745 /* TODO: Finish this. Hmm, is this finished? */
Daniel Veillard01fa6152004-06-29 17:04:39 +000011746
11747 /*
11748 * 2 All simple type definitions must be derived ultimately from the ·simple
11749 * ur-type definition (so· circular definitions are disallowed). That is, it
11750 * must be possible to reach a built-in primitive datatype or the ·simple
11751 * ur-type definition· by repeatedly following the {base type definition}.
11752 */
11753 baseType = type->baseType;
11754 while ((baseType != NULL) && (baseType->type != XML_SCHEMA_TYPE_BASIC)) {
11755 if (baseType->contentType == XML_SCHEMA_CONTENT_UNKNOWN)
11756 xmlSchemaTypeFixup(baseType, ctxt, NULL);
11757 if (baseType == anySimpleType)
11758 break;
11759 else if (baseType == type) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011760 xmlSchemaPCustomErr(ctxt,
11761 XML_SCHEMAP_ST_PROPS_CORRECT_2,
11762 NULL, type, NULL,
11763 "The definition is circular", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011764 return (XML_SCHEMAP_ST_PROPS_CORRECT_2);
11765 }
11766 baseType = baseType->baseType;
11767 }
11768 /*
11769 * 3 The {final} of the {base type definition} must not contain restriction.
11770 */
11771 if (xmlSchemaTypeFinalContains(ctxt->schema, baseType,
11772 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011773 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011774 XML_SCHEMAP_ST_PROPS_CORRECT_3,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011775 NULL, type, NULL,
11776 "The 'final' of its base type %s must not contain "
11777 "'restriction'",
11778 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
11779 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011780 return (XML_SCHEMAP_ST_PROPS_CORRECT_3);
11781 }
11782 return (0);
11783}
11784
11785/**
11786 * xmlSchemaCheckDerivationValidSimpleRestriction:
11787 * @ctxt: the schema parser context
11788 * @type: the simple type definition
11789 *
11790 * Checks if the given @type (simpleType) is derived
11791 * validly by restriction.
11792 *
11793 * Returns -1 on internal errors, 0 if the type is validly derived,
11794 * a positive error code otherwise.
11795 */
11796static int
11797xmlSchemaCheckCOSSTRestricts(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011798 xmlSchemaTypePtr type)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011799{
Daniel Veillardc0826a72004-08-10 14:17:33 +000011800 xmlChar *str = NULL;
11801
11802 /* STATE: error funcs converted. */
Daniel Veillard01fa6152004-06-29 17:04:39 +000011803
11804 if (type->type != XML_SCHEMA_TYPE_SIMPLE) {
11805 xmlSchemaPErr(ctxt, type->node,
11806 XML_ERR_INTERNAL_ERROR,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011807 "xmlSchemaCheckDerivationValidSimpleRestriction: The given "
11808 "type '%s' is not a user-derived simpleType.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000011809 type->name, NULL);
11810 return (-1);
11811 }
11812
11813 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) {
11814 xmlSchemaTypePtr primitive;
11815 /*
11816 * 1.1 The {base type definition} must be an atomic simple
11817 * type definition or a built-in primitive datatype.
11818 */
11819 if ((type->baseType->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011820 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011821 XML_SCHEMAP_COS_ST_RESTRICTS_1_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011822 NULL, type, NULL,
11823 "The base type %s is not an atomic simple type",
11824 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
11825 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011826 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_1);
11827 }
11828 /* 1.2 The {final} of the {base type definition} must not contain
11829 * restriction.
11830 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000011831 /* OPTIMIZE TODO : This is already done in xmlSchemaCheckStPropsCorrect */
Daniel Veillard01fa6152004-06-29 17:04:39 +000011832 if (xmlSchemaTypeFinalContains(ctxt->schema, type->baseType,
11833 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011834 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011835 XML_SCHEMAP_COS_ST_RESTRICTS_1_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011836 NULL, type, NULL,
11837 "The final of its base type %s must not contain 'restriction'",
11838 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
11839 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011840 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_2);
11841 }
11842
11843 /*
11844 * 1.3.1 DF must be an allowed constraining facet for the {primitive
11845 * type definition}, as specified in the appropriate subsection of 3.2
11846 * Primitive datatypes.
11847 */
11848 if (type->facets != NULL) {
11849 xmlSchemaFacetPtr facet;
11850 int ok = 1;
11851
11852 primitive = xmlSchemaGetPrimitiveType(type);
11853 if (primitive == NULL) {
11854 xmlSchemaPErr(ctxt, type->node,
11855 XML_ERR_INTERNAL_ERROR,
11856 "xmlSchemaCheckDerivationValidSimpleRestriction: failed "
Daniel Veillardc0826a72004-08-10 14:17:33 +000011857 "to get primitive type of type '%s'.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000011858 type->name, NULL);
11859 return (-1);
11860 }
11861 facet = type->facets;
11862 do {
11863 if (xmlSchemaIsBuiltInTypeFacet(primitive, facet->type) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011864 ok = 0;
11865 xmlSchemaPIllegalFacetAtomicErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011866 XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011867 NULL, type, primitive, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011868 }
11869 facet = facet->next;
11870 } while (facet != NULL);
11871 if (ok == 0)
Daniel Veillardc0826a72004-08-10 14:17:33 +000011872 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011873 }
11874 /*
11875 * TODO: 1.3.2 (facet derivation)
11876 */
11877 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
11878 xmlSchemaTypePtr itemType = NULL;
11879
11880 itemType = xmlSchemaGetListSimpleTypeItemType(type);
11881 if (itemType == NULL) {
11882 xmlSchemaPErr(ctxt, type->node,
11883 XML_ERR_INTERNAL_ERROR,
11884 "Internal error: xmlSchemaCheckDerivationValidSimpleRestriction: "
Daniel Veillardc0826a72004-08-10 14:17:33 +000011885 "failed to evaluate the item type of type '%s'.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000011886 type->name, NULL);
11887 return (-1);
11888 }
11889 /*
11890 * 2.1 The {item type definition} must have a {variety} of atomic or
11891 * union (in which case all the {member type definitions}
11892 * must be atomic).
11893 */
11894 if (((itemType->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) &&
11895 ((itemType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) == 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011896 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011897 XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011898 NULL, type, NULL,
11899 "The item type %s must have a variety of atomic or union",
11900 xmlSchemaFormatItemForReport(&str, NULL, itemType, NULL, 1));
11901 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011902 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
11903 } else if (itemType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
11904 xmlSchemaTypeLinkPtr member;
11905
11906 member = itemType->memberTypes;
11907 while (member != NULL) {
11908 if ((member->type->flags &
11909 XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011910 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011911 XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011912 NULL, type, NULL,
11913 "The item type is a union type, but the "
11914 "member type %s of this item type is not atomic",
11915 xmlSchemaFormatItemForReport(&str, NULL, member->type, NULL, 1));
11916 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011917 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
11918 }
11919 member = member->next;
11920 }
11921 }
11922
11923 if (type->baseType == xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE)) {
11924 xmlSchemaFacetPtr facet;
11925 /*
11926 * This is the case if we have: <simpleType><list ..
11927 */
11928 /*
11929 * 2.3.1
11930 * 2.3.1.1 The {final} of the {item type definition} must not
11931 * contain list.
11932 */
11933 if (xmlSchemaTypeFinalContains(ctxt->schema,
11934 itemType, XML_SCHEMAS_TYPE_FINAL_LIST)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011935 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011936 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011937 NULL, type, NULL,
11938 "The final of its item type %s must not contain 'list'",
11939 xmlSchemaFormatItemForReport(&str, NULL, itemType, NULL, 1));
11940 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011941 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1);
11942 }
11943 /*
11944 * 2.3.1.2 The {facets} must only contain the whiteSpace
11945 * facet component.
11946 */
11947 if (type->facets != NULL) {
11948 facet = type->facets;
11949 do {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011950 if (facet->type != XML_SCHEMA_FACET_WHITESPACE) {
11951 xmlSchemaPIllegalFacetListUnionErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011952 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011953 NULL, type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011954 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2);
11955 }
11956 facet = facet->next;
11957 } while (facet != NULL);
11958 }
11959 /*
11960 * TODO: Datatypes states:
11961 * A ·list· datatype can be ·derived· from an ·atomic· datatype
11962 * whose ·lexical space· allows space (such as string or anyURI)or
11963 * a ·union· datatype any of whose {member type definitions}'s
11964 * ·lexical space· allows space.
11965 */
11966 } else {
11967 /*
11968 * This is the case if we have: <simpleType><restriction ...
11969 */
11970 /*
11971 * 2.3.2
11972 * 2.3.2.1 The {base type definition} must have a {variety} of list.
11973 */
11974 if ((type->baseType->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011975 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011976 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011977 NULL, type, NULL,
11978 "The base type %s must be a list type",
11979 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
11980 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011981 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1);
11982 }
11983 /*
11984 * 2.3.2.2 The {final} of the {base type definition} must not
11985 * contain restriction.
11986 */
11987 if (xmlSchemaTypeFinalContains(ctxt->schema, type->baseType,
11988 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011989 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011990 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011991 NULL, type, NULL,
11992 "The final of the base type %s must not contain 'restriction'",
11993 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
11994 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011995 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2);
11996 }
11997 /*
11998 * 2.3.2.3 The {item type definition} must be validly derived
11999 * from the {base type definition}'s {item type definition} given
12000 * the empty set, as defined in Type Derivation OK (Simple) (§3.14.6).
12001 */
12002 {
12003 xmlSchemaTypePtr baseItemType;
12004
12005 baseItemType = xmlSchemaGetListSimpleTypeItemType(type->baseType);
12006 if (baseItemType == NULL) {
12007 xmlSchemaPErr(ctxt, type->node,
12008 XML_ERR_INTERNAL_ERROR,
12009 "xmlSchemaCheckDerivationValidSimpleRestriction: "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012010 "List simple type '%s': Failed to "
12011 "evaluate the item type of its base type '%s'.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000012012 type->name, type->baseType->name);
12013 return (-1);
12014 }
12015 if ((itemType != baseItemType) &&
12016 (xmlSchemaCheckCOSSTDerivedOK(ctxt->schema, itemType,
12017 baseItemType, 0) != 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012018 xmlChar *strBIT = NULL, *strBT = NULL;
12019 xmlSchemaPCustomErrExt(ctxt,
12020 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3,
12021 NULL, type, NULL,
12022 "The item type %s is not validly derived from the "
12023 "item type %s of the base type %s",
12024 xmlSchemaFormatItemForReport(&str, NULL, itemType, NULL, 1),
12025 xmlSchemaFormatItemForReport(&strBIT, NULL, baseItemType, NULL, 1),
12026 xmlSchemaFormatItemForReport(&strBT, NULL, type->baseType, NULL, 1));
12027
12028 FREE_AND_NULL(str)
12029 FREE_AND_NULL(strBIT)
12030 FREE_AND_NULL(strBT)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012031 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3);
12032 }
12033 }
12034
12035 if (type->facets != NULL) {
12036 xmlSchemaFacetPtr facet;
12037 int ok = 1;
12038 /*
12039 * 2.3.2.4 Only length, minLength, maxLength, whiteSpace, pattern
12040 * and enumeration facet components are allowed among the {facets}.
12041 */
12042 facet = type->facets;
12043 do {
12044 switch (facet->type) {
12045 case XML_SCHEMA_FACET_LENGTH:
12046 case XML_SCHEMA_FACET_MINLENGTH:
12047 case XML_SCHEMA_FACET_MAXLENGTH:
12048 case XML_SCHEMA_FACET_WHITESPACE:
12049 /*
12050 * TODO: 2.5.1.2 List datatypes
12051 * The value of ·whiteSpace· is fixed to the value collapse.
12052 */
12053 case XML_SCHEMA_FACET_PATTERN:
12054 case XML_SCHEMA_FACET_ENUMERATION:
12055 break;
12056 default: {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012057 xmlSchemaPIllegalFacetListUnionErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012058 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012059 NULL, type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012060 /*
12061 * We could return, but it's nicer to report all
12062 * invalid facets.
12063 */
12064 ok = 0;
12065 }
12066 }
12067 facet = facet->next;
12068 } while (facet != NULL);
12069 if (ok == 0)
12070 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4);
12071 /*
12072 * TODO: 2.3.2.5 For each facet in the {facets} (call this DF), if there
12073 * is a facet of the same kind in the {facets} of the {base type
12074 * definition} (call this BF),then the DF's {value} must be a valid
12075 * restriction of BF's {value} as defined in [XML Schemas: Datatypes].
12076 */
12077 }
12078
12079
12080 }
12081 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
12082 /*
12083 * 3.1 The {member type definitions} must all have {variety} of
12084 * atomic or list.
12085 */
12086 xmlSchemaTypeLinkPtr member;
12087
12088 member = type->memberTypes;
12089 while (member != NULL) {
12090 if (((member->type->flags &
12091 XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) &&
12092 ((member->type->flags &
12093 XML_SCHEMAS_TYPE_VARIETY_LIST) == 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012094 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012095 XML_SCHEMAP_COS_ST_RESTRICTS_3_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012096 NULL, type, NULL,
12097 "The member type %s is neither an atomic, nor a list type",
12098 xmlSchemaFormatItemForReport(&str, NULL, member->type, NULL, 1));
12099 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012100 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_1);
12101 }
12102 member = member->next;
12103 }
12104 /*
12105 * 3.3.1 If the {base type definition} is the ·simple ur-type
12106 * definition·
12107 */
12108 if (type->baseType == xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE)) {
12109 /*
12110 * 3.3.1.1 All of the {member type definitions} must have a
12111 * {final} which does not contain union.
12112 */
12113 member = type->memberTypes;
12114 while (member != NULL) {
12115 if (xmlSchemaTypeFinalContains(ctxt->schema, member->type,
12116 XML_SCHEMAS_TYPE_FINAL_UNION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012117 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012118 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012119 NULL, type, NULL,
12120 "The final of member type %s contains 'union'",
12121 xmlSchemaFormatItemForReport(&str, NULL, member->type, NULL, 1));
12122 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012123 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1);
12124 }
12125 member = member->next;
12126 }
12127 /*
12128 * 3.3.1.2 The {facets} must be empty.
12129 */
12130 if (type->facetSet != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012131 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012132 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012133 NULL, type, NULL,
12134 "No facets allowed", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012135 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2);
12136 }
12137 } else {
12138 /*
12139 * 3.3.2.1 The {base type definition} must have a {variety} of union.
12140 */
12141 if ((type->baseType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012142 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012143 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012144 NULL, type, NULL,
12145 "The base type %s is not a union type",
12146 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
12147 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012148 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1);
12149 }
12150 /*
12151 * 3.3.2.2 The {final} of the {base type definition} must not contain restriction.
12152 */
12153 if (xmlSchemaTypeFinalContains(ctxt->schema, type->baseType,
12154 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012155 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012156 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012157 NULL, type, NULL,
12158 "The final of its base type %s must not contain 'restriction'",
12159 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
12160 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012161 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2);
12162 }
12163 /*
12164 * 3.3.2.3 The {member type definitions}, in order, must be validly
12165 * derived from the corresponding type definitions in the {base
12166 * type definition}'s {member type definitions} given the empty set,
12167 * as defined in Type Derivation OK (Simple) (§3.14.6).
12168 */
12169 {
12170 xmlSchemaTypeLinkPtr baseMember;
12171
12172 /*
12173 * OPTIMIZE: if the type is restricting, it has no local defined
12174 * member types and inherits the member types of the base type;
12175 * thus a check for equality can be skipped.
12176 */
12177 /*
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000012178 * Even worse: I cannot see a scenario where a restricting
Daniel Veillard01fa6152004-06-29 17:04:39 +000012179 * union simple type can have other member types as the member
12180 * types of it's base type. This check seems not necessary with
12181 * respect to the derivation process in libxml2.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000012182 * But necessary if constructing types with an API.
Daniel Veillard01fa6152004-06-29 17:04:39 +000012183 */
12184 if (type->memberTypes != NULL) {
12185 member = type->memberTypes;
12186 baseMember = xmlSchemaGetUnionSimpleTypeMemberTypes(type->baseType);
12187 if ((member == NULL) && (baseMember != NULL)) {
12188 xmlSchemaPErr(ctxt, type->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012189 XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012190 "Internal error: "
12191 "xmlSchemaCheckDerivationValidSimpleRestriction "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012192 "(3.3.2.3), union simple type '%s', unequal number "
Daniel Veillard01fa6152004-06-29 17:04:39 +000012193 "of member types in the base type\n",
12194 type->name, NULL);
12195 }
12196 while (member != NULL) {
12197 if (baseMember == NULL) {
12198 xmlSchemaPErr(ctxt, type->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012199 XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012200 "Internal error: "
12201 "xmlSchemaCheckDerivationValidSimpleRestriction "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012202 "(3.3.2.3), union simple type '%s', unequal number "
12203 "of member types in the base type.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000012204 type->name, NULL);
12205 }
12206 if ((member->type != baseMember->type) &&
12207 (xmlSchemaCheckCOSSTDerivedOK(ctxt->schema,
12208 member->type, baseMember->type, 0) != 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012209 xmlChar *strBMT = NULL, *strBT = NULL;
12210
12211 xmlSchemaPCustomErrExt(ctxt,
12212 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3,
12213 NULL, type, NULL,
12214 "The member type %s is not validly derived from its "
12215 "corresponding member type %s of the base type %s",
12216 xmlSchemaFormatItemForReport(&str, NULL, member->type, NULL, 1),
12217 xmlSchemaFormatItemForReport(&strBMT, NULL, baseMember->type, NULL, 1),
12218 xmlSchemaFormatItemForReport(&strBT, NULL, type->baseType, NULL, 1));
12219 FREE_AND_NULL(str)
12220 FREE_AND_NULL(strBMT)
12221 FREE_AND_NULL(strBT)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012222 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3);
12223 }
12224 member = member->next;
12225 baseMember = baseMember->next;
12226 }
12227 }
12228 }
12229 /*
12230 * 3.3.2.4 Only pattern and enumeration facet components are
12231 * allowed among the {facets}.
12232 */
12233 if (type->facets != NULL) {
12234 xmlSchemaFacetPtr facet;
12235 int ok = 1;
12236
12237 facet = type->facets;
12238 do {
12239 if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
12240 (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012241 xmlSchemaPIllegalFacetListUnionErr(ctxt,
12242 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4,
12243 NULL, type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012244 ok = 0;
12245 }
12246 facet = facet->next;
12247 } while (facet != NULL);
12248 if (ok == 0)
12249 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4);
12250
12251 }
12252 /*
12253 * TODO: 3.3.2.5 (facet derivation)
12254 */
12255 }
12256 }
12257
12258 return (0);
12259}
12260
12261/**
12262 * xmlSchemaCheckSRCSimpleType:
12263 * @ctxt: the schema parser context
12264 * @type: the simple type definition
12265 *
12266 * Checks crc-simple-type constraints.
12267 *
12268 * Returns 0 if the constraints are satisfied,
12269 * if not a positive error code and -1 on internal
12270 * errors.
12271 */
12272static int
12273xmlSchemaCheckSRCSimpleType(xmlSchemaParserCtxtPtr ctxt,
12274 xmlSchemaTypePtr type)
12275{
12276 /*
12277 * NOTE: src-simple-type 2-4 are redundant, since the checks
12278 * were are done for the corresponding <restriction>, <list> and <union>
12279 * elements, but W3C wants a <simpleType> error as well, so it gets one.
12280 * Maby this can be skipped in the future, if we get sure it's not needed.
12281 */
12282 if (type->subtypes == NULL) {
12283 xmlSchemaPErr(ctxt, type->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012284 XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012285 "Internal error: xmlSchemaCheckSRCSimpleType, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012286 "no subtype on simple type '%s'.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000012287 type->name, NULL);
12288 return (-1);
12289 }
12290 /*
12291 * src-simple-type.1 The corresponding simple type definition, if any,
12292 * must satisfy the conditions set out in Constraints on Simple Type
12293 * Definition Schema Components (§3.14.6).
12294 */
12295 if ((xmlSchemaCheckSTPropsCorrect(ctxt, type) != 0) ||
12296 (xmlSchemaCheckCOSSTRestricts(ctxt, type) != 0)) {
12297 /*
12298 * TODO: Removed this, since it got annoying to get an
12299 * extra error report, if anything failed until now.
12300 * Enable this if needed.
12301 */
12302 /*
12303 xmlSchemaPErr(ctxt, type->node,
12304 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012305 "Simple type '%s' does not satisfy the constraints "
Daniel Veillard01fa6152004-06-29 17:04:39 +000012306 "on simple type definitions.\n",
12307 type->name, NULL);
12308 */
12309 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_1);
12310 }
12311
12312 if (type->subtypes->type == XML_SCHEMA_TYPE_RESTRICTION) {
12313 /*
12314 * src-simple-type.2 If the <restriction> alternative is chosen,
12315 * either it must have a base [attribute] or a <simpleType> among its
12316 * [children], but not both.
12317 */
William M. Brack2f2a6632004-08-20 23:09:47 +000012318 /*
12319 * XML_SCHEMAP_SRC_SIMPLE_TYPE_2
12320 * NOTE: This was removed, since this will be already handled
12321 * in the parse function for <restriction>.
12322 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000012323 } else if (type->subtypes->type == XML_SCHEMA_TYPE_LIST) {
12324 /* src-simple-type.3 If the <list> alternative is chosen, either it must have
12325 * an itemType [attribute] or a <simpleType> among its [children],
12326 * but not both.
12327 * NOTE: baseType is set to the local simple type definiton,
12328 * if existent, at parse time. This is a hack and not nice.
12329 */
William M. Brack2f2a6632004-08-20 23:09:47 +000012330 /*
12331 * TODO: Remove this, and add the check to the parse function of <list>.
12332 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000012333 if (((type->subtypes->base == NULL) &&
12334 (type->baseType == NULL)) ||
12335 ((type->subtypes->base != NULL) &&
12336 (type->subtypes->baseType != NULL))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012337 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012338 XML_SCHEMAP_SRC_SIMPLE_TYPE_3,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012339 NULL, type, NULL,
12340 "Either the attribute 'itemType' or the <simpleType> child "
12341 "must be present on the <list> child ", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012342 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_3);
12343 }
12344
12345
12346 } else if (type->subtypes->type == XML_SCHEMA_TYPE_UNION) {
12347 xmlSchemaTypeLinkPtr member;
12348 xmlSchemaTypePtr ancestor, anySimpleType;
12349
12350 anySimpleType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
12351
12352 /* src-simple-type.4 Circular union type definition is disallowed. That is, if
12353 * the <union> alternative is chosen, there must not be any entries
12354 * in the memberTypes [attribute] at any depth which resolve to the
12355 * component corresponding to the <simpleType>.
12356 */
12357 member = type->memberTypes;
12358 while (member != NULL) {
12359 ancestor = member->type;
12360 while ((ancestor != NULL) && (ancestor->type != XML_SCHEMA_TYPE_BASIC)) {
12361 if (ancestor->contentType == XML_SCHEMA_CONTENT_UNKNOWN)
12362 xmlSchemaTypeFixup(ancestor, ctxt, NULL);
12363 if (ancestor == anySimpleType)
12364 break;
12365 else if (ancestor == type) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012366 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012367 XML_SCHEMAP_SRC_SIMPLE_TYPE_4,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012368 NULL, type, NULL,
12369 "The definition is circular", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012370 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_4);
12371 } else if (ancestor->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
12372 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000012373 * TODO, FIXME: Although a list simple type must not have a union ST
Daniel Veillard01fa6152004-06-29 17:04:39 +000012374 * type as item type, which in turn has a list ST as member
12375 * type, we will assume this here as well, since this check
12376 * was not yet performed.
12377 */
12378
12379 }
12380 ancestor = ancestor->baseType;
12381 }
12382 member = member->next;
12383 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000012384 }
12385
12386 return (0);
12387}
12388
William M. Brack2f2a6632004-08-20 23:09:47 +000012389#if 0 /* Not yet used code for CT schema validation */
12390static int
12391xmlSchemaCheckCVCSimpleType(xmlSchemaValidCtxtPtr ctxt,
12392 const xmlChar * value,
12393 xmlSchemaTypePtr type,
12394 int fireErrors)
12395{
12396 int ret;
12397 /*
12398 * 3.14.4 Simple Type Definition Validation Rules
12399 * Validation Rule: String Valid
12400 */
12401 /*
12402 * 1 It is schema-valid with respect to that definition as defined
12403 * by Datatype Valid in [XML Schemas: Datatypes].
12404 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012405 ret = xmlSchemaValidateSimpleTypeValue(ctxt, type, value,
12406 fireErrors, 1, 1, 1);
William M. Brack2f2a6632004-08-20 23:09:47 +000012407 return (ret);
12408 /*
12409 * 2.1 If The definition is ENTITY or is validly derived from ENTITY given
12410 * the empty set, as defined in Type Derivation OK (Simple) (§3.14.6), then
12411 * the string must be a ·declared entity name·.
12412 */
12413 /*
12414 * 2.2 If The definition is ENTITIES or is validly derived from ENTITIES
12415 * given the empty set, as defined in Type Derivation OK (Simple) (§3.14.6),
12416 * then every whitespace-delimited substring of the string must be a ·declared
12417 * entity name·.
12418 */
12419 /*
12420 * 2.3 otherwise no further condition applies.
12421 */
12422
12423 return (0);
12424}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012425#endif
12426
William M. Brack2f2a6632004-08-20 23:09:47 +000012427
12428static int
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012429xmlSchemaCreatePCtxtOnVCtxt(xmlSchemaValidCtxtPtr vctxt)
12430{
12431 if (vctxt->pctxt == NULL) {
12432 vctxt->pctxt =xmlSchemaNewParserCtxtUseDict("*", vctxt->schema->dict);
12433 /* vctxt->pctxt = xmlSchemaNewParserCtxt("*"); */
12434 if (vctxt->pctxt == NULL) {
12435 xmlSchemaVErr(vctxt, NULL,
12436 XML_SCHEMAV_INTERNAL,
12437 "Internal error: xmlSchemaCreatePCtxtOnVCtxt, "
12438 "failed to create a temp. parser context.\n",
William M. Brack2f2a6632004-08-20 23:09:47 +000012439 NULL, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012440 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012441 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012442 /* TODO: Pass user data. */
12443 xmlSchemaSetParserErrors(vctxt->pctxt, vctxt->error, vctxt->warning, NULL);
12444 }
12445 return (0);
12446}
12447
12448static int
12449xmlSchemaCreateVCtxtOnPCtxt(xmlSchemaParserCtxtPtr ctxt)
12450{
12451 if (ctxt->vctxt == NULL) {
12452 ctxt->vctxt = xmlSchemaNewValidCtxt(NULL);
12453 if (ctxt->vctxt == NULL) {
12454 xmlSchemaPErr(ctxt, NULL,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012455 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012456 "Internal error: xmlSchemaCreatePCtxtOnVCtxt, "
12457 "failed to create a temp. validation context.\n",
12458 NULL, NULL);
12459 return (-1);
12460 }
12461 /* TODO: Pass user data. */
12462 xmlSchemaSetValidErrors(ctxt->vctxt, ctxt->error, ctxt->warning, NULL);
12463 }
12464 return (0);
12465}
12466
12467/**
12468 * xmlSchemaCheckCOSValidDefault:
12469 * @ctxt: the schema parser context
12470 * @type: the simple type definition
12471 * @value: the default value
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000012472 * @val: the precomputed value to be returned
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012473 * @node: an optional node (the holder of the value)
12474 *
12475 * Checks the "cos-valid-default" constraints.
12476 *
12477 * Returns 0 if the constraints are satisfied,
12478 * if not, a positive error code and -1 on internal
12479 * errors.
12480 */
12481static int
12482xmlSchemaCheckCOSValidDefault(xmlSchemaParserCtxtPtr pctxt,
12483 xmlSchemaValidCtxtPtr vctxt,
12484 xmlSchemaTypePtr type,
12485 const xmlChar *value,
12486 xmlNodePtr node)
12487{
12488 int ret = 0;
12489
12490 /*
12491 * cos-valid-default:
12492 * Schema Component Constraint: Element Default Valid (Immediate)
12493 * For a string to be a valid default with respect to a type
12494 * definition the appropriate case among the following must be true:
12495 */
12496 /*
12497 * NOTE: This has to work without a given node (the holder of the
12498 * value), since it should work on the component, i.e. an underlying
12499 * DOM must not be mandatory.
12500 */
12501 if ((pctxt == NULL) || (vctxt == NULL)) {
12502 xmlSchemaPErr(pctxt, node,
12503 XML_SCHEMAP_INTERNAL,
12504 "Internal error: xmlSchemaCheckCOSValidDefault, "
12505 "bad arguments: the parser and/or validation context is "
12506 "missing.\n",
12507 NULL, NULL);
12508 return (-1);
12509 }
12510 if IS_COMPLEX_TYPE(type) {
William M. Brack2f2a6632004-08-20 23:09:47 +000012511 /*
12512 * Complex type.
12513 *
12514 * 2.1 its {content type} must be a simple type definition or mixed.
12515 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012516 /*
12517 * TODO: Adjust this when the content type will be computed
12518 * correctly.
12519 */
12520 if ((type->contentType != XML_SCHEMA_CONTENT_SIMPLE) &&
12521 (type->contentType != XML_SCHEMA_CONTENT_BASIC) &&
12522 (type->contentType != XML_SCHEMA_CONTENT_MIXED)) {
12523 xmlSchemaPSimpleTypeErr(pctxt,
12524 XML_SCHEMAP_COS_VALID_DEFAULT_2_1,
12525 NULL, NULL, node,
12526 type, NULL, NULL,
12527 "If the type of a constraint value is complex, its content "
12528 "type must be mixed or a simple type",
12529 NULL, NULL);
12530 return(XML_SCHEMAP_COS_VALID_DEFAULT_2_1);
12531 }
12532 if (type->contentType == XML_SCHEMA_CONTENT_MIXED) {
William M. Brack2f2a6632004-08-20 23:09:47 +000012533 /*
12534 * 2.2.2 If the {content type} is mixed, then the {content type}'s
12535 * particle must be ·emptiable· as defined by Particle Emptiable
12536 * (§3.9.6).
12537 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012538
William M. Brack2f2a6632004-08-20 23:09:47 +000012539 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012540 * URGENT TODO: Implement this.
William M. Brack2f2a6632004-08-20 23:09:47 +000012541 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012542 return (0);
William M. Brack2f2a6632004-08-20 23:09:47 +000012543 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012544 }
12545 /*
12546 * 1 If the type definition is a simple type definition, then the string
12547 * must be ·valid· with respect to that definition as defined by String
12548 * Valid (§3.14.4).
12549 *
12550 * AND
12551 *
12552 * 2.2.1 If the {content type} is a simple type definition, then the
12553 * string must be ·valid· with respect to that simple type definition
12554 * as defined by String Valid (§3.14.4).
12555 */
12556 vctxt->node = node;
12557 vctxt->cur = NULL;
12558 ret = xmlSchemaValidateSimpleTypeValue(vctxt, type, value, 1, 1, 1, 0);
12559 /* ret = xmlSchemaCheckCVCSimpleType(vctxt, elemDecl->value, typeDef, 0); */
12560 if (ret < 0) {
12561 xmlSchemaPErr(pctxt, node,
12562 /* NOTNICE: error code: This function will be used during
12563 * schema construction and xsi:type validation.
12564 */
12565 XML_SCHEMAP_INTERNAL,
12566 "Internal error: xmlSchemaCheckCOSValidDefault, "
12567 "while validating a value constaint value.\n",
12568 NULL, NULL);
12569
12570 }
12571 return (ret);
William M. Brack2f2a6632004-08-20 23:09:47 +000012572}
12573
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012574#if 0 /* Not yet used code for CT schema validation */
William M. Brack2f2a6632004-08-20 23:09:47 +000012575/**
12576 * xmlSchemaGetSTContentOfCT:
12577 * @ctxt: the schema parser context
12578 * @type: the complex type definition
12579 *
12580 *
12581 * Returns the corresponding simple type for the content of
12582 * the complex type.
12583 */
12584static xmlSchemaTypePtr
12585xmlSchemaGetSTContentOfCT(xmlSchemaParserCtxtPtr ctxt,
12586 xmlSchemaTypePtr type)
12587{
12588 xmlSchemaTypePtr orig = type, anyType;
12589
12590 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
12591 while ((type != NULL) && (type != anyType) &&
12592 (type->type == XML_SCHEMA_TYPE_COMPLEX)) {
12593 if (type->type == XML_SCHEMA_TYPE_SIMPLE)
12594 return(type);
12595 type = type->baseType;
12596 }
12597 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012598 XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000012599 NULL, orig, NULL,
12600 "Internal error: xmlSchemaGetSTContentTypeOfCT, "
12601 "no simple type for the content of complex type '%s' could be "
12602 "computed", orig->name);
12603 return (NULL);
12604}
12605
12606
William M. Brack2f2a6632004-08-20 23:09:47 +000012607
William M. Brack2f2a6632004-08-20 23:09:47 +000012608
12609/**
12610 * xmlSchemaCheckCOSCTExtends:
12611 * @ctxt: the schema parser context
12612 * @type: the complex type definition
12613 *
12614 * Schema Component Constraint: Derivation Valid (Extension)
12615 *
12616 * Returns 0 if the constraints are satisfied, a positive
12617 * error code if not and -1 if an internal error occured.
12618 */
12619static int
12620xmlSchemaCheckCOSCTExtends(xmlSchemaParserCtxtPtr ctxt,
12621 xmlSchemaTypePtr type)
12622{
12623 xmlSchemaTypePtr base;
12624 /*
12625 * 1 If the {base type definition} is a complex type definition,
12626 * then all of the following must be true:
12627 */
12628 base = type->baseType;
12629 if (base == NULL) {
12630 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012631 XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000012632 NULL, type, NULL,
12633 "Internal error: xmlSchemaCheckCOSCTExtends, "
12634 "the complex type '%s' has no base type", type->name);
12635 return (-1);
12636 }
12637 if (base->type == XML_SCHEMA_TYPE_COMPLEX) {
12638 /*
12639 * 1.1 The {final} of the {base type definition} must not
12640 * contain extension.
12641 */
12642 if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
12643 xmlSchemaPCustomErr(ctxt,
12644 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
12645 NULL, type, NULL,
12646 "The 'final' of the base type definition "
12647 "contains extension", NULL);
12648 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
12649 }
12650 /*
12651 * 1.2 Its {attribute uses} must be a subset of the {attribute uses}
12652 * of the complex type definition itself, that is, for every attribute
12653 * use in the {attribute uses} of the {base type definition}, there
12654 * must be an attribute use in the {attribute uses} of the complex
12655 * type definition itself whose {attribute declaration} has the same
12656 * {name}, {target namespace} and {type definition} as its attribute
12657 * declaration
12658 *
12659 * NOTE: This will be already satisfied by the way the attribute uses
12660 * are extended in xmlSchemaBuildAttributeValidation; thus this check
12661 * is not needed.
12662 */
12663
12664 /*
12665 * 1.3 If it has an {attribute wildcard}, the complex type definition
12666 * must also have one, and the base type definition's {attribute
12667 * wildcard}'s {namespace constraint} must be a subset of the complex
12668 * type definition's {attribute wildcard}'s {namespace constraint},
12669 * as defined by Wildcard Subset (§3.10.6).
12670 *
12671 * This is already checked in xmlSchemaBuildAttributeValidation; thus
12672 * this check is not needed.
12673 */
12674
12675 /*
12676 * 1.4 One of the following must be true:
12677 *
12678 * 1.4.1 The {content type} of the {base type definition} and the
12679 * {content type} of the complex type definition itself must be the same
12680 * simple type definition
12681 */
12682
12683
12684
12685 } else {
12686 /*
12687 * 2 If the {base type definition} is a simple type definition,
12688 * then all of the following must be true:
12689 */
12690 /*
12691 * 2.1 The {content type} must be the same simple type definition.
12692 */
12693 /*
12694 * 2.2 The {final} of the {base type definition} must not contain
12695 * extension
12696 */
12697 }
12698
12699}
12700
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012701static int
12702xmlSchemaCheckSRCCT(xmlSchemaParserCtxtPtr ctxt,
12703 xmlSchemaTypePtr type)
12704{
12705 xmlSchemaTypePtr base, content;
12706 int OK = 0;
12707
12708 /*
12709 * TODO: Adjust the error codes here, as I used
12710 * XML_SCHEMAP_SRC_CT_1 only yet.
12711 */
12712 /*
12713 * Schema Representation Constraint:
12714 * Complex Type Definition Representation OK
12715 */
12716 base = type->baseType;
12717 if (base == NULL) {
12718 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL, NULL, type, NULL,
12719 "Internal error: xmlSchemaCheckSRCCT, '%s', no base type",
12720 type->name);
12721 return (-1);
12722 }
12723
12724 if (type->subtypes != NULL) {
12725 if (type->subtypes->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
12726 if IS_COMPLEX_TYPE(base) {
12727 /*
12728 * 1 If the <complexContent> alternative is chosen, the type definition
12729 * ·resolved· to by the ·actual value· of the base [attribute]
12730 * must be a complex type definition;
12731 */
12732 xmlSchemaPCustomErr(ctxt,
12733 XML_SCHEMAP_SRC_CT_1,
12734 NULL, type, NULL,
12735 "The base type is not a complex type", NULL);
12736 return (XML_SCHEMAP_SRC_CT_1);
12737 }
12738 } else if (type->subtypes->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
12739
12740 if IS_SIMPLE_TYPE(base) {
12741 if (type->flags &
12742 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
12743 /*
12744 * 2.1.3 only if the <extension> alternative is also
12745 * chosen, a simple type definition.
12746 */
12747 /* TODO: Change error code to ..._SRC_CT_2_1_3. */
12748 xmlSchemaPCustomErr(ctxt,
12749 XML_SCHEMAP_SRC_CT_1,
12750 NULL, type, NULL,
12751 "A complex type (simple content) cannot restrict "
12752 "an other simple type",
12753 NULL);
12754 return (XML_SCHEMAP_SRC_CT_1);
12755 }
12756 OK = 1;
12757
12758 } else { /* if IS_SIMPLE_TYPE(base) */
12759 if (base->contentType = XML_SCHEMA_CONTENT_MIXED) {
12760 /*
12761 * 2.1.2 only if the <restriction> alternative is also
12762 * chosen, a complex type definition whose {content type}
12763 * is mixed and a particle emptyable.
12764 */
12765 /*
12766 * FIXME TODO: Check for *empiable particle* is missing.
12767 */
12768 if ((type->flags &
12769 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) == 0) {
12770 xmlSchemaPCustomErr(ctxt,
12771 XML_SCHEMAP_SRC_CT_1,
12772 NULL, type, NULL,
12773 "A complex type (simple content) cannot "
12774 "extend an other complex type which has a "
12775 "content type of: 'mixed' and emptiable particle",
12776 NULL);
12777 return (XML_SCHEMAP_SRC_CT_1);
12778 }
12779 /*
12780 * NOTE: This will be fired as well, if the base type
12781 * is *'anyType'*.
12782 * NOTE: type->subtypes->subtypes will be the
12783 * <restriction> item.
12784 */
12785 if (type->subtypes->subtypes == NULL) {
12786 /* Yes, this is paranoid programming. */
12787 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
12788 NULL, type, NULL,
12789 "Internal error: xmlSchemaCheckSRCCT, "
12790 "'%s', <simpleContent> has no <restriction>",
12791 type->name);
12792 return (-1);
12793 }
12794 /*
12795 * 2.2 If clause 2.1.2 above is satisfied, then there
12796 * must be a <simpleType> among the [children] of
12797 * <restriction>.
12798 */
12799 if (type->subtypes->subtypes->type !=
12800 XML_SCHEMA_TYPE_SIMPLE) {
12801 /* TODO: Change error code to ..._SRC_CT_2_2. */
12802 xmlSchemaPCustomErr(ctxt,
12803 XML_SCHEMAP_SRC_CT_1,
12804 NULL, type, NULL,
12805 "A <simpleType> is expected among the children "
12806 "of <restriction>", NULL);
12807 return (XML_SCHEMAP_SRC_CT_1);
12808 }
12809 OK = 1;
12810 } else { /* if (base->contentType = XML_SCHEMA_CONTENT_MIXED)*/
12811 /*
12812 * 2.1.1 a complex type definition whose {content type} is a
12813 * simple type definition;
12814 */
12815 if (base->contentType == XML_SCHEMA_CONTENT_ELEMENTS) {
12816 xmlSchemaPCustomErr(ctxt,
12817 XML_SCHEMAP_SRC_CT_1,
12818 NULL, type, NULL,
12819 "A complex type (simple content) cannot "
12820 "be derived from the complex type '%s'",
12821 base->name);
12822 return (XML_SCHEMAP_SRC_CT_1);
12823 }
12824 content = base->contentTypeDef;
12825 if (content == NULL) {
12826 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
12827 NULL, type, NULL,
12828 "Internal error: xmlSchemaCheckSRCCT, "
12829 "'%s', base type has no content type",
12830 type->name);
12831 return (-1);
12832 }
12833 if (content->type != XML_SCHEMA_TYPE_SIMPLE) {
12834 xmlSchemaPCustomErr(ctxt,
12835 XML_SCHEMAP_SRC_CT_1,
12836 NULL, type, NULL,
12837 "A complex type (simple content) cannot "
12838 "be derived from the complex type '%s'",
12839 base->name);
12840 return (XML_SCHEMAP_SRC_CT_1);
12841 }
12842 }
12843 }
12844 }
12845 }
12846 /*
12847 * TODO: 3 The corresponding complex type definition component must
12848 * satisfy the conditions set out in Constraints on Complex Type
12849 * Definition Schema Components (§3.4.6);
12850 *
12851 * TODO: 4 If clause 2.2.1 or clause 2.2.2 in the correspondence specification
12852 * above for {attribute wildcard} is satisfied, the intensional
12853 * intersection must be expressible, as defined in Attribute Wildcard
12854 * Intersection (§3.10.6).
12855 */
12856
12857}
William M. Brack2f2a6632004-08-20 23:09:47 +000012858#endif
12859
Daniel Veillard01fa6152004-06-29 17:04:39 +000012860/**
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000012861 * xmlSchemaGroupDefFixup:
12862 * @typeDecl: the schema model group definition
12863 * @ctxt: the schema parser context
12864 *
12865 * Fixes model group definitions.
12866 */
12867static void
12868xmlSchemaGroupDefFixup(xmlSchemaTypePtr group,
12869 xmlSchemaParserCtxtPtr ctxt,
12870 const xmlChar * name ATTRIBUTE_UNUSED)
12871{
12872 group->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
12873 if ((group->ref != NULL) && (group->subtypes == NULL)) {
12874 xmlSchemaTypePtr groupDef;
12875 /*
12876 * Resolve the reference.
12877 */
12878 groupDef = xmlSchemaGetGroup(ctxt->schema, group->ref,
12879 group->refNs);
12880 if (groupDef == NULL) {
12881 xmlSchemaPResCompAttrErr(ctxt,
12882 XML_SCHEMAP_SRC_RESOLVE,
12883 NULL, group, NULL,
12884 "ref", group->ref, group->refNs,
12885 XML_SCHEMA_TYPE_GROUP, NULL);
12886 return;
12887 }
12888 group->subtypes = groupDef;
12889 }
12890}
12891
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012892#if 0 /* Enable when the content type will be computed. */
12893static int
12894xmlSchemaComputeContentType(xmlSchemaParserCtxtPtr ctxt,
12895 xmlSchemaTypePtr type)
12896{
12897 xmlSchemaTypePtr base, res = NULL;
12898
12899 base = type->baseType;
12900 if (base == NULL) {
12901 xmlSchemaPCustomErr(ctxt,
12902 XML_SCHEMAP_INTERNAL,
12903 NULL, type, NULL,
12904 "Internal error: xmlSchemaGetContentType, "
12905 "the complex type '%s' has no base type", type->name);
12906 return (-1);
12907 }
12908 if (IS_ANYTYPE(base) || (type->subtypes->type ==
12909 XML_SCHEMA_TYPE_COMPLEX_CONTENT)) {
12910 xmlSchemaTypePtr start;
12911 /*
12912 * Effective 'mixed'.
12913 */
12914 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
12915 type->contentType = XML_SCHEMA_CONTENT_MIXED;
12916 /*
12917 * Effective content.
12918 */
12919 if (IS_ANYTYPE(base))
12920 start = type;
12921 else
12922 start = type->subtypes;
12923
12924 } else { /* if XML_SCHEMA_TYPE_COMPLEX_CONTENT */
12925 xmlSchemaTypePtr baseContentItem;
12926
12927 /*
12928 * Complex type with simple content.
12929 */
12930 if IS_COMPLEX_TYPE(base) {
12931 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
12932 /*
12933 * Summary: a complex type (simple content) can *restrict*
12934 * a complex type with the following content type:
12935 * 1. 'mixed' and an emptiable particle
12936 * 2. simple type
12937 */
12938 if (base->contentType == XML_SCHEMA_CONTENT_MIXED) {
12939 /*
12940 * 2 if the {content type} of the base type is mixed and a
12941 * particle which is ·emptiable·,
12942 * [...]
12943 * then starting from the simple type definition
12944 * corresponding to the <simpleType> among the [children]
12945 * of <restriction> (**which must be present**)
12946 *
12947 * FIXME TODO: Handle "emptiable particle".
12948 */
12949 res = type->subtypes->subtypes;
12950 if (res == NULL) {
12951 xmlSchemaPCustomErr(ctxt,
12952 XML_SCHEMAP_INTERNAL,
12953 NULL, type, NULL,
12954 "Internal error: xmlSchemaGetContentType, "
12955 "CT '%s' (restricting): <simpleContent> has no "
12956 "<restriction>",
12957 type->name);
12958 return (-1);
12959 }
12960
12961 res->subtypes;
12962 if (res == NULL) {
12963 xmlSchemaPCustomErr(ctxt,
12964 XML_SCHEMAP_INTERNAL,
12965 NULL, type, NULL,
12966 "Internal error: xmlSchemaGetContentType, "
12967 "CT '%s' (restricting): <restriction> has no "
12968 "mandatory <simpleType>",
12969 type->name);
12970 return (-1);
12971 }
12972 } else {
12973 baseContentItem = base->contentTypeDef;
12974 if (baseContentItem == NULL) {
12975 xmlSchemaPCustomErr(ctxt,
12976 XML_SCHEMAP_INTERNAL,
12977 NULL, type, NULL,
12978 "Internal error: xmlSchemaGetContentType, "
12979 "CT '%s' (restricting), the base type has no "
12980 "content type", type->name);
12981 return (-1);
12982 }
12983 if IS_SIMPLE_TYPE(baseContentItem) {
12984 /*
12985 * 1 If the base type is a complex type whose own
12986 * {content type} is a simple type and the <restriction>
12987 * alternative is chosen
12988 */
12989 /* type->subtypes->subtypes will be the restriction item.*/
12990 res = type->subtypes->subtypes;
12991 if (res == NULL) {
12992 xmlSchemaPCustomErr(ctxt,
12993 XML_SCHEMAP_INTERNAL,
12994 NULL, type, NULL,
12995 "Internal error: xmlSchemaGetContentType, "
12996 "CT '%s' (restricting): <simpleType> has no "
12997 "<restriction>", type->name);
12998 return (-1);
12999 }
13000 /*
13001 * 1.1 the simple type definition corresponding to the
13002 * <simpleType> among the [children] of <restriction>if
13003 * there is one;
13004 */
13005 res = res->subtypes;
13006 if (res == NULL) {
13007 /*
13008 * 1.2 otherwise the {content type}
13009 * of the base type .
13010 */
13011 res = baseContentItem;
13012 }
13013 }
13014 }
13015 /*
13016 * SPECIAL TODO: If *restricting* the spec wants us to
13017 * create an *additional* simple type which restricts the
13018 * located simple type; we won't do this yet, and look how
13019 * far we get with it.
13020 */
13021 } else { /* if XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION */
13022 /*
13023 * Summary: a complex type (simple content) can *extend*
13024 * only a complex base with a simple type as content.
13025 */
13026 /*
13027 * 3 If the type definition ·resolved· to by the ·actual
13028 * value· of the base [attribute] is a complex type
13029 * definition (whose own {content type} *must be* a simple
13030 * type definition, see below) and the *<extension>*
13031 * alternative is chosen, then the {content type} of that
13032 * complex type definition;
13033 */
13034 res = base->contentTypeDef;
13035 if (res == NULL) {
13036 xmlSchemaPCustomErr(ctxt,
13037 XML_SCHEMAP_INTERNAL,
13038 NULL, type, NULL,
13039 "Internal error: xmlSchemaGetContentType, "
13040 "CT '%s' (extending), the base type has no content "
13041 "type", type->name);
13042 return (-1);
13043 }
13044 if (! IS_SIMPLE_TYPE(res)) {
13045 xmlSchemaPCustomErr(ctxt,
13046 XML_SCHEMAP_INTERNAL,
13047 NULL, type, NULL,
13048 "Internal error: xmlSchemaGetContentType, "
13049 "CT '%s' (extending), the content type of the "
13050 "base is not a simple type", type->name);
13051 return (-1);
13052 }
13053 }
13054 } else /* if IS_COMPLEX_TYPE(base) */
13055 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
13056 /*
13057 * 4 otherwise (the type definition ·resolved· to by the
13058 * ·actual value· of the base [attribute] is a simple type
13059 * definition and the <extension> alternative is chosen),
13060 * then that simple type definition.
13061 */
13062 res = base;
13063 }
13064 type->contentTypeDef = res;
13065 if (res == NULL) {
13066 xmlSchemaPCustomErr(ctxt,
13067 XML_SCHEMAP_INTERNAL,
13068 NULL, type, NULL,
13069 "Internal error: xmlSchemaGetContentType, "
13070 "'%s', the content type could not be determined",
13071 type->name);
13072 return (-1);
13073 }
13074
13075 }
13076
13077}
13078#endif
13079
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000013080/**
Daniel Veillard4255d502002-04-16 15:50:10 +000013081 * xmlSchemaTypeFixup:
13082 * @typeDecl: the schema type definition
13083 * @ctxt: the schema parser context
13084 *
13085 * Fixes the content model of the type.
13086 */
13087static void
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013088xmlSchemaTypeFixup(xmlSchemaTypePtr item,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013089 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +000013090{
Daniel Veillard01fa6152004-06-29 17:04:39 +000013091 xmlSchemaTypePtr ctxtType;
13092
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013093 if (item == NULL)
Daniel Veillard82bbbd42003-05-11 20:16:09 +000013094 return;
Daniel Veillard4e5d6652004-06-29 21:01:12 +000013095 /*
13096 * Do not allow the following types to be typefixed, prior to
13097 * the corresponding simple/complex types.
13098 */
13099 if (ctxt->ctxtType == NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013100 switch (item->type) {
Daniel Veillard4e5d6652004-06-29 21:01:12 +000013101 case XML_SCHEMA_TYPE_SIMPLE_CONTENT:
13102 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:
13103 case XML_SCHEMA_TYPE_UNION:
13104 case XML_SCHEMA_TYPE_RESTRICTION:
13105 case XML_SCHEMA_TYPE_EXTENSION:
13106 return;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000013107 default:
13108 break;
Daniel Veillard4e5d6652004-06-29 21:01:12 +000013109 }
13110 }
Daniel Veillard4255d502002-04-16 15:50:10 +000013111 if (name == NULL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013112 name = item->name;
13113 if (item->contentType == XML_SCHEMA_CONTENT_UNKNOWN) {
13114 switch (item->type) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013115 case XML_SCHEMA_TYPE_SIMPLE_CONTENT:{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013116 if (item->subtypes != NULL) {
13117 if (item->subtypes->contentType ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013118 XML_SCHEMA_CONTENT_UNKNOWN) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013119 xmlSchemaTypeFixup(item->subtypes, ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013120 NULL);
13121 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013122 item->contentType =
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013123 XML_SCHEMA_CONTENT_SIMPLE;
13124 /* item->subtypes->contentType; */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013125 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013126 break;
13127 }
13128 case XML_SCHEMA_TYPE_RESTRICTION:{
Daniel Veillard01fa6152004-06-29 17:04:39 +000013129 xmlSchemaTypePtr base = NULL;
13130
13131 ctxt->ctxtType->flags |=
13132 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013133 if (item->baseType != NULL)
13134 base = item->baseType;
13135 else if (item->base != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013136 base =
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013137 xmlSchemaGetType(ctxt->schema, item->base,
13138 item->baseNs);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013139 if (base == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013140 xmlSchemaPResCompAttrErr(ctxt,
13141 XML_SCHEMAP_SRC_RESOLVE,
William M. Brack2f2a6632004-08-20 23:09:47 +000013142 NULL, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013143 (xmlNodePtr) xmlSchemaGetPropNode(item->node, "base"),
13144 "base", item->base, item->baseNs,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013145 XML_SCHEMA_TYPE_BASIC, "type definition");
Daniel Veillard01fa6152004-06-29 17:04:39 +000013146 } else if (base->contentType ==
Daniel Veillard3646d642004-06-02 19:19:14 +000013147 XML_SCHEMA_CONTENT_UNKNOWN) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013148 xmlSchemaTypeFixup(base, ctxt, NULL);
13149 }
William M. Brack2f2a6632004-08-20 23:09:47 +000013150 }
13151 ctxt->ctxtType->baseType = base;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013152 if (ctxt->ctxtType->type == XML_SCHEMA_TYPE_COMPLEX) {
13153 /*
13154 * ComplexType restriction.
William M. Brack2f2a6632004-08-20 23:09:47 +000013155 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013156 /*
13157 * Content type.
13158 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013159 if (item->subtypes == NULL)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013160 /* 1.1.1 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013161 item->contentType = XML_SCHEMA_CONTENT_EMPTY;
13162 else if ((item->subtypes->subtypes == NULL) &&
13163 ((item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013164 XML_SCHEMA_TYPE_ALL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013165 || (item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013166 XML_SCHEMA_TYPE_SEQUENCE)))
13167 /* 1.1.2 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013168 item->contentType = XML_SCHEMA_CONTENT_EMPTY;
13169 else if ((item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013170 XML_SCHEMA_TYPE_CHOICE)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013171 && (item->subtypes->subtypes == NULL))
Daniel Veillard01fa6152004-06-29 17:04:39 +000013172 /* 1.1.3 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013173 item->contentType = XML_SCHEMA_CONTENT_EMPTY;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013174 else {
13175 /* 1.2 and 2.X are applied at the other layer */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013176 item->contentType =
Daniel Veillard01fa6152004-06-29 17:04:39 +000013177 XML_SCHEMA_CONTENT_ELEMENTS;
13178 }
13179 } else {
13180 /*
13181 * SimpleType restriction.
13182 */
William M. Brack2f2a6632004-08-20 23:09:47 +000013183 /* TODO: Nothing? */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013184 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013185 break;
13186 }
13187 case XML_SCHEMA_TYPE_EXTENSION:{
Daniel Veillard01fa6152004-06-29 17:04:39 +000013188 xmlSchemaTypePtr base = NULL;
13189 xmlSchemaContentType explicitContentType;
13190
13191 /*
13192 * An extension does exist on a complexType only.
13193 */
13194 ctxt->ctxtType->flags |=
13195 XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013196 if (item->recurse) {
Daniel Veillard3646d642004-06-02 19:19:14 +000013197 /* TODO: The word "recursive" should be changed to "circular" here. */
Daniel Veillardc0826a72004-08-10 14:17:33 +000013198 xmlSchemaPCustomErr(ctxt,
13199 XML_SCHEMAP_UNKNOWN_BASE_TYPE,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013200 NULL, item, item->node,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013201 "This item is circular", NULL);
Daniel Veillard2582a332004-04-18 19:49:46 +000013202 return;
13203 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013204 if (item->base != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013205 base =
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013206 xmlSchemaGetType(ctxt->schema, item->base,
13207 item->baseNs);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013208 if (base == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013209 xmlSchemaPResCompAttrErr(ctxt,
13210 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013211 NULL, item, item->node,
13212 "base", item->base, item->baseNs,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013213 XML_SCHEMA_TYPE_BASIC, "type definition");
Daniel Veillard01fa6152004-06-29 17:04:39 +000013214 } else if (base->contentType ==
13215 XML_SCHEMA_CONTENT_UNKNOWN) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013216 item->recurse = 1;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013217 xmlSchemaTypeFixup(base, ctxt, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013218 item->recurse = 0;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013219 }
13220 /*
13221 * The type definition ·resolved· to by the ·actual
13222 * value· of the base [attribute]
13223 */
13224 ctxt->ctxtType->baseType = base;
13225 /*
13226 * TODO: This one is still needed for computation of
13227 * the content model by xmlSchemaBuildAContentModel.
13228 * Try to get rid of it.
13229 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013230 item->baseType = base;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013231 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013232 if ((item->subtypes != NULL) &&
13233 (item->subtypes->contentType == XML_SCHEMA_CONTENT_UNKNOWN))
13234 xmlSchemaTypeFixup(item->subtypes, ctxt, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013235
13236 explicitContentType = XML_SCHEMA_CONTENT_ELEMENTS;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013237 if (item->subtypes == NULL)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013238 /* 1.1.1 */
13239 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013240 else if ((item->subtypes->subtypes == NULL) &&
13241 ((item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013242 XML_SCHEMA_TYPE_ALL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013243 || (item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013244 XML_SCHEMA_TYPE_SEQUENCE)))
13245 /* 1.1.2 */
13246 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013247 else if ((item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013248 XML_SCHEMA_TYPE_CHOICE)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013249 && (item->subtypes->subtypes == NULL))
Daniel Veillard01fa6152004-06-29 17:04:39 +000013250 /* 1.1.3 */
13251 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
13252 if (base != NULL) {
13253 /* It will be reported later, if the base is missing. */
13254 if (explicitContentType == XML_SCHEMA_CONTENT_EMPTY) {
13255 /* 2.1 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013256 item->contentType = base->contentType;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013257 } else if (base->contentType ==
13258 XML_SCHEMA_CONTENT_EMPTY) {
13259 /* 2.2 imbitable ! */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013260 item->contentType =
Daniel Veillard01fa6152004-06-29 17:04:39 +000013261 XML_SCHEMA_CONTENT_ELEMENTS;
13262 } else {
13263 /* 2.3 imbitable pareil ! */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013264 item->contentType =
Daniel Veillard01fa6152004-06-29 17:04:39 +000013265 XML_SCHEMA_CONTENT_ELEMENTS;
13266 }
13267 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013268 break;
13269 }
13270 case XML_SCHEMA_TYPE_COMPLEX:{
Daniel Veillard4e5d6652004-06-29 21:01:12 +000013271 ctxtType = ctxt->ctxtType;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013272 ctxt->ctxtType = item;
13273 /*
13274 * Start with an empty content-type type.
13275 */
13276 if (item->subtypes == NULL)
13277 item->contentType = XML_SCHEMA_CONTENT_EMPTY;
13278
13279 if ((item->subtypes == NULL) ||
13280 ((item->subtypes->type !=
Daniel Veillard01fa6152004-06-29 17:04:39 +000013281 XML_SCHEMA_TYPE_SIMPLE_CONTENT) &&
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013282 (item->subtypes->type !=
Daniel Veillard01fa6152004-06-29 17:04:39 +000013283 XML_SCHEMA_TYPE_COMPLEX_CONTENT))) {
13284 /*
13285 * This case is understood as shorthand for complex
13286 * content restricting the ur-type definition, and
13287 * the details of the mappings should be modified as
13288 * necessary.
13289 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013290 item->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
13291 item->flags |=
Daniel Veillard01fa6152004-06-29 17:04:39 +000013292 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013293 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013294 * Assume that we inherit the content-type type
13295 * from 'anyType', which is 'mixed' and a particle
13296 * emptiable.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013297 */
13298 item->contentType = item->baseType->contentType;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013299 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013300 /*
13301 * Fixup the sub components.
13302 */
13303 if ((item->subtypes != NULL) &&
13304 (item->subtypes->contentType ==
13305 XML_SCHEMA_CONTENT_UNKNOWN)) {
13306 xmlSchemaTypeFixup(item->subtypes, ctxt, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013307 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013308 if (item->flags & XML_SCHEMAS_TYPE_MIXED) {
13309 item->contentType = XML_SCHEMA_CONTENT_MIXED;
13310 } else if (item->subtypes != NULL) {
13311 /*
13312 * Use the content-type type of the model groups
13313 * defined, if 'mixed' is not set. If 'mixed' is set
13314 * it will expand the content-type by allowing character
13315 * content to appear.
13316 */
13317 item->contentType =
13318 item->subtypes->contentType;
13319 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000013320
13321 /*
13322 * Some optimization for validation:
13323 * If there are no facets beside the "whitespace" facet,
13324 * then a value needs not to checked against against a
13325 * facet, thus no computed value is needed.
13326 * TODO URGENT: This is just a workaround, we need to
13327 * introduce the correct usage of contentType to store the
13328 * facets in!
13329 */
Daniel Veillardd3210bc2005-01-28 17:56:39 +000013330 if ((item->baseType != NULL) &&
13331 (item->baseType->flags &
13332 XML_SCHEMAS_TYPE_FACETSNEEDVALUE))
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000013333 item->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
13334 else {
13335 xmlSchemaFacetLinkPtr cur;
13336
13337 for (cur = item->facetSet; cur != NULL;
13338 cur = cur->next) {
13339 if (cur->facet->type != XML_SCHEMA_FACET_WHITESPACE) {
13340 item->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
13341 break;
13342 }
13343 }
13344 }
13345
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013346 xmlSchemaBuildAttributeValidation(ctxt, item);
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +000013347 xmlSchemaCheckDefaults(item, ctxt, item->name);
Daniel Veillard4e5d6652004-06-29 21:01:12 +000013348 ctxt->ctxtType = ctxtType;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013349 break;
13350 }
13351 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013352 if (item->subtypes == NULL) {
13353 item->contentType = XML_SCHEMA_CONTENT_EMPTY;
13354 if (item->flags & XML_SCHEMAS_TYPE_MIXED)
13355 item->contentType =
Daniel Veillard1aefc862004-03-04 11:40:48 +000013356 XML_SCHEMA_CONTENT_MIXED;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013357 } else {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013358 if (item->flags & XML_SCHEMAS_TYPE_MIXED) {
13359 item->contentType =
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013360 XML_SCHEMA_CONTENT_MIXED;
Daniel Veillard3646d642004-06-02 19:19:14 +000013361 } else {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013362 xmlSchemaTypeFixup(item->subtypes, ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013363 NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013364 if (item->subtypes != NULL)
13365 item->contentType =
13366 item->subtypes->contentType;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013367 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013368 /*
13369 * Removed due to implementation of the build of attribute uses.
13370 */
13371 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013372 if (item->attributes == NULL)
13373 item->attributes =
13374 item->subtypes->attributes;
Daniel Veillard3646d642004-06-02 19:19:14 +000013375 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013376 }
13377 break;
13378 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013379 case XML_SCHEMA_TYPE_SIMPLE:
13380 /*
13381 * Simple Type Definition Schema Component
13382 *
13383 */
Daniel Veillard4e5d6652004-06-29 21:01:12 +000013384 ctxtType = ctxt->ctxtType;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013385 item->contentType = XML_SCHEMA_CONTENT_SIMPLE;
13386 if (item->subtypes->contentType ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013387 XML_SCHEMA_CONTENT_UNKNOWN) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013388 ctxt->ctxtType = item;
13389 xmlSchemaTypeFixup(item->subtypes, ctxt, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013390 }
13391 /* Fixup base type */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013392 if ((item->baseType != NULL) &&
13393 (item->baseType->contentType ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013394 XML_SCHEMA_CONTENT_UNKNOWN)) {
13395 /* OPTIMIZE: Actually this one will never by hit, since
13396 * the base type is already type-fixed in <restriction>.
13397 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013398 ctxt->ctxtType = item;
13399 xmlSchemaTypeFixup(item->baseType, ctxt, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013400 }
13401 /* Base type:
13402 * 2 If the <list> or <union> alternative is chosen,
13403 * then the ·simple ur-type definition·.
13404 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013405 if (item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013406 XML_SCHEMA_TYPE_LIST) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013407 item->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
13408 item->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
13409 } else if (item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013410 XML_SCHEMA_TYPE_UNION) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013411 item->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
13412 item->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
13413 } else if (item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013414 XML_SCHEMA_TYPE_RESTRICTION) {
13415 xmlSchemaFacetLinkPtr facet, cur, last = NULL;
13416
13417 /*
13418 * Variety
13419 * If the <restriction> alternative is chosen, then the
13420 * {variety} of the {base type definition}.
13421 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013422 if (item->baseType != NULL) {
13423 if (item->baseType->flags &
Daniel Veillard01fa6152004-06-29 17:04:39 +000013424 XML_SCHEMAS_TYPE_VARIETY_ATOMIC)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013425 item->flags |= XML_SCHEMAS_TYPE_VARIETY_ATOMIC;
13426 else if (item->baseType->flags &
Daniel Veillard01fa6152004-06-29 17:04:39 +000013427 XML_SCHEMAS_TYPE_VARIETY_LIST)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013428 item->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
13429 else if (item->baseType->flags &
Daniel Veillard01fa6152004-06-29 17:04:39 +000013430 XML_SCHEMAS_TYPE_VARIETY_UNION)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013431 item->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013432 /*
13433 * Schema Component Constraint: Simple Type Restriction
13434 * (Facets)
13435 * NOTE: Satisfaction of 1 and 2 arise from the fixup
13436 * applied beforehand.
13437 *
13438 * 3 The {facets} of R are the union of S and the {facets}
13439 * of B, eliminating duplicates. To eliminate duplicates,
13440 * when a facet of the same kind occurs in both S and the
13441 * {facets} of B, the one in the {facets} of B is not
13442 * included, with the exception of enumeration and pattern
13443 * facets, for which multiple occurrences with distinct values
13444 * are allowed.
13445 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013446 if (item->baseType->facetSet != NULL) {
13447 last = item->facetSet;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013448 if (last != NULL)
13449 while (last->next != NULL)
13450 last = last->next;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000013451 cur = item->baseType->facetSet;
13452 for (; cur != NULL; cur = cur->next) {
13453 /*
13454 * Base patterns won't be add here:
13455 * they are ORed in a type and
13456 * ANDed in derived types. This will
13457 * happed at validation level by
13458 * walking the base axis of the type.
13459 */
13460 if (cur->facet->type ==
13461 XML_SCHEMA_FACET_PATTERN)
13462 continue;
13463 facet = NULL;
13464 if ((item->facetSet != NULL) &&
13465 /* REMOVED: a check for
13466 * XML_SCHEMA_FACET_PATTERN was already
13467 * performed above.
13468
13469 * (cur->facet->type !=
13470 * XML_SCHEMA_FACET_PATTERN) &&
Daniel Veillard01fa6152004-06-29 17:04:39 +000013471 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000013472 (cur->facet->type !=
13473 XML_SCHEMA_FACET_ENUMERATION)) {
13474 facet = item->facetSet;
13475 do {
13476 if (cur->facet->type ==
13477 facet->facet->type)
13478 break;
13479 facet = facet->next;
13480 } while (facet != NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013481 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000013482 if (facet == NULL) {
13483 facet = (xmlSchemaFacetLinkPtr)
13484 xmlMalloc(sizeof(xmlSchemaFacetLink));
13485 if (facet == NULL) {
13486 xmlSchemaPErrMemory(ctxt,
13487 "fixing simpleType", NULL);
13488 return;
13489 }
13490 /*
13491 * The facets are not copied but referenced
13492 * via the facet link.
13493 */
13494 facet->facet = cur->facet;
13495 facet->next = NULL;
13496 if (last == NULL)
13497 item->facetSet = facet;
13498 else
13499 last->next = facet;
13500 last = facet;
13501 }
13502 }
13503 }
13504 /*
13505 * Some optimization for validation:
13506 * If there are no facets beside the "whitespace" facet,
13507 * then a value needs not to checked against against a
13508 * facet, thus no computed value is needed.
13509 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000013510 if (item->baseType->flags & XML_SCHEMAS_TYPE_FACETSNEEDVALUE)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000013511 item->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
13512 else {
13513 for (cur = item->facetSet; cur != NULL;
13514 cur = cur->next) {
13515 if (cur->facet->type != XML_SCHEMA_FACET_WHITESPACE) {
13516 item->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
13517 break;
13518 }
13519 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013520 }
13521 }
13522 }
13523 /*
13524 * Check constraints.
13525 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013526 xmlSchemaCheckSRCSimpleType(ctxt, item);
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +000013527 xmlSchemaCheckDefaults(item, ctxt, item->name);
Daniel Veillard4e5d6652004-06-29 21:01:12 +000013528 ctxt->ctxtType = ctxtType;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013529 break;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000013530 case XML_SCHEMA_TYPE_SEQUENCE:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013531 case XML_SCHEMA_TYPE_ALL:
13532 case XML_SCHEMA_TYPE_CHOICE:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013533 item->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013534 break;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000013535 case XML_SCHEMA_TYPE_GROUP:
13536 /*
13537 * TODO: Handling was moved to xmlSchemaGroupDefFixup.
13538 */
13539 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013540 case XML_SCHEMA_TYPE_LIST:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013541 xmlSchemaParseListRefFixup(item, ctxt);
13542 item->contentType = XML_SCHEMA_CONTENT_SIMPLE;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013543 break;
13544 case XML_SCHEMA_TYPE_UNION:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013545 xmlSchemaParseUnionRefCheck(item, ctxt);
13546 item->contentType = XML_SCHEMA_CONTENT_SIMPLE;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013547 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013548 case XML_SCHEMA_TYPE_BASIC:
13549 case XML_SCHEMA_TYPE_ANY:
13550 case XML_SCHEMA_TYPE_FACET:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013551 case XML_SCHEMA_TYPE_UR:
13552 case XML_SCHEMA_TYPE_ELEMENT:
13553 case XML_SCHEMA_TYPE_ATTRIBUTE:
13554 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
William M. Brack29aa7722004-05-12 00:27:56 +000013555 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013556 case XML_SCHEMA_TYPE_NOTATION:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013557 case XML_SCHEMA_FACET_MININCLUSIVE:
13558 case XML_SCHEMA_FACET_MINEXCLUSIVE:
13559 case XML_SCHEMA_FACET_MAXINCLUSIVE:
13560 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
13561 case XML_SCHEMA_FACET_TOTALDIGITS:
13562 case XML_SCHEMA_FACET_FRACTIONDIGITS:
13563 case XML_SCHEMA_FACET_PATTERN:
13564 case XML_SCHEMA_FACET_ENUMERATION:
13565 case XML_SCHEMA_FACET_WHITESPACE:
13566 case XML_SCHEMA_FACET_LENGTH:
13567 case XML_SCHEMA_FACET_MAXLENGTH:
13568 case XML_SCHEMA_FACET_MINLENGTH:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013569 item->contentType = XML_SCHEMA_CONTENT_SIMPLE;
13570 if (item->subtypes != NULL)
13571 xmlSchemaTypeFixup(item->subtypes, ctxt, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013572 break;
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +000013573 case XML_SCHEMA_TYPE_IDC_UNIQUE:
13574 case XML_SCHEMA_TYPE_IDC_KEY:
13575 case XML_SCHEMA_TYPE_IDC_KEYREF:
13576 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013577 }
13578 }
Daniel Veillard8651f532002-04-17 09:06:27 +000013579#ifdef DEBUG_TYPE
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013580 if (item->node != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013581 xmlGenericError(xmlGenericErrorContext,
13582 "Type of %s : %s:%d :", name,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013583 item->node->doc->URL,
13584 xmlGetLineNo(item->node));
Daniel Veillarddecd64d2002-04-18 14:41:51 +000013585 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013586 xmlGenericError(xmlGenericErrorContext, "Type of %s :", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +000013587 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013588 switch (item->contentType) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013589 case XML_SCHEMA_CONTENT_SIMPLE:
13590 xmlGenericError(xmlGenericErrorContext, "simple\n");
13591 break;
13592 case XML_SCHEMA_CONTENT_ELEMENTS:
13593 xmlGenericError(xmlGenericErrorContext, "elements\n");
13594 break;
Daniel Veillard8651f532002-04-17 09:06:27 +000013595 case XML_SCHEMA_CONTENT_UNKNOWN:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013596 xmlGenericError(xmlGenericErrorContext, "unknown !!!\n");
13597 break;
Daniel Veillard8651f532002-04-17 09:06:27 +000013598 case XML_SCHEMA_CONTENT_EMPTY:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013599 xmlGenericError(xmlGenericErrorContext, "empty\n");
13600 break;
Daniel Veillard8651f532002-04-17 09:06:27 +000013601 case XML_SCHEMA_CONTENT_MIXED:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013602 xmlGenericError(xmlGenericErrorContext, "mixed\n");
13603 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013604 /* Removed, since not used. */
13605 /*
Daniel Veillard8651f532002-04-17 09:06:27 +000013606 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013607 xmlGenericError(xmlGenericErrorContext, "mixed or elems\n");
13608 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013609 */
Daniel Veillard8651f532002-04-17 09:06:27 +000013610 case XML_SCHEMA_CONTENT_BASIC:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013611 xmlGenericError(xmlGenericErrorContext, "basic\n");
13612 break;
13613 default:
13614 xmlGenericError(xmlGenericErrorContext,
13615 "not registered !!!\n");
13616 break;
Daniel Veillard8651f532002-04-17 09:06:27 +000013617 }
13618#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000013619}
13620
13621/**
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000013622 * xmlSchemaCheckFacet:
13623 * @facet: the facet
13624 * @typeDecl: the schema type definition
13625 * @ctxt: the schema parser context or NULL
13626 * @name: name of the type
13627 *
13628 * Checks the default values types, especially for facets
13629 *
13630 * Returns 0 if okay or -1 in cae of error
13631 */
13632int
13633xmlSchemaCheckFacet(xmlSchemaFacetPtr facet,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013634 xmlSchemaTypePtr typeDecl,
13635 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000013636{
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +000013637 xmlSchemaTypePtr nonNegativeIntegerType = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013638 int ret = 0, reuseValCtxt = 0;
13639
Daniel Veillardce682bc2004-11-05 17:22:25 +000013640 if ((facet == NULL) || (typeDecl == NULL))
13641 return(-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013642 /*
13643 * TODO: will the parser context be given if used from
13644 * the relaxNG module?
13645 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000013646
13647 if (nonNegativeIntegerType == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013648 nonNegativeIntegerType =
Daniel Veillard01fa6152004-06-29 17:04:39 +000013649 xmlSchemaGetBuiltInType(XML_SCHEMAS_NNINTEGER);
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000013650 }
13651 switch (facet->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013652 case XML_SCHEMA_FACET_MININCLUSIVE:
13653 case XML_SCHEMA_FACET_MINEXCLUSIVE:
13654 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Daniel Veillardf4b05d02004-07-05 13:10:37 +000013655 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
13656 case XML_SCHEMA_FACET_ENUMERATION: {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013657 /*
13658 * Okay we need to validate the value
13659 * at that point.
13660 */
13661 xmlSchemaValidCtxtPtr vctxt;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013662 xmlSchemaTypePtr base;
Daniel Veillardf4b05d02004-07-05 13:10:37 +000013663
13664 /* 4.3.5.5 Constraints on enumeration Schema Components
13665 * Schema Component Constraint: enumeration valid restriction
13666 * It is an ·error· if any member of {value} is not in the
13667 * ·value space· of {base type definition}.
13668 *
13669 * minInclusive, maxInclusive, minExclusive, maxExclusive:
13670 * The value ·must· be in the
13671 * ·value space· of the ·base type·.
13672 */
13673 /*
13674 * This function is intended to deliver a compiled value
13675 * on the facet. In XML Schemas the type holding a facet,
13676 * cannot be a built-in type. Thus to ensure that other API
13677 * calls (relaxng) do work, if the given type is a built-in
13678 * type, we will assume that the given built-in type *is
13679 * already* the base type.
13680 */
13681 if (typeDecl->type != XML_SCHEMA_TYPE_BASIC) {
13682 base = typeDecl->baseType;
13683 if (base == NULL) {
13684 xmlSchemaPErr(ctxt, typeDecl->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013685 XML_SCHEMAP_INTERNAL,
Daniel Veillardf4b05d02004-07-05 13:10:37 +000013686 "Internal error: xmlSchemaCheckFacet, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000013687 "the type '%s' has no base type.\n",
Daniel Veillardf4b05d02004-07-05 13:10:37 +000013688 typeDecl->name, NULL);
13689 return (-1);
13690 }
13691 } else
13692 base = typeDecl;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013693 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013694 * This avoids perseverative creation of the
13695 * validation context if a parser context is
13696 * used.
Daniel Veillard01fa6152004-06-29 17:04:39 +000013697 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013698 if (ctxt != NULL) {
13699 reuseValCtxt = 1;
13700 if (ctxt->vctxt == NULL) {
13701 if (xmlSchemaCreateVCtxtOnPCtxt(ctxt) == -1)
13702 return (-1);
13703 }
13704 vctxt = ctxt->vctxt;
13705 } else {
13706 vctxt = xmlSchemaNewValidCtxt(NULL);
13707 if (vctxt == NULL) {
13708 xmlSchemaPErr(ctxt, typeDecl->node,
13709 XML_SCHEMAP_INTERNAL,
13710 "Internal error: xmlSchemaCheckFacet, "
13711 "creating a new validation context.\n",
13712 NULL, NULL);
13713 return (-1);
13714 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013715 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013716
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013717 vctxt->node = facet->node;
13718 vctxt->cur = NULL;
13719 /*
13720 * NOTE: This call does not check the content nodes,
13721 * since they are not available:
13722 * facet->node is just the node holding the facet
13723 * definition, *not* the attribute holding the *value*
13724 * of the facet.
13725 */
13726 ret = xmlSchemaValidateSimpleTypeValue(vctxt, base,
13727 facet->value, 0, 1, 1, 0);
Daniel Veillardf4b05d02004-07-05 13:10:37 +000013728 facet->val = vctxt->value;
13729 vctxt->value = NULL;
13730 if (ret > 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013731 /* error code */
13732 if (ctxt != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013733 xmlSchemaPErrExt(ctxt, facet->node,
13734 XML_SCHEMAP_INVALID_FACET,
13735 NULL, NULL, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013736 "Type definition '%s': The value '%s' of the "
13737 "facet '%s' is not valid.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000013738 name, facet->value,
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000013739 BAD_CAST xmlSchemaFacetTypeToString(facet->type),
Daniel Veillard01fa6152004-06-29 17:04:39 +000013740 NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013741 }
13742 ret = -1;
Daniel Veillardf4b05d02004-07-05 13:10:37 +000013743 } else if (ret < 0) {
13744 xmlSchemaPErrExt(ctxt, facet->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013745 XML_SCHEMAP_INTERNAL,
Daniel Veillardf4b05d02004-07-05 13:10:37 +000013746 NULL, NULL, NULL,
13747 "Internal error: xmlSchemaCheckFacet, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000013748 "failed to validate the value '%s' name of the "
13749 "facet '%s' against the base type '%s'.\n",
Daniel Veillardf4b05d02004-07-05 13:10:37 +000013750 facet->value,
13751 BAD_CAST xmlSchemaFacetTypeToString(facet->type),
13752 base->name, NULL, NULL);
13753 ret = -1;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013754 }
13755 if (reuseValCtxt == 0)
13756 xmlSchemaFreeValidCtxt(vctxt);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013757 break;
13758 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013759 case XML_SCHEMA_FACET_PATTERN:
13760 facet->regexp = xmlRegexpCompile(facet->value);
13761 if (facet->regexp == NULL) {
13762 xmlSchemaPErr(ctxt, typeDecl->node,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013763 XML_SCHEMAP_REGEXP_INVALID,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013764 "Type definition '%s': The value '%s' of the "
13765 "facet 'pattern' is not valid.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000013766 name, facet->value);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013767 ret = -1;
13768 }
13769 break;
13770 case XML_SCHEMA_FACET_TOTALDIGITS:
13771 case XML_SCHEMA_FACET_FRACTIONDIGITS:
13772 case XML_SCHEMA_FACET_LENGTH:
13773 case XML_SCHEMA_FACET_MAXLENGTH:
13774 case XML_SCHEMA_FACET_MINLENGTH:{
13775 int tmp;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000013776
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013777 tmp =
13778 xmlSchemaValidatePredefinedType(nonNegativeIntegerType,
13779 facet->value,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +000013780 &(facet->val));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013781 if (tmp != 0) {
13782 /* error code */
13783 if (ctxt != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013784 xmlSchemaPErrExt(ctxt, facet->node,
13785 XML_SCHEMAP_INVALID_FACET_VALUE,
13786 NULL, NULL, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013787 "Type definition '%s': The value '%s' of the "
13788 "facet '%s' is not valid.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000013789 name, facet->value,
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000013790 BAD_CAST xmlSchemaFacetTypeToString(facet->type),
Daniel Veillard01fa6152004-06-29 17:04:39 +000013791 NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013792 }
13793 ret = -1;
13794 }
13795 break;
13796 }
13797 case XML_SCHEMA_FACET_WHITESPACE:{
13798 if (xmlStrEqual(facet->value, BAD_CAST "preserve")) {
13799 facet->whitespace = XML_SCHEMAS_FACET_PRESERVE;
13800 } else if (xmlStrEqual(facet->value, BAD_CAST "replace")) {
13801 facet->whitespace = XML_SCHEMAS_FACET_REPLACE;
13802 } else if (xmlStrEqual(facet->value, BAD_CAST "collapse")) {
13803 facet->whitespace = XML_SCHEMAS_FACET_COLLAPSE;
13804 } else {
13805 if (ctxt != NULL) {
13806 xmlSchemaPErr(ctxt, facet->node,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013807 XML_SCHEMAP_INVALID_WHITE_SPACE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013808 "Type definition '%s': The value '%s' of the "
13809 "facet 'whiteSpace' is not valid.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000013810 name, facet->value);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013811 }
13812 ret = -1;
13813 }
13814 }
13815 default:
13816 break;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000013817 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013818 return (ret);
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000013819}
13820
13821/**
Daniel Veillard4255d502002-04-16 15:50:10 +000013822 * xmlSchemaCheckDefaults:
13823 * @typeDecl: the schema type definition
13824 * @ctxt: the schema parser context
13825 *
13826 * Checks the default values types, especially for facets
13827 */
13828static void
13829xmlSchemaCheckDefaults(xmlSchemaTypePtr typeDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013830 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +000013831{
Daniel Veillard4255d502002-04-16 15:50:10 +000013832 if (name == NULL)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013833 name = typeDecl->name;
13834 /*
13835 * NOTE: It is intended to use the facets list, instead
13836 * of facetSet.
13837 */
13838 if (typeDecl->facets != NULL) {
13839 xmlSchemaFacetPtr facet = typeDecl->facets;
13840
13841 while (facet != NULL) {
13842 xmlSchemaCheckFacet(facet, typeDecl, ctxt, name);
13843 facet = facet->next;
13844 }
13845 }
Daniel Veillard4255d502002-04-16 15:50:10 +000013846}
13847
13848/**
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000013849 * xmlSchemaGetCircModelGrDefRef:
13850 * @ctxtGr: the searched model group
13851 * @list: the list of model groups to be processed
13852 *
13853 * This one is intended to be used by
13854 * xmlSchemaCheckGroupDefCircular only.
13855 *
13856 * Returns the circular model group definition reference, otherwise NULL.
13857 */
13858static xmlSchemaTypePtr
13859xmlSchemaGetCircModelGrDefRef(xmlSchemaTypePtr ctxtGrDef,
13860 xmlSchemaTypePtr gr)
13861{
13862 xmlSchemaTypePtr circ = NULL;
13863 int marked;
13864 /*
13865 * We will search for an model group reference which
13866 * references the context model group definition.
13867 */
13868 while (gr != NULL) {
13869 if (((gr->type == XML_SCHEMA_TYPE_GROUP) ||
13870 (gr->type == XML_SCHEMA_TYPE_ALL) ||
13871 (gr->type == XML_SCHEMA_TYPE_SEQUENCE) ||
13872 (gr->type == XML_SCHEMA_TYPE_CHOICE)) &&
13873 (gr->subtypes != NULL)) {
13874 marked = 0;
13875 if ((gr->type == XML_SCHEMA_TYPE_GROUP) &&
13876 (gr->ref != NULL)) {
13877 if (gr->subtypes == ctxtGrDef)
13878 return (gr);
13879 else if (gr->subtypes->flags &
13880 XML_SCHEMAS_TYPE_MARKED) {
13881 gr = gr->next;
13882 continue;
13883 } else {
13884 /*
13885 * Mark to avoid infinite recursion on
13886 * circular references not yet examined.
13887 */
13888 gr->subtypes->flags |= XML_SCHEMAS_TYPE_MARKED;
13889 marked = 1;
13890 }
13891 if (gr->subtypes->subtypes != NULL)
13892 circ = xmlSchemaGetCircModelGrDefRef(ctxtGrDef,
13893 gr->subtypes->subtypes);
13894 /*
13895 * Unmark the visited model group definition.
13896 */
13897 if (marked)
13898 gr->subtypes->flags ^= XML_SCHEMAS_TYPE_MARKED;
13899 if (circ != NULL)
13900 return (circ);
13901 } else {
13902 circ = xmlSchemaGetCircModelGrDefRef(ctxtGrDef,
13903 (xmlSchemaTypePtr) gr->subtypes);
13904 if (circ != NULL)
13905 return (circ);
13906 }
13907
13908 }
13909 gr = gr->next;
13910 }
13911 return (NULL);
13912}
13913
13914/**
13915 * xmlSchemaCheckGroupDefCircular:
13916 * attrGr: the model group definition
13917 * @ctxt: the parser context
13918 * @name: the name
13919 *
13920 * Checks for circular references to model group definitions.
13921 */
13922static void
13923xmlSchemaCheckGroupDefCircular(xmlSchemaTypePtr modelGrDef,
13924 xmlSchemaParserCtxtPtr ctxt,
13925 const xmlChar * name ATTRIBUTE_UNUSED)
13926{
13927 /*
13928 * Schema Component Constraint: Model Group Correct
13929 * 2 Circular groups are disallowed. That is, within the {particles}
13930 * of a group there must not be at any depth a particle whose {term}
13931 * is the group itself.
13932 */
13933 /*
13934 * NOTE: "gr->subtypes" holds the referenced group.
13935 */
13936 if ((modelGrDef->type != XML_SCHEMA_TYPE_GROUP) ||
13937 ((modelGrDef->flags & XML_SCHEMAS_TYPE_GLOBAL) == 0) ||
13938 (modelGrDef->subtypes == NULL))
13939 return;
13940 else {
13941 xmlSchemaTypePtr circ;
13942
13943 circ = xmlSchemaGetCircModelGrDefRef(modelGrDef, modelGrDef->subtypes);
13944 if (circ != NULL) {
13945 /*
13946 * TODO: Report the referenced attr group as QName.
13947 */
13948 xmlSchemaPCustomErr(ctxt,
13949 XML_SCHEMAP_MG_PROPS_CORRECT_2,
13950 NULL, NULL, circ->node,
13951 "Circular reference to the model group definition '%s' "
13952 "defined", modelGrDef->name);
13953 /*
13954 * NOTE: We will cut the reference to avoid further
13955 * confusion of the processor.
13956 * TODO: SPEC: Does the spec define how to process here?
13957 */
13958 circ->subtypes = NULL;
13959 }
13960 }
13961}
13962
13963
13964/**
13965 * xmlSchemaGetCircAttrGrRef:
13966 * @ctxtGr: the searched attribute group
13967 * @attr: the current attribute list to be processed
13968 *
13969 * This one is intended to be used by
13970 * xmlSchemaCheckSRCAttributeGroupCircular only.
13971 *
13972 * Returns the circular attribute grou reference, otherwise NULL.
13973 */
13974static xmlSchemaAttributeGroupPtr
13975xmlSchemaGetCircAttrGrRef(xmlSchemaAttributeGroupPtr ctxtGr,
13976 xmlSchemaAttributePtr attr)
13977{
13978 xmlSchemaAttributeGroupPtr circ = NULL, gr;
13979 int marked;
13980 /*
13981 * We will search for an attribute group reference which
13982 * references the context attribute group.
13983 */
13984 while (attr != NULL) {
13985 marked = 0;
13986 if (attr->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
13987 gr = (xmlSchemaAttributeGroupPtr) attr;
13988 if (gr->refItem != NULL) {
13989 if (gr->refItem == ctxtGr)
13990 return (gr);
13991 else if (gr->refItem->flags &
13992 XML_SCHEMAS_ATTRGROUP_MARKED) {
13993 attr = attr->next;
13994 continue;
13995 } else {
13996 /*
13997 * Mark as visited to avoid infinite recursion on
13998 * circular references not yet examined.
13999 */
14000 gr->refItem->flags |= XML_SCHEMAS_ATTRGROUP_MARKED;
14001 marked = 1;
14002 }
14003 }
14004 if (gr->attributes != NULL)
14005 circ = xmlSchemaGetCircAttrGrRef(ctxtGr, gr->attributes);
14006 /*
14007 * Unmark the visited group's attributes.
14008 */
14009 if (marked)
14010 gr->refItem->flags ^= XML_SCHEMAS_ATTRGROUP_MARKED;
14011 if (circ != NULL)
14012 return (circ);
14013 }
14014 attr = attr->next;
14015 }
14016 return (NULL);
14017}
14018
14019/**
14020 * xmlSchemaCheckSRCAttributeGroupCircular:
14021 * attrGr: the attribute group definition
14022 * @ctxt: the parser context
14023 * @name: the name
14024 *
14025 * Checks for circular references of attribute groups.
14026 */
14027static void
14028xmlSchemaCheckAttributeGroupCircular(xmlSchemaAttributeGroupPtr attrGr,
14029 xmlSchemaParserCtxtPtr ctxt,
14030 const xmlChar * name ATTRIBUTE_UNUSED)
14031{
14032 /*
14033 * Schema Representation Constraint:
14034 * Attribute Group Definition Representation OK
14035 * 3 Circular group reference is disallowed outside <redefine>.
14036 * That is, unless this element information item's parent is
14037 * <redefine>, then among the [children], if any, there must
14038 * not be an <attributeGroup> with ref [attribute] which resolves
14039 * to the component corresponding to this <attributeGroup>. Indirect
14040 * circularity is also ruled out. That is, when QName resolution
14041 * (Schema Document) (§3.15.3) is applied to a ·QName· arising from
14042 * any <attributeGroup>s with a ref [attribute] among the [children],
14043 * it must not be the case that a ·QName· is encountered at any depth
14044 * which resolves to the component corresponding to this <attributeGroup>.
14045 */
14046 /*
14047 * Only global components can be referenced.
14048 */
14049 if (((attrGr->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL) == 0) ||
14050 (attrGr->attributes == NULL))
14051 return;
14052 else {
14053 xmlSchemaAttributeGroupPtr circ;
14054
14055 circ = xmlSchemaGetCircAttrGrRef(attrGr, attrGr->attributes);
14056 if (circ != NULL) {
14057 /*
14058 * TODO: Report the referenced attr group as QName.
14059 */
14060 xmlSchemaPCustomErr(ctxt,
14061 XML_SCHEMAP_SRC_ATTRIBUTE_GROUP_3,
14062 NULL, NULL, circ->node,
14063 "Circular reference to the attribute group '%s' "
14064 "defined", attrGr->name);
14065 /*
14066 * NOTE: We will cut the reference to avoid further
14067 * confusion of the processor.
14068 * BADSPEC: The spec should define how to process in this case.
14069 */
14070 circ->attributes = NULL;
14071 circ->refItem = NULL;
14072 }
14073 }
14074}
14075
14076/**
Daniel Veillard13e04c62002-04-23 17:51:29 +000014077 * xmlSchemaAttrGrpFixup:
14078 * @attrgrpDecl: the schema attribute definition
14079 * @ctxt: the schema parser context
14080 * @name: the attribute name
14081 *
14082 * Fixes finish doing the computations on the attributes definitions
14083 */
14084static void
Daniel Veillard3646d642004-06-02 19:19:14 +000014085xmlSchemaAttrGrpFixup(xmlSchemaAttributeGroupPtr attrgrp,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014086 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard13e04c62002-04-23 17:51:29 +000014087{
14088 if (name == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000014089 name = attrgrp->name;
14090 if (attrgrp->attributes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014091 return;
Daniel Veillard3646d642004-06-02 19:19:14 +000014092 if (attrgrp->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014093 xmlSchemaAttributeGroupPtr ref;
Daniel Veillard13e04c62002-04-23 17:51:29 +000014094
Daniel Veillardc0826a72004-08-10 14:17:33 +000014095 ref = xmlSchemaGetAttributeGroup(ctxt->schema, attrgrp->ref,
14096 attrgrp->refNs);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014097 if (ref == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000014098 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014099 XML_SCHEMAP_SRC_RESOLVE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014100 NULL, (xmlSchemaTypePtr) attrgrp, attrgrp->node,
14101 "ref", attrgrp->ref, attrgrp->refNs,
14102 XML_SCHEMA_TYPE_ATTRIBUTEGROUP, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014103 return;
14104 }
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000014105 attrgrp->refItem = ref;
14106 /*
14107 * Check for self reference!
14108 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014109 xmlSchemaAttrGrpFixup(ref, ctxt, NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +000014110 attrgrp->attributes = ref->attributes;
14111 attrgrp->attributeWildcard = ref->attributeWildcard;
14112 }
Daniel Veillard13e04c62002-04-23 17:51:29 +000014113}
14114
14115/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014116 * xmlSchemaAttrCheckValConstr:
14117 * @item: an schema attribute declaration/use
14118 * @ctxt: a schema parser context
14119 * @name: the name of the attribute
14120 *
14121 * Validates the value constraints of an attribute declaration/use.
Daniel Veillard4255d502002-04-16 15:50:10 +000014122 *
14123 * Fixes finish doing the computations on the attributes definitions
14124 */
14125static void
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014126xmlSchemaCheckAttrValConstr(xmlSchemaAttributePtr item,
14127 xmlSchemaParserCtxtPtr ctxt,
14128 const xmlChar * name ATTRIBUTE_UNUSED)
14129{
14130
14131 /*
14132 * a-props-correct
14133 * Schema Component Constraint: Attribute Declaration Properties Correct
14134 *
14135 * 2 if there is a {value constraint}, the canonical lexical
14136 * representation of its value must be ·valid· with respect
14137 * to the {type definition} as defined in String Valid (§3.14.4).
14138 */
14139
14140 if (item->defValue != NULL) {
14141 int ret;
14142 xmlNodePtr node;
14143 xmlSchemaTypePtr type;
14144
14145 if (item->subtypes == NULL) {
14146 xmlSchemaPErr(ctxt, item->node,
14147 XML_SCHEMAP_INTERNAL,
14148 "Internal error: xmlSchemaCheckAttrValConstr, "
14149 "type is missing... skipping validation of "
14150 "value constraint", NULL, NULL);
14151 return;
14152 }
14153
14154 /*
14155 * TODO: Try to avoid creating a new context.
14156 * TODO: This all is not very performant.
14157 */
14158 type = item->subtypes;
14159 /*
14160 * Ensure there's validation context.
14161 */
14162 if (ctxt->vctxt == NULL) {
14163 if (xmlSchemaCreateVCtxtOnPCtxt(ctxt) == -1) {
14164 xmlSchemaPErr(ctxt, item->node,
14165 XML_SCHEMAP_INTERNAL,
14166 "Internal error: xmlSchemaCheckAttrValConstr, "
14167 "creating a new validation context.\n",
14168 NULL, NULL);
14169 return;
14170 }
14171 }
14172
14173 if (item->flags & XML_SCHEMAS_ATTR_FIXED)
14174 node = (xmlNodePtr) xmlHasProp(item->node, BAD_CAST "fixed");
14175 else
14176 node = (xmlNodePtr) xmlHasProp(item->node, BAD_CAST "default");
14177 ctxt->vctxt->node = node;
14178 ctxt->vctxt->cur = NULL;
14179 /*
14180 * NOTE: This call does not check the content nodes,
14181 * since they are not available:
14182 * facet->node is just the node holding the facet
14183 * definition, *not* the attribute holding the *value*
14184 * of the facet.
14185 */
14186 ret = xmlSchemaValidateSimpleTypeValue(ctxt->vctxt, type,
14187 item->defValue, 0, 1, 1, 0);
14188 if (ret == 0) {
14189 /*
14190 * Store the computed value.
14191 */
14192 item->defVal = ctxt->vctxt->value;
14193 ctxt->vctxt->value = NULL;
14194 } else if (ret > 0) {
14195 if (ctxt != NULL) {
14196 xmlSchemaPSimpleTypeErr(ctxt,
14197 XML_SCHEMAP_A_PROPS_CORRECT_2,
14198 NULL, NULL, node,
14199 type, NULL, item->defValue,
14200 NULL, NULL, NULL);
14201 }
14202 } else if (ret < 0) {
14203 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
14204 NULL, NULL, node,
14205 "Internal error: xmlSchemaAttrCheckValConstr, "
14206 "failed to validate the value constraint of the "
14207 "attribute decl/use against the type '%s'",
14208 type->name);
14209 }
14210 }
14211}
14212
14213#if 0 /* Not used yet. */
14214static int
14215xmlSchemaCheckElemPropsCorrect(xmlSchemaParserCtxtPtr ctxt,
14216 xmlSchemaElementPtr edecl)
14217{
14218 /*
14219 * TODO: 1 The values of the properties of an element declaration must be as
14220 * described in the property tableau in The Element Declaration Schema
14221 * Component (§3.3.1), modulo the impact of Missing Sub-components (§5.3).
14222 */
14223 /*
14224 * 2 If there is a {value constraint}, the canonical lexical
14225 * representation of its value must be ·valid· with respect to the {type
14226 * definition} as defined in Element Default Valid (Immediate) (§3.3.6).
14227 *
14228 * NOTE: This is done in xmlSchemaCheckElemValConstr.
14229 */
14230 /*
14231 * 3 If there is a non-·absent· {substitution group affiliation},
14232 * then {scope} must be global.
14233 *
14234 * NOTE: This is done in xmlSchemaParseElement.
14235 * TODO: Move it to this layer here.
14236 */
14237 /*
14238 * TODO: 4 If there is a {substitution group affiliation}, the {type definition}
14239 * of the element declaration must be validly derived from the {type
14240 * definition} of the {substitution group affiliation}, given the value
14241 * of the {substitution group exclusions} of the {substitution group
14242 * affiliation}, as defined in Type Derivation OK (Complex) (§3.4.6)
14243 * (if the {type definition} is complex) or as defined in
14244 * Type Derivation OK (Simple) (§3.14.6) (if the {type definition} is
14245 * simple).
14246 */
14247 /*
14248 * TODO: 5 If the {type definition} or {type definition}'s {content type}
14249 * is or is derived from ID then there must not be a {value constraint}.
14250 * Note: The use of ID as a type definition for elements goes beyond
14251 * XML 1.0, and should be avoided if backwards compatibility is desired
14252 */
14253 /*
14254 * TODO: 6 Circular substitution groups are disallowed. That is, it must not
14255 * be possible to return to an element declaration by repeatedly following
14256 * the {substitution group affiliation} property.
14257 */
14258}
14259#endif
14260
14261/**
14262 * xmlSchemaCheckElemValConstr:
14263 * @item: an schema element declaration/particle
14264 * @ctxt: a schema parser context
14265 * @name: the name of the attribute
14266 *
14267 * Validates the value constraints of an element declaration.
14268 *
14269 * Fixes finish doing the computations on the element declarations.
14270 */
14271static void
14272xmlSchemaCheckElemValConstr(xmlSchemaElementPtr decl,
14273 xmlSchemaParserCtxtPtr ctxt,
14274 const xmlChar * name ATTRIBUTE_UNUSED)
14275{
14276 if (decl->value != NULL) {
14277 int ret;
14278 xmlNodePtr node = NULL;
14279 xmlSchemaTypePtr type;
14280
14281 /*
14282 * 2 If there is a {value constraint}, the canonical lexical
14283 * representation of its value must be ·valid· with respect to the {type
14284 * definition} as defined in Element Default Valid (Immediate) (§3.3.6).
14285 */
14286 if (decl->subtypes == NULL) {
14287 xmlSchemaPErr(ctxt, decl->node,
14288 XML_SCHEMAP_INTERNAL,
14289 "Internal error: xmlSchemaCheckElemValConstr, "
14290 "type is missing... skipping validation of "
14291 "the value constraint", NULL, NULL);
14292 return;
14293 }
14294 /*
14295 * Ensure there's a validation context.
14296 */
14297 if (xmlSchemaCreateVCtxtOnPCtxt(ctxt) == -1)
14298 return;
14299
14300 type = decl->subtypes;
14301
14302 if (decl->node != NULL) {
14303 if (decl->flags & XML_SCHEMAS_ELEM_FIXED)
14304 node = (xmlNodePtr) xmlHasProp(decl->node, BAD_CAST "fixed");
14305 else
14306 node = (xmlNodePtr) xmlHasProp(decl->node, BAD_CAST "default");
14307 }
14308 ctxt->vctxt->node = node;
14309 ctxt->vctxt->cur = NULL;
14310 ret = xmlSchemaCheckCOSValidDefault(ctxt, ctxt->vctxt, type, decl->value,
14311 node);
14312 if (ret == 0) {
14313 /*
14314 * Consume the computed value.
14315 */
14316 decl->defVal = ctxt->vctxt->value;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000014317 ctxt->vctxt->value = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014318 } else if (ret < 0) {
14319 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
14320 NULL, NULL, node,
14321 "Internal error: xmlSchemaElemCheckValConstr, "
14322 "failed to validate the value constraint of the "
14323 "element declaration '%s'",
14324 decl->name);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000014325 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014326 }
14327}
14328
14329/**
14330 * xmlSchemaAttrFixup:
14331 * @item: an schema attribute declaration/use.
14332 * @ctxt: a schema parser context
14333 * @name: the name of the attribute
14334 *
14335 * Fixes finish doing the computations on attribute declarations/uses.
14336 */
14337static void
14338xmlSchemaAttrFixup(xmlSchemaAttributePtr item,
14339 xmlSchemaParserCtxtPtr ctxt,
14340 const xmlChar * name ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +000014341{
Daniel Veillardc0826a72004-08-10 14:17:33 +000014342 /*
14343 * TODO: If including this is done twice (!) for every attribute.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014344 * -> Hmm, check if this is still done.
Daniel Veillardc0826a72004-08-10 14:17:33 +000014345 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000014346 /*
14347 * The simple type definition corresponding to the <simpleType> element
14348 * information item in the [children], if present, otherwise the simple
14349 * type definition ·resolved· to by the ·actual value· of the type
14350 * [attribute], if present, otherwise the ·simple ur-type definition·.
14351 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014352 if (item->flags & XML_SCHEMAS_ATTR_INTERNAL_RESOLVED)
Daniel Veillardc0826a72004-08-10 14:17:33 +000014353 return;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014354 item->flags |= XML_SCHEMAS_ATTR_INTERNAL_RESOLVED;
14355 if (item->subtypes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014356 return;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014357 if (item->typeName != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014358 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000014359
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014360 type = xmlSchemaGetType(ctxt->schema, item->typeName,
14361 item->typeNs);
14362 if ((type == NULL) || (! IS_SIMPLE_TYPE(type))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000014363 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014364 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014365 NULL, (xmlSchemaTypePtr) item, item->node,
14366 "type", item->typeName, item->typeNs,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014367 XML_SCHEMA_TYPE_SIMPLE, NULL);
14368 } else
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014369 item->subtypes = type;
14370
14371 } else if (item->ref != NULL) {
14372 xmlSchemaAttributePtr decl;
Daniel Veillard4255d502002-04-16 15:50:10 +000014373
Daniel Veillardc0826a72004-08-10 14:17:33 +000014374 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014375 * We have an attribute use here; assign the referenced
14376 * attribute declaration.
14377 */
14378 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000014379 * TODO: Evaluate, what errors could occur if the declaration is not
14380 * found. It might be possible that the "typefixup" might crash if
14381 * no ref declaration was found.
14382 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014383 decl = xmlSchemaGetAttribute(ctxt->schema, item->ref, item->refNs);
14384 if (decl == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000014385 xmlSchemaPResCompAttrErr(ctxt,
14386 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014387 NULL, (xmlSchemaTypePtr) item, item->node,
14388 "ref", item->ref, item->refNs,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014389 XML_SCHEMA_TYPE_ATTRIBUTE, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014390 return;
14391 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014392 item->refDecl = decl;
14393 xmlSchemaAttrFixup(decl, ctxt, NULL);
14394
14395 item->subtypes = decl->subtypes;
14396 /*
14397 * Attribute Use Correct
14398 * au-props-correct.2: If the {attribute declaration} has a fixed
14399 * {value constraint}, then if the attribute use itself has a
14400 * {value constraint}, it must also be fixed and its value must match
14401 * that of the {attribute declaration}'s {value constraint}.
14402 */
14403 if ((decl->flags & XML_SCHEMAS_ATTR_FIXED) &&
14404 (item->defValue != NULL)) {
14405 if (((item->flags & XML_SCHEMAS_ATTR_FIXED) == 0) ||
14406 (!xmlStrEqual(item->defValue, decl->defValue))) {
14407 xmlSchemaPCustomErr(ctxt,
14408 XML_SCHEMAP_AU_PROPS_CORRECT_2,
14409 NULL, NULL, item->node,
14410 "The value constraint must be fixed "
14411 "and match the referenced attribute "
14412 "declarations's value constraint '%s'",
14413 decl->defValue);
14414 }
14415 /*
14416 * FUTURE: One should change the values of the attr. use
14417 * if ever validation should be attempted even if the
14418 * schema itself was not fully valid.
14419 */
14420 }
Daniel Veillard3646d642004-06-02 19:19:14 +000014421 } else {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014422 item->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
14423 }
Daniel Veillard4255d502002-04-16 15:50:10 +000014424}
14425
14426/**
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000014427 * xmlSchemaResolveIDCKeyRef:
14428 * @idc: the identity-constraint definition
14429 * @ctxt: the schema parser context
14430 * @name: the attribute name
14431 *
14432 * Resolve keyRef references to key/unique IDCs.
14433 */
14434static void
14435xmlSchemaResolveIDCKeyRef(xmlSchemaIDCPtr idc,
14436 xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +000014437 const xmlChar * name ATTRIBUTE_UNUSED)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000014438{
14439 if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF)
14440 return;
14441 if (idc->ref->name != NULL) {
14442 idc->ref->item = (xmlSchemaBasicItemPtr) xmlHashLookup2(
14443 ctxt->schema->idcDef,
14444 idc->ref->name,
14445 idc->ref->targetNamespace);
14446 if (idc->ref->item == NULL) {
14447 /*
14448 * TODO: It is actually not an error to fail to resolve.
14449 */
14450 xmlSchemaPResCompAttrErr(ctxt,
14451 XML_SCHEMAP_SRC_RESOLVE,
14452 NULL, (xmlSchemaTypePtr) idc, idc->node,
14453 "refer", idc->ref->name,
14454 idc->ref->targetNamespace,
14455 XML_SCHEMA_TYPE_IDC_KEYREF, NULL);
14456 return;
14457 }
14458 }
14459}
14460
14461/**
Daniel Veillard4255d502002-04-16 15:50:10 +000014462 * xmlSchemaParse:
14463 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +000014464 *
Daniel Veillard01c13b52002-12-10 15:19:08 +000014465 * parse a schema definition resource and build an internal
Daniel Veillard4255d502002-04-16 15:50:10 +000014466 * XML Shema struture which can be used to validate instances.
14467 * *WARNING* this interface is highly subject to change
14468 *
14469 * Returns the internal XML Schema structure built from the resource or
14470 * NULL in case of error
14471 */
14472xmlSchemaPtr
14473xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt)
14474{
14475 xmlSchemaPtr ret = NULL;
14476 xmlDocPtr doc;
Daniel Veillardbd2904b2003-11-25 15:38:59 +000014477 xmlNodePtr root;
Daniel Veillarddda22c12004-01-24 08:31:30 +000014478 int preserve = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000014479
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014480 /*
14481 * This one is used if the schema to be parsed was specified via
14482 * the API; i.e. not automatically by the validated instance document.
14483 */
14484
Daniel Veillard4255d502002-04-16 15:50:10 +000014485 xmlSchemaInitTypes();
14486
Daniel Veillard6045c902002-10-09 21:13:59 +000014487 if (ctxt == NULL)
Daniel Veillard4255d502002-04-16 15:50:10 +000014488 return (NULL);
14489
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000014490 ctxt->nberrors = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000014491 ctxt->counter = 0;
14492 ctxt->container = NULL;
14493
14494 /*
14495 * First step is to parse the input document into an DOM/Infoset
14496 */
Daniel Veillard6045c902002-10-09 21:13:59 +000014497 if (ctxt->URL != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +000014498 doc = xmlReadFile((const char *) ctxt->URL, NULL,
14499 SCHEMAS_PARSE_OPTIONS);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014500 if (doc == NULL) {
14501 xmlSchemaPErr(ctxt, NULL,
14502 XML_SCHEMAP_FAILED_LOAD,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014503 "xmlSchemaParse: could not load '%s'.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014504 ctxt->URL, NULL);
14505 return (NULL);
14506 }
Daniel Veillard6045c902002-10-09 21:13:59 +000014507 } else if (ctxt->buffer != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +000014508 doc = xmlReadMemory(ctxt->buffer, ctxt->size, NULL, NULL,
14509 SCHEMAS_PARSE_OPTIONS);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014510 if (doc == NULL) {
14511 xmlSchemaPErr(ctxt, NULL,
14512 XML_SCHEMAP_FAILED_PARSE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014513 "xmlSchemaParse: could not parse.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014514 NULL, NULL);
14515 return (NULL);
14516 }
14517 doc->URL = xmlStrdup(BAD_CAST "in_memory_buffer");
Daniel Veillard65765282004-01-08 16:59:30 +000014518 ctxt->URL = xmlDictLookup(ctxt->dict, BAD_CAST "in_memory_buffer", -1);
Daniel Veillard9d751502003-10-29 13:21:47 +000014519 } else if (ctxt->doc != NULL) {
14520 doc = ctxt->doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +000014521 preserve = 1;
Daniel Veillard6045c902002-10-09 21:13:59 +000014522 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014523 xmlSchemaPErr(ctxt, NULL,
14524 XML_SCHEMAP_NOTHING_TO_PARSE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014525 "xmlSchemaParse: could not parse.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014526 NULL, NULL);
14527 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000014528 }
14529
14530 /*
14531 * Then extract the root and Schema parse it
14532 */
14533 root = xmlDocGetRootElement(doc);
14534 if (root == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014535 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
14536 XML_SCHEMAP_NOROOT,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014537 "The schema has no document element.\n", NULL, NULL);
Daniel Veillarddda22c12004-01-24 08:31:30 +000014538 if (!preserve) {
14539 xmlFreeDoc(doc);
14540 }
Daniel Veillard4255d502002-04-16 15:50:10 +000014541 return (NULL);
14542 }
14543
14544 /*
14545 * Remove all the blank text nodes
14546 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +000014547 xmlSchemaCleanupDoc(ctxt, root);
Daniel Veillard4255d502002-04-16 15:50:10 +000014548
14549 /*
14550 * Then do the parsing for good
14551 */
14552 ret = xmlSchemaParseSchema(ctxt, root);
Daniel Veillard1d913862003-11-21 00:28:39 +000014553 if (ret == NULL) {
Daniel Veillarddda22c12004-01-24 08:31:30 +000014554 if (!preserve) {
14555 xmlFreeDoc(doc);
14556 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014557 return (NULL);
Daniel Veillard1d913862003-11-21 00:28:39 +000014558 }
Daniel Veillard4255d502002-04-16 15:50:10 +000014559 ret->doc = doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +000014560 ret->preserve = preserve;
Daniel Veillard4255d502002-04-16 15:50:10 +000014561 ctxt->schema = ret;
Daniel Veillardc0826a72004-08-10 14:17:33 +000014562 ctxt->ctxtType = NULL;
14563 ctxt->parentItem = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000014564 /*
Daniel Veillardf2a12832003-11-24 13:04:35 +000014565 * Then fixup all attributes declarations
14566 */
14567 xmlHashScan(ret->attrDecl, (xmlHashScanner) xmlSchemaAttrFixup, ctxt);
14568
14569 /*
14570 * Then fixup all attributes group declarations
14571 */
14572 xmlHashScan(ret->attrgrpDecl, (xmlHashScanner) xmlSchemaAttrGrpFixup,
14573 ctxt);
14574
14575 /*
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000014576 * Resolve identity-constraint keyRefs.
14577 */
14578 xmlHashScan(ret->idcDef, (xmlHashScanner) xmlSchemaResolveIDCKeyRef, ctxt);
14579
14580 /*
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000014581 * Check attribute groups for circular references.
14582 */
14583 xmlHashScan(ret->attrgrpDecl, (xmlHashScanner)
14584 xmlSchemaCheckAttributeGroupCircular, ctxt);
14585
14586 /*
14587 * Then fixup all model group definitions.
14588 */
14589 xmlHashScan(ret->groupDecl, (xmlHashScanner) xmlSchemaGroupDefFixup, ctxt);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014590
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000014591 /*
Daniel Veillard4255d502002-04-16 15:50:10 +000014592 * Then fixup all types properties
Daniel Veillardc0826a72004-08-10 14:17:33 +000014593 */
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000014594 xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaTypeFixup, ctxt);
Daniel Veillardc0826a72004-08-10 14:17:33 +000014595
14596 /*
14597 * Then fix references of element declaration; apply constraints.
14598 */
14599 xmlHashScanFull(ret->elemDecl,
14600 (xmlHashScannerFull) xmlSchemaRefFixupCallback, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +000014601
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000014602 /*
14603 * Check model groups defnitions for circular references.
14604 */
14605 xmlHashScan(ret->groupDecl, (xmlHashScanner)
14606 xmlSchemaCheckGroupDefCircular, ctxt);
14607
Daniel Veillard4255d502002-04-16 15:50:10 +000014608 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014609 * Then build the content model for all complex types
Daniel Veillard4255d502002-04-16 15:50:10 +000014610 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014611 xmlHashScan(ret->typeDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014612 (xmlHashScanner) xmlSchemaBuildContentModel, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +000014613
14614 /*
14615 * Then check the defaults part of the type like facets values
14616 */
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +000014617 /* OLD: xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaCheckDefaults, ctxt); */
Daniel Veillard4255d502002-04-16 15:50:10 +000014618
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014619 /*
14620 * Validate the value constraint of attribute declarations/uses.
14621 */
14622 xmlHashScan(ret->attrDecl, (xmlHashScanner) xmlSchemaCheckAttrValConstr, ctxt);
14623
14624 /*
14625 * Validate the value constraint of element declarations.
14626 */
14627 xmlHashScan(ret->elemDecl, (xmlHashScanner) xmlSchemaCheckElemValConstr, ctxt);
14628
Daniel Veillardc0826a72004-08-10 14:17:33 +000014629
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000014630 if (ctxt->nberrors != 0) {
14631 xmlSchemaFree(ret);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014632 ret = NULL;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000014633 }
Daniel Veillard4255d502002-04-16 15:50:10 +000014634 return (ret);
14635}
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014636
Daniel Veillard4255d502002-04-16 15:50:10 +000014637/**
Daniel Veillard01c13b52002-12-10 15:19:08 +000014638 * xmlSchemaSetParserErrors:
Daniel Veillard4255d502002-04-16 15:50:10 +000014639 * @ctxt: a schema validation context
Daniel Veillard01c13b52002-12-10 15:19:08 +000014640 * @err: the error callback
14641 * @warn: the warning callback
14642 * @ctx: contextual data for the callbacks
Daniel Veillard4255d502002-04-16 15:50:10 +000014643 *
Daniel Veillard01c13b52002-12-10 15:19:08 +000014644 * Set the callback functions used to handle errors for a validation context
Daniel Veillard4255d502002-04-16 15:50:10 +000014645 */
14646void
14647xmlSchemaSetParserErrors(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014648 xmlSchemaValidityErrorFunc err,
14649 xmlSchemaValidityWarningFunc warn, void *ctx)
14650{
Daniel Veillard4255d502002-04-16 15:50:10 +000014651 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014652 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000014653 ctxt->error = err;
14654 ctxt->warning = warn;
14655 ctxt->userData = ctx;
14656}
14657
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000014658/**
Daniel Veillard259f0df2004-08-18 09:13:18 +000014659 * xmlSchemaGetParserErrors:
14660 * @ctxt: a XMl-Schema parser context
14661 * @err: the error callback result
14662 * @warn: the warning callback result
14663 * @ctx: contextual data for the callbacks result
14664 *
14665 * Get the callback information used to handle errors for a parser context
14666 *
14667 * Returns -1 in case of failure, 0 otherwise
14668 */
14669int
14670xmlSchemaGetParserErrors(xmlSchemaParserCtxtPtr ctxt,
14671 xmlSchemaValidityErrorFunc * err,
14672 xmlSchemaValidityWarningFunc * warn, void **ctx)
14673{
14674 if (ctxt == NULL)
14675 return(-1);
14676 if (err != NULL)
14677 *err = ctxt->error;
14678 if (warn != NULL)
14679 *warn = ctxt->warning;
14680 if (ctx != NULL)
14681 *ctx = ctxt->userData;
14682 return(0);
14683}
14684
14685/**
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000014686 * xmlSchemaFacetTypeToString:
14687 * @type: the facet type
14688 *
14689 * Convert the xmlSchemaTypeType to a char string.
14690 *
14691 * Returns the char string representation of the facet type if the
14692 * type is a facet and an "Internal Error" string otherwise.
14693 */
14694static const char *
14695xmlSchemaFacetTypeToString(xmlSchemaTypeType type)
14696{
14697 switch (type) {
14698 case XML_SCHEMA_FACET_PATTERN:
14699 return ("pattern");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014700 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000014701 return ("maxExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014702 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000014703 return ("maxInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014704 case XML_SCHEMA_FACET_MINEXCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000014705 return ("minExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014706 case XML_SCHEMA_FACET_MININCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000014707 return ("minInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014708 case XML_SCHEMA_FACET_WHITESPACE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000014709 return ("whiteSpace");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014710 case XML_SCHEMA_FACET_ENUMERATION:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000014711 return ("enumeration");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014712 case XML_SCHEMA_FACET_LENGTH:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000014713 return ("length");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014714 case XML_SCHEMA_FACET_MAXLENGTH:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000014715 return ("maxLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014716 case XML_SCHEMA_FACET_MINLENGTH:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000014717 return ("minLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014718 case XML_SCHEMA_FACET_TOTALDIGITS:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000014719 return ("totalDigits");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014720 case XML_SCHEMA_FACET_FRACTIONDIGITS:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000014721 return ("fractionDigits");
14722 default:
14723 break;
14724 }
14725 return ("Internal Error");
14726}
14727
Daniel Veillardc0826a72004-08-10 14:17:33 +000014728
Daniel Veillardc0826a72004-08-10 14:17:33 +000014729
14730static int
14731xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type)
14732{
14733 xmlSchemaTypePtr anc;
14734
14735 /*
14736 * The normalization type can be changed only for types which are derived
14737 * from xsd:string.
14738 */
14739 if (type->type == XML_SCHEMA_TYPE_BASIC) {
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +000014740 if (type->builtInType == XML_SCHEMAS_STRING)
Daniel Veillardc0826a72004-08-10 14:17:33 +000014741 return(XML_SCHEMAS_VAL_WTSP_PRESERVE);
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +000014742 else if (type->builtInType == XML_SCHEMAS_NORMSTRING)
14743 return(XML_SCHEMAS_VAL_WTSP_REPLACE);
Daniel Veillardc0826a72004-08-10 14:17:33 +000014744 else {
14745 /*
14746 * For all ·atomic· datatypes other than string (and types ·derived·
14747 * by ·restriction· from it) the value of whiteSpace is fixed to
14748 * collapse
14749 */
14750 return(XML_SCHEMAS_VAL_WTSP_COLLAPSE);
14751 }
14752 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
14753 /*
14754 * For list types the facet "whiteSpace" is fixed to "collapse".
14755 */
14756 return (XML_SCHEMAS_VAL_WTSP_COLLAPSE);
14757 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
14758 return (-1);
14759 } else if (type->facetSet != NULL) {
14760 xmlSchemaTypePtr anyST;
14761 xmlSchemaFacetLinkPtr lin;
14762
14763 /*
14764 * Atomic types.
14765 */
14766 anyST = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
14767 anc = type->baseType;
14768 do {
14769 /*
14770 * For all ·atomic· datatypes other than string (and types ·derived·
14771 * by ·restriction· from it) the value of whiteSpace is fixed to
14772 * collapse
14773 */
14774 if ((anc->type == XML_SCHEMA_TYPE_BASIC) &&
14775 (anc->builtInType == XML_SCHEMAS_STRING)) {
14776
14777 lin = type->facetSet;
14778 do {
14779 if (lin->facet->type == XML_SCHEMA_FACET_WHITESPACE) {
14780 if (lin->facet->whitespace ==
14781 XML_SCHEMAS_FACET_COLLAPSE) {
14782 return(XML_SCHEMAS_VAL_WTSP_COLLAPSE);
14783 } else if (lin->facet->whitespace ==
14784 XML_SCHEMAS_FACET_REPLACE) {
14785 return(XML_SCHEMAS_VAL_WTSP_REPLACE);
14786 } else
14787 return(XML_SCHEMAS_VAL_WTSP_PRESERVE);
14788 break;
14789 }
14790 lin = lin->next;
14791 } while (lin != NULL);
14792 break;
14793 }
14794 anc = anc->baseType;
14795 } while (anc != anyST);
14796 return (XML_SCHEMAS_VAL_WTSP_COLLAPSE);
14797 }
14798 return (-1);
14799}
14800
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000014801/**
Daniel Veillard377e1a92004-04-16 16:30:05 +000014802 * xmlSchemaValidateFacetsInternal:
14803 * @ctxt: a schema validation context
Daniel Veillardc0826a72004-08-10 14:17:33 +000014804 * @type: the type holding the facets
Daniel Veillard377e1a92004-04-16 16:30:05 +000014805 * @facets: the list of facets to check
14806 * @value: the lexical repr of the value to validate
14807 * @val: the precomputed value
William M. Bracke7091952004-05-11 15:09:58 +000014808 * @fireErrors: if 0, only internal errors will be fired;
14809 * otherwise all errors will be fired.
Daniel Veillard377e1a92004-04-16 16:30:05 +000014810 *
14811 * Check a value against all facet conditions
14812 *
14813 * Returns 0 if the element is schemas valid, a positive error code
14814 * number otherwise and -1 in case of internal or API error.
14815 */
14816static int
14817xmlSchemaValidateFacetsInternal(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014818 xmlSchemaTypePtr type,
14819 const xmlChar * value,
14820 unsigned long length,
14821 int fireErrors)
Daniel Veillard377e1a92004-04-16 16:30:05 +000014822{
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000014823 int ret = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014824 xmlNodePtr node;
Daniel Veillardc0826a72004-08-10 14:17:33 +000014825 xmlSchemaTypePtr biType; /* The build-in type. */
14826 xmlSchemaTypePtr tmpType;
14827 xmlSchemaFacetLinkPtr facetLink;
Daniel Veillardc7e3cc42004-09-28 12:33:52 +000014828 int retFacet;
Daniel Veillardc0826a72004-08-10 14:17:33 +000014829 xmlSchemaFacetPtr facet;
14830 unsigned long len = 0;
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000014831
Daniel Veillardc0826a72004-08-10 14:17:33 +000014832#ifdef DEBUG_UNION_VALIDATION
14833 printf("Facets of type: '%s'\n", (const char *) type->name);
14834 printf(" fireErrors: %d\n", fireErrors);
14835#endif
14836
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014837 node = ctxt->node;
Daniel Veillardc0826a72004-08-10 14:17:33 +000014838 /*
14839 * NOTE: Do not jump away, if the facetSet of the given type is
14840 * empty: until now, "pattern" facets of the *base types* need to
14841 * be checked as well.
14842 */
14843 biType = type->baseType;
14844 while ((biType != NULL) && (biType->type != XML_SCHEMA_TYPE_BASIC))
14845 biType = biType->baseType;
14846 if (biType == NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014847 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014848 "Internal error: xmlSchemaValidateFacetsInternal, "
14849 "the base type axis of the given type '%s' does not resolve to "
14850 "a built-in type.\n",
14851 type->name, NULL);
14852 return (-1);
14853 }
14854
14855 if (type->facetSet != NULL) {
14856 facetLink = type->facetSet;
14857 while (facetLink != NULL) {
14858 facet = facetLink->facet;
14859 /*
14860 * Skip the pattern "whiteSpace": it is used to
14861 * format the character content beforehand.
14862 */
14863 switch (facet->type) {
14864 case XML_SCHEMA_FACET_WHITESPACE:
14865 case XML_SCHEMA_FACET_PATTERN:
14866 case XML_SCHEMA_FACET_ENUMERATION:
14867 break;
14868 case XML_SCHEMA_FACET_LENGTH:
14869 case XML_SCHEMA_FACET_MINLENGTH:
14870 case XML_SCHEMA_FACET_MAXLENGTH:
14871 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
14872 ret = xmlSchemaValidateListSimpleTypeFacet(facet,
14873 value, length, 0);
14874 len = length;
14875 } else
14876 ret = xmlSchemaValidateLengthFacet(biType, facet,
14877 value, ctxt->value, &len);
14878 break;
14879 default:
14880 ret = xmlSchemaValidateFacet(biType, facet, value,
14881 ctxt->value);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014882 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000014883 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014884 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014885 "Internal error: xmlSchemaValidateFacetsInternal, "
14886 "validating facet of type '%s'.\n",
14887 type->name, NULL);
14888 break;
14889 } else if ((ret > 0) && (fireErrors)) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014890 xmlSchemaVFacetErr(ctxt, ret, node, value, len,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014891 type, facet, NULL, NULL, NULL, NULL);
14892 }
14893
14894 facetLink = facetLink->next;
14895 }
14896 if (ret >= 0) {
14897 /*
14898 * Process enumerations.
14899 */
14900 retFacet = 0;
14901 facetLink = type->facetSet;
14902 while (facetLink != NULL) {
14903 if (facetLink->facet->type == XML_SCHEMA_FACET_ENUMERATION) {
14904 retFacet = xmlSchemaValidateFacet(biType, facetLink->facet,
14905 value, ctxt->value);
14906 if (retFacet <= 0)
14907 break;
14908 }
14909 facetLink = facetLink->next;
14910 }
14911 if (retFacet > 0) {
14912 ret = XML_SCHEMAV_CVC_ENUMERATION_VALID;
14913 if (fireErrors)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014914 xmlSchemaVFacetErr(ctxt, ret, node,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014915 value, 0, type, NULL, NULL, NULL, NULL, NULL);
14916 } else if (retFacet < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014917 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014918 "Internal error: xmlSchemaValidateFacetsInternal, "
14919 "validating facet of type '%s'.\n",
14920 BAD_CAST "enumeration", NULL);
14921 ret = -1;
14922 }
14923 }
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000014924 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000014925 if (ret >= 0) {
14926 /*
14927 * Process patters. Pattern facets are ORed at type level
14928 * and ANDed if derived. Walk the base type axis.
14929 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000014930 tmpType = type;
14931 facet = NULL;
14932 do {
14933 retFacet = 0;
14934 for (facetLink = tmpType->facetSet; facetLink != NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014935 facetLink = facetLink->next) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000014936 if (facetLink->facet->type != XML_SCHEMA_FACET_PATTERN)
14937 continue;
14938 retFacet = xmlSchemaValidateFacet(biType, facetLink->facet,
14939 value, ctxt->value);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014940 if (retFacet == 0)
Daniel Veillardc0826a72004-08-10 14:17:33 +000014941 break;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014942 else if (retFacet < 0) {
14943 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
14944 "Internal error: xmlSchemaValidateFacetsInternal, "
14945 "validating 'pattern' facet '%s' of type '%s'.\n",
14946 facetLink->facet->value, tmpType->name);
14947 ret = -1;
14948 break;
14949 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +000014950 /* Save the last non-validating facet. */
14951 facet = facetLink->facet;
14952 }
14953 if (retFacet != 0)
14954 break;
14955 tmpType = tmpType->baseType;
14956 } while ((tmpType != NULL) && (tmpType->type != XML_SCHEMA_TYPE_BASIC));
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014957 if (retFacet > 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000014958 ret = XML_SCHEMAV_CVC_PATTERN_VALID;
14959 if (fireErrors) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014960 xmlSchemaVFacetErr(ctxt, ret, node, value, 0, type, facet,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014961 NULL, NULL, NULL, NULL);
14962 }
14963 }
14964 }
14965
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000014966 return (ret);
14967}
14968
Daniel Veillard4255d502002-04-16 15:50:10 +000014969/************************************************************************
14970 * *
14971 * Simple type validation *
14972 * *
14973 ************************************************************************/
Daniel Veillard377e1a92004-04-16 16:30:05 +000014974
Daniel Veillard4255d502002-04-16 15:50:10 +000014975
14976/************************************************************************
14977 * *
14978 * DOM Validation code *
14979 * *
14980 ************************************************************************/
14981
Daniel Veillard4255d502002-04-16 15:50:10 +000014982static int xmlSchemaValidateAttributes(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014983 xmlNodePtr elem,
Daniel Veillard3646d642004-06-02 19:19:14 +000014984 xmlSchemaTypePtr type);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014985static int xmlSchemaValidateElementByType(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014986 xmlSchemaTypePtr type,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000014987 int isNil,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014988 int valSimpleContent);
Daniel Veillard4255d502002-04-16 15:50:10 +000014989
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000014990static void xmlSchemaBeginElement(xmlSchemaValidCtxtPtr vctxt);
14991static void xmlSchemaEndElement(xmlSchemaValidCtxtPtr vctxt);
14992
14993#ifdef ELEM_INFO_ENABLED
14994/**
14995 * xmlSchemaGetFreshElemInfo:
14996 * @vctxt: the schema validation context
14997 *
14998 * Creates/reuses and initializes the element info item for
14999 * the currect tree depth.
15000 *
15001 * Returns the element info item or NULL on API or internal errors.
15002 */
15003static xmlSchemaElemInfoPtr
15004xmlSchemaGetFreshElemInfo(xmlSchemaValidCtxtPtr vctxt)
15005{
15006 xmlSchemaElemInfoPtr info = NULL;
15007
15008 if (vctxt->depth > vctxt->sizeElemInfos) {
15009 xmlSchemaVErr(vctxt, NULL, XML_SCHEMAV_INTERNAL,
15010 "Internal error: xmlSchemaPushDepthInfo, "
15011 "an inconsistent depth encountered.\n",
15012 NULL, NULL);
15013 return (NULL);
15014 }
15015 if (vctxt->elemInfos == NULL) {
15016 vctxt->elemInfos = (xmlSchemaElemInfoPtr *)
15017 xmlMalloc(10 * sizeof(xmlSchemaElemInfoPtr));
15018 if (vctxt->elemInfos == NULL) {
15019 xmlSchemaVErrMemory(vctxt,
15020 "allocating the element info array", NULL);
15021 return (NULL);
15022 }
15023 memset(vctxt->elemInfos, 0, 10 * sizeof(xmlSchemaElemInfoPtr));
15024 vctxt->sizeElemInfos = 10;
15025 } else if (vctxt->sizeElemInfos == vctxt->depth) {
15026 int i = vctxt->sizeElemInfos;
15027
15028 vctxt->sizeElemInfos *= 2;
15029 vctxt->elemInfos = (xmlSchemaElemInfoPtr *)
15030 xmlRealloc(vctxt->elemInfos, vctxt->sizeElemInfos *
15031 sizeof(xmlSchemaElemInfoPtr));
15032 if (vctxt->elemInfos == NULL) {
15033 xmlSchemaVErrMemory(vctxt,
15034 "re-allocating the element info array", NULL);
15035 return (NULL);
15036 }
15037 /*
15038 * We need the new memory to be NULLed.
15039 * TODO: Use memset instead?
15040 */
15041 for (; i < vctxt->sizeElemInfos; i++)
15042 vctxt->elemInfos[i] = NULL;
15043 } else
15044 info = vctxt->elemInfos[vctxt->depth];
15045
15046 if (info == NULL) {
15047 info = (xmlSchemaElemInfoPtr)
15048 xmlMalloc(sizeof(xmlSchemaElemInfo));
15049 if (info == NULL) {
15050 xmlSchemaVErrMemory(vctxt,
15051 "allocating an element info", NULL);
15052 return (NULL);
15053 }
15054 vctxt->elemInfos[vctxt->depth] = info;
15055 }
15056 memset(info, 0, sizeof(xmlSchemaElemInfo));
15057 info->depth = vctxt->depth;
15058
15059 return (info);
15060}
15061#endif /* ELEM_INFO_ENABLED */
15062
Daniel Veillard3646d642004-06-02 19:19:14 +000015063
15064/**
15065 * xmlSchemaFreeAttrStates:
15066 * @state: a list of attribute states
15067 *
15068 * Free the given list of attribute states
15069 *
15070 */
15071static void
15072xmlSchemaFreeAttributeStates(xmlSchemaAttrStatePtr state)
15073{
15074 xmlSchemaAttrStatePtr tmp;
15075 while (state != NULL) {
15076 tmp = state;
15077 state = state->next;
15078 xmlFree(tmp);
15079 }
15080}
15081
Daniel Veillard4255d502002-04-16 15:50:10 +000015082/**
15083 * xmlSchemaRegisterAttributes:
15084 * @ctxt: a schema validation context
15085 * @attrs: a list of attributes
15086 *
15087 * Register the list of attributes as the set to be validated on that element
15088 *
15089 * Returns -1 in case of error, 0 otherwise
15090 */
15091static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015092xmlSchemaRegisterAttributes(xmlSchemaValidCtxtPtr ctxt, xmlAttrPtr attrs)
15093{
Daniel Veillard3646d642004-06-02 19:19:14 +000015094 xmlSchemaAttrStatePtr tmp;
15095
15096 ctxt->attr = NULL;
15097 ctxt->attrTop = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000015098 while (attrs != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015099 if ((attrs->ns != NULL) &&
15100 (xmlStrEqual(attrs->ns->href, xmlSchemaInstanceNs))) {
15101 attrs = attrs->next;
15102 continue;
15103 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000015104 tmp = (xmlSchemaAttrStatePtr)
15105 xmlMalloc(sizeof(xmlSchemaAttrState));
15106 if (tmp == NULL) {
15107 xmlSchemaVErrMemory(ctxt, "registering attributes", NULL);
15108 return (-1);
15109 }
Daniel Veillard3646d642004-06-02 19:19:14 +000015110 tmp->attr = attrs;
15111 tmp->state = XML_SCHEMAS_ATTR_UNKNOWN;
15112 tmp->next = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015113 tmp->decl = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000015114 if (ctxt->attr == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015115 ctxt->attr = tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000015116 else
15117 ctxt->attrTop->next = tmp;
15118 ctxt->attrTop = tmp;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015119 attrs = attrs->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000015120 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015121 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000015122}
15123
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015124#if 0 /* Currently not used */
Daniel Veillard4255d502002-04-16 15:50:10 +000015125/**
Daniel Veillard4255d502002-04-16 15:50:10 +000015126 * xmlSchemaValidateCheckNodeList
15127 * @nodelist: the list of nodes
15128 *
15129 * Check the node list is only made of text nodes and entities pointing
15130 * to text nodes
15131 *
15132 * Returns 1 if true, 0 if false and -1 in case of error
15133 */
15134static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015135xmlSchemaValidateCheckNodeList(xmlNodePtr nodelist)
15136{
Daniel Veillard4255d502002-04-16 15:50:10 +000015137 while (nodelist != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015138 if (nodelist->type == XML_ENTITY_REF_NODE) {
15139 TODO /* implement recursion in the entity content */
15140 }
15141 if ((nodelist->type != XML_TEXT_NODE) &&
15142 (nodelist->type != XML_COMMENT_NODE) &&
15143 (nodelist->type != XML_PI_NODE) &&
William M. Bracke7091952004-05-11 15:09:58 +000015144 (nodelist->type != XML_CDATA_SECTION_NODE)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015145 return (0);
15146 }
15147 nodelist = nodelist->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000015148 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015149 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +000015150}
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015151#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000015152
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015153static void
15154xmlSchemaPostSchemaAssembleFixup(xmlSchemaParserCtxtPtr ctxt)
15155{
15156 int i, nbItems;
15157 xmlSchemaTypePtr item, *items;
15158
15159
15160 /*
15161 * During the Assemble of the schema ctxt->curItems has
15162 * been filled with the relevant new items. Fix those up.
15163 */
15164 nbItems = ctxt->assemble->nbItems;
15165 items = (xmlSchemaTypePtr *) ctxt->assemble->items;
15166
15167 for (i = 0; i < nbItems; i++) {
15168 item = items[i];
15169 switch (item->type) {
15170 case XML_SCHEMA_TYPE_ATTRIBUTE:
15171 xmlSchemaAttrFixup((xmlSchemaAttributePtr) item, ctxt, NULL);
15172 break;
15173 case XML_SCHEMA_TYPE_ELEMENT:
15174 xmlSchemaRefFixupCallback((xmlSchemaElementPtr) item, ctxt,
15175 NULL, NULL, NULL);
15176 break;
15177 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
15178 xmlSchemaAttrGrpFixup((xmlSchemaAttributeGroupPtr) item,
15179 ctxt, NULL);
15180 break;
15181 case XML_SCHEMA_TYPE_GROUP:
15182 xmlSchemaGroupDefFixup(item, ctxt, NULL);
15183 default:
15184 break;
15185 }
15186 }
15187 /*
15188 * Circularity checks.
15189 */
15190 for (i = 0; i < nbItems; i++) {
15191 item = items[i];
15192 switch (item->type) {
15193 case XML_SCHEMA_TYPE_GROUP:
15194 xmlSchemaCheckGroupDefCircular(item, ctxt, NULL);
15195 break;
15196 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
15197 xmlSchemaCheckAttributeGroupCircular(
15198 (xmlSchemaAttributeGroupPtr) item, ctxt, NULL);
15199 break;
15200 default:
15201 break;
15202 }
15203 }
15204 /*
15205 * Fixup for all other item.
15206 * TODO: Hmm, not sure if starting from complex/simple types,
15207 * all subsequent items will be reached.
15208 */
15209 for (i = 0; i < nbItems; i++) {
15210 item = items[i];
15211 switch (item->type) {
15212 case XML_SCHEMA_TYPE_SIMPLE:
15213 case XML_SCHEMA_TYPE_COMPLEX:
15214 xmlSchemaTypeFixup(item, ctxt, NULL);
15215 break;
15216 default:
15217 break;
15218 }
15219 }
15220 /*
15221 * Check facet values. Note that facets are
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +000015222 * hold by simple type components only (and
15223 * by complex types in the current implementation).
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015224 */
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +000015225 /* OLD:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015226 for (i = 0; i < nbItems; i++) {
15227 item = items[i];
15228 switch (item->type) {
15229 case XML_SCHEMA_TYPE_SIMPLE:
15230 case XML_SCHEMA_TYPE_COMPLEX:
15231 xmlSchemaCheckDefaults(item, ctxt, NULL);
15232 break;
15233 default:
15234 break;
15235 }
15236 }
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +000015237 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015238 /*
15239 * Build the content model for complex types.
15240 */
15241 for (i = 0; i < nbItems; i++) {
15242 item = items[i];
15243 switch (item->type) {
15244 case XML_SCHEMA_TYPE_COMPLEX:
15245 xmlSchemaBuildContentModel(item, ctxt, NULL);
15246 break;
15247 default:
15248 break;
15249 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015250 }
15251 /*
15252 * Validate value contraint values.
15253 */
15254 for (i = 0; i < nbItems; i++) {
15255 item = items[i];
15256 switch (item->type) {
15257 case XML_SCHEMA_TYPE_ATTRIBUTE:
15258 xmlSchemaCheckAttrValConstr((xmlSchemaAttributePtr) item, ctxt, NULL);
15259 break;
15260 case XML_SCHEMA_TYPE_ELEMENT:
15261 xmlSchemaCheckElemValConstr((xmlSchemaElementPtr) item, ctxt, NULL);
15262 break;
15263 default:
15264 break;
15265 }
15266 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015267}
15268
15269/**
15270 * xmlSchemaAssembleByLocation:
15271 * @pctxt: a schema parser context
15272 * @vctxt: a schema validation context
15273 * @schema: the existing schema
15274 * @node: the node that fired the assembling
15275 * @nsName: the namespace name of the new schema
15276 * @location: the location of the schema
15277 *
15278 * Expands an existing schema by an additional schema.
15279 *
15280 * Returns 0 if the new schema is correct, a positive error code
15281 * number otherwise and -1 in case of an internal or API error.
15282 */
15283static int
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015284xmlSchemaAssembleByLocation(xmlSchemaValidCtxtPtr vctxt,
15285 xmlSchemaPtr schema,
15286 xmlNodePtr node,
15287 const xmlChar *nsName,
15288 const xmlChar *location)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015289{
15290 const xmlChar *targetNs, *oldtns;
15291 xmlDocPtr doc, olddoc;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015292 int oldflags, ret = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015293 xmlNodePtr docElem;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015294 xmlSchemaParserCtxtPtr pctxt;
15295
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015296 /*
15297 * This should be used:
15298 * 1. on <import>(s)
15299 * 2. if requested by the validated instance
15300 * 3. if requested via the API
15301 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015302 if ((vctxt == NULL) || (schema == NULL))
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015303 return (-1);
15304 /*
15305 * Create a temporary parser context.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015306 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015307 if ((vctxt->pctxt == NULL) &&
15308 (xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1)) {
15309 xmlSchemaVErr(vctxt, node,
15310 XML_SCHEMAV_INTERNAL,
15311 "Internal error: xmlSchemaAssembleByLocation, "
15312 "failed to create a temp. parser context.\n",
15313 NULL, NULL);
15314 return (-1);
15315 }
15316 pctxt = vctxt->pctxt;
15317 /*
15318 * Set the counter to produce unique names for anonymous items.
15319 */
15320 pctxt->counter = schema->counter;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015321 /*
15322 * Acquire the schema document.
15323 */
15324 ret = xmlSchemaAcquireSchemaDoc(pctxt, schema, node,
15325 nsName, location, &doc, &targetNs, 0);
15326 if (ret != 0) {
15327 if (doc != NULL)
15328 xmlFreeDoc(doc);
15329 } else if (doc != NULL) {
15330 docElem = xmlDocGetRootElement(doc);
15331 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015332 * Create new assemble info.
15333 */
15334 if (pctxt->assemble == NULL) {
15335 pctxt->assemble = xmlSchemaNewAssemble();
15336 if (pctxt->assemble == NULL) {
15337 xmlSchemaVErrMemory(vctxt,
15338 "Memory error: xmlSchemaAssembleByLocation, "
15339 "allocating assemble info", NULL);
15340 xmlFreeDoc(doc);
15341 return (-1);
15342 }
15343 }
15344 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015345 * Save and reset the context & schema.
15346 */
15347 oldflags = schema->flags;
15348 oldtns = schema->targetNamespace;
15349 olddoc = schema->doc;
15350
15351 xmlSchemaClearSchemaDefaults(schema);
15352 schema->targetNamespace = targetNs;
15353 /* schema->nbCurItems = 0; */
15354 pctxt->schema = schema;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015355 pctxt->ctxtType = NULL;
15356 pctxt->parentItem = NULL;
15357
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015358 xmlSchemaParseSchemaDefaults(pctxt, schema, docElem);
15359 xmlSchemaParseSchemaTopLevel(pctxt, schema, docElem->children);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015360 xmlSchemaPostSchemaAssembleFixup(pctxt);
15361 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015362 * Set the counter of items.
15363 */
15364 schema->counter = pctxt->counter;
15365 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015366 * Free the list of assembled components.
15367 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015368 pctxt->assemble->nbItems = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015369 /*
15370 * Restore the context & schema.
15371 */
15372 schema->flags = oldflags;
15373 schema->targetNamespace = oldtns;
15374 schema->doc = olddoc;
15375 ret = pctxt->err;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015376 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015377 return (ret);
15378}
15379
15380/**
15381 * xmlSchemaAssembleByXSIAttr:
15382 * @vctxt: a schema validation context
15383 * @xsiAttr: an xsi attribute
15384 * @noNamespace: whether a schema with no target namespace is exptected
15385 *
15386 * Expands an existing schema by an additional schema using
15387 * the xsi:schemaLocation or xsi:noNamespaceSchemaLocation attribute
15388 * of an instance. If xsi:noNamespaceSchemaLocation is used, @noNamespace
15389 * must be set to 1.
15390 *
15391 * Returns 0 if the new schema is correct, a positive error code
15392 * number otherwise and -1 in case of an internal or API error.
15393 */
15394static int
15395xmlSchemaAssembleByXSIAttr(xmlSchemaValidCtxtPtr vctxt,
15396 xmlAttrPtr xsiAttr,
15397 int noNamespace)
15398{
15399 xmlChar *value;
15400 const xmlChar *cur, *end;
15401 const xmlChar *nsname = NULL, *location;
15402 int count = 0;
15403 int ret = 0;
15404
15405 if (xsiAttr == NULL) {
15406 xmlSchemaVCustomErr(vctxt, XML_SCHEMAV_INTERNAL,
15407 NULL, NULL,
15408 "Internal error: xmlSchemaAssembleByXSIAttr, "
15409 "bad arguments", NULL);
15410 return (-1);
15411 }
15412 /*
15413 * Parse the value; we will assume an even number of values
15414 * to be given (this is how Xerces and XSV work).
15415 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015416 value = xmlNodeGetContent((xmlNodePtr) xsiAttr);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015417 cur = value;
15418 do {
15419 if (noNamespace != 1) {
15420 /*
15421 * Get the namespace name.
15422 */
15423 while (IS_BLANK_CH(*cur))
15424 cur++;
15425 end = cur;
15426 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
15427 end++;
15428 if (end == cur)
15429 break;
15430 count++;
15431 nsname = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
15432 cur = end;
15433 }
15434 /*
15435 * Get the URI.
15436 */
15437 while (IS_BLANK_CH(*cur))
15438 cur++;
15439 end = cur;
15440 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
15441 end++;
15442 if (end == cur)
15443 break;
15444 count++;
15445 location = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015446 cur = end;
15447 ret = xmlSchemaAssembleByLocation(vctxt, vctxt->schema,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015448 xsiAttr->parent, nsname, location);
15449 if (ret == -1) {
15450 xmlSchemaVCustomErr(vctxt,
15451 XML_SCHEMAV_INTERNAL,
15452 (xmlNodePtr) xsiAttr, NULL,
15453 "Internal error: xmlSchemaAssembleByXSIAttr, "
15454 "assembling schemata", NULL);
15455 if (value != NULL)
15456 xmlFree(value);
15457 return (-1);
15458 }
15459 } while (*cur != 0);
15460 if (value != NULL)
15461 xmlFree(value);
15462 return (ret);
15463}
15464
15465/**
15466 * xmlSchemaAssembleByXSIElem:
15467 * @vctxt: a schema validation context
15468 * @elem: an element node possibly holding xsi attributes
15469 * @noNamespace: whether a schema with no target namespace is exptected
15470 *
15471 * Assembles an existing schema by an additional schema using
15472 * the xsi:schemaLocation or xsi:noNamespaceSchemaLocation attributes
15473 * of the given @elem.
15474 *
15475 * Returns 0 if the new schema is correct, a positive error code
15476 * number otherwise and -1 in case of an internal or API error.
15477 */
15478static int
15479xmlSchemaAssembleByXSIElem(xmlSchemaValidCtxtPtr vctxt,
15480 xmlNodePtr elem)
15481{
15482 int ret = 0, retNs = 0;
15483 xmlAttrPtr attr;
15484
15485 attr = xmlHasNsProp(elem, BAD_CAST "schemaLocation", xmlSchemaInstanceNs);
15486 if (attr != NULL) {
15487 retNs = xmlSchemaAssembleByXSIAttr(vctxt, attr, 0);
15488 if (retNs == -1)
15489 return (-1);
15490 }
15491 attr = xmlHasNsProp(elem, BAD_CAST "noNamespaceSchemaLocation", xmlSchemaInstanceNs);
15492 if (attr != NULL) {
15493 ret = xmlSchemaAssembleByXSIAttr(vctxt, attr, 1);
15494 if (ret == -1)
15495 return (-1);
15496 }
15497 if (retNs != 0)
15498 return (retNs);
15499 else
15500 return (ret);
15501}
15502
Daniel Veillard4255d502002-04-16 15:50:10 +000015503/**
Daniel Veillard4255d502002-04-16 15:50:10 +000015504 * xmlSchemaValidateCallback:
15505 * @ctxt: a schema validation context
15506 * @name: the name of the element detected (might be NULL)
15507 * @type: the type
15508 *
15509 * A transition has been made in the automata associated to an element
15510 * content model
15511 */
15512static void
15513xmlSchemaValidateCallback(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015514 const xmlChar * name ATTRIBUTE_UNUSED,
15515 xmlSchemaTypePtr type, xmlNodePtr node)
15516{
Daniel Veillard4255d502002-04-16 15:50:10 +000015517 xmlSchemaTypePtr oldtype = ctxt->type;
15518 xmlNodePtr oldnode = ctxt->node;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015519
Daniel Veillard4255d502002-04-16 15:50:10 +000015520#ifdef DEBUG_CONTENT
Daniel Veillard8651f532002-04-17 09:06:27 +000015521 xmlGenericError(xmlGenericErrorContext,
15522 "xmlSchemaValidateCallback: %s, %s, %s\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015523 name, type->name, node->name);
Daniel Veillard4255d502002-04-16 15:50:10 +000015524#endif
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015525 /*
15526 * @type->type will be XML_SCHEMA_TYPE_ANY or XML_SCHEMA_TYPE_ELEMENT.
15527 */
Daniel Veillard4255d502002-04-16 15:50:10 +000015528 ctxt->type = type;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015529 ctxt->node = node;
15530 ctxt->cur = node->children;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015531
15532#ifdef ELEM_INFO_ENABLED
15533 xmlSchemaBeginElement(ctxt);
15534#endif
15535
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015536 /*
15537 * Assemble new schemata using xsi.
15538 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015539 if (ctxt->xsiAssemble) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015540 int ret;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015541
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015542 ret = xmlSchemaAssembleByXSIElem(ctxt, ctxt->node);
15543 if (ret == -1) {
15544 xmlSchemaVCustomErr(ctxt,
15545 XML_SCHEMAV_INTERNAL,
15546 ctxt->node, NULL,
15547 "Internal error: xmlSchemaValidateElement, "
15548 "assembling schema by xsi", NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015549 goto leave;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015550 }
15551 /*
15552 * NOTE: We won't react on schema parser errors here.
15553 * TODO: But a warning would be nice.
15554 */
15555 }
15556 switch (type->type) {
15557 case XML_SCHEMA_TYPE_ELEMENT: {
15558 /*
15559 * NOTE: The build of the content model
15560 * (xmlSchemaBuildAContentModel) ensures that the element
15561 * declaration (and not a reference to it) will be given.
15562 */
15563 if (((xmlSchemaElementPtr) ctxt->type)->ref != NULL) {
15564 /*
15565 * This is paranoid coding ;-)... it should not
15566 * happen here any more.
15567 */
15568 xmlSchemaVCustomErr(ctxt,
15569 XML_SCHEMAV_INTERNAL,
15570 node, NULL,
15571 "Internal error: xmlSchemaValidateCallback, "
15572 "element declaration 'reference' encountered, "
15573 "but an element declaration was expected",
15574 NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015575 goto leave;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015576 }
15577 xmlSchemaValidateElementByDeclaration(ctxt,
15578 (xmlSchemaElementPtr) type);
15579 break;
15580 }
15581 case XML_SCHEMA_TYPE_ANY:
15582 xmlSchemaValidateElementByWildcard(ctxt, type);
15583 break;
15584 default:
15585 break;
15586 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015587leave:
15588
15589#ifdef ELEM_INFO_ENABLED
15590 xmlSchemaEndElement(ctxt);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015591#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000015592 ctxt->type = oldtype;
15593 ctxt->node = oldnode;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015594}
Daniel Veillard4255d502002-04-16 15:50:10 +000015595
Daniel Veillard01fa6152004-06-29 17:04:39 +000015596/**
15597 * xmlSchemaValidateSimpleTypeValue:
15598 * @ctxt: a schema validation context
15599 * @value: the value to be validated
15600 * @fireErrors: shall errors be reported?
15601 * @applyFacets: shall facets be applied?
Daniel Veillardc0826a72004-08-10 14:17:33 +000015602 * @normalize: shall the value be normalized?
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015603 * @checkNodes: shall the content nodes be checked?
Daniel Veillard01fa6152004-06-29 17:04:39 +000015604 *
15605 * Validates a value by the given type (user derived or built-in).
15606 *
15607 * Returns 0 if the value is valid, a positive error code
15608 * number otherwise and -1 in case of an internal or API error.
Daniel Veillard01fa6152004-06-29 17:04:39 +000015609 */
15610static int
15611xmlSchemaValidateSimpleTypeValue(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015612 xmlSchemaTypePtr type,
15613 const xmlChar *value,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015614 int fireErrors,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015615 int applyFacets,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015616 int normalize,
15617 int checkNodes)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015618{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015619 xmlNodePtr node;
Daniel Veillardc0826a72004-08-10 14:17:33 +000015620 int ret = 0;
15621 xmlChar *normValue = NULL;
15622 int wtsp;
15623
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015624 node = ctxt->node;
15625 /* Save the current whitespace normalization type. */
Daniel Veillardc0826a72004-08-10 14:17:33 +000015626 wtsp = ctxt->valueWS;
15627 /*
15628 * Normalize the value.
15629 */
15630 if (normalize &&
15631 (ctxt->valueWS != XML_SCHEMAS_VAL_WTSP_COLLAPSE)) {
15632 int norm = xmlSchemaGetWhiteSpaceFacetValue(type);
15633
15634 if ((norm != -1) && (norm > ctxt->valueWS)) {
15635 if (norm == XML_SCHEMAS_VAL_WTSP_COLLAPSE)
15636 normValue = xmlSchemaCollapseString(value);
15637 else
15638 normValue = xmlSchemaWhiteSpaceReplace(value);
15639 ctxt->valueWS = norm;
15640 if (normValue != NULL)
15641 value = (const xmlChar *) normValue;
15642 }
15643 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015644 /*
15645 * The nodes of a content must be checked only once,
15646 * this is not working since list types will fire this
15647 * multiple times.
15648 */
15649 if ((checkNodes == 1) && (ctxt->cur != NULL)) {
15650 xmlNodePtr cur = ctxt->cur;
15651
15652 do {
15653 switch (cur->type) {
15654 case XML_TEXT_NODE:
15655 case XML_CDATA_SECTION_NODE:
15656 case XML_PI_NODE:
15657 case XML_COMMENT_NODE:
15658 case XML_XINCLUDE_START:
15659 case XML_XINCLUDE_END:
15660 break;
15661 case XML_ENTITY_REF_NODE:
15662 case XML_ENTITY_NODE:
15663 /* TODO: Scour the entities for illegal nodes. */
15664 TODO break;
15665 case XML_ELEMENT_NODE: {
15666 /* NOTE: Changed to an internal error, since the
15667 * existence of an element node will be already checked in
15668 * xmlSchemaValidateElementBySimpleType and in
15669 * xmlSchemaValidateElementByComplexType.
15670 */
15671 xmlSchemaVCustomErr(ctxt,
15672 XML_SCHEMAV_INTERNAL,
15673 /* XML_SCHEMAS_ERR_INVALIDELEM, */
15674 node, type,
15675 "Element '%s' found in simple type content",
15676 cur->name);
15677 return (XML_SCHEMAV_INTERNAL);
15678 }
15679 case XML_ATTRIBUTE_NODE:
15680 case XML_DOCUMENT_NODE:
15681 case XML_DOCUMENT_TYPE_NODE:
15682 case XML_DOCUMENT_FRAG_NODE:
15683 case XML_NOTATION_NODE:
15684 case XML_HTML_DOCUMENT_NODE:
15685 case XML_DTD_NODE:
15686 case XML_ELEMENT_DECL:
15687 case XML_ATTRIBUTE_DECL:
15688 case XML_ENTITY_DECL:
15689 case XML_NAMESPACE_DECL:
15690#ifdef LIBXML_DOCB_ENABLED
15691 case XML_DOCB_DOCUMENT_NODE:
15692#endif
15693 xmlSchemaVCustomErr(ctxt,
15694 XML_SCHEMAV_INTERNAL,
15695 /* XML_SCHEMAS_ERR_INVALIDELEM, */
15696 node, NULL,
15697 "Node of unexpected type found in simple type content",
15698 NULL);
15699 return (XML_SCHEMAV_INTERNAL);
15700 }
15701 cur = cur->next;
15702 } while (cur != NULL);
15703 }
15704
William M. Brack2f2a6632004-08-20 23:09:47 +000015705 if (type->type == XML_SCHEMA_TYPE_COMPLEX) {
15706 xmlSchemaTypePtr base, anyType;
15707
15708 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
15709
15710 base = type->baseType;
15711 while ((base != NULL) &&
15712 (base->type != XML_SCHEMA_TYPE_SIMPLE) &&
15713 (base->type != XML_SCHEMA_TYPE_BASIC) &&
15714 (base != anyType)) {
15715 base = base->baseType;
15716 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015717 ret = xmlSchemaValidateSimpleTypeValue(ctxt, base, value, 1, 0, 1, 0);
William M. Brack2f2a6632004-08-20 23:09:47 +000015718 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015719 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000015720 "Internal error: xmlSchemaValidateSimpleTypeValue, "
15721 "validating complex type '%s'\n",
15722 type->name, NULL);
15723 } else if ((ret == 0) && (applyFacets) && (type->facetSet != NULL)) {
15724 /*
15725 * Check facets.
15726 */
15727 /*
15728 * This is somehow not nice, since if an error occurs
15729 * the reported type will be the complex type; the spec
15730 * wants a simple type to be created on the complex type
15731 * if it has a simple content. For now we have to live with
15732 * it.
15733 */
15734 ret = xmlSchemaValidateFacetsInternal(ctxt, type,
15735 value, 0, fireErrors);
15736 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015737 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000015738 "Internal error: xmlSchemaValidateSimpleTypeValue, "
15739 "validating facets of complex type '%s'\n",
15740 type->name, NULL);
15741 } else if (ret > 0) {
15742 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
William M. Brack2f2a6632004-08-20 23:09:47 +000015743 if (fireErrors)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015744 xmlSchemaVSimpleTypeErr(ctxt, ret, node, value, type);
William M. Brack2f2a6632004-08-20 23:09:47 +000015745 }
15746 }
15747 } else if (type->type == XML_SCHEMA_TYPE_BASIC) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000015748
15749 if (ctxt->value != NULL) {
15750 xmlSchemaFreeValue(ctxt->value);
15751 ctxt->value = NULL;
15752 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015753 /*
15754 * STREAM-READ-CHILDREN.
15755 */
15756 ret = xmlSchemaValPredefTypeNodeNoNorm(type, value, &(ctxt->value), node);
Daniel Veillardc0826a72004-08-10 14:17:33 +000015757 if (ret > 0) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000015758 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST)
15759 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
15760 else
15761 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
Daniel Veillardc0826a72004-08-10 14:17:33 +000015762 if (fireErrors)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015763 xmlSchemaVSimpleTypeErr(ctxt, ret, node, value, type);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015764 } else if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015765 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015766 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000015767 "validating built-in type '%s'\n", type->name, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015768 }
15769 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) {
15770 /* 1.2.1 if {variety} is ·atomic· then the string must ·match·
15771 * a literal in the ·lexical space· of {base type definition}
15772 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015773 ret = xmlSchemaValidateSimpleTypeValue(ctxt, type->baseType, value, 0, 0, 0, 0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015774 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015775 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015776 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000015777 "validating atomic simple type '%s'\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000015778 type->name, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +000015779 } else if (ret > 0) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000015780 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
Daniel Veillardc0826a72004-08-10 14:17:33 +000015781 if (fireErrors)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015782 xmlSchemaVSimpleTypeErr(ctxt, ret, node, value, type);
Daniel Veillardc0826a72004-08-10 14:17:33 +000015783 } else if ((applyFacets) && (type->facetSet != NULL)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000015784 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000015785 * Check facets.
Daniel Veillard01fa6152004-06-29 17:04:39 +000015786 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000015787 ret = xmlSchemaValidateFacetsInternal(ctxt, type,
15788 value, 0, fireErrors);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015789 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015790 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015791 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000015792 "validating facets of atomic simple type '%s'\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000015793 type->name, NULL);
15794 } else if (ret > 0) {
15795 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
Daniel Veillardc0826a72004-08-10 14:17:33 +000015796 /*
15797 Disabled, since the facet validation already reports errors.
15798 if (fireErrors)
15799 xmlSchemaVSimpleTypeErr(ctxt, ret, ctxt->cur, value, type);
15800 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000015801 }
15802 }
15803 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
15804
15805 xmlSchemaTypePtr tmpType;
15806 const xmlChar *cur, *end;
15807 xmlChar *tmp;
Daniel Veillardc0826a72004-08-10 14:17:33 +000015808 unsigned long len = 0;
Daniel Veillard01fa6152004-06-29 17:04:39 +000015809
15810 /* 1.2.2 if {variety} is ·list· then the string must be a sequence
15811 * of white space separated tokens, each of which ·match·es a literal
15812 * in the ·lexical space· of {item type definition}
15813 */
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +000015814
Kasimier T. Buchcikde938cd2005-01-13 12:25:57 +000015815 if (value == NULL)
15816 value = BAD_CAST "";
Daniel Veillardc0826a72004-08-10 14:17:33 +000015817 tmpType = xmlSchemaGetListSimpleTypeItemType(type);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015818 cur = value;
15819 do {
15820 while (IS_BLANK_CH(*cur))
15821 cur++;
15822 end = cur;
15823 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
15824 end++;
15825 if (end == cur)
15826 break;
15827 tmp = xmlStrndup(cur, end - cur);
15828 len++;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015829 ret = xmlSchemaValidateSimpleTypeValue(ctxt, tmpType, tmp, 0, 1, 0, 0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015830 xmlFree(tmp);
Daniel Veillardc0826a72004-08-10 14:17:33 +000015831 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015832 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015833 "Internal error: xmlSchemaValidateSimpleTypeValue, "
15834 "validating an item of list simple type '%s'\n",
15835 type->name, NULL);
15836 break;
15837 } else if (ret > 0) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000015838 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
Daniel Veillardc0826a72004-08-10 14:17:33 +000015839 if (fireErrors)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015840 xmlSchemaVSimpleTypeErr(ctxt, ret, node, value, type);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015841 break;
Daniel Veillardc0826a72004-08-10 14:17:33 +000015842 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000015843 cur = end;
15844 } while (*cur != 0);
15845 /*
15846 * Check facets.
15847 */
15848 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015849 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015850 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000015851 "validating list simple type '%s'\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000015852 type->name, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +000015853 } else if ((ret == 0) && (applyFacets)) {
15854 ret = xmlSchemaValidateFacetsInternal(ctxt, type,
15855 value, len, fireErrors);
15856 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015857 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015858 "Internal error: xmlSchemaValidateSimpleTypeValue, "
15859 "validating facets of list simple type '%s'\n",
15860 type->name, NULL);
15861 } else if (ret > 0) {
15862 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
Daniel Veillard01fa6152004-06-29 17:04:39 +000015863 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000015864 Disabled, since the facet validation already reports errors.
15865 if (fireErrors)
15866 xmlSchemaVSimpleTypeErr(ctxt, ret, ctxt->cur, value, type);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015867 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000015868 }
15869
Daniel Veillard01fa6152004-06-29 17:04:39 +000015870 }
15871 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
15872 xmlSchemaTypeLinkPtr memberLink;
15873
15874 /*
15875 * TODO: For all datatypes ·derived· by ·union· whiteSpace does
15876 * not apply directly; however, the normalization behavior of ·union·
15877 * types is controlled by the value of whiteSpace on that one of the
15878 * ·memberTypes· against which the ·union· is successfully validated.
15879 *
15880 * This means that the value is normalized by the first validating
15881 * member type, then the facets of the union type are applied. This
15882 * needs changing of the value!
15883 */
15884
15885 /*
15886 * 1.2.3 if {variety} is ·union· then the string must ·match· a
15887 * literal in the ·lexical space· of at least one member of
15888 * {member type definitions}
15889 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000015890#ifdef DEBUG_UNION_VALIDATION
15891 printf("Union ST : '%s'\n", (const char *) type->name);
15892 printf(" fireErrors : %d\n", fireErrors);
15893 printf(" applyFacets: %d\n", applyFacets);
15894#endif
Daniel Veillard01fa6152004-06-29 17:04:39 +000015895 memberLink = xmlSchemaGetUnionSimpleTypeMemberTypes(type);
15896 if (memberLink == NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015897 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015898 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000015899 "union simple type '%s' has no member types\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000015900 type->name, NULL);
15901 ret = -1;
15902 }
15903 if (ret == 0) {
15904 while (memberLink != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015905 ret = xmlSchemaValidateSimpleTypeValue(ctxt, memberLink->type,
15906 value, 0, 1, 1, 0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015907 if ((ret <= 0) || (ret == 0))
15908 break;
15909 memberLink = memberLink->next;
15910 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000015911 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015912 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015913 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000015914 "validating members of union simple type '%s'\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000015915 type->name, NULL);
15916 } else if (ret > 0) {
15917 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
Daniel Veillardc0826a72004-08-10 14:17:33 +000015918 if (fireErrors)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015919 xmlSchemaVSimpleTypeErr(ctxt, ret, node, value, type);
Daniel Veillardc0826a72004-08-10 14:17:33 +000015920 }
15921 }
15922 /*
15923 * Apply facets (pattern, enumeration).
15924 */
15925 if ((ret == 0) && (applyFacets) && (type->facetSet != NULL)) {
15926 int mws;
15927 /*
15928 * The normalization behavior of ·union· types is controlled by
15929 * the value of whiteSpace on that one of the ·memberTypes·
15930 * against which the ·union· is successfully validated.
15931 */
15932 if (normValue != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015933 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015934 "Internal error: xmlSchemaValidateSimpleTypeValue, "
15935 "the value was already normalized for the union simple "
15936 "type '%s'.\n", type->name, NULL);
15937 }
15938 mws = xmlSchemaGetWhiteSpaceFacetValue(memberLink->type);
15939 if (mws > ctxt->valueWS) {
15940 if (mws == XML_SCHEMAS_VAL_WTSP_COLLAPSE)
15941 normValue = xmlSchemaCollapseString(value);
15942 else
15943 normValue = xmlSchemaWhiteSpaceReplace(value);
15944 if (normValue != NULL)
15945 value = (const xmlChar *) normValue;
15946 }
15947
15948 ret = xmlSchemaValidateFacetsInternal(ctxt, type,
15949 value, 0, fireErrors);
15950 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015951 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015952 "Internal error: xmlSchemaValidateSimpleTypeValue, "
15953 "validating facets of union simple type '%s'\n",
15954 type->name, NULL);
15955 } else if (ret > 0) {
15956 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
15957 /*
15958 if (fireErrors)
15959 xmlSchemaVSimpleTypeErr(ctxt, ret, ctxt->cur, value, type);
15960 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000015961 }
15962 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000015963 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000015964 ctxt->valueWS = wtsp;
15965 if (normValue != NULL)
15966 xmlFree(normValue);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015967 return (ret);
15968}
15969
15970/**
15971 * xmlSchemaValidateSimpleTypeElement:
15972 * @ctxt: a schema validation context
15973 * @node: the element node to be validated.
15974 *
15975 * Validate the element against a simple type.
15976 *
15977 * Returns 0 if the element is valid, a positive error code
15978 * number otherwise and -1 in case of an internal or API error.
15979 */
15980static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015981xmlSchemaValidateElementBySimpleType(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015982 xmlSchemaTypePtr type,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000015983 int isNil,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015984 int valSimpleContent)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015985{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015986 xmlSchemaTypePtr oldtype;
15987 xmlNodePtr node;
Daniel Veillard01fa6152004-06-29 17:04:39 +000015988 xmlAttrPtr attr;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015989 xmlNodePtr cur;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015990 int ret = 0, retval = 0;
15991
Daniel Veillard01fa6152004-06-29 17:04:39 +000015992 if ((ctxt == NULL) || (type == NULL)) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015993 xmlSchemaVCustomErr(ctxt, XML_SCHEMAV_INTERNAL, NULL, NULL,
15994 "Internal error: xmlSchemaValidateElementBySimpleType, "
15995 "bad arguments", NULL);
15996 return (-1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015997 }
15998
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015999 oldtype = ctxt->type;
16000 node = ctxt->node;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000016001 /*
16002 * cvc-type: 3.1.2 The element information item must have no element
16003 * information item [children].
16004 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016005 /*
16006 * STREAM: Child nodes are processed.
16007 */
16008 cur = node->children;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000016009 while (cur != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016010 /*
16011 * TODO: Entities, will they produce elements as well?
16012 */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000016013 if (cur->type == XML_ELEMENT_NODE) {
16014 xmlSchemaVCustomErr(ctxt,
16015 XML_SCHEMAV_CVC_TYPE_3_1_2,
16016 node, type,
16017 "No element content allowed", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016018 ret = XML_SCHEMAV_CVC_TYPE_3_1_2;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000016019 }
16020 cur = cur->next;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016021 }
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000016022
Daniel Veillard01fa6152004-06-29 17:04:39 +000016023 /*
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000016024 * cvc-type 3.1.1:
16025 *
16026 * The attributes of must be empty, excepting those whose namespace name
16027 * is identical to http://www.w3.org/2001/XMLSchema-instance and whose local
16028 * name is one of type, nil, schemaLocation or noNamespaceSchemaLocation.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016029 */
16030 /*
16031 * STREAM: Attribute nodes are processed.
16032 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000016033 attr = node->properties;
16034 while (attr != NULL) {
16035 if ((attr->ns == NULL) ||
16036 (!xmlStrEqual(attr->ns->href, xmlSchemaInstanceNs)) ||
16037 ((!xmlStrEqual(attr->name, BAD_CAST "type")) &&
16038 (!xmlStrEqual(attr->name, BAD_CAST "nil")) &&
16039 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation")) &&
16040 (!xmlStrEqual
16041 (attr->name, BAD_CAST "noNamespaceSchemaLocation")))) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000016042 xmlSchemaVIllegalAttrErr(ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016043 XML_SCHEMAV_CVC_TYPE_3_1_1, attr);
16044 ret = XML_SCHEMAV_CVC_TYPE_3_1_1;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016045 }
16046 attr = attr->next;
16047 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016048 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016049 * This will skip validation if the type is 'anySimpleType' and
16050 * if the value was already validated (e.g. default values).
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016051 */
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000016052 if ((! isNil) &&
16053 (valSimpleContent == 1) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016054 ((type->type != XML_SCHEMA_TYPE_BASIC) ||
16055 (type->builtInType != XML_SCHEMAS_ANYSIMPLETYPE))) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016056 xmlChar *value;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016057
16058 value = xmlNodeGetContent(node);
16059 /*
16060 * NOTE: This call will not check the content nodes, since
16061 * this should be checked here already.
16062 */
16063 retval = xmlSchemaValidateSimpleTypeValue(ctxt, type, value,
16064 1, 1, 1, 0);
William M. Brack2f2a6632004-08-20 23:09:47 +000016065 if (value != NULL)
16066 xmlFree(value);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016067 if (retval != 0)
16068 ret = retval;
William M. Brack2f2a6632004-08-20 23:09:47 +000016069 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016070 ctxt->type = oldtype;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016071 return (ret);
16072}
Daniel Veillard4255d502002-04-16 15:50:10 +000016073
16074/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016075 * xmlSchemaValQNameAcquire:
16076 * @value: the lexical represantation of the QName value
16077 * @node: the node to search for the corresponding namespace declaration
16078 * @nsName: the resulting namespace name if found
16079 *
16080 * Checks that a value conforms to the lexical space of the type QName;
16081 * if valid, the corresponding namespace name is searched and retured
16082 * as a copy in @nsName. The local name is returned in @localName as
16083 * a copy.
16084 *
16085 * Returns 0 if valid, 1 if not valid by type, 2 if no corresponding
16086 * namespace declaration was found in scope; -1 in case of an internal or
16087 * API error.
16088 */
16089static int
16090xmlSchemaValQNameAcquire(const xmlChar *value, xmlNodePtr node,
16091 xmlChar **nsName, xmlChar **localName)
16092{
16093 int ret;
16094 xmlChar *local = NULL;
16095
16096 if ((nsName == NULL) || (localName == NULL) || (node == NULL))
16097 return (-1);
16098 *nsName = NULL;
16099 *localName = NULL;
16100 ret = xmlValidateQName(value, 1);
16101 if (ret == 0) {
16102 xmlChar *prefix;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016103 xmlNsPtr ns;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016104
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016105 /*
16106 * NOTE: xmlSplitQName2 will return a duplicated
16107 * string.
16108 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016109 local = xmlSplitQName2(value, &prefix);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016110 if (local == NULL)
16111 local = xmlStrdup(value);
16112 ns = xmlSearchNs(node->doc, node, prefix);
16113 /*
16114 * A namespace need not to be found if the prefix is NULL.
16115 */
16116 if (ns != NULL) {
16117 /*
16118 * TODO: Is it necessary to duplicate the URI here?
16119 */
16120 *nsName = xmlStrdup(ns->href);
16121 } else if (prefix != NULL) {
16122 xmlFree(prefix);
16123 if (local != NULL)
16124 xmlFree(local);
16125 return (2);
16126 }
16127 *localName = local;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016128 if (prefix != NULL)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016129 xmlFree(prefix);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016130 } else
16131 return (1);
16132 return (ret);
16133}
16134
16135/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016136 * xmlSchemaHasElemContent:
16137 * @node: the node
16138 *
16139 * Scours the content of the given node for element
16140 * nodes.
16141 *
16142 * Returns 1 if an element node is found,
16143 * 0 otherwise.
16144 */
16145static int
16146xmlSchemaHasElemContent(xmlNodePtr node)
16147{
16148 if (node == NULL)
16149 return (0);
16150 node = node->children;
16151 while (node != NULL) {
16152 if (node->type == XML_ELEMENT_NODE)
16153 return (1);
16154 node = node->next;
16155 }
16156 return (0);
16157}
16158/**
16159 * xmlSchemaHasElemOrCharContent:
16160 * @node: the node
16161 *
16162 * Scours the content of the given node for element
16163 * and character nodes.
16164 *
16165 * Returns 1 if an element or character node is found,
16166 * 0 otherwise.
16167 */
16168static int
16169xmlSchemaHasElemOrCharContent(xmlNodePtr node)
16170{
16171 if (node == NULL)
16172 return (0);
16173 node = node->children;
16174 while (node != NULL) {
16175 switch (node->type) {
16176 case XML_ELEMENT_NODE:
16177 /*
16178 * TODO: Ask Daniel if these are all character nodes.
16179 */
16180 case XML_TEXT_NODE:
16181 case XML_CDATA_SECTION_NODE:
16182 /*
16183 * TODO: How XML_ENTITY_NODEs evaluated?
16184 */
16185 case XML_ENTITY_REF_NODE:
16186 case XML_ENTITY_NODE:
16187 return (1);
16188 break;
16189 default:
16190 break;
16191 }
16192 node = node->next;
16193 }
16194 return (0);
16195}
16196
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016197/************************************************************************
16198 * *
16199 * Identity-constraints (IDC) *
16200 * *
16201 ************************************************************************/
16202
16203#ifdef IDC_ENABLED
16204
16205/**
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000016206 * xmlSchemaAugmentIDC:
16207 * @idcDef: the IDC definition
16208 *
16209 * Creates an augmented IDC definition item.
16210 *
16211 * Returns the item, or NULL on internal errors.
16212 */
16213static void
16214xmlSchemaAugmentIDC(xmlSchemaIDCPtr idcDef,
16215 xmlSchemaValidCtxtPtr vctxt)
16216{
16217 xmlSchemaIDCAugPtr aidc;
16218
16219 aidc = (xmlSchemaIDCAugPtr) xmlMalloc(sizeof(xmlSchemaIDCAug));
16220 if (aidc == NULL) {
16221 xmlSchemaVErrMemory(vctxt,
16222 "xmlSchemaAugmentIDC: allocating an augmented IDC definition",
16223 NULL);
16224 return;
16225 }
16226 aidc->bubbleDepth = -1;
16227 aidc->def = idcDef;
16228 aidc->next = NULL;
16229 if (vctxt->aidcs == NULL)
16230 vctxt->aidcs = aidc;
16231 else {
16232 aidc->next = vctxt->aidcs;
16233 vctxt->aidcs = aidc;
16234 }
16235}
16236
16237/**
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016238 * xmlSchemaIDCNewBinding:
16239 * @idcDef: the IDC definition of this binding
16240 *
16241 * Creates a new IDC binding.
16242 *
16243 * Returns the new binding in case of succeeded, NULL on internal errors.
16244 */
16245static xmlSchemaPSVIIDCBindingPtr
16246xmlSchemaIDCNewBinding(xmlSchemaIDCPtr idcDef)
16247{
16248 xmlSchemaPSVIIDCBindingPtr ret;
16249
16250 ret = (xmlSchemaPSVIIDCBindingPtr) xmlMalloc(
16251 sizeof(xmlSchemaPSVIIDCBinding));
16252 if (ret == NULL) {
16253 xmlSchemaVErrMemory(NULL,
16254 "allocating a PSVI IDC binding item", NULL);
16255 return (NULL);
16256 }
16257 memset(ret, 0, sizeof(xmlSchemaPSVIIDCBinding));
16258 ret->definition = idcDef;
16259 return (ret);
16260}
16261
16262/**
16263 * xmlSchemaIDCStoreNodeTableItem:
16264 * @vctxt: the WXS validation context
16265 * @item: the IDC node table item
16266 *
16267 * The validation context is used to store an IDC node table items.
16268 * They are stored to avoid copying them if IDC node-tables are merged
16269 * with corresponding parent IDC node-tables (bubbling).
16270 *
16271 * Returns 0 if succeeded, -1 on internal errors.
16272 */
16273static int
16274xmlSchemaIDCStoreNodeTableItem(xmlSchemaValidCtxtPtr vctxt,
16275 xmlSchemaPSVIIDCNodePtr item)
16276{
16277 /*
16278 * Add to gobal list.
16279 */
16280 if (vctxt->idcNodes == NULL) {
16281 vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
16282 xmlMalloc(20 * sizeof(xmlSchemaPSVIIDCNodePtr));
16283 if (vctxt->idcNodes == NULL) {
16284 xmlSchemaVErrMemory(vctxt,
16285 "allocating the IDC node table item list", NULL);
16286 return (-1);
16287 }
16288 vctxt->sizeIdcNodes = 20;
16289 } else if (vctxt->sizeIdcNodes <= vctxt->nbIdcNodes) {
16290 vctxt->sizeIdcNodes *= 2;
16291 vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
16292 xmlRealloc(vctxt->idcNodes, vctxt->sizeIdcNodes *
16293 sizeof(xmlSchemaPSVIIDCNodePtr));
16294 if (vctxt->idcNodes == NULL) {
16295 xmlSchemaVErrMemory(vctxt,
16296 "re-allocating the IDC node table item list", NULL);
16297 return (-1);
16298 }
16299 }
16300 vctxt->idcNodes[vctxt->nbIdcNodes++] = item;
16301
16302 return (0);
16303}
16304
16305/**
16306 * xmlSchemaIDCStoreKey:
16307 * @vctxt: the WXS validation context
16308 * @item: the IDC key
16309 *
16310 * The validation context is used to store an IDC key.
16311 *
16312 * Returns 0 if succeeded, -1 on internal errors.
16313 */
16314static int
16315xmlSchemaIDCStoreKey(xmlSchemaValidCtxtPtr vctxt,
16316 xmlSchemaPSVIIDCKeyPtr key)
16317{
16318 /*
16319 * Add to gobal list.
16320 */
16321 if (vctxt->idcKeys == NULL) {
16322 vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
16323 xmlMalloc(40 * sizeof(xmlSchemaPSVIIDCKeyPtr));
16324 if (vctxt->idcKeys == NULL) {
16325 xmlSchemaVErrMemory(vctxt,
16326 "allocating the IDC key storage list", NULL);
16327 return (-1);
16328 }
16329 vctxt->sizeIdcKeys = 40;
16330 } else if (vctxt->sizeIdcKeys <= vctxt->nbIdcKeys) {
16331 vctxt->sizeIdcKeys *= 2;
16332 vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
16333 xmlRealloc(vctxt->idcKeys, vctxt->sizeIdcKeys *
16334 sizeof(xmlSchemaPSVIIDCKeyPtr));
16335 if (vctxt->idcKeys == NULL) {
16336 xmlSchemaVErrMemory(vctxt,
16337 "re-allocating the IDC key storage list", NULL);
16338 return (-1);
16339 }
16340 }
16341 vctxt->idcKeys[vctxt->nbIdcKeys++] = key;
16342
16343 return (0);
16344}
16345
16346/**
16347 * xmlSchemaIDCAppendNodeTableItem:
16348 * @bind: the IDC binding
16349 * @ntItem: the node-table item
16350 *
16351 * Appends the IDC node-table item to the binding.
16352 *
16353 * Returns 0 on success and -1 on internal errors.
16354 */
16355static int
16356xmlSchemaIDCAppendNodeTableItem(xmlSchemaPSVIIDCBindingPtr bind,
16357 xmlSchemaPSVIIDCNodePtr ntItem)
16358{
16359 if (bind->nodeTable == NULL) {
16360 bind->sizeNodes = 10;
16361 bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
16362 xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr));
16363 if (bind->nodeTable == NULL) {
16364 xmlSchemaVErrMemory(NULL,
16365 "allocating an array of IDC node-table items", NULL);
16366 return(-1);
16367 }
16368 } else if (bind->sizeNodes <= bind->nbNodes) {
16369 bind->sizeNodes *= 2;
16370 bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
16371 xmlRealloc(bind->nodeTable, bind->sizeNodes *
16372 sizeof(xmlSchemaPSVIIDCNodePtr));
16373 if (bind->nodeTable == NULL) {
16374 xmlSchemaVErrMemory(NULL,
16375 "re-allocating an array of IDC node-table items", NULL);
16376 return(-1);
16377 }
16378 }
16379 bind->nodeTable[bind->nbNodes++] = ntItem;
16380 return(0);
16381}
16382
16383/**
16384 * xmlSchemaIDCAquireBinding:
16385 * @vctxt: the WXS validation context
16386 * @matcher: the IDC matcher
16387 *
16388 * Looks up an PSVI IDC binding, for the IDC definition and
16389 * of the given matcher. If none found, a new one is created
16390 * and added to the IDC table.
16391 *
16392 * Returns an IDC binding or NULL on internal errors.
16393 */
16394static xmlSchemaPSVIIDCBindingPtr
16395xmlSchemaIDCAquireBinding(xmlSchemaValidCtxtPtr vctxt,
16396 xmlSchemaIDCMatcherPtr matcher)
16397{
16398 xmlSchemaElemInfoPtr info;
16399
16400 info = vctxt->elemInfos[matcher->depth];
16401
16402 if (info->idcTable == NULL) {
16403 info->idcTable = xmlSchemaIDCNewBinding(matcher->aidc->def);
16404 if (info->idcTable == NULL)
16405 return (NULL);
16406 return(info->idcTable);
16407 } else {
16408 xmlSchemaPSVIIDCBindingPtr bind = NULL;
16409
16410 bind = info->idcTable;
16411 do {
16412 if (bind->definition == matcher->aidc->def)
16413 return(bind);
16414 if (bind->next == NULL) {
16415 bind->next = xmlSchemaIDCNewBinding(matcher->aidc->def);
16416 if (bind->next == NULL)
16417 return (NULL);
16418 return(bind->next);
16419 }
16420 bind = bind->next;
16421 } while (bind != NULL);
16422 }
16423 return (NULL);
16424}
16425
16426/**
16427 * xmlSchemaIDCFreeKey:
16428 * @key: the IDC key
16429 *
16430 * Frees an IDC key together with its compiled value.
16431 */
16432static void
16433xmlSchemaIDCFreeKey(xmlSchemaPSVIIDCKeyPtr key)
16434{
16435 if (key->compValue != NULL)
16436 xmlSchemaFreeValue(key->compValue);
16437 xmlFree(key);
16438}
16439
16440/**
16441 * xmlSchemaIDCFreeBinding:
16442 *
16443 * Frees an IDC binding. Note that the node table-items
16444 * are not freed.
16445 */
16446xmlSchemaIDCFreeBinding(xmlSchemaPSVIIDCBindingPtr bind)
16447{
16448 if (bind->nodeTable != NULL) {
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000016449 if (bind->definition->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
16450 int i;
16451 /*
16452 * Node-table items for keyrefs are not stored globally
16453 * to the validation context, since they are not bubbled.
16454 * We need to free them here.
16455 */
16456 for (i = 0; i < bind->nbNodes; i++) {
16457 xmlFree(bind->nodeTable[i]->keys);
16458 xmlFree(bind->nodeTable[i]);
16459 }
16460 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016461 xmlFree(bind->nodeTable);
16462 }
16463 xmlFree(bind);
16464}
16465
16466/**
16467 * xmlSchemaIDCFreeIDCTable:
16468 * @bind: the first IDC binding in the list
16469 *
16470 * Frees an IDC table, i.e. all the IDC bindings in the list.
16471 */
16472static void
16473xmlSchemaIDCFreeIDCTable(xmlSchemaPSVIIDCBindingPtr bind)
16474{
16475 xmlSchemaPSVIIDCBindingPtr prev;
16476
16477 while (bind != NULL) {
16478 prev = bind;
16479 bind = bind->next;
16480 xmlSchemaIDCFreeBinding(prev);
16481 }
16482}
16483
16484/**
16485 * xmlSchemaIDCFreeMatcherList:
16486 * @matcher: the first IDC matcher in the list
16487 *
16488 * Frees a list of IDC matchers.
16489 */
16490static void
16491xmlSchemaIDCFreeMatcherList(xmlSchemaIDCMatcherPtr matcher)
16492{
16493 xmlSchemaIDCMatcherPtr next;
16494
16495 while (matcher != NULL) {
16496 next = matcher->next;
16497 if (matcher->keySeqs != NULL) {
16498 int i;
16499 for (i = 0; i < matcher->sizeKeySeqs; i++)
16500 if (matcher->keySeqs[i] != NULL)
16501 xmlFree(matcher->keySeqs[i]);
16502 xmlFree(matcher->keySeqs);
16503 }
16504 xmlFree(matcher);
16505 matcher = next;
16506 }
16507}
16508
16509/**
16510 * xmlSchemaAreValuesEqual:
16511 * @ta: the first type
16512 * @a: the first value
16513 * @tb: the second type
16514 * @b: the second value
16515 *
16516 * Compares two values.
16517 *
16518 * Returns 1 if they are equal, 0 if not and -1 on internal errors.
16519 */
16520static int
16521xmlSchemaAreValuesEqual(xmlSchemaTypePtr ta,
16522 xmlSchemaValPtr a,
16523 xmlSchemaTypePtr tb,
16524 xmlSchemaValPtr b)
16525{
16526 int typeEqual = 0;
16527
16528 /* Same user derived/built-in derived/built-in primitive types. */
16529 if (ta == tb)
16530 goto compareValue;
16531
16532 /*
16533 * Comparison with anySimpleTypes is not supported by this implemention.
16534 */
16535 if ((ta->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) ||
16536 (tb->builtInType == XML_SCHEMAS_ANYSIMPLETYPE))
16537 return(0);
16538
16539 /*
16540 * 4.2.1 equal (data-types)
16541 *
16542 * the ·value space·s of all ·primitive· datatypes are disjoint
16543 * (they do not share any values)
16544 */
16545 if ((ta->builtInType != 0) && (tb->builtInType != 0) &&
16546 (ta->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE) &&
16547 (tb->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE))
16548 return(0);
16549
16550 if ((ta->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) ||
16551 (ta->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) ||
16552 (tb->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) ||
16553 (tb->flags & XML_SCHEMAS_TYPE_VARIETY_UNION)) {
16554 TODO
16555 return(0);
16556 }
16557 /*
16558 * (1) if a datatype T' is ·derived· by ·restriction· from an atomic datatype
16559 * T then the ·value space· of T' is a subset of the ·value space· of T.
16560 */
16561 /*
16562 * (2) if datatypes T' and T'' are ·derived· by ·restriction· from a common
16563 * atomic ancestor T then the ·value space·s of T' and T'' may overlap.
16564 */
16565
16566 {
16567 xmlSchemaTypePtr pta = ta, ptb = tb;
16568
16569 /* Note that we will compare the primitives here. */
16570 while ((pta->builtInType == 0) ||
16571 ((pta->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE) == 0))
16572 pta = pta->baseType;
16573 while ((ptb->builtInType == 0) ||
16574 ((ptb->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE) == 0))
16575 ptb = ptb->baseType;
16576 if (pta == ptb)
16577 goto compareValue;
16578 return(0);
16579 }
16580compareValue:
16581 {
16582#ifdef IDC_VALUE_SUPPORT
16583 int ret;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000016584 ret = xmlSchemaCompareValues(a, b);
16585 /*
16586 * ret = xmlSchemaCompareValuesOpt(a, b,
16587 * XML_SCHEMA_VALUECOMP_STRISNORM);
16588 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016589 if (ret == 0)
16590 return(1);
16591 else if (ret == -2)
16592 return(-1);
16593 else
16594 return(0);
16595#else
16596 return (1);
16597#endif
16598 }
16599}
16600
16601/**
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016602 * xmlSchemaIDCAddStateObject:
16603 * @vctxt: the WXS validation context
16604 * @matcher: the IDC matcher
16605 * @sel: the XPath information
16606 * @parent: the parent "selector" state object if any
16607 * @type: "selector" or "field"
16608 *
16609 * Creates/reuses and activates state objects for the given
16610 * XPath information; if the XPath expression consists of unions,
16611 * multiple state objects are created for every unioned expression.
16612 *
16613 * Returns 0 on success and -1 on internal errors.
16614 */
16615static int
16616xmlSchemaIDCAddStateObject(xmlSchemaValidCtxtPtr vctxt,
16617 xmlSchemaIDCMatcherPtr matcher,
16618 xmlSchemaIDCSelectPtr sel,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016619 int type)
16620{
16621 xmlSchemaIDCStateObjPtr sto;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016622
16623 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000016624 * Reuse the state objects from the pool.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016625 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000016626 if (vctxt->xpathStatePool != NULL) {
16627 sto = vctxt->xpathStatePool;
16628 vctxt->xpathStatePool = sto->next;
16629 sto->next = NULL;
16630 } else {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016631 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000016632 * Create a new state object.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016633 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000016634 sto = (xmlSchemaIDCStateObjPtr) xmlMalloc(sizeof(xmlSchemaIDCStateObj));
16635 if (sto == NULL) {
16636 xmlSchemaVErrMemory(NULL,
16637 "allocating an IDC state object", NULL);
16638 return (-1);
16639 }
16640 memset(sto, 0, sizeof(xmlSchemaIDCStateObj));
16641 }
16642 /*
16643 * Add to global list.
16644 */
16645 if (vctxt->xpathStates != NULL)
16646 sto->next = vctxt->xpathStates;
16647 vctxt->xpathStates = sto;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016648
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000016649 /*
16650 * Free the old xpath validation context.
16651 */
16652 if (sto->xpathCtxt != NULL)
16653 xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
16654
16655 /*
16656 * Create a new XPath (pattern) validation context.
16657 */
16658 sto->xpathCtxt = (void *) xmlPatternGetStreamCtxt(
16659 (xmlPatternPtr) sel->xpathComp);
16660 if (sto->xpathCtxt == NULL) {
16661 xmlSchemaVErr(vctxt, vctxt->node,
16662 XML_SCHEMAV_INTERNAL,
16663 "Internal error: xmlSchemaIDCAddStateObject, "
16664 "failed to create the XPath validation context.\n",
16665 NULL, NULL);
16666 return (-1);
16667 }
16668 sto->type = type;
16669 sto->depth = vctxt->depth;
16670 sto->matcher = matcher;
16671 sto->sel = sel;
16672 sto->nbHistory = 0;
16673
16674#if DEBUG_IDC
16675 xmlGenericError(xmlGenericErrorContext, "IDC: STO push '%s'\n",
16676 sto->sel->xpath);
16677#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016678 return (0);
16679}
16680
16681/**
16682 * xmlSchemaXPathEvaluate:
16683 * @vctxt: the WXS validation context
16684 * @nodeType: the nodeType of the current node
16685 *
16686 * Evaluates all active XPath state objects.
16687 *
16688 * Returns the number of IC "field" state objects which resolved to
16689 * this node, 0 if none resolved and -1 on internal errors.
16690 */
16691static int
16692xmlSchemaXPathEvaluate(xmlSchemaValidCtxtPtr vctxt,
16693 const xmlChar *namespaceName,
16694 const xmlChar *localName,
16695 xmlElementType nodeType)
16696{
16697 xmlSchemaIDCStateObjPtr sto, head = NULL, first;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016698 int res, resolved = 0;
16699
16700 if (vctxt->xpathStates == NULL)
16701 return (0);
16702#if DEBUG_IDC
16703 {
16704 xmlChar *str = NULL;
16705 xmlGenericError(xmlGenericErrorContext,
16706 "IDC: EVAL on %s, depth %d, type %d\n",
16707 xmlSchemaFormatNsUriLocal(&str, namespaceName,
16708 localName), vctxt->depth, nodeType);
16709 FREE_AND_NULL(str)
16710 }
16711#endif
16712 /*
16713 * Process all active XPath state objects.
16714 */
16715 first = vctxt->xpathStates;
16716 sto = first;
16717 while (sto != head) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016718#if DEBUG_IDC
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000016719 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016720 xmlGenericError(xmlGenericErrorContext, "IDC: ['%s'] selector '%s'\n",
16721 sto->matcher->aidc->def->name, sto->sel->xpath);
16722 else
16723 xmlGenericError(xmlGenericErrorContext, "IDC: ['%s'] field '%s'\n",
16724 sto->matcher->aidc->def->name, sto->sel->xpath);
16725#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016726
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016727#ifdef IDC_XPATH_SUPPORT
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000016728 res = xmlStreamPush((xmlStreamCtxtPtr) sto->xpathCtxt,
16729 localName, namespaceName);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016730#else
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000016731 res = 0;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000016732#endif
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000016733 if (res == -1) {
16734 xmlSchemaVErr(vctxt, vctxt->node,
16735 XML_SCHEMAV_INTERNAL,
16736 "Internal error: xmlSchemaXPathEvaluate, "
16737 "failed to evaluate a node.\n",
16738 NULL, NULL);
16739 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016740 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000016741 if (res == 0)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016742 goto next_sto;
16743 /*
16744 * Full match.
16745 */
16746#if DEBUG_IDC
16747 xmlGenericError(xmlGenericErrorContext, "IDC: "
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000016748 "MATCH\n");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016749#endif
16750 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000016751 * Register a match in the state object history.
16752 */
16753 if (sto->history == NULL) {
16754 sto->history = (int *) xmlMalloc(5 * sizeof(int));
16755 if (sto->history == NULL) {
16756 xmlSchemaVErrMemory(NULL,
16757 "allocating the state object history", NULL);
16758 return(-1);
16759 }
16760 sto->sizeHistory = 10;
16761 } else if (sto->sizeHistory <= sto->nbHistory) {
16762 sto->sizeHistory *= 2;
16763 sto->history = (int *) xmlRealloc(sto->history,
16764 sto->sizeHistory * sizeof(int));
16765 if (sto->history == NULL) {
16766 xmlSchemaVErrMemory(NULL,
16767 "re-allocating the state object history", NULL);
16768 return(-1);
16769 }
16770 }
16771 sto->history[sto->nbHistory++] = vctxt->depth;
16772
16773#ifdef DEBUG_IDC
16774 xmlGenericError(xmlGenericErrorContext, "IDC: push match '%d'\n",
16775 vctxt->depth);
16776#endif
16777
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016778 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
16779 xmlSchemaIDCSelectPtr sel;
16780 /*
16781 * Activate state objects for the IDC fields of
16782 * the IDC selector.
16783 */
16784#if DEBUG_IDC
16785 xmlGenericError(xmlGenericErrorContext, "IDC: "
16786 "activating field states\n");
16787#endif
16788 sel = sto->matcher->aidc->def->fields;
16789 while (sel != NULL) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000016790 if (xmlSchemaIDCAddStateObject(vctxt, sto->matcher,
16791 sel, XPATH_STATE_OBJ_TYPE_IDC_FIELD) == -1)
16792 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016793 sel = sel->next;
16794 }
16795 } else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
16796 /*
16797 * An IDC key node was found.
16798 */
16799#if DEBUG_IDC
16800 xmlGenericError(xmlGenericErrorContext,
16801 "IDC: key found\n");
16802#endif
16803 /*
16804 * Notify that the character value of this node is
16805 * needed.
16806 */
16807 if (resolved == 0)
16808 vctxt->elemInfo->flags |= XML_SCHEMA_ELEM_INFO_VALUE_NEEDED;
16809 resolved++;
16810 }
16811next_sto:
16812 if (sto->next == NULL) {
16813 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000016814 * Evaluate field state objects created on this node as well.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016815 */
16816 head = first;
16817 sto = vctxt->xpathStates;
16818 } else
16819 sto = sto->next;
16820 }
16821 return (resolved);
16822}
16823
16824/**
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000016825 * xmlSchemaXPathProcessHistory:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016826 * @vctxt: the WXS validation context
16827 * @type: the simple/complex type of the current node if any at all
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000016828 * @compValue: the precompiled value
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016829 *
16830 * Processes and pops the history items of the IDC state objects.
16831 * IDC key-sequences are validated/created on IDC bindings.
16832 *
16833 * Returns 0 on success and -1 on internal errors.
16834 */
16835static int
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000016836xmlSchemaXPathProcessHistory(xmlSchemaValidCtxtPtr vctxt,
16837 xmlSchemaTypePtr type,
16838 xmlSchemaValPtr *compValue)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016839{
16840 xmlSchemaIDCStateObjPtr sto, nextsto;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000016841 int res, matchDepth;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016842 xmlSchemaPSVIIDCKeyPtr key = NULL;
16843
16844 if (vctxt->xpathStates == NULL)
16845 return (0);
16846 sto = vctxt->xpathStates;
16847
16848#if DEBUG_IDC
16849 {
16850 xmlChar *str = NULL;
16851 xmlGenericError(xmlGenericErrorContext,
16852 "IDC: BACK on %s, depth %d\n",
16853 xmlSchemaFormatNsUriLocal(&str, vctxt->elemInfo->namespaceName,
16854 vctxt->elemInfo->localName), vctxt->depth);
16855 FREE_AND_NULL(str)
16856 }
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000016857#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016858 /*
16859 * Evaluate the state objects.
16860 */
16861 while (sto != NULL) {
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000016862#ifdef IDC_XPATH_SUPPORT
16863 xmlStreamPop((xmlStreamCtxtPtr) sto->xpathCtxt);
16864 #if DEBUG_IDC
16865 xmlGenericError(xmlGenericErrorContext, "IDC: stream pop '%s'\n",
16866 sto->sel->xpath);
16867 #endif
16868#endif
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000016869 if (sto->nbHistory == 0)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016870 goto deregister_check;
16871
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000016872 matchDepth = sto->history[sto->nbHistory -1];
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016873
16874 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000016875 * Only matches at the current depth are of interest.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016876 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000016877 if (matchDepth != vctxt->depth) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016878 sto = sto->next;
16879 continue;
16880 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000016881
16882 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
16883 if (! IS_SIMPLE_TYPE(type)) {
16884 /*
16885 * Not qualified if the field resolves to a node of non
16886 * simple type.
16887 */
16888 xmlSchemaVCustomErr(vctxt,
16889 XML_SCHEMAV_CVC_IDC,
16890 vctxt->node,
16891 (xmlSchemaTypePtr) sto->matcher->aidc->def,
16892 "The field '%s' does evaluate to a node of "
16893 "non-simple type", sto->sel->xpath);
16894
16895 sto->nbHistory--;
16896 goto deregister_check;
16897 }
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000016898 if ((key == NULL) && (*compValue == NULL)) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000016899 /*
16900 * Failed to provide the normalized value; maby
16901 * the value was invalid.
16902 */
16903 xmlSchemaVErr(vctxt, NULL,
16904 XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000016905 "Internal error: xmlSchemaXPathProcessHistory, "
16906 "computed value not available.\n",
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000016907 NULL, NULL);
16908 sto->nbHistory--;
16909 goto deregister_check;
16910 } else {
16911 xmlSchemaIDCMatcherPtr matcher = sto->matcher;
16912 xmlSchemaPSVIIDCKeyPtr *keySeq;
16913 int pos, index;
16914
16915 /*
16916 * The key will be anchored on the matcher's list of
16917 * key-sequences. The position in this list is determined
16918 * by the target node's depth relative to the matcher's
16919 * depth of creation (i.e. the depth of the scope element).
16920 */
16921 pos = sto->depth - matcher->depth;
16922 index = sto->sel->index;
16923
16924 /*
16925 * Create/grow the array of key-sequences.
16926 */
16927 if (matcher->keySeqs == NULL) {
16928 if (pos > 9)
16929 matcher->sizeKeySeqs = pos * 2;
16930 else
16931 matcher->sizeKeySeqs = 10;
16932 matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
16933 xmlMalloc(matcher->sizeKeySeqs *
16934 sizeof(xmlSchemaPSVIIDCKeyPtr *));
16935 if (matcher->keySeqs == NULL) {
16936 xmlSchemaVErrMemory(NULL,
16937 "allocating an array of key-sequences",
16938 NULL);
16939 return(-1);
16940 }
16941 memset(matcher->keySeqs, 0,
16942 matcher->sizeKeySeqs *
16943 sizeof(xmlSchemaPSVIIDCKeyPtr *));
16944 } else if (pos >= matcher->sizeKeySeqs) {
16945 int i = matcher->sizeKeySeqs;
16946
16947 matcher->sizeKeySeqs *= 2;
16948 matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
16949 xmlRealloc(matcher->keySeqs,
16950 matcher->sizeKeySeqs *
16951 sizeof(xmlSchemaPSVIIDCKeyPtr *));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016952 if (matcher->keySeqs == NULL) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000016953 xmlSchemaVErrMemory(NULL,
16954 "reallocating an array of key-sequences",
16955 NULL);
16956 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016957 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016958 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000016959 * The array needs to be NULLed.
16960 * TODO: Use memset?
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016961 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000016962 for (; i < matcher->sizeKeySeqs; i++)
16963 matcher->keySeqs[i] = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016964 }
16965
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000016966 /*
16967 * Get/create the key-sequence.
16968 */
16969 keySeq = matcher->keySeqs[pos];
16970 if (keySeq == NULL) {
16971 goto create_sequence;
16972 } else {
16973 if (keySeq[index] != NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016974 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000016975 * cvc-identity-constraint:
16976 * 3 For each node in the ·target node set· all
16977 * of the {fields}, with that node as the context
16978 * node, evaluate to either an empty node-set or
16979 * a node-set with exactly one member, which must
16980 * have a simple type.
16981 *
16982 * The key was already set; report an error.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016983 */
16984 xmlSchemaVCustomErr(vctxt,
16985 XML_SCHEMAV_CVC_IDC,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000016986 vctxt->node, (xmlSchemaTypePtr) matcher->aidc->def,
16987 "The field '%s' evaluates to a node-set "
16988 "with more than one member", sto->sel->xpath);
16989 sto->nbHistory--;
16990 goto deregister_check;
16991 } else {
16992 goto create_key;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016993 }
16994 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016995
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000016996create_sequence:
16997 /*
16998 * Create a key-sequence.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016999 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017000 keySeq = (xmlSchemaPSVIIDCKeyPtr *) xmlMalloc(
17001 matcher->aidc->def->nbFields *
17002 sizeof(xmlSchemaPSVIIDCKeyPtr));
17003 if (keySeq == NULL) {
17004 xmlSchemaVErrMemory(NULL,
17005 "allocating an IDC key-sequence", NULL);
17006 return(-1);
17007 }
17008 memset(keySeq, 0, matcher->aidc->def->nbFields *
17009 sizeof(xmlSchemaPSVIIDCKeyPtr));
17010 matcher->keySeqs[pos] = keySeq;
17011create_key:
17012 /*
17013 * Created a key once per node only.
17014 */
17015 if (key == NULL) {
17016 key = (xmlSchemaPSVIIDCKeyPtr) xmlMalloc(
17017 sizeof(xmlSchemaPSVIIDCKey));
17018 if (key == NULL) {
17019 xmlSchemaVErrMemory(NULL,
17020 "allocating a IDC key", NULL);
17021 xmlFree(keySeq);
17022 matcher->keySeqs[pos] = NULL;
17023 return(-1);
17024 }
17025 /*
17026 * Consume the compiled value.
17027 */
17028 key->type = type;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000017029 key->compValue = *compValue;
17030 (*compValue) = NULL;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017031 /*
17032 * Store the key in a global list.
17033 */
17034 if (xmlSchemaIDCStoreKey(vctxt, key) == -1) {
17035 xmlSchemaIDCFreeKey(key);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017036 return (-1);
17037 }
17038 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017039 keySeq[index] = key;
17040 }
17041 } else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017042
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017043 xmlSchemaPSVIIDCKeyPtr **keySeq = NULL;
17044 xmlSchemaPSVIIDCBindingPtr bind;
17045 xmlSchemaPSVIIDCNodePtr ntItem;
17046 xmlSchemaIDCMatcherPtr matcher;
17047 xmlSchemaIDCPtr idc;
17048 int pos, i, j, nbKeys;
17049 /*
17050 * Here we have the following scenario:
17051 * An IDC 'selector' state object resolved to a target node,
17052 * during the time this target node was in the
17053 * ancestor-or-self axis, the 'field' state object(s) looked
17054 * out for matching nodes to create a key-sequence for this
17055 * target node. Now we are back to this target node and need
17056 * to put the key-sequence, together with the target node
17057 * itself, into the node-table of the corresponding IDC
17058 * binding.
17059 */
17060 matcher = sto->matcher;
17061 idc = matcher->aidc->def;
17062 nbKeys = idc->nbFields;
17063 pos = vctxt->depth - matcher->depth;
17064 /*
17065 * Check if the matcher has any key-sequences at all, plus
17066 * if it has a key-sequence for the current target node.
17067 */
17068 if ((matcher->keySeqs == NULL) ||
17069 (matcher->sizeKeySeqs <= pos)) {
17070 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
17071 goto selector_key_error;
17072 else
17073 goto selector_leave;
17074 }
17075
17076 keySeq = &(matcher->keySeqs[pos]);
17077 if (*keySeq == NULL) {
17078 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
17079 goto selector_key_error;
17080 else
17081 goto selector_leave;
17082 }
17083
17084 for (i = 0; i < nbKeys; i++) {
17085 if ((*keySeq)[i] == NULL) {
17086 /*
17087 * Not qualified, if not all fields did resolve.
17088 */
17089 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY) {
17090 /*
17091 * All fields of a "key" IDC must resolve.
17092 */
17093 goto selector_key_error;
17094 }
17095 goto selector_leave;
17096 }
17097 }
17098 /*
17099 * All fields did resolve.
17100 */
17101
17102 /*
17103 * 4.1 If the {identity-constraint category} is unique(/key),
17104 * then no two members of the ·qualified node set· have
17105 * ·key-sequences· whose members are pairwise equal, as
17106 * defined by Equal in [XML Schemas: Datatypes].
17107 *
17108 * Get the IDC binding from the matcher and check for
17109 * duplicate key-sequences.
17110 */
17111 bind = xmlSchemaIDCAquireBinding(vctxt, matcher);
17112 if ((idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) &&
17113 (bind->nbNodes != 0)) {
17114 xmlSchemaPSVIIDCKeyPtr key, bkey, *bkeySeq;
17115
17116 i = 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017117 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017118 * Compare the key-sequences, key by key.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017119 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017120 do {
17121 bkeySeq = bind->nodeTable[i]->keys;
17122 for (j = 0; j < nbKeys; j++) {
17123 key = (*keySeq)[j];
17124 bkey = bkeySeq[j];
17125 res = xmlSchemaAreValuesEqual(key->type,
17126 key->compValue, bkey->type, bkey->compValue);
17127 if (res == -1) {
17128 return (-1);
17129 } else if (res == 0)
17130 break;
17131 }
17132 if (res == 1) {
17133 /*
17134 * Duplicate found.
17135 */
17136 break;
17137 }
17138 i++;
17139 } while (i < bind->nbNodes);
17140 if (i != bind->nbNodes) {
17141 /*
17142 * TODO: Try to report the key-sequence.
17143 */
17144 xmlSchemaVCustomErr(vctxt,
17145 XML_SCHEMAV_CVC_IDC,
17146 vctxt->node,
17147 (xmlSchemaTypePtr) idc,
17148 "Duplicate key-sequence found", NULL);
17149
17150 goto selector_leave;
17151 }
17152 }
17153 /*
17154 * Add a node-table item to the IDC binding.
17155 */
17156 ntItem = (xmlSchemaPSVIIDCNodePtr) xmlMalloc(
17157 sizeof(xmlSchemaPSVIIDCNode));
17158 if (ntItem == NULL) {
17159 xmlSchemaVErrMemory(NULL,
17160 "allocating an IDC node-table item", NULL);
17161 xmlFree(*keySeq);
17162 *keySeq = NULL;
17163 return(-1);
17164 }
17165 memset(ntItem, 0, sizeof(xmlSchemaPSVIIDCNode));
17166
17167 /*
17168 * Store the node-table item on global list.
17169 */
17170 if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) {
17171 if (xmlSchemaIDCStoreNodeTableItem(vctxt, ntItem) == -1) {
17172 xmlFree(ntItem);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017173 xmlFree(*keySeq);
17174 *keySeq = NULL;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017175 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017176 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017177 }
17178 /*
17179 * Init the node-table item. Consume the key-sequence.
17180 */
17181 ntItem->node = vctxt->node;
17182 ntItem->keys = *keySeq;
17183 *keySeq = NULL;
17184 if (xmlSchemaIDCAppendNodeTableItem(bind, ntItem) == -1) {
17185 if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
17186 /*
17187 * Free the item, since keyref items won't be
17188 * put on a global list.
17189 */
17190 xmlFree(ntItem->keys);
17191 xmlFree(ntItem);
17192 }
17193 return (-1);
17194 }
17195
17196 goto selector_leave;
17197selector_key_error:
17198 /*
17199 * 4.2.1 (KEY) The ·target node set· and the
17200 * ·qualified node set· are equal, that is, every
17201 * member of the ·target node set· is also a member
17202 * of the ·qualified node set· and vice versa.
17203 */
17204 xmlSchemaVCustomErr(vctxt,
17205 XML_SCHEMAV_CVC_IDC,
17206 vctxt->node,
17207 (xmlSchemaTypePtr) idc,
17208 "All 'key' fields must evaluate to a node",
17209 NULL);
17210selector_leave:
17211 /*
17212 * Free the key-sequence if not added to the IDC table.
17213 */
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000017214 if ((keySeq != NULL) && (*keySeq != NULL)) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017215 xmlFree(*keySeq);
17216 *keySeq = NULL;
17217 }
17218 } /* if selector */
17219
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017220 sto->nbHistory--;
17221
17222deregister_check:
17223 /*
17224 * Deregister state objects if they reach the depth of creation.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017225 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017226 if ((sto->nbHistory == 0) && (sto->depth == vctxt->depth)) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017227#if DEBUG_IDC
17228 xmlGenericError(xmlGenericErrorContext, "IDC: STO pop '%s'\n",
17229 sto->sel->xpath);
17230#endif
17231 if (vctxt->xpathStates != sto) {
17232 xmlSchemaVErr(vctxt, vctxt->node,
17233 XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000017234 "Internal error: xmlSchemaXPathProcessHistory, "
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017235 "The state object to be removed is not the first "
17236 "in the list.\n",
17237 NULL, NULL);
17238 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017239 nextsto = sto->next;
17240 /*
17241 * Unlink from the list of active XPath state objects.
17242 */
17243 vctxt->xpathStates = sto->next;
17244 sto->next = vctxt->xpathStatePool;
17245 /*
17246 * Link it to the pool of reusable state objects.
17247 */
17248 vctxt->xpathStatePool = sto;
17249 sto = nextsto;
17250 } else
17251 sto = sto->next;
17252 } /* while (sto != NULL) */
17253 return (0);
17254}
17255
17256/**
17257 * xmlSchemaIDCRegisterMatchers:
17258 * @vctxt: the WXS validation context
17259 * @elemDecl: the element declaration
17260 *
17261 * Creates helper objects to evaluate IDC selectors/fields
17262 * successively.
17263 *
17264 * Returns 0 if OK and -1 on internal errors.
17265 */
17266static int
17267xmlSchemaIDCRegisterMatchers(xmlSchemaValidCtxtPtr vctxt,
17268 xmlSchemaElementPtr elemDecl)
17269{
17270 xmlSchemaIDCMatcherPtr matcher, last = NULL;
17271 xmlSchemaIDCPtr idc, refIdc;
17272 xmlSchemaIDCAugPtr aidc;
17273
17274 idc = (xmlSchemaIDCPtr) elemDecl->idcs;
17275 if (idc == NULL)
17276 return (0);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000017277
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017278#if DEBUG_IDC
17279 {
17280 xmlChar *str = NULL;
17281 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017282 "IDC: REGISTER on %s, depth %d\n",
17283 (char *) xmlSchemaFormatNsUriLocal(&str, vctxt->elemInfo->namespaceName,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017284 vctxt->elemInfo->localName), vctxt->depth);
17285 FREE_AND_NULL(str)
17286 }
17287#endif
17288 if (vctxt->elemInfo->idcMatchers != NULL) {
17289 xmlSchemaVErr(vctxt, vctxt->node,
17290 XML_SCHEMAV_INTERNAL,
17291 "Internal error: xmlSchemaIDCRegisterMatchers: "
17292 "The chain of IDC matchers is expected to be empty.\n",
17293 NULL, NULL);
17294 return (-1);
17295 }
17296 do {
17297 if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
17298 /*
17299 * Since IDCs bubbles are expensive we need to know the
17300 * depth at which the bubbles should stop; this will be
17301 * the depth of the top-most keyref IDC. If no keyref
17302 * references a key/unique IDC, the bubbleDepth will
17303 * be -1, indicating that no bubbles are needed.
17304 */
17305 refIdc = (xmlSchemaIDCPtr) idc->ref->item;
17306 if (refIdc != NULL) {
17307 /*
17308 * Lookup the augmented IDC.
17309 */
17310 aidc = vctxt->aidcs;
17311 while (aidc != NULL) {
17312 if (aidc->def == refIdc)
17313 break;
17314 aidc = aidc->next;
17315 }
17316 if (aidc == NULL) {
17317 xmlSchemaVErr(vctxt, vctxt->node,
17318 XML_SCHEMAV_INTERNAL,
17319 "Internal error: xmlSchemaIDCRegisterMatchers: "
17320 "Could not find an augmented IDC item for an IDC "
17321 "definition.\n",
17322 NULL, NULL);
17323 return (-1);
17324 }
17325 if ((aidc->bubbleDepth == -1) ||
17326 (vctxt->depth < aidc->bubbleDepth))
17327 aidc->bubbleDepth = vctxt->depth;
17328 }
17329 }
17330 /*
17331 * Lookup the augmented IDC item for the IDC definition.
17332 */
17333 aidc = vctxt->aidcs;
17334 while (aidc != NULL) {
17335 if (aidc->def == idc)
17336 break;
17337 aidc = aidc->next;
17338 }
17339 if (aidc == NULL) {
17340 xmlSchemaVErr(vctxt, vctxt->node,
17341 XML_SCHEMAV_INTERNAL,
17342 "Internal error: xmlSchemaIDCRegisterMatchers: "
17343 "Could not find an augmented IDC item for an IDC definition.\n",
17344 NULL, NULL);
17345 return (-1);
17346 }
17347 /*
17348 * Create an IDC matcher for every IDC definition.
17349 */
17350 matcher = (xmlSchemaIDCMatcherPtr)
17351 xmlMalloc(sizeof(xmlSchemaIDCMatcher));
17352 if (matcher == NULL) {
17353 xmlSchemaVErrMemory(vctxt,
17354 "allocating an IDC matcher", NULL);
17355 return (-1);
17356 }
17357 memset(matcher, 0, sizeof(xmlSchemaIDCMatcher));
17358 if (last == NULL)
17359 vctxt->elemInfo->idcMatchers = matcher;
17360 else
17361 last->next = matcher;
17362 last = matcher;
17363
17364 matcher->type = IDC_MATCHER;
17365 matcher->depth = vctxt->depth;
17366 matcher->aidc = aidc;
17367#if DEBUG_IDC
17368 xmlGenericError(xmlGenericErrorContext, "IDC: register matcher\n");
17369#endif
17370 /*
17371 * Init the automaton state object.
17372 */
17373 if (xmlSchemaIDCAddStateObject(vctxt, matcher,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017374 idc->selector, XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) == -1)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017375 return (-1);
17376
17377 idc = idc->next;
17378 } while (idc != NULL);
17379 return (0);
17380}
17381
17382/**
17383 * xmlSchemaBubbleIDCNodeTables:
17384 * @depth: the current tree depth
17385 *
17386 * Merges IDC bindings of an element at @depth into the corresponding IDC
17387 * bindings of its parent element. If a duplicate note-table entry is found,
17388 * both, the parent node-table entry and child entry are discarded from the
17389 * node-table of the parent.
17390 *
17391 * Returns 0 if OK and -1 on internal errors.
17392 */
17393static int
17394xmlSchemaBubbleIDCNodeTables(xmlSchemaValidCtxtPtr vctxt)
17395{
17396 xmlSchemaPSVIIDCBindingPtr bind; /* IDC bindings of the current node. */
17397 xmlSchemaPSVIIDCBindingPtr *parTable, parBind, lastParBind; /* parent IDC bindings. */
17398 xmlSchemaPSVIIDCNodePtr node, parNode; /* node-table entries. */
17399 xmlSchemaPSVIIDCKeyPtr key, parKey; /* keys of in a key-sequence. */
17400 xmlSchemaIDCAugPtr aidc;
17401 int i, j, k, ret, oldNum, newDupls = 0;
17402 int duplTop;
17403
17404 /*
17405 * The node table has the following sections:
17406 *
17407 * O --> old node-table entries (first)
17408 * O
17409 * + --> new node-table entries
17410 * +
17411 * % --> new duplicate node-table entries
17412 * %
17413 * # --> old duplicate node-table entries
17414 * # (last)
17415 *
17416 */
17417 bind = vctxt->elemInfo->idcTable;
17418 if (bind == NULL) {
17419 /* Fine, no table, no bubbles. */
17420 return (0);
17421 }
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000017422
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017423 parTable = &(vctxt->elemInfos[vctxt->depth -1]->idcTable);
17424 /*
17425 * Walk all bindings; create new or add to existing bindings.
17426 * Remove duplicate key-sequences.
17427 */
17428start_binding:
17429 while (bind != NULL) {
17430 /*
17431 * Skip keyref IDCs.
17432 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017433 if (bind->definition->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
17434 bind = bind->next;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017435 continue;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017436 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017437 /*
17438 * Check if the key/unique IDC table needs to be bubbled.
17439 */
17440 aidc = vctxt->aidcs;
17441 do {
17442 if (aidc->def == bind->definition) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017443 if (aidc->bubbleDepth >= vctxt->depth) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017444 bind = bind->next;
17445 goto start_binding;
17446 }
17447 break;
17448 }
17449 aidc = aidc->next;
17450 } while (aidc != NULL);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017451
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017452 if (parTable != NULL)
17453 parBind = *parTable;
17454 while (parBind != NULL) {
17455 /*
17456 * Search a matching parent binding for the
17457 * IDC definition.
17458 */
17459 if (parBind->definition == bind->definition) {
17460
17461 /*
17462 * Compare every node-table entry of the child node,
17463 * i.e. the key-sequence within, ...
17464 */
17465 oldNum = parBind->nbNodes; /* Skip newly added items. */
17466 duplTop = oldNum + parBind->nbDupls;
17467
17468 for (i = 0; i < bind->nbNodes; i++) {
17469 node = bind->nodeTable[i];
17470 if (node == NULL)
17471 continue;
17472 /*
17473 * ...with every key-sequence of the parent node, already
17474 * evaluated to be a duplicate key-sequence.
17475 */
17476 if (parBind->nbDupls != 0) {
17477 j = bind->nbNodes + newDupls;
17478 while (j < duplTop) {
17479 parNode = parBind->nodeTable[j];
17480 for (k = 0; k < bind->definition->nbFields; k++) {
17481 key = node->keys[k];
17482 parKey = parNode->keys[k];
17483 ret = xmlSchemaAreValuesEqual(key->type,
17484 key->compValue,
17485 parKey->type, parKey->compValue);
17486 if (ret == -1) {
17487 /* TODO: Internal error */
17488 return(-1);
17489 } else if (ret == 0)
17490 break;
17491
17492 }
17493 if (ret == 1)
17494 /* Duplicate found. */
17495 break;
17496 j++;
17497 }
17498 if (j != duplTop) {
17499 /* Duplicate found. */
17500 continue;
17501 }
17502 }
17503 /*
17504 * ... and with every key-sequence of the parent node.
17505 */
17506 j = 0;
17507 while (j < oldNum) {
17508 parNode = parBind->nodeTable[j];
17509 /*
17510 * Compare key by key.
17511 */
17512 for (k = 0; k < parBind->definition->nbFields; k++) {
17513 key = node->keys[k];
17514 parKey = parNode->keys[k];
17515
17516 ret = xmlSchemaAreValuesEqual(key->type,
17517 key->compValue,
17518 parKey->type, parKey->compValue);
17519 if (ret == -1) {
17520 /* TODO: Internal error */
17521 } else if (ret == 0)
17522 break;
17523
17524 }
17525 if (ret == 1)
17526 /*
17527 * The key-sequences are equal.
17528 */
17529 break;
17530 j++;
17531 }
17532 if (j != oldNum) {
17533 /*
17534 * Handle duplicates.
17535 */
17536 newDupls++;
17537 oldNum--;
17538 parBind->nbNodes--;
17539 /*
17540 * Move last old item to pos of duplicate.
17541 */
17542 parBind->nodeTable[j] =
17543 parBind->nodeTable[oldNum];
17544
17545 if (parBind->nbNodes != oldNum) {
17546 /*
17547 * If new items exist, move last new item to
17548 * last of old items.
17549 */
17550 parBind->nodeTable[oldNum] =
17551 parBind->nodeTable[parBind->nbNodes];
17552 }
17553 /*
17554 * Move duplicate to last pos of new/old items.
17555 */
17556 parBind->nodeTable[parBind->nbNodes] = parNode;
17557
17558 } else {
17559 /*
17560 * Add the node-table entry (node and key-sequence) of
17561 * the child node to the node table of the parent node.
17562 */
17563 if (parBind->nodeTable == NULL) {
17564 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
17565 xmlMalloc(1 * sizeof(xmlSchemaPSVIIDCNodePtr));
17566 if (parBind->nodeTable == NULL) {
17567 xmlSchemaVErrMemory(NULL,
17568 "allocating IDC list of node-table items", NULL);
17569 return(-1);
17570 }
17571 parBind->sizeNodes = 1;
17572 } else if (duplTop >= parBind->sizeNodes) {
17573 parBind->sizeNodes++;
17574 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
17575 xmlRealloc(parBind->nodeTable, parBind->sizeNodes *
17576 sizeof(xmlSchemaPSVIIDCNodePtr));
17577 if (parBind->nodeTable == NULL) {
17578 xmlSchemaVErrMemory(NULL,
17579 "re-allocating IDC list of node-table items", NULL);
17580 return(-1);
17581 }
17582 }
17583
17584 /*
17585 * Move first old duplicate to last position
17586 * of old duplicates +1.
17587 */
17588 if (parBind->nbDupls != 0) {
17589 parBind->nodeTable[duplTop] =
17590 parBind->nodeTable[parBind->nbNodes + newDupls];
17591 }
17592 /*
17593 * Move first new duplicate to last position of
17594 * new duplicates +1.
17595 */
17596 if (newDupls != 0) {
17597 parBind->nodeTable[parBind->nbNodes + newDupls] =
17598 parBind->nodeTable[parBind->nbNodes];
17599 }
17600 /*
17601 * Append the new node-table entry to the 'new node-table
17602 * entries' section.
17603 */
17604 parBind->nodeTable[parBind->nbNodes] = node;
17605 parBind->nbNodes++;
17606 duplTop++;
17607 }
17608 }
17609 parBind->nbDupls += newDupls;
17610 break;
17611 }
17612 if (parBind->next == NULL)
17613 lastParBind = parBind;
17614 parBind = parBind->next;
17615 }
17616 if (parBind == NULL) {
17617 /*
17618 * No binding for the IDC was found: create a new one and
17619 * copy all node-tables.
17620 */
17621 parBind = xmlSchemaIDCNewBinding(bind->definition);
17622 if (parBind == NULL)
17623 return(-1);
17624
17625 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
17626 xmlMalloc(bind->nbNodes * sizeof(xmlSchemaPSVIIDCNodePtr));
17627 if (parBind->nodeTable == NULL) {
17628 xmlSchemaVErrMemory(NULL,
17629 "allocating an array of IDC node-table items", NULL);
17630 xmlSchemaIDCFreeBinding(parBind);
17631 return(-1);
17632 }
17633 parBind->sizeNodes = bind->nbNodes;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017634 parBind->nbNodes = bind->nbNodes;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017635 memcpy(parBind->nodeTable, bind->nodeTable,
17636 bind->nbNodes * sizeof(xmlSchemaPSVIIDCNodePtr));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017637 if (*parTable == NULL)
17638 *parTable = parBind;
17639 else
17640 lastParBind->next = parBind;
17641 }
17642 bind = bind->next;
17643 }
17644 return (0);
17645}
17646
17647/**
17648 * xmlSchemaCheckCVCIDCKeyRef:
17649 * @vctxt: the WXS validation context
17650 * @elemDecl: the element declaration
17651 *
17652 * Check the cvc-idc-keyref constraints.
17653 */
17654static int
17655xmlSchemaCheckCVCIDCKeyRef(xmlSchemaValidCtxtPtr vctxt)
17656{
17657 xmlSchemaPSVIIDCBindingPtr refbind, bind;
17658
17659 refbind = vctxt->elemInfo->idcTable;
17660 /*
17661 * Find a keyref.
17662 */
17663 while (refbind != NULL) {
17664 if (refbind->definition->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
17665 int i, j, k, res;
17666 xmlSchemaPSVIIDCKeyPtr *refKeys, *keys;
17667 xmlSchemaPSVIIDCKeyPtr refKey, key;
17668
17669 /*
17670 * Find the referred key/unique.
17671 */
17672 bind = vctxt->elemInfo->idcTable;
17673 do {
17674 if ((xmlSchemaIDCPtr) refbind->definition->ref->item ==
17675 bind->definition)
17676 break;
17677 bind = bind->next;
17678 } while (bind != NULL);
17679
17680 /*
17681 * Search for a matching key-sequences.
17682 */
17683 for (i = 0; i < refbind->nbNodes; i++) {
17684 res = 0;
17685 if (bind != NULL) {
17686 refKeys = refbind->nodeTable[i]->keys;
17687 for (j = 0; j < bind->nbNodes; j++) {
17688 keys = bind->nodeTable[j]->keys;
17689 for (k = 0; k < bind->definition->nbFields; k++) {
17690 refKey = refKeys[k];
17691 key = keys[k];
17692 res = xmlSchemaAreValuesEqual(key->type, key->compValue,
17693 refKey->type, refKey->compValue);
17694 if (res == 0)
17695 break;
17696 else if (res == -1) {
17697 return (-1);
17698 }
17699 }
17700 if (res == 1) {
17701 /*
17702 * Match found.
17703 */
17704 break;
17705 }
17706 }
17707 }
17708 if (res == 0) {
17709 /* TODO: Report the key-sequence. */
17710 xmlSchemaVCustomErr(vctxt,
17711 XML_SCHEMAV_CVC_IDC,
17712 refbind->nodeTable[i]->node,
17713 (xmlSchemaTypePtr) refbind->definition,
17714 "No matching key-sequence found", NULL);
17715 }
17716 }
17717 }
17718 refbind = refbind->next;
17719 }
17720 return (0);
17721}
17722#endif /* IDC_ENABLED */
17723
17724#ifdef ELEM_INFO_ENABLED
17725/**
17726 * xmlSchemaBeginElement:
17727 * @vctxt: the WXS validation context
17728 *
17729 * Just a temporary workaround to simulate streaming validation
17730 * a bit.
17731 */
17732static void
17733xmlSchemaBeginElement(xmlSchemaValidCtxtPtr vctxt)
17734{
17735 vctxt->depth++;
17736 vctxt->elemInfo = xmlSchemaGetFreshElemInfo(vctxt);
17737 vctxt->elemInfo->node = vctxt->node;
17738 vctxt->elemInfo->localName = vctxt->node->name;
17739 if (vctxt->node->ns != NULL)
17740 vctxt->elemInfo->namespaceName = vctxt->node->ns->href;
17741 else
17742 vctxt->elemInfo->namespaceName = NULL;
17743}
17744
17745/**
17746 * xmlSchemaEndElement:
17747 * @vctxt: the WXS validation context
17748 *
17749 * Just a temporary workaround to simulate streaming validation
17750 * a bit.
17751 */
17752static void
17753xmlSchemaEndElement(xmlSchemaValidCtxtPtr vctxt)
17754{
17755 if (vctxt->depth < 0) {
17756 /* TODO: raise error? */
17757 vctxt->depth--;
17758 return;
17759 }
17760#ifdef IDC_ENABLED
17761 /*
17762 * Evaluate the history of changes of active state objects.
17763 */
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000017764 xmlSchemaXPathProcessHistory(vctxt, vctxt->elemInfo->typeDef,
17765 &(vctxt->elemInfo->value));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017766
17767 if (vctxt->elemInfo->value != NULL) {
17768 xmlSchemaFreeValue(vctxt->elemInfo->value);
17769 vctxt->elemInfo->value = NULL;
17770 }
17771 /*
17772 * TODO: 6 The element information item must be ·valid· with respect to each of
17773 * the {identity-constraint definitions} as per Identity-constraint
17774 * Satisfied (§3.11.4).
17775 */
17776 /*
17777 * Validate IDC keyrefs.
17778 */
17779 xmlSchemaCheckCVCIDCKeyRef(vctxt);
17780#endif
17781
17782 /*
17783 * Merge/free the IDC table.
17784 */
17785 if (vctxt->elemInfo->idcTable != NULL) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000017786#ifdef IDC_ENABLED
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017787#ifdef DEBUG_IDC
17788 xmlSchemaDebugDumpIDCTable(stdout,
17789 vctxt->elemInfo->namespaceName,
17790 vctxt->elemInfo->localName,
17791 vctxt->elemInfo->idcTable);
17792#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017793 if (vctxt->depth > 0) {
17794 /*
17795 * Merge the IDC node table with the table of the parent node.
17796 */
17797 xmlSchemaBubbleIDCNodeTables(vctxt);
17798 }
17799 /*
17800 * TODO: Don't free the PSVI IDC tables if they are
17801 * requested for the PSVI.
17802 */
17803 xmlSchemaIDCFreeIDCTable(vctxt->elemInfo->idcTable);
17804#endif
17805 vctxt->elemInfo->idcTable = NULL;
17806 }
17807
17808 /*
17809 * Cleanup IDC matchers.
17810 */
17811#ifdef IDC_ENABLED
17812 if (vctxt->elemInfo->idcMatchers != NULL) {
17813 xmlSchemaIDCFreeMatcherList(vctxt->elemInfo->idcMatchers);
17814 vctxt->elemInfo->idcMatchers = NULL;
17815 }
17816#endif
17817
17818 /*
17819 * Skip further processing if we are on the validation root.
17820 */
17821 if (vctxt->depth == 0) {
17822 vctxt->depth--;
17823 return;
17824 }
17825
17826 /*
17827 * Reset the bubbleDepth if needed.
17828 */
17829#ifdef IDC_ENABLED
17830 if (vctxt->aidcs != NULL) {
17831 xmlSchemaIDCAugPtr aidc = vctxt->aidcs;
17832 do {
17833 if (aidc->bubbleDepth == vctxt->depth) {
17834 /*
17835 * A bubbleDepth of a key/unique IDC matches the current
17836 * depth, this means that we are leaving the scope of the
17837 * top-most keyref IDC.
17838 */
17839 aidc->bubbleDepth = -1;
17840 }
17841 aidc = aidc->next;
17842 } while (aidc != NULL);
17843 }
17844#endif
17845 vctxt->depth--;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000017846 /*
17847 * Clear the current elemInfo.
17848 */
17849 if (vctxt->elemInfo->value != NULL) {
17850 xmlSchemaFreeValue(vctxt->elemInfo->value);
17851 vctxt->elemInfo->value = NULL;
17852 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017853 vctxt->elemInfo = vctxt->elemInfos[vctxt->depth];
17854 vctxt->node = vctxt->elemInfo->node;
17855}
17856
17857#endif /* ELEM_INFO_ENABLED */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017858
17859/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017860 * xmlSchemaValidateElementByDeclaration:
Daniel Veillard4255d502002-04-16 15:50:10 +000017861 * @ctxt: a schema validation context
17862 * @node: the top node.
17863 *
17864 * Validate the content of an element type.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017865 * Validation Rule: Element Locally Valid (Element)
Daniel Veillard4255d502002-04-16 15:50:10 +000017866 *
17867 * Returns 0 if the element is schemas valid, a positive error code
17868 * number otherwise and -1 in case of internal or API error.
17869 */
17870static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017871xmlSchemaValidateElementByDeclaration(xmlSchemaValidCtxtPtr ctxt,
17872 xmlSchemaElementPtr elemDecl)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017873{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017874 xmlNodePtr elem;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017875 int ret = 0;
17876 xmlSchemaTypePtr actualType = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017877 xmlAttrPtr attr;
17878 xmlChar *attrValue;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017879 int nilled = 0, elemHasContent = -1;
Daniel Veillard3646d642004-06-02 19:19:14 +000017880
17881 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017882 * This one is called by xmlSchemaValidateElementByWildcardInternal,
17883 * xmlSchemaValidateElementByAnyType and xmlSchemaValidateElement.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017884 * Note that @elemDecl will be the declaration and never the
17885 * reference to a declaration.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017886 */
Daniel Veillard3646d642004-06-02 19:19:14 +000017887
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017888 if (ctxt == NULL) {
17889 xmlSchemaVErr(ctxt, NULL, XML_SCHEMAV_INTERNAL,
17890 "Internal error: xmlSchemaValidateElementByDeclaration, "
17891 "bad arguments.\n",
17892 NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017893 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000017894 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017895
17896 elem = ctxt->node;
17897
17898 /*
17899 * cvc-elt (3.3.4) : 1
17900 */
17901 if (elemDecl == NULL) {
17902 xmlSchemaVCustomErr(ctxt,
17903 XML_SCHEMAV_CVC_ELT_1,
17904 elem, NULL,
17905 "No matching declaration available", NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017906 /*
17907 * Evaluate IDCs even if an error occured.
17908 */
17909#ifdef IDC_ENABLED
17910 if (xmlSchemaXPathEvaluate(ctxt, ctxt->elemInfo->namespaceName,
17911 ctxt->elemInfo->localName, XML_ELEMENT_NODE) == -1)
17912 return (-1);
17913#endif
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017914 return (ctxt->err);
17915 }
17916 /*
17917 * cvc-elt (3.3.4) : 2
17918 */
17919 if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT) {
17920 xmlSchemaVCustomErr(ctxt,
17921 XML_SCHEMAV_CVC_ELT_2,
17922 elem, NULL,
17923 "The element declaration is abstract", NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017924 /*
17925 * Evaluate IDCs even if an error occured.
17926 */
17927#ifdef IDC_ENABLED
17928 if (xmlSchemaXPathEvaluate(ctxt, ctxt->elemInfo->namespaceName,
17929 ctxt->elemInfo->localName, XML_ELEMENT_NODE) == -1)
17930 return (-1);
17931#endif
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017932 return (ctxt->err);
17933 }
17934
17935 /*
17936 * cvc-elt (3.3.4) : 3
17937 * Handle 'xsi:nil'.
17938 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017939
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017940 attr = xmlHasNsProp(elem, BAD_CAST "nil", xmlSchemaInstanceNs);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017941 if (attr != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017942 attrValue = xmlNodeGetContent((xmlNodePtr) attr);
17943 ctxt->node = (xmlNodePtr) attr;
17944 ctxt->cur = attr->children;
17945 ret = xmlSchemaValidateSimpleTypeValue(ctxt,
17946 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
17947 BAD_CAST attrValue, 1, 1, 1, 1);
17948 ctxt->node = elem;
17949 ctxt->type = (xmlSchemaTypePtr) elemDecl;
17950 if (ret < 0) {
17951 xmlSchemaVCustomErr(ctxt,
17952 XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017953 (xmlNodePtr) attr, (xmlSchemaTypePtr) elemDecl,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017954 "Internal error: xmlSchemaValidateElementByDeclaration, "
17955 "validating the attribute 'xsi:nil'", NULL);
17956 if (attrValue != NULL)
17957 xmlFree(attrValue);
17958 return (-1);
17959 }
17960 if ((elemDecl->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017961 /*
17962 * cvc-elt (3.3.4) : 3.1
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017963 */
17964 xmlSchemaVCustomErr(ctxt,
17965 XML_SCHEMAV_CVC_ELT_3_1,
17966 elem, NULL,
17967 "The element is not 'nillable'", NULL);
17968 } else {
17969 if (xmlStrEqual(BAD_CAST attrValue, BAD_CAST "true") ||
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017970 xmlStrEqual(BAD_CAST attrValue, BAD_CAST "1")) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017971 ret = 0;
17972 /*
17973 * cvc-elt (3.3.4) : 3.2.1
17974 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017975 elemHasContent = xmlSchemaHasElemOrCharContent(elem);
17976 if (elemHasContent == 1) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017977 xmlSchemaVCustomErr(ctxt,
17978 XML_SCHEMAV_CVC_ELT_3_2_1,
17979 /* XML_SCHEMAS_ERR_NOTEMPTY, */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017980 elem, (xmlSchemaTypePtr) elemDecl,
17981 "The 'nilled' element must have no character or "
17982 "element content", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017983 ret = XML_SCHEMAV_CVC_ELT_3_2_1;
17984 }
17985 /*
17986 * cvc-elt (3.3.4) : 3.2.2
17987 */
17988 if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) &&
17989 (elemDecl->value != NULL)) {
17990 xmlSchemaVCustomErr(ctxt, XML_SCHEMAV_CVC_ELT_3_2_2,
17991 /* XML_SCHEMAS_ERR_HAVEDEFAULT, */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017992 elem, (xmlSchemaTypePtr) elemDecl,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017993 "There is a fixed value constraint defined for "
17994 "the 'nilled' element", NULL);
17995 ret = XML_SCHEMAV_CVC_ELT_3_2_2;
17996 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017997 if (ret == 0)
17998 nilled = 1;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017999 }
18000 }
18001 if (attrValue != NULL)
18002 xmlFree(attrValue);
18003 }
18004
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018005
18006 actualType = elemDecl->subtypes;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018007 /*
18008 * cvc-elt (3.3.4) : 4
18009 * Handle 'xsi:type'.
18010 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018011
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018012 attr = xmlHasNsProp(elem, BAD_CAST "type", xmlSchemaInstanceNs);
18013 if (attr != NULL) {
18014 xmlChar *nsName = NULL, *local = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018015
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018016 /*
18017 * TODO: We should report a *warning* that the type was overriden
18018 * by the instance.
18019 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018020
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018021 /*
18022 * cvc-elt (3.3.4) : 4.1
18023 */
18024 attrValue = xmlNodeGetContent((xmlNodePtr) attr);
18025 ret = xmlSchemaValQNameAcquire(attrValue, attr->parent,
18026 &nsName, &local);
18027 if (ret < 0) {
18028 xmlSchemaVCustomErr(ctxt,
18029 XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018030 (xmlNodePtr) attr, (xmlSchemaTypePtr) elemDecl,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018031 "Internal error: xmlSchemaValidateElementByDeclaration, "
18032 "validating the attribute 'xsi:type'", NULL);;
18033 FREE_AND_NULL(attrValue)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018034 FREE_AND_NULL(nsName)
18035 FREE_AND_NULL(local)
18036 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018037 } else if (ret == 1) {
18038 xmlSchemaVSimpleTypeErr(ctxt,
18039 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1,
18040 (xmlNodePtr) attr, attrValue,
18041 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME));
18042 } else if (ret == 2) {
18043 xmlSchemaVCustomErr(ctxt,
18044 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1,
18045 (xmlNodePtr) attr,
18046 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
18047 "The QName value '%s' has no "
18048 "corresponding namespace declaration in scope",
18049 attrValue);
18050 } else {
18051 /*
18052 * cvc-elt (3.3.4) : 4.2
18053 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018054 actualType = xmlSchemaGetType(ctxt->schema, local, nsName);
18055 if (actualType == NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018056 xmlChar *strA = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018057
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018058 xmlSchemaVCustomErr(ctxt,
18059 XML_SCHEMAV_CVC_ELT_4_2,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018060 (xmlNodePtr) attr,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018061 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
18062 "The value %s does not resolve to a type "
18063 "definition",
18064 xmlSchemaFormatNsUriLocal(&strA, nsName, local));
18065 FREE_AND_NULL(strA);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018066 } else {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018067 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018068 * URGENT TODO: cvc-elt (3.3.4) : 4.3 (Type Derivation OK)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018069 */
18070 }
18071 }
18072 FREE_AND_NULL(attrValue)
18073 FREE_AND_NULL(nsName)
18074 FREE_AND_NULL(local)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018075 }
18076 /* TODO: Change the handling of missing types according to
18077 * the spec.
18078 */
18079 if (actualType == NULL) {
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000018080 xmlSchemaVCustomErr(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018081 XML_SCHEMAV_CVC_TYPE_1,
18082 elem, (xmlSchemaTypePtr) elemDecl,
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000018083 "The type definition is absent", NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018084 /*
18085 * Evaluate IDCs even if an error occured.
18086 */
18087#ifdef IDC_ENABLED
18088 if (xmlSchemaXPathEvaluate(ctxt, ctxt->elemInfo->namespaceName,
18089 ctxt->elemInfo->localName, XML_ELEMENT_NODE) == -1)
18090 return (-1);
18091#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018092 return (XML_SCHEMAV_CVC_TYPE_1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018093 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018094
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018095 /*
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000018096 * Remember the actual-type definition.
18097 */
18098#ifdef ELEM_INFO_ENABLED
18099 ctxt->elemInfo->typeDef = actualType;
18100#endif
18101
18102 /*
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018103 * TODO: Since this should be already checked by the content model automaton,
18104 * and we want to get rid of the XML_SCHEMAS_ERR... types, the error code
18105 * has been changed to XML_SCHEMAV_INTERNAL.
18106 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018107 /*
Daniel Veillard4255d502002-04-16 15:50:10 +000018108 if (child == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000018109 if (decl->minOccurs > 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018110 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018111 XML_SCHEMAS_ERR_MISSING,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018112 "Element %s: missing child %s\n",
18113 node->name, decl->name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018114 }
18115 return (ctxt->err);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018116 }
18117 */
Daniel Veillard4255d502002-04-16 15:50:10 +000018118 /*
18119 * Verify the element matches
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018120 * TODO, FIXME: Can this still happen here? Isn't this already checked
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018121 * by the content model automaton?
Daniel Veillardc0826a72004-08-10 14:17:33 +000018122 if (!xmlStrEqual(child->name, decl->name)) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018123 xmlSchemaVErr3(ctxt, node, XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018124 XML_SCHEMAS_ERR_WRONGELEM,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018125 "Element %s: missing child %s found %s\n",
18126 node->name, decl->name, child->name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018127 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000018128 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018129 */
18130 if (elemHasContent == -1)
18131 elemHasContent = xmlSchemaHasElemOrCharContent(elem);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018132
18133 /*
18134 * IDC: Register identity-constraint XPath matchers.
18135 */
18136#ifdef IDC_ENABLED
18137 if (elemDecl->idcs != NULL)
18138 xmlSchemaIDCRegisterMatchers(ctxt, elemDecl);
18139 /*
18140 * Evaluate IDCs.
18141 */
18142 if (xmlSchemaXPathEvaluate(ctxt, ctxt->elemInfo->namespaceName,
18143 ctxt->elemInfo->localName, XML_ELEMENT_NODE) == -1)
18144 return (-1);
18145#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018146 /*
18147 * cvc-elt (3.3.4) : 5
18148 * The appropriate case among the following must be true:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018149 */
Daniel Veillard4255d502002-04-16 15:50:10 +000018150 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018151 * cvc-elt (3.3.4) : 5.1
18152 * If the declaration has a {value constraint},
18153 * the item has neither element nor character [children] and
18154 * clause 3.2 has not applied, then all of the following must be true:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018155 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018156 if ((elemHasContent == 0) && (nilled == 0) && (elemDecl->value != NULL)) {
18157 /*
18158 * cvc-elt (3.3.4) : 5.1.1
18159 * If the ·actual type definition· is a ·local type definition·
18160 * then the canonical lexical representation of the {value constraint}
18161 * value must be a valid default for the ·actual type definition· as
18162 * defined in Element Default Valid (Immediate) (§3.3.6).
18163 */
18164 /*
18165 * NOTE: 'local' above means types aquired by xsi:type.
18166 */
18167 ret = 0;
18168 if (actualType != elemDecl->subtypes) {
18169 xmlSchemaCreatePCtxtOnVCtxt(ctxt);
18170 ret = xmlSchemaCheckCOSValidDefault(ctxt->pctxt, ctxt, actualType,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000018171 elemDecl->value, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018172 if (ret < 0) {
18173 xmlSchemaVCustomErr(ctxt,
18174 XML_SCHEMAV_INTERNAL,
18175 elem, actualType,
18176 "Internal error: xmlSchemaValidateElementByDeclaration, "
18177 "validating a default value", NULL);
18178 return (-1);
18179 }
18180 }
18181 /*
18182 * cvc-elt (3.3.4) : 5.1.2
18183 * The element information item with the canonical lexical
18184 * representation of the {value constraint} value used as its
18185 * ·normalized value· must be ·valid· with respect to the
18186 * ·actual type definition· as defined by Element Locally Valid (Type)
18187 * (§3.3.4).
18188 */
18189 /*
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000018190 * Disable validation of the simple content, if it was already
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018191 * done above.
18192 */
18193 if (ret == 0) {
18194 if (actualType != elemDecl->subtypes)
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000018195 ret = xmlSchemaValidateElementByType(ctxt, actualType, 0, 0);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018196 else
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000018197 ret = xmlSchemaValidateElementByType(ctxt, actualType, 0, 1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018198 ctxt->node = elem;
18199 if (ret < 0) {
18200 xmlSchemaVCustomErr(ctxt,
18201 XML_SCHEMAV_INTERNAL,
18202 elem, actualType,
18203 "Internal error: xmlSchemaValidateElementByDeclaration, "
18204 "validating against the type", NULL);
18205 return (-1);
18206 }
18207 /*
18208 * PSVI: Create a text node on the instance element.
18209 */
18210 if (ctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) {
18211 xmlNodePtr textChild;
18212
18213 textChild = xmlNewText(elemDecl->value);
18214 if (textChild == NULL) {
18215 xmlSchemaVCustomErr(ctxt,
18216 XML_SCHEMAV_INTERNAL,
18217 elem, actualType,
18218 "Internal error: xmlSchemaValidateElementByDeclaration, "
18219 "could not create a default text node for the instance",
18220 NULL);
18221 } else
18222 xmlAddChild(elem, textChild);
18223 }
18224 }
18225
18226 } else {
18227 /*
18228 * 5.2.1 The element information item must be ·valid· with respect
18229 * to the ·actual type definition· as defined by Element Locally
18230 * Valid (Type) (§3.3.4).
18231 */
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000018232 ret = xmlSchemaValidateElementByType(ctxt, actualType, nilled, 1);
18233 /*
18234 * Consume the computed value for IDCs, ect. Note that default
18235 * values are not supported yet.
18236 */
18237#ifdef ELEM_INFO_ENABLED
18238 if (ctxt->value != NULL) {
18239 ctxt->elemInfo->value = ctxt->value;
18240 ctxt->value = NULL;
18241 }
18242#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018243 ctxt->node = elem;
18244 if (ret < 0) {
18245 xmlSchemaVCustomErr(ctxt,
18246 XML_SCHEMAV_INTERNAL,
18247 elem, actualType,
18248 "Internal error: xmlSchemaValidateElementByDeclaration, "
18249 "validating a default value", NULL);
18250 return (-1);
18251 }
18252 /*
18253 * 5.2.2 If there is a fixed {value constraint} and clause 3.2 has
18254 * not applied, all of the following must be true:
18255 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018256 if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) && (nilled == 0)) {
18257 /*
18258 * 5.2.2.1 The element information item must have no element
18259 * information item [children].
18260 *
18261 * TODO REDUNDANT: If the actual type exists, the above call to
18262 * xmlSchemaValidateElementByType will already check for element
18263 * nodes.
18264 */
18265 if (xmlSchemaHasElemContent(elem)) {
18266 xmlSchemaVCustomErr(ctxt,
18267 XML_SCHEMAV_CVC_ELT_5_2_2_1,
18268 elem, (xmlSchemaTypePtr) elemDecl,
18269 "Elements in the content are not allowed if it is "
18270 "constrained by a fixed value", NULL);
18271 } else {
18272 /*
18273 * 5.2.2.2 The appropriate case among the following must
18274 * be true:
18275 */
18276
18277 if (actualType->contentType == XML_SCHEMA_CONTENT_MIXED) {
18278 xmlChar *value;
18279 /*
18280 * 5.2.2.2.1 If the {content type} of the ·actual type
18281 * definition· is mixed, then the *initial value* of the
18282 * item must match the canonical lexical representation
18283 * of the {value constraint} value.
18284 *
18285 * ... the *initial value* of an element information
18286 * item is the string composed of, in order, the
18287 * [character code] of each character information item in
18288 * the [children] of that element information item.
18289 */
18290 value = xmlNodeListGetString(elem->doc, elem->children, 1);
18291 if (! xmlStrEqual(BAD_CAST value, elemDecl->value)) {
18292 /*
18293 * TODO: Report invalid & expected values as well.
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000018294 * TODO: Implement the canonical stuff.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018295 */
18296 xmlSchemaVCustomErr(ctxt,
18297 XML_SCHEMAV_CVC_ELT_5_2_2_2_1,
18298 elem, (xmlSchemaTypePtr) elemDecl,
18299 "The value does not match the cononical "
18300 "lexical representation of the fixed constraint",
18301 NULL);
18302 }
18303 if (value != NULL)
18304 xmlFree(value);
18305 } else if ((actualType->contentType ==
18306 XML_SCHEMA_CONTENT_SIMPLE) ||
18307 (actualType->contentType == XML_SCHEMA_CONTENT_BASIC)) {
18308 xmlChar *value;
18309
18310 /*
18311 * 5.2.2.2.2 If the {content type} of the ·actual type
18312 * definition· is a simple type definition, then the
18313 * *actual value* of the item must match the canonical
18314 * lexical representation of the {value constraint} value.
18315 */
18316 /*
18317 * TODO: *actual value* is the normalized value, impl. this.
18318 * TODO: Report invalid & expected values as well.
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000018319 * TODO: Implement the canonical stuff.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018320 *
18321 */
18322 value = xmlNodeListGetString(elem->doc, elem->children, 1);
18323 if (! xmlStrEqual(BAD_CAST value, elemDecl->value)) {
18324 xmlSchemaVCustomErr(ctxt,
18325 XML_SCHEMAV_CVC_ELT_5_2_2_2_2,
18326 elem, (xmlSchemaTypePtr) elemDecl,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000018327 "The normalized value does not match the canonical "
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018328 "lexical representation of the fixed constraint",
18329 NULL);
18330 }
18331 if (value != NULL)
18332 xmlFree(value);
18333
18334 }
18335 /*
18336 * TODO: What if the content type is not 'mixed' or simple?
18337 */
18338
18339 }
18340
18341 }
18342 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018343 /*
18344 * TODO: 7 If the element information item is the ·validation root·, it must be
18345 * ·valid· per Validation Root Valid (ID/IDREF) (§3.3.4).
18346 */
18347
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018348 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000018349}
18350
Daniel Veillard4255d502002-04-16 15:50:10 +000018351/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018352 * xmlSchemaValidateElementByWildcardInternal:
Daniel Veillardc0826a72004-08-10 14:17:33 +000018353 * @ctxt: a schema validation context
18354 * @node: the top node.
18355 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018356 * Represents the recursive portion of xmlSchemaValidateElementByWildcard.
18357 * Not intended to be used by other functions.
Daniel Veillardc0826a72004-08-10 14:17:33 +000018358 *
18359 * Returns 0 if the element is valid, a positive error code
18360 * number otherwise and -1 in case of an internal error.
18361 */
18362static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018363xmlSchemaValidateElementByWildcardInternal(xmlSchemaValidCtxtPtr ctxt,
18364 xmlSchemaWildcardPtr wild,
18365 xmlNodePtr node)
Daniel Veillardc0826a72004-08-10 14:17:33 +000018366{
18367 const xmlChar *uri;
18368 int ret = 0;
18369 xmlNodePtr child;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018370
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018371 if (ctxt->xsiAssemble) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018372 ret = xmlSchemaAssembleByXSIElem(ctxt, ctxt->node);
18373 if (ret == -1) {
18374 xmlSchemaVCustomErr(ctxt,
18375 XML_SCHEMAV_INTERNAL,
18376 ctxt->node, NULL,
18377 "Internal error: xmlSchemaValidateElement, "
18378 "assembling schema by xsi", NULL);
18379 return (-1);
18380 }
18381 /*
18382 * NOTE: We won't react on schema parser errors here.
18383 * TODO: But a warning would be nice.
18384 */
18385 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000018386 if (wild->processContents != XML_SCHEMAS_ANY_SKIP) {
18387 xmlSchemaElementPtr decl = NULL;
18388
18389 if (node->ns != NULL)
18390 decl = xmlHashLookup3(ctxt->schema->elemDecl,
18391 node->name, node->ns->href, NULL);
18392 else
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018393 decl = xmlHashLookup3(ctxt->schema->elemDecl, node->name,
18394 NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +000018395 if (decl != NULL) {
18396 ctxt->node = node;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018397 ret = xmlSchemaValidateElementByDeclaration(ctxt, decl);
Daniel Veillardc0826a72004-08-10 14:17:33 +000018398 if (ret < 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018399 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000018400 "Internal error: xmlSchemaValidateAnyInternal, "
18401 "validating an element in the context of a wildcard.",
18402 NULL, NULL);
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +000018403 }
18404 return (ret);
Daniel Veillardc0826a72004-08-10 14:17:33 +000018405 } else if (wild->processContents == XML_SCHEMAS_ANY_STRICT) {
18406 /* TODO: Change to proper error code. */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018407 xmlSchemaVWildcardErr(ctxt, XML_SCHEMAV_CVC_ELT_1,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018408 node, wild, "No matching global declaration available");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018409 /*
18410 * Evaluate IDCs even if a validation error occured.
18411 */
18412#ifdef IDC_ENABLED
18413 if (xmlSchemaXPathEvaluate(ctxt, ctxt->elemInfo->namespaceName,
18414 ctxt->elemInfo->localName, XML_ELEMENT_NODE) == -1)
18415 return(-1);
18416#endif
Daniel Veillardc0826a72004-08-10 14:17:33 +000018417 return (ctxt->err);
18418 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018419 /*
18420 * Evaluate IDCs; we need to know if an IDC field resolves to
18421 * such a node. This node has no type definition and will
18422 * definitely result in an IDC validation error if an IDC field
18423 * resolves.
18424 */
18425#ifdef IDC_ENABLED
18426 if (xmlSchemaXPathEvaluate(ctxt, ctxt->elemInfo->namespaceName,
18427 ctxt->elemInfo->localName, XML_ELEMENT_NODE) == -1)
18428 return(-1);
18429#endif
Daniel Veillardc0826a72004-08-10 14:17:33 +000018430 }
18431 if (node->children != NULL) {
18432 child = node->children;
18433 do {
18434 if (child->type == XML_ELEMENT_NODE) {
18435 if (child->ns != NULL)
18436 uri = child->ns->href;
18437 else
18438 uri = NULL;
18439 if (xmlSchemaMatchesWildcardNs(wild, uri) == 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018440 /* TODO: error code. */
18441 xmlSchemaVWildcardErr(ctxt, XML_SCHEMAV_ELEMENT_CONTENT,
Daniel Veillardc0826a72004-08-10 14:17:33 +000018442 child, wild,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018443 "The namespace of the element is not allowed");
Daniel Veillardc0826a72004-08-10 14:17:33 +000018444 return (ctxt->err);
18445 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018446#ifdef ELEM_INFO_ENABLED
18447 ctxt->node = child;
18448 xmlSchemaBeginElement(ctxt);
18449#endif
18450 /*
18451 * Recurse over the children.
18452 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018453 ret = xmlSchemaValidateElementByWildcardInternal(ctxt,
18454 wild, child);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018455#ifdef ELEM_INFO_ENABLED
18456 xmlSchemaEndElement(ctxt);
18457#endif
Daniel Veillardc0826a72004-08-10 14:17:33 +000018458 if (ret != 0)
18459 return (ret);
18460 }
18461 child = child->next;
18462 } while (child != NULL);
18463 }
18464 return (0);
18465}
18466
18467/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018468 * xmlSchemaValidateElementContByWildcard:
Daniel Veillardc0826a72004-08-10 14:17:33 +000018469 * @ctxt: a schema validation context
18470 *
18471 * Returns 0 if the element is valid, a positive error code
18472 * number otherwise and -1 in case of an internal or API error.
18473 */
18474static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018475xmlSchemaValidateElementByWildcard(xmlSchemaValidCtxtPtr ctxt,
18476 xmlSchemaTypePtr type)
Daniel Veillardc0826a72004-08-10 14:17:33 +000018477{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018478 if ((type == NULL) || (type->type != XML_SCHEMA_TYPE_ANY) ||
18479 (ctxt->node == NULL)) {
18480 xmlSchemaVCustomErr(ctxt,
18481 XML_SCHEMAV_INTERNAL, ctxt->node, NULL,
18482 "Internal error: xmlSchemaValidateElementByWildcard, "
18483 "bad arguments", NULL);
18484 return (-1);
18485 }
18486 return(xmlSchemaValidateElementByWildcardInternal(ctxt,
18487 type->attributeWildcard, ctxt->node));
Daniel Veillardc0826a72004-08-10 14:17:33 +000018488}
18489
18490/**
William M. Brack2f2a6632004-08-20 23:09:47 +000018491 * xmlSchemaValidateAnyTypeContent:
18492 * @ctxt: a schema validation context
18493 * @node: the current element
18494 *
18495 * This one validates the content of an element of the type
18496 * 'anyType'. The process contents of the wildcard of 'anyType' is "lax",
18497 * thus elements in the subtree will be validated, if a corresponding
18498 * declaration in the schema exists.
18499 *
18500 * Returns 0 if the element and its subtree is valid, a positive error code
18501 * otherwise and -1 in case of an internal or API error.
18502 */
18503static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018504xmlSchemaValidateElementByAnyType(xmlSchemaValidCtxtPtr ctxt,
18505 xmlSchemaTypePtr type)
William M. Brack2f2a6632004-08-20 23:09:47 +000018506{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018507 xmlSchemaTypePtr oldtype;
18508 xmlNodePtr top, cur;
18509 xmlSchemaElementPtr decl;
William M. Brack2f2a6632004-08-20 23:09:47 +000018510 int skipContent, ret;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018511
18512 if ((type == NULL) || (ctxt->node == NULL))
18513 return (-1);
18514
18515 if (ctxt->node->children == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +000018516 return (0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018517
18518 oldtype = ctxt->type;
18519 top = ctxt->node;
18520 /*
18521 * STREAM: Child nodes are processed.
18522 */
18523 cur = ctxt->node->children;
18524 while (cur != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +000018525 skipContent = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018526 if (cur->type == XML_ELEMENT_NODE) {
William M. Brack2f2a6632004-08-20 23:09:47 +000018527 /*
18528 * The process contents of the wildcard is "lax", thus
18529 * we need to validate the element if a declaration
18530 * exists.
18531 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018532 if (cur->ns != NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +000018533 decl = xmlHashLookup3(ctxt->schema->elemDecl,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018534 cur->name, cur->ns->href, NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +000018535 else
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018536 decl = xmlHashLookup3(ctxt->schema->elemDecl, cur->name, NULL, NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +000018537 if (decl != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018538 ctxt->node = cur;
18539 ret = xmlSchemaValidateElementByDeclaration(ctxt, decl);
18540 ctxt->node = top;
William M. Brack2f2a6632004-08-20 23:09:47 +000018541 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018542 xmlSchemaVErr(ctxt, cur, XML_SCHEMAV_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000018543 "Internal error: xmlSchemaValidateAnyTypeContent, "
18544 "validating an element in the context of a wildcard.",
18545 NULL, NULL);
18546 return (ret);
18547 } else if (ret > 0)
18548 return (ret);
18549 skipContent = 1;
18550 }
18551 }
18552 /*
18553 * Browse the full subtree, deep first.
18554 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018555 if ((skipContent == 0) && (cur->children != NULL)) {
William M. Brack2f2a6632004-08-20 23:09:47 +000018556 /* deep first */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018557 cur = cur->children;
18558 } else if ((cur != top) && (cur->next != NULL)) {
William M. Brack2f2a6632004-08-20 23:09:47 +000018559 /* then siblings */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018560 cur = cur->next;
18561 } else if (cur != top) {
William M. Brack2f2a6632004-08-20 23:09:47 +000018562 /* go up to parents->next if needed */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018563 while (cur != top) {
18564 if (cur->parent != NULL)
18565 cur = cur->parent;
18566 if ((cur != top) && (cur->next != NULL)) {
18567 cur = cur->next;
William M. Brack2f2a6632004-08-20 23:09:47 +000018568 break;
18569 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018570 if (cur->parent == NULL) {
18571 cur = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +000018572 break;
18573 }
18574 }
18575 /* exit condition */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018576 if (cur == top)
18577 cur = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +000018578 } else
18579 break;
18580 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018581 ctxt->type = oldtype;
William M. Brack2f2a6632004-08-20 23:09:47 +000018582 return (0);
18583}
18584
18585/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018586 * xmlSchemaValidateElementByComplexType:
Daniel Veillard4255d502002-04-16 15:50:10 +000018587 * @ctxt: a schema validation context
18588 * @node: the top node.
18589 *
18590 * Validate the content of an element expected to be a complex type type
18591 * xmlschema-1.html#cvc-complex-type
18592 * Validation Rule: Element Locally Valid (Complex Type)
18593 *
18594 * Returns 0 if the element is schemas valid, a positive error code
Daniel Veillard01fa6152004-06-29 17:04:39 +000018595 * number otherwise and -1 in case of internal or API error.
18596 * Note on reported errors: Although it might be nice to report
18597 * the name of the simple/complex type, used to validate the content
18598 * of a node, it is quite unnecessary: for global defined types
18599 * the local name of the element is equal to the NCName of the type,
18600 * for local defined types it makes no sense to output the internal
18601 * computed name of the type. TODO: Instead, one should attach the
18602 * struct of the type involved to the error handler - this allows
18603 * the report of any additional information by the user.
Daniel Veillard4255d502002-04-16 15:50:10 +000018604 */
18605static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018606xmlSchemaValidateElementByComplexType(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018607 xmlSchemaTypePtr type,
18608 int valSimpleContent)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018609{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018610 xmlSchemaTypePtr oldtype;
18611 xmlNodePtr elem, child;
Daniel Veillard01fa6152004-06-29 17:04:39 +000018612 int ret = 0;
William M. Brack2f2a6632004-08-20 23:09:47 +000018613 const xmlChar *nsUri;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018614 xmlSchemaAttrStatePtr attrs = NULL, attrTop = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000018615
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018616 if ((ctxt == NULL) || (type->type != XML_SCHEMA_TYPE_COMPLEX))
18617 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000018618
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018619 oldtype = ctxt->type;
18620 ctxt->type = type;
18621 elem = ctxt->node;
18622
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018623 /*
18624 * Verify the attributes
18625 */
18626 /*
18627 * TODO: This "attrTop" thing is not needed any more.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018628 */
18629 /* NOTE: removed, since a check for abstract is
18630 * done in the cvc-type constraint.
18631 *
18632 *
18633 * if (type->flags & XML_SCHEMAS_TYPE_ABSTRACT) {
18634 * xmlSchemaVComplexTypeErr(ctxt,
18635 * XML_SCHEMAV_CVC_COMPLEX_TYPE_1,
18636 * elem, type,
18637 * "The type definition is abstract");
18638 * return (XML_SCHEMAV_CVC_COMPLEX_TYPE_1);
18639 *}
18640 */
18641
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018642 attrs = ctxt->attr;
18643 attrTop = ctxt->attrTop;
18644 /*
18645 * STREAM: Attribute nodes are processed.
18646 */
18647 xmlSchemaRegisterAttributes(ctxt, elem->properties);
18648 xmlSchemaValidateAttributes(ctxt, elem, type);
18649 if (ctxt->attr != NULL)
18650 xmlSchemaFreeAttributeStates(ctxt->attr);
18651 ctxt->attr = attrs;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018652 ctxt->attrTop = attrTop;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018653
18654 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018655 * TODO: This one creates a regexp even if no content
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018656 * model was defined. Somehow ->contModel is always not NULL
18657 * for complex types, even if they are empty.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018658 * TODO: Check if the obove still occurs.
18659 */
Daniel Veillard4255d502002-04-16 15:50:10 +000018660 switch (type->contentType) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000018661 case XML_SCHEMA_CONTENT_EMPTY: {
18662 /*
18663 * 1 If the {content type} is empty, then the element information
18664 * item has no character or element information item [children].
Daniel Veillard3646d642004-06-02 19:19:14 +000018665 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000018666 /*
18667 * TODO: Is the entity stuff correct?
18668 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018669 if (xmlSchemaHasElemOrCharContent(elem) == 1) {
William M. Brack2f2a6632004-08-20 23:09:47 +000018670 xmlSchemaVComplexTypeErr(ctxt,
18671 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018672 elem, type,
William M. Brack2f2a6632004-08-20 23:09:47 +000018673 "Character or element content is not allowed, "
18674 "because the content type is empty");
Daniel Veillard01fa6152004-06-29 17:04:39 +000018675 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018676 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +000018677 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018678 case XML_SCHEMA_CONTENT_MIXED:
18679 if ((type->subtypes == NULL) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018680 (type->baseType->builtInType == XML_SCHEMAS_ANYTYPE)) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018681 /*
18682 * The type has 'anyType' as its base and no content model
18683 * is defined -> use 'anyType' as the type to validate
18684 * against.
18685 */
18686 ret = xmlSchemaValidateElementByAnyType(ctxt, type->baseType);
18687 /* TODO: Handle -1. */
18688 break;
18689 }
18690 /* No break on purpose. */
Daniel Veillard01fa6152004-06-29 17:04:39 +000018691 case XML_SCHEMA_CONTENT_ELEMENTS:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018692 {
18693 xmlRegExecCtxtPtr oldregexp = NULL;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000018694 xmlChar *values[10];
18695 int terminal, nbval = 10, nbneg;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018696
18697 /*
18698 * Content model check initialization.
18699 */
18700 if (type->contModel != NULL) {
18701 oldregexp = ctxt->regexp;
18702 ctxt->regexp = xmlRegNewExecCtxt(type->contModel,
18703 (xmlRegExecCallbacks)
18704 xmlSchemaValidateCallback, ctxt);
18705#ifdef DEBUG_AUTOMATA
18706 xmlGenericError(xmlGenericErrorContext, "====> %s\n", elem->name);
18707#endif
18708 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018709 /*
18710 * STREAM: Children are processed.
18711 */
18712 child = elem->children;
Daniel Veillard01fa6152004-06-29 17:04:39 +000018713 while (child != NULL) {
18714 if (child->type == XML_ELEMENT_NODE) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000018715 if (child->ns != NULL)
18716 nsUri = child->ns->href;
18717 else
18718 nsUri = NULL;
18719 ret = xmlRegExecPushString2(ctxt->regexp,
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000018720 child->name, nsUri, child);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018721 /*
18722 * URGENT TODO: Could we anchor an error report
18723 * here to notify of invalid elements?
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000018724 * TODO: Perhaps it would be better to report
18725 * only the first erroneous element and then break.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018726 */
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000018727#ifdef DEBUG_AUTOMATA
Daniel Veillard01fa6152004-06-29 17:04:39 +000018728 if (ret < 0)
18729 xmlGenericError(xmlGenericErrorContext,
18730 " --> %s Error\n", child->name);
William M. Bracke7091952004-05-11 15:09:58 +000018731 else
18732 xmlGenericError(xmlGenericErrorContext,
Daniel Veillard01fa6152004-06-29 17:04:39 +000018733 " --> %s\n", child->name);
18734#endif
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000018735 if (ret < 0) {
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000018736 xmlRegExecErrInfo(ctxt->regexp, NULL, &nbval, &nbneg,
18737 &values[0], &terminal);
18738 xmlSchemaVComplexTypeElemErr(ctxt,
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000018739 XML_SCHEMAV_ELEMENT_CONTENT,
18740 child, NULL/* type */,
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000018741 "This element is not expected",
18742 nbval, nbneg, values);
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000018743 ret = 1;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000018744 /*
18745 * Note that this will skip further validation of the
18746 * content.
18747 */
18748 break;
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000018749 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000018750 } else if ((type->contentType == XML_SCHEMA_CONTENT_ELEMENTS) &&
18751 /*
18752 * TODO: Ask Daniel if this are all character nodes.
18753 */
18754 (((child->type == XML_TEXT_NODE) && (!IS_BLANK_NODE(child))) ||
18755 (child->type == XML_ENTITY_NODE) ||
18756 (child->type == XML_ENTITY_REF_NODE) ||
18757 (child->type == XML_CDATA_SECTION_NODE))) {
18758 /*
18759 * 2.3 If the {content type} is element-only, then the
18760 * element information item has no character information
18761 * item [children] other than those whose [character
18762 * code] is defined as a white space in [XML 1.0 (Second
18763 * Edition)].
18764 */
William M. Brack2f2a6632004-08-20 23:09:47 +000018765 xmlSchemaVComplexTypeErr(ctxt,
18766 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_3,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018767 elem, type,
William M. Brack2f2a6632004-08-20 23:09:47 +000018768 "Character content is not allowed, "
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000018769 "because the content type is element-only");
18770 ret = 1;
Daniel Veillard01fa6152004-06-29 17:04:39 +000018771 break;
18772 }
18773 child = child->next;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018774 }
18775 /*
18776 * Content model check finalization.
18777 */
18778 if (type->contModel != NULL) {
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000018779 if (ret == 0) {
18780 xmlRegExecNextValues(ctxt->regexp, &nbval, &nbneg,
18781 &values[0], &terminal);
18782 if (nbval + nbneg != 0) {
18783 /*
18784 * If a next value still exists, I does not have to
18785 * mean that there's an element missing, since it
18786 * might be an optional element. So double check it.
18787 */
18788 ret = xmlRegExecPushString(ctxt->regexp,
18789 NULL, NULL);
18790 if (ret <= 0) {
18791 ret = 1;
18792 xmlSchemaVComplexTypeElemErr(ctxt,
18793 XML_SCHEMAV_ELEMENT_CONTENT,
18794 elem, type, "Missing child element(s)",
18795 nbval, nbneg, values);
18796 } else
18797 ret = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018798#ifdef DEBUG_AUTOMATA
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000018799 xmlGenericError(xmlGenericErrorContext,
18800 "====> %s : %d\n", elem->name, ret);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018801#endif
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000018802 }
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000018803#ifdef DEBUG_CONTENT
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000018804 if (ret == 0)
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000018805 xmlGenericError(xmlGenericErrorContext,
18806 "Element %s content check succeeded\n",
18807 elem->name);
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000018808#endif
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018809 }
18810 xmlRegFreeExecCtxt(ctxt->regexp);
18811 ctxt->regexp = oldregexp;
18812 }
18813 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000018814 break;
18815 case XML_SCHEMA_CONTENT_SIMPLE:
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018816 case XML_SCHEMA_CONTENT_BASIC:
18817 /*
18818 * If the simple content was already validated
18819 * (e.g. a default value), the content need not
18820 * to be validated again.
18821 */
18822 if (valSimpleContent == 1) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000018823 xmlChar *value = NULL;
18824 /*
18825 * We hit a complexType with a simpleContent resolving
18826 * to a user derived or built-in simple type.
William M. Brack2f2a6632004-08-20 23:09:47 +000018827 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000018828 /*
18829 * 2.2 If the {content type} is a simple type definition,
18830 * then the element information item has no element
18831 * information item [children], and the ·normalized value·
18832 * of the element information item is ·valid· with respect
18833 * to that simple type definition as defined by String
18834 * Valid (§3.14.4).
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018835 */
18836 /*
18837 * STREAM: Children are processed.
18838 */
18839 child = elem->children;
Daniel Veillard01fa6152004-06-29 17:04:39 +000018840 while (child != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018841 /*
18842 * TODO: Could the entity stuff produce elements
18843 * as well?
18844 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000018845 if (child->type == XML_ELEMENT_NODE) {
William M. Brack2f2a6632004-08-20 23:09:47 +000018846 xmlSchemaVComplexTypeErr(ctxt,
18847 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018848 elem, type,
William M. Brack2f2a6632004-08-20 23:09:47 +000018849 "Element content is not allowed, because "
18850 "the content type is a simple type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000018851 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
18852 break;
18853 }
18854 child = child->next;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018855 }
18856 ctxt->node = elem;
18857 ctxt->cur = elem->children;
Daniel Veillard01fa6152004-06-29 17:04:39 +000018858 if (ret == 0) {
18859 /*
18860 * Validate the character content against a simple type.
Daniel Veillard3646d642004-06-02 19:19:14 +000018861 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018862 /*
18863 * STREAM: Children are processed.
18864 */
18865 if (elem->children == NULL)
Daniel Veillard01fa6152004-06-29 17:04:39 +000018866 value = NULL;
18867 else
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018868 value = xmlNodeGetContent(elem);
18869 /*
18870 * URGENT TODO: Should facets for the simple type validation be
18871 * disabled, if the derivation of facets for complex types
18872 * is implemented?
18873 */
18874 /*
18875 * NOTE: This call won't check the correct types of the
18876 * content nodes, since this should be done here.
18877 */
18878 ret = xmlSchemaValidateSimpleTypeValue(ctxt, type, value, 1, 1, 1, 0);
William M. Brack2f2a6632004-08-20 23:09:47 +000018879 if (ret > 0) {
18880 /*
18881 * NOTE: Although an error will be reported by
18882 * xmlSchemaValidateSimpleTypeValue, the spec wants
18883 * a specific complex type error to be reported
18884 * additionally.
18885 */
18886 xmlSchemaVComplexTypeErr(ctxt,
18887 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018888 elem, type,
William M. Brack2f2a6632004-08-20 23:09:47 +000018889 "The character content is not valid");
Daniel Veillard01fa6152004-06-29 17:04:39 +000018890 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
18891 } else if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018892 xmlSchemaVErr(ctxt, elem, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000018893 "Internal error: xmlSchemaValidateComplexType, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000018894 "Element '%s': Error while validating character "
18895 "content against complex type '%s'.\n",
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018896 elem->name, type->name);
18897 if (value != NULL)
18898 xmlFree(value);
18899 ctxt->type = oldtype;
Daniel Veillard01fa6152004-06-29 17:04:39 +000018900 return (-1);
18901 }
William M. Brack2f2a6632004-08-20 23:09:47 +000018902 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000018903 if (ret == 0) {
18904 /*
18905 * Apply facets of the complexType. Be sure to pass the
18906 * built-in type to xmlSchemaValidateFacetsInternal.
18907 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018908 /* URGENT TODO: I don't know yet if the facets of the simple type
Daniel Veillard01fa6152004-06-29 17:04:39 +000018909 * are used, or if the facets, defined by this complex type,
18910 * are to be used only. This here applies both facet sets.
18911 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000018912
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018913 ret = xmlSchemaValidateFacetsInternal(ctxt,
18914 type, value, 0, 1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000018915 if (ret > 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +000018916 xmlSchemaVComplexTypeErr(ctxt,
18917 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018918 elem, type,
William M. Brack2f2a6632004-08-20 23:09:47 +000018919 "The character content is not valid");
Daniel Veillard01fa6152004-06-29 17:04:39 +000018920 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
18921 } else if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018922 xmlSchemaVErr(ctxt, elem, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000018923 "Internal error: xmlSchemaValidateComplexType, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000018924 "Element '%s': Error while validating character "
18925 "content against complex type '%s'; failed to "
Daniel Veillard01fa6152004-06-29 17:04:39 +000018926 "apply facets.\n",
18927 type->name, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018928 if (value != NULL)
18929 xmlFree(value);
18930 ctxt->type = oldtype;
18931 return (-1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000018932 }
18933 }
18934 if (value != NULL)
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000018935 xmlFree(value);
18936
Daniel Veillard01fa6152004-06-29 17:04:39 +000018937 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018938 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018939 default:
18940 TODO xmlGenericError(xmlGenericErrorContext,
18941 "unimplemented content type %d\n",
18942 type->contentType);
Daniel Veillard4255d502002-04-16 15:50:10 +000018943 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018944 ctxt->type = oldtype;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018945 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000018946}
18947
18948/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018949 * xmlSchemaValidateElementByType:
Daniel Veillard4255d502002-04-16 15:50:10 +000018950 * @ctxt: a schema validation context
18951 * @elem: an element
18952 * @type: the list of type declarations
18953 *
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018954 * Validation Rule: Element Locally Valid (Type).
Daniel Veillard4255d502002-04-16 15:50:10 +000018955 *
18956 * Returns 0 if the element is schemas valid, a positive error code
18957 * number otherwise and -1 in case of internal or API error.
18958 */
18959static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018960xmlSchemaValidateElementByType(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018961 xmlSchemaTypePtr type,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000018962 int isNil,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018963 int valSimpleContent)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018964{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018965 int ret;
Daniel Veillard4255d502002-04-16 15:50:10 +000018966
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018967
18968 if ((ctxt == NULL) || (type == NULL)) {
18969 xmlSchemaVCustomErr(ctxt, XML_SCHEMAV_INTERNAL, NULL, NULL,
18970 "Internal error: xmlSchemaValidateElementByType, "
18971 "bad arguments", NULL);
18972 return (-1);
18973 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018974 /*
18975 * This one is called by "xmlSchemaValidateElementByDeclaration".
18976 * It will forward to the proper validation
18977 * procedures for the given type.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018978 */
18979 if (type == NULL) {
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000018980 xmlSchemaVCustomErr(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018981 XML_SCHEMAV_CVC_TYPE_1,
18982 ctxt->node, NULL,
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000018983 "The type definition is absent", NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018984 return (XML_SCHEMAV_CVC_TYPE_1);
18985 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018986
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018987 if (type->flags & XML_SCHEMAS_TYPE_ABSTRACT) {
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000018988 xmlSchemaVCustomErr(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018989 XML_SCHEMAV_CVC_TYPE_2,
18990 ctxt->node, type,
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000018991 "The type definition is abstract", NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018992 return (XML_SCHEMAV_CVC_TYPE_2);
18993 }
18994
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018995 switch (type->type) {
18996 case XML_SCHEMA_TYPE_COMPLEX:
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018997 ret = xmlSchemaValidateElementByComplexType(ctxt, type,
18998 valSimpleContent);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018999 break;
19000 case XML_SCHEMA_TYPE_SIMPLE:
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019001 ret = xmlSchemaValidateElementBySimpleType(ctxt, type,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019002 isNil, valSimpleContent);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019003 break;
19004 case XML_SCHEMA_TYPE_BASIC:
19005 if (type->builtInType == XML_SCHEMAS_ANYTYPE)
19006 ret = xmlSchemaValidateElementByAnyType(ctxt, type);
19007 else
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019008 ret = xmlSchemaValidateElementBySimpleType(ctxt, type,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019009 isNil, valSimpleContent);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019010 break;
19011 default:
19012 ret = -1;
19013 break;
19014 }
19015 if (ret == -1)
19016 return (-1);
19017 else
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019018 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000019019}
19020
19021
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019022static int
19023xmlSchemaCheckAttrLocallyValid(xmlSchemaValidCtxtPtr ctxt,
19024 xmlSchemaAttributePtr decl,
19025 xmlSchemaAttrStatePtr state,
19026 xmlAttrPtr attr)
19027{
19028 xmlChar *value;
19029 const xmlChar *defValue;
19030 xmlSchemaValPtr defVal;
19031 int fixed;
19032 int ret;
19033
19034 if (decl->subtypes == NULL) {
19035 state->state = XML_SCHEMAS_ATTR_TYPE_NOT_RESOLVED;
19036 return (XML_SCHEMAS_ATTR_TYPE_NOT_RESOLVED);
19037 }
19038 value = xmlNodeListGetString(attr->doc, attr->children, 1);
19039 ctxt->node = (xmlNodePtr) attr;
19040 ctxt->cur = attr->children;
19041 /*
19042 * NOTE: This call also checks the content nodes for correct type.
19043 */
19044 ret = xmlSchemaValidateSimpleTypeValue(ctxt, decl->subtypes,
19045 value, 1, 1, 1, 1);
19046
19047 /*
19048 * Handle 'fixed' attributes.
19049 */
19050 if (ret > 0) {
19051 state->state = XML_SCHEMAS_ATTR_INVALID_VALUE;
19052 /*
19053 * NOTE: Fixed value constraints will be not
19054 * applied if the value was invalid, because:
19055 * 1. The validation process does not return a precomputed
19056 * value.
19057 * 2. An invalid value implies a violation of a fixed
19058 * value constraint.
19059 */
19060 } else if (ret == 0) {
19061 state->state = XML_SCHEMAS_ATTR_CHECKED;
19062 if (xmlSchemaGetEffectiveValueConstraint(decl,
19063 &fixed, &defValue, &defVal) && (fixed == 1)) {
19064 /*
19065 * cvc-au : Attribute Locally Valid (Use)
19066 * For an attribute information item to be·valid·
19067 * with respect to an attribute use its ·normalized
19068 * value· must match the canonical lexical representation
19069 * of the attribute use's {value constraint} value, if it
19070 * is present and fixed.
19071 */
19072 /*
19073 * NOTE: the validation context holds in ctxt->value the
19074 * precomputed value of the attribute; well for some types,
19075 * fallback to string comparison if no computed value
19076 * exists.
19077 */
19078 if (((ctxt->value != NULL) &&
19079 (xmlSchemaCompareValues(ctxt->value, defVal) != 0)) ||
19080 ((ctxt->value == NULL) &&
19081 (! xmlStrEqual(defValue, BAD_CAST value)))) {
19082 state->state =
19083 XML_SCHEMAS_ATTR_INVALID_FIXED_VALUE;
19084 }
19085 }
19086 }
19087 if (value != NULL) {
19088 xmlFree(value);
19089 }
19090 return (ret);
19091}
19092
Daniel Veillard4255d502002-04-16 15:50:10 +000019093/**
19094 * xmlSchemaValidateAttributes:
19095 * @ctxt: a schema validation context
19096 * @elem: an element
Daniel Veillard3646d642004-06-02 19:19:14 +000019097 * @type: the complexType holding the attribute uses
Daniel Veillard4255d502002-04-16 15:50:10 +000019098 *
19099 * Validate the attributes of an element.
19100 *
Daniel Veillardc0826a72004-08-10 14:17:33 +000019101 * 1. Existent, invalid attributes are reported in the form
19102 * "prefix:localName".
19103 * Reason: readability - it is easier to find the actual XML
19104 * representation of the attributes QName.
19105 * 2. Missing attributes are reported in the form
19106 * {"URI", "localName"}.
19107 * This is necessary, since the the prefix need not to be declared
19108 * at all, and thus is not computable.
19109 *
Daniel Veillard4255d502002-04-16 15:50:10 +000019110 * Returns 0 if the element is schemas valid, a positive error code
19111 * number otherwise and -1 in case of internal or API error.
19112 */
19113static int
Daniel Veillard3646d642004-06-02 19:19:14 +000019114xmlSchemaValidateAttributes(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem, xmlSchemaTypePtr type)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019115{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019116 const xmlChar *nsURI;
Daniel Veillard3646d642004-06-02 19:19:14 +000019117 int ret;
19118 xmlAttrPtr attr; /* An attribute on the element. */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019119 const xmlChar *defValue;
19120 xmlSchemaValPtr defVal;
19121 int fixed;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019122 xmlSchemaAttributeLinkPtr attrUse = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000019123 xmlSchemaAttributePtr attrDecl;
Daniel Veillardc85d0fe2004-04-16 16:46:51 +000019124 int found;
William M. Brack803812b2004-06-03 02:11:24 +000019125 xmlSchemaAttrStatePtr curState, reqAttrStates = NULL, reqAttrStatesTop = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019126 xmlSchemaAttrStatePtr defAttrStates = NULL, defAttrStatesTop = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019127 xmlNodePtr oldnode;
Daniel Veillard3646d642004-06-02 19:19:14 +000019128#ifdef DEBUG_ATTR_VALIDATION
19129 int redundant = 0;
19130#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000019131
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019132
Daniel Veillardc0826a72004-08-10 14:17:33 +000019133 /*
19134 * Allow all attributes if the type is anyType.
19135 */
19136 if (type == xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE))
19137 return (0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019138
19139 oldnode = ctxt->node;
19140 if (type != NULL)
19141 attrUse = type->attributeUses;
Daniel Veillard3646d642004-06-02 19:19:14 +000019142 while (attrUse != NULL) {
Daniel Veillardc85d0fe2004-04-16 16:46:51 +000019143 found = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000019144 attrDecl = attrUse->attr;
19145#ifdef DEBUG_ATTR_VALIDATION
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019146 printf("attr use - name: %s\n", xmlSchemaGetAttrName(attrDecl));
Daniel Veillard3646d642004-06-02 19:19:14 +000019147 printf("attr use - use: %d\n", attrDecl->occurs);
19148#endif
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019149 for (curState = ctxt->attr; curState != NULL; curState = curState->next) {
Daniel Veillard3646d642004-06-02 19:19:14 +000019150
19151 if (curState->decl == attrUse->attr) {
19152#ifdef DEBUG_ATTR_VALIDATION
19153 redundant = 1;
19154#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019155 }
Daniel Veillard3646d642004-06-02 19:19:14 +000019156 attr = curState->attr;
19157#ifdef DEBUG_ATTR_VALIDATION
19158 printf("attr - name: %s\n", attr->name);
19159 if (attr->ns != NULL)
19160 printf("attr - ns: %s\n", attr->ns->href);
19161 else
19162 printf("attr - ns: none\n");
19163#endif
19164 /* TODO: Can this ever happen? */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019165 if (attr == NULL)
19166 continue;
Daniel Veillard3646d642004-06-02 19:19:14 +000019167 if (attrDecl->ref != NULL) {
19168 if (!xmlStrEqual(attr->name, attrDecl->ref))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019169 continue;
19170 if (attr->ns != NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +000019171 if ((attrDecl->refNs == NULL) ||
19172 (!xmlStrEqual(attr->ns->href, attrDecl->refNs)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019173 continue;
Daniel Veillard3646d642004-06-02 19:19:14 +000019174 } else if (attrDecl->refNs != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019175 continue;
19176 }
19177 } else {
Daniel Veillard3646d642004-06-02 19:19:14 +000019178 if (!xmlStrEqual(attr->name, attrDecl->name))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019179 continue;
19180 /*
Daniel Veillardbe9c6322003-11-22 20:37:51 +000019181 * handle the namespaces checks here
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019182 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +000019183 if (attr->ns == NULL) {
19184 /*
William M. Bracke7091952004-05-11 15:09:58 +000019185 * accept an unqualified attribute only if the target
19186 * namespace of the declaration is absent.
Daniel Veillardbe9c6322003-11-22 20:37:51 +000019187 */
Daniel Veillard3646d642004-06-02 19:19:14 +000019188 if (attrDecl->targetNamespace != NULL)
William M. Bracke7091952004-05-11 15:09:58 +000019189 /*
19190 * This check was removed, since the target namespace
19191 * was evaluated during parsing and already took
19192 * "attributeFormDefault" into account.
19193 */
19194 /* ((attributes->flags & XML_SCHEMAS_ATTR_NSDEFAULT) == 0)) */
Daniel Veillardbe9c6322003-11-22 20:37:51 +000019195 continue;
19196 } else {
Daniel Veillard3646d642004-06-02 19:19:14 +000019197 if (attrDecl->targetNamespace == NULL)
Daniel Veillardbe9c6322003-11-22 20:37:51 +000019198 continue;
Daniel Veillard3646d642004-06-02 19:19:14 +000019199 if (!xmlStrEqual(attrDecl->targetNamespace,
Daniel Veillardbe9c6322003-11-22 20:37:51 +000019200 attr->ns->href))
19201 continue;
19202 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019203 }
Daniel Veillard3646d642004-06-02 19:19:14 +000019204#ifdef DEBUG_ATTR_VALIDATION
19205 printf("found\n");
19206#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019207 found = 1;
Daniel Veillard3646d642004-06-02 19:19:14 +000019208 curState->decl = attrDecl;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019209 curState->state = XML_SCHEMAS_ATTR_VALIDATE_VALUE;
19210 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019211 ret = xmlSchemaCheckAttrLocallyValid(ctxt, attrDecl, curState, attr);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019212 */
Daniel Veillard3646d642004-06-02 19:19:14 +000019213 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019214 if (!found) {
19215 if (attrDecl->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED) {
19216 xmlSchemaAttrStatePtr tmp;
19217
Daniel Veillard3646d642004-06-02 19:19:14 +000019218#ifdef DEBUG_ATTR_VALIDATION
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019219 printf("required attr not found\n");
Daniel Veillard3646d642004-06-02 19:19:14 +000019220#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019221 /*
19222 * Add a new dummy attribute state.
19223 */
19224 tmp = (xmlSchemaAttrStatePtr) xmlMalloc(sizeof(xmlSchemaAttrState));
19225 if (tmp == NULL) {
19226 xmlSchemaVErrMemory(ctxt, "registering required attributes", NULL);
19227 ctxt->node = oldnode;
19228 return (-1);
19229 }
19230 tmp->attr = NULL;
19231 tmp->state = XML_SCHEMAS_ATTR_MISSING;
19232 tmp->decl = attrDecl;
19233 tmp->next = NULL;
19234
19235 if (reqAttrStates == NULL) {
19236 reqAttrStates = tmp;
19237 reqAttrStatesTop = tmp;
19238 } else {
19239 reqAttrStatesTop->next = tmp;
19240 reqAttrStatesTop = tmp;
19241 }
19242 } else if ((attrDecl->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
19243 (xmlSchemaGetEffectiveValueConstraint(attrDecl,
19244 &fixed, &defValue, &defVal))) {
19245 xmlSchemaAttrStatePtr tmp;
19246 /*
19247 * Handle non existent default/fixed attributes.
19248 */
19249 tmp = (xmlSchemaAttrStatePtr)
19250 xmlMalloc(sizeof(xmlSchemaAttrState));
19251 if (tmp == NULL) {
19252 xmlSchemaVErrMemory(ctxt,
19253 "registering schema specified attributes", NULL);
19254 ctxt->node = oldnode;
19255 return (-1);
19256 }
19257 tmp->attr = NULL;
19258 tmp->state = XML_SCHEMAS_ATTR_DEFAULT;
19259 tmp->decl = attrDecl;
19260 tmp->value = defValue;
19261 tmp->next = NULL;
19262
19263 if (defAttrStates == NULL) {
19264 defAttrStates = tmp;
19265 defAttrStates = tmp;
19266 } else {
19267 defAttrStates->next = tmp;
19268 defAttrStatesTop = tmp;
19269 }
19270 }
Daniel Veillard3646d642004-06-02 19:19:14 +000019271 }
19272 attrUse = attrUse->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000019273 }
Daniel Veillard3646d642004-06-02 19:19:14 +000019274 /*
19275 * Add required attributes to the attribute states of the context.
19276 */
19277 if (reqAttrStates != NULL) {
19278 if (ctxt->attr == NULL) {
19279 ctxt->attr = reqAttrStates;
19280 } else {
19281 ctxt->attrTop->next = reqAttrStates;
19282 }
19283 ctxt->attrTop = reqAttrStatesTop;
Daniel Veillardc0826a72004-08-10 14:17:33 +000019284 }
Daniel Veillard3646d642004-06-02 19:19:14 +000019285 /*
19286 * Process wildcards.
19287 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019288
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019289 if ((type != NULL) && (type->attributeWildcard != NULL)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000019290#ifdef DEBUG_ATTR_VALIDATION
19291 xmlSchemaWildcardNsPtr ns;
19292 printf("matching wildcard: [%d] of complexType: %s\n", type->attributeWildcard, type->name);
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000019293 if (type->attributeWildcard->processContents ==
19294 XML_SCHEMAS_ANY_LAX)
19295 printf("processContents: lax\n");
19296 else if (type->attributeWildcard->processContents ==
19297 XML_SCHEMAS_ANY_STRICT)
19298 printf("processContents: strict\n");
19299 else
19300 printf("processContents: skip\n");
Daniel Veillard3646d642004-06-02 19:19:14 +000019301 if (type->attributeWildcard->any)
19302 printf("type: any\n");
19303 else if (type->attributeWildcard->negNsSet != NULL) {
19304 printf("type: negated\n");
19305 if (type->attributeWildcard->negNsSet->value == NULL)
19306 printf("ns: (absent)\n");
19307 else
19308 printf("ns: %s\n", type->attributeWildcard->negNsSet->value);
19309 } else if (type->attributeWildcard->nsSet != NULL) {
19310 printf("type: set\n");
19311 ns = type->attributeWildcard->nsSet;
19312 while (ns != NULL) {
19313 if (ns->value == NULL)
19314 printf("ns: (absent)\n");
19315 else
19316 printf("ns: %s\n", ns->value);
19317 ns = ns->next;
19318 }
19319 } else
19320 printf("empty\n");
19321
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000019322
19323#endif
Daniel Veillard3646d642004-06-02 19:19:14 +000019324 curState = ctxt->attr;
19325 while (curState != NULL) {
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000019326 if (curState->state == XML_SCHEMAS_ATTR_UNKNOWN) {
19327 if (curState->attr->ns != NULL)
19328 nsURI = curState->attr->ns->href;
19329 else
19330 nsURI = NULL;
19331 if (xmlSchemaMatchesWildcardNs(type->attributeWildcard,
19332 nsURI)) {
19333 /*
19334 * Handle processContents.
19335 */
19336 if ((type->attributeWildcard->processContents ==
19337 XML_SCHEMAS_ANY_LAX) ||
19338 (type->attributeWildcard->processContents ==
19339 XML_SCHEMAS_ANY_STRICT)) {
19340
19341 attr = curState->attr;
19342 attrDecl = xmlSchemaGetAttribute(ctxt->schema,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019343 attr->name, nsURI);
19344 curState->decl = attrDecl;
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000019345 if (attrDecl != NULL) {
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000019346 curState->decl = attrDecl;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019347 curState->state = XML_SCHEMAS_ATTR_VALIDATE_VALUE;
19348 /* TODO
19349 ret = xmlSchemaCheckAttrLocallyValid(ctxt, attrDecl, curState, attr);
19350 */
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000019351 } else if (type->attributeWildcard->processContents ==
19352 XML_SCHEMAS_ANY_LAX) {
19353 curState->state = XML_SCHEMAS_ATTR_CHECKED;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019354 } else
19355 curState->state = XML_SCHEMAS_ATTR_WILD_NO_DECL;
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000019356 } else
Daniel Veillard3646d642004-06-02 19:19:14 +000019357 curState->state = XML_SCHEMAS_ATTR_CHECKED;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019358 }
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000019359 }
Daniel Veillard3646d642004-06-02 19:19:14 +000019360 curState = curState->next;
19361 }
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019362 }
19363
Daniel Veillardc0826a72004-08-10 14:17:33 +000019364 if (ctxt->attr != NULL) {
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019365
19366 /*
19367 * Validate the value of the attribute.
19368 */
19369 if (ctxt->value != NULL) {
19370 xmlSchemaFreeValue(ctxt->value);
19371 ctxt->value = NULL;
19372 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000019373 curState = ctxt->attr;
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019374 while ((curState != NULL) && (curState != ctxt->attrTop->next)) {
19375#ifdef IDC_ENABLED
19376 xmlSchemaTypePtr attrType;
19377#endif
19378 switch (curState->state) {
19379 case XML_SCHEMAS_ATTR_VALIDATE_VALUE:
19380 ret = xmlSchemaCheckAttrLocallyValid(ctxt,
19381 curState->decl, curState, curState->attr);
19382 if (ret == -1)
19383 return (-1);
19384 if ((ret != 0) && (ctxt->value != NULL)) {
19385 xmlSchemaFreeValue(ctxt->value);
19386 ctxt->value = NULL;
19387 }
19388 /* No break on purpose. */
19389 case XML_SCHEMAS_ATTR_CHECKED:
19390#ifdef IDC_ENABLED
19391 if (ctxt->xpathStates != NULL) {
19392 /*
19393 * Evaluate IDCs.
19394 */
19395 if (curState->attr->ns != NULL)
19396 nsURI = curState->attr->ns->href;
19397 else
19398 nsURI = NULL;
19399 xmlSchemaXPathEvaluate(ctxt, nsURI, attr->name,
19400 XML_ATTRIBUTE_NODE);
19401 if (curState->decl != NULL)
19402 attrType = curState->decl->subtypes;
19403 else
19404 attrType = NULL;
19405 xmlSchemaXPathProcessHistory(ctxt,
19406 curState->decl->subtypes,
19407 &(ctxt->value));
19408 }
19409 break;
19410#endif
19411 default:
19412 break;
19413 }
19414 curState = curState->next;
19415 }
19416
19417 /*
19418 * Report missing and illegal attributes.
19419 */
19420 curState = ctxt->attr;
19421 while ((curState != NULL) && (curState != ctxt->attrTop->next)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000019422 if (curState->state != XML_SCHEMAS_ATTR_CHECKED) {
19423 attr = curState->attr;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019424 if (curState->decl != NULL) {
19425 if (curState->decl->ref != NULL)
19426 attrDecl = curState->decl->refDecl;
19427 else
19428 attrDecl = curState->decl;
19429 } else
19430 attrDecl = NULL;
19431 if (curState->state == XML_SCHEMAS_ATTR_MISSING) {
19432 xmlSchemaVMissingAttrErr(ctxt, elem, attrDecl);
19433 } else if (curState->state ==
19434 XML_SCHEMAS_ATTR_TYPE_NOT_RESOLVED) {
19435 xmlSchemaVCustomErr(ctxt,
19436 XML_SCHEMAV_CVC_ATTRIBUTE_2,
19437 (xmlNodePtr) attr,
19438 (xmlSchemaTypePtr) attrDecl,
19439 "The type definition is absent",
19440 NULL);
19441 } else if (curState->state ==
19442 XML_SCHEMAS_ATTR_INVALID_FIXED_VALUE) {
19443 xmlSchemaVCustomErr(ctxt,
19444 XML_SCHEMAV_CVC_AU,
19445 (xmlNodePtr) attr, (xmlSchemaTypePtr) attrDecl,
19446 "The value does not match the fixed value "
19447 "constraint", NULL);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019448 } else if (curState->state == XML_SCHEMAS_ATTR_WILD_NO_DECL) {
19449 xmlSchemaVWildcardErr(ctxt,
19450 XML_SCHEMAV_CVC_WILDCARD,
19451 (xmlNodePtr) attr,
19452 type->attributeWildcard,
19453 "No global attribute declaration found, but "
19454 "stipulated by the strict processContents of "
19455 "the wildcard");
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019456 } else if (curState->state == XML_SCHEMAS_ATTR_UNKNOWN) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000019457 /* TODO: "prohibited" won't ever be touched here!.
19458 (curState->state == XML_SCHEMAS_ATTR_PROHIBITED))
19459 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019460 /*
19461 * TODO: One might report different error messages
19462 * for the following errors.
19463 */
19464 if ((type == NULL) || (type->attributeWildcard == NULL)) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000019465 xmlSchemaVIllegalAttrErr(ctxt,
19466 XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_1, attr);
19467 } else {
19468 xmlSchemaVIllegalAttrErr(ctxt,
19469 XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_2, attr);
19470 }
19471 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000019472 }
19473 curState = curState->next;
19474 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019475 }
19476
19477 /*
19478 * Add missing default/fixed attributes.
19479 */
19480 if (ctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) {
19481 curState = defAttrStates;
19482 while (curState != NULL) {
19483 attrDecl = curState->decl;
19484 if (attrDecl->ref != NULL)
19485 attrDecl = attrDecl->refDecl;
19486 /*
19487 * PSVI: Add a new attribute node to the current element.
19488 */
19489 if (attrDecl->targetNamespace == NULL) {
19490 xmlNewProp(elem, attrDecl->name, curState->value);
19491 } else {
19492 xmlNsPtr ns;
19493
19494 ns = xmlSearchNsByHref(elem->doc, elem,
19495 attrDecl->targetNamespace);
19496 if (ns == NULL) {
19497 xmlChar prefix[12];
19498 int counter = 1;
19499
19500 attr = curState->attr;
19501 /*
19502 * Create a namespace declaration on the validation
19503 * root node if no namespace declaration is in scope.
19504 */
19505 snprintf((char *) prefix, sizeof(prefix), "p");
19506 /*
19507 * This is somehow not performant, since the ancestor
19508 * axis beyond @elem will be searched as well.
19509 */
19510 ns = xmlSearchNs(elem->doc, elem, BAD_CAST prefix);
19511 while (ns != NULL) {
19512 if (counter > 1000) {
19513 xmlSchemaVErr(ctxt, (xmlNodePtr) attr,
19514 XML_SCHEMAV_INTERNAL,
19515 "Internal error: xmlSchemaValidateAttributes, "
19516 "could not compute a ns prefix for "
19517 "default/fixed attribute '%s'.\n",
19518 attrDecl->name, NULL);
19519
19520 break;
19521 }
19522 snprintf((char *) prefix,
19523 sizeof(prefix), "p%d", counter++);
19524 ns = xmlSearchNs(elem->doc, elem,
19525 BAD_CAST prefix);
19526 }
19527 if (ns == NULL) {
19528 ns = xmlNewNs(ctxt->validationRoot,
19529 attrDecl->targetNamespace, BAD_CAST prefix);
19530 xmlNewNsProp(elem, ns, attrDecl->name,
19531 curState->value);
19532 }
19533 } else {
19534 xmlNewNsProp(elem, ns, attrDecl->name,
19535 curState->value);
19536 }
19537 }
19538 curState = curState->next;
19539 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000019540 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019541 if (defAttrStates != NULL)
19542 xmlSchemaFreeAttributeStates(defAttrStates);
19543
Daniel Veillard3646d642004-06-02 19:19:14 +000019544#ifdef DEBUG_ATTR_VALIDATION
19545 if (redundant)
19546 xmlGenericError(xmlGenericErrorContext,
19547 "xmlSchemaValidateAttributes: redundant call by type: %s\n",
19548 type->name);
19549#endif
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019550 ctxt->node = oldnode;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019551 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000019552}
19553
19554/**
19555 * xmlSchemaValidateElement:
19556 * @ctxt: a schema validation context
19557 * @elem: an element
19558 *
19559 * Validate an element in a tree
19560 *
19561 * Returns 0 if the element is schemas valid, a positive error code
19562 * number otherwise and -1 in case of internal or API error.
19563 */
19564static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019565xmlSchemaValidateElement(xmlSchemaValidCtxtPtr ctxt)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019566{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019567 xmlSchemaElementPtr elemDecl;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019568 int ret = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000019569
Daniel Veillardc0826a72004-08-10 14:17:33 +000019570 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019571 * This one is called by xmlSchemaValidateDocument and
19572 * xmlSchemaValidateOneElement.
19573 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019574 if (ctxt->schema == NULL) {
19575 /*
19576 * No schema was specified at time of creation of the validation
19577 * context. Use xsi:schemaLocation and xsi:noNamespaceSchemaLocation
19578 * of the instance to build a schema.
19579 */
19580 if (ctxt->pctxt == NULL)
19581 ctxt->pctxt = xmlSchemaNewParserCtxt("*");
19582 if (ctxt->pctxt == NULL)
19583 return (-1);
19584 ctxt->schema = xmlSchemaNewSchema(ctxt->pctxt);
19585 if (ctxt->schema == NULL)
19586 return (-1);
19587 /* TODO: assign user data. */
19588 ctxt->pctxt->error = ctxt->error;
19589 ctxt->pctxt->warning = ctxt->warning;
19590 ctxt->xsiAssemble = 1;
19591 } else
19592 ctxt->xsiAssemble = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019593 /*
19594 * Assemble new schemata using xsi.
Daniel Veillardc0826a72004-08-10 14:17:33 +000019595 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019596 if (ctxt->xsiAssemble) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019597 ret = xmlSchemaAssembleByXSIElem(ctxt, ctxt->node);
19598 if (ret == -1) {
19599 xmlSchemaVCustomErr(ctxt,
19600 XML_SCHEMAV_INTERNAL,
19601 ctxt->node, NULL,
19602 "Internal error: xmlSchemaValidateElement, "
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019603 "assembling schema by xsi", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019604 }
19605 /*
19606 * NOTE: We won't react on schema parser errors here.
19607 * TODO: But a warning would be nice.
19608 */
19609 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019610 if (ret != -1) {
19611 if (ctxt->node->ns != NULL)
19612 elemDecl = xmlSchemaGetElem(ctxt->schema, ctxt->node->name,
19613 ctxt->node->ns->href);
19614 else
19615 elemDecl = xmlSchemaGetElem(ctxt->schema, ctxt->node->name, NULL);
19616
19617 if (elemDecl == NULL) {
19618 xmlSchemaVCustomErr(ctxt,
19619 XML_SCHEMAV_CVC_ELT_1,
19620 ctxt->node, NULL,
19621 "No matching global declaration available", NULL);
19622 ret = XML_SCHEMAV_CVC_ELT_1;
19623 } else {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019624#ifdef IDC_ENABLED
19625 /*
19626 * Augment the IDC definitions.
19627 */
19628 if (ctxt->schema->idcDef != NULL) {
19629 xmlHashScan(ctxt->schema->idcDef,
19630 (xmlHashScanner) xmlSchemaAugmentIDC, ctxt);
19631 }
19632#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019633#ifdef ELEM_INFO_ENABLED
19634 ctxt->depth = -1;
19635 xmlSchemaBeginElement(ctxt);
19636#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019637 ret = xmlSchemaValidateElementByDeclaration(ctxt, elemDecl);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019638#ifdef ELEM_INFO_ENABLED
19639 xmlSchemaEndElement(ctxt);
19640#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019641 if (ret < 0) {
19642 xmlSchemaVCustomErr(ctxt,
19643 XML_SCHEMAV_INTERNAL, ctxt->node, NULL,
19644 "Internal error: xmlSchemaValidateElement, "
19645 "calling validation by declaration", NULL);
19646 }
19647 }
19648 }
19649 /* ctxt->xsiAssemble = 0; */
19650 if (ctxt->xsiAssemble) {
19651 if (ctxt->schema != NULL) {
19652 xmlSchemaFree(ctxt->schema);
19653 ctxt->schema = NULL;
19654 }
Daniel Veillard4255d502002-04-16 15:50:10 +000019655 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019656 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000019657}
19658
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019659
Daniel Veillard4255d502002-04-16 15:50:10 +000019660/**
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000019661 * xmlSchemaValidateOneElement:
19662 * @ctxt: a schema validation context
19663 * @elem: an element node
19664 *
19665 * Validate a branch of a tree, starting with the given @elem.
19666 *
19667 * Returns 0 if the element and its subtree is valid, a positive error
19668 * code number otherwise and -1 in case of an internal or API error.
19669 */
19670int
19671xmlSchemaValidateOneElement(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem)
19672{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019673 if ((ctxt == NULL) || (elem == NULL) || (elem->type != XML_ELEMENT_NODE))
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000019674 return (-1);
19675
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019676 if (ctxt->schema == NULL) {
19677 xmlSchemaVErr(ctxt, NULL,
19678 XML_SCHEMAV_INTERNAL,
19679 "API error: xmlSchemaValidateOneElement, "
19680 "no schema specified.\n", NULL, NULL);
19681 return (-1);
19682 }
19683
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000019684 ctxt->doc = elem->doc;
19685 ctxt->err = 0;
19686 ctxt->nberrors = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019687 ctxt->node = elem;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019688 ctxt->validationRoot = elem;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019689 return (xmlSchemaValidateElement(ctxt));
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000019690}
19691
19692/**
Daniel Veillard4255d502002-04-16 15:50:10 +000019693 * xmlSchemaValidateDocument:
19694 * @ctxt: a schema validation context
19695 * @doc: a parsed document tree
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019696 * @xsiAssemble: should schemata be added if requested by the instance?
Daniel Veillard4255d502002-04-16 15:50:10 +000019697 *
19698 * Validate a document tree in memory.
19699 *
19700 * Returns 0 if the document is schemas valid, a positive error code
19701 * number otherwise and -1 in case of internal or API error.
19702 */
19703static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019704xmlSchemaValidateDocument(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
19705{
Daniel Veillard4255d502002-04-16 15:50:10 +000019706 xmlNodePtr root;
Daniel Veillard01fa6152004-06-29 17:04:39 +000019707
Daniel Veillard4255d502002-04-16 15:50:10 +000019708 root = xmlDocGetRootElement(doc);
19709 if (root == NULL) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000019710 xmlSchemaVCustomErr(ctxt,
19711 XML_SCHEMAV_DOCUMENT_ELEMENT_MISSING,
19712 (xmlNodePtr) doc, NULL,
19713 "The document has no document element", NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019714 return (ctxt->err);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019715 }
Daniel Veillard4255d502002-04-16 15:50:10 +000019716 /*
19717 * Okay, start the recursive validation
19718 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019719 ctxt->node = root;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019720 ctxt->validationRoot = root;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019721 xmlSchemaValidateElement(ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +000019722
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019723 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000019724}
19725
19726/************************************************************************
19727 * *
19728 * SAX Validation code *
19729 * *
19730 ************************************************************************/
19731
19732/************************************************************************
19733 * *
19734 * Validation interfaces *
19735 * *
19736 ************************************************************************/
19737
19738/**
19739 * xmlSchemaNewValidCtxt:
19740 * @schema: a precompiled XML Schemas
19741 *
19742 * Create an XML Schemas validation context based on the given schema
19743 *
19744 * Returns the validation context or NULL in case of error
19745 */
19746xmlSchemaValidCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019747xmlSchemaNewValidCtxt(xmlSchemaPtr schema)
19748{
Daniel Veillard4255d502002-04-16 15:50:10 +000019749 xmlSchemaValidCtxtPtr ret;
19750
19751 ret = (xmlSchemaValidCtxtPtr) xmlMalloc(sizeof(xmlSchemaValidCtxt));
19752 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019753 xmlSchemaVErrMemory(NULL, "allocating validation context", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000019754 return (NULL);
19755 }
19756 memset(ret, 0, sizeof(xmlSchemaValidCtxt));
Daniel Veillardc0826a72004-08-10 14:17:33 +000019757 ret->schema = schema;
Daniel Veillard3646d642004-06-02 19:19:14 +000019758 ret->attrTop = NULL;
19759 ret->attr = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000019760 return (ret);
19761}
19762
19763/**
19764 * xmlSchemaFreeValidCtxt:
19765 * @ctxt: the schema validation context
19766 *
19767 * Free the resources associated to the schema validation context
19768 */
19769void
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019770xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt)
19771{
Daniel Veillard4255d502002-04-16 15:50:10 +000019772 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019773 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000019774 if (ctxt->attr != NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000019775 xmlSchemaFreeAttributeStates(ctxt->attr);
Daniel Veillard88c58912002-04-23 07:12:20 +000019776 if (ctxt->value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019777 xmlSchemaFreeValue(ctxt->value);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019778 if (ctxt->pctxt != NULL) {
19779 xmlSchemaFreeParserCtxt(ctxt->pctxt);
19780 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019781
19782#ifdef IDC_ENABLED
19783 if (ctxt->idcNodes != NULL) {
19784 int i;
19785 xmlSchemaPSVIIDCNodePtr item;
19786
19787 for (i = 0; i < ctxt->nbIdcNodes; i++) {
19788 item = ctxt->idcNodes[i];
19789 xmlFree(item->keys);
19790 xmlFree(item);
19791 }
19792 xmlFree(ctxt->idcNodes);
19793 }
19794
19795 if (ctxt->idcKeys != NULL) {
19796 int i;
19797 for (i = 0; i < ctxt->nbIdcKeys; i++)
19798 xmlSchemaIDCFreeKey(ctxt->idcKeys[i]);
19799 xmlFree(ctxt->idcKeys);
19800 }
19801
19802 if (ctxt->xpathStates != NULL)
19803 xmlSchemaFreeIDCStateObjList(ctxt->xpathStates);
19804 if (ctxt->xpathStatePool != NULL)
19805 xmlSchemaFreeIDCStateObjList(ctxt->xpathStatePool);
19806
19807 /*
19808 * Augmented IDC information.
19809 */
19810 if (ctxt->aidcs != NULL) {
19811 xmlSchemaIDCAugPtr cur = ctxt->aidcs, next;
19812 do {
19813 next = cur->next;
19814 xmlFree(cur);
19815 cur = next;
19816 } while (cur != NULL);
19817 }
19818#endif /* IDC_ENABLED */
19819#ifdef ELEM_INFO_ENABLED
19820 if (ctxt->elemInfos != NULL) {
19821 int i;
19822 xmlSchemaElemInfoPtr info;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019823
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019824 for (i = 0; i < ctxt->sizeElemInfos; i++) {
19825 info = ctxt->elemInfos[i];
19826 if (info == NULL)
19827 continue;
19828 if (info->value != NULL)
19829 xmlSchemaFreeValue(info->value);
19830#ifdef IDC_ENABLED
19831 if (info->idcMatchers != NULL)
19832 xmlSchemaIDCFreeMatcherList(info->idcMatchers);
19833#endif
19834 /*
19835 * TODO: Free the IDC table if still existent.
19836 */
19837
19838 /*
19839 xmlFree(info->localName);
19840 if (info->namespaceName != NULL)
19841 xmlFree(info->namespaceName);
19842 */
19843 xmlFree(info);
19844 }
19845 xmlFree(ctxt->elemInfos);
19846 }
19847#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000019848 xmlFree(ctxt);
19849}
19850
19851/**
19852 * xmlSchemaSetValidErrors:
19853 * @ctxt: a schema validation context
19854 * @err: the error function
19855 * @warn: the warning function
Daniel Veillarda9b66d02002-12-11 14:23:49 +000019856 * @ctx: the functions context
Daniel Veillard4255d502002-04-16 15:50:10 +000019857 *
William M. Brack2f2a6632004-08-20 23:09:47 +000019858 * Set the error and warning callback informations
Daniel Veillard4255d502002-04-16 15:50:10 +000019859 */
19860void
19861xmlSchemaSetValidErrors(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019862 xmlSchemaValidityErrorFunc err,
19863 xmlSchemaValidityWarningFunc warn, void *ctx)
19864{
Daniel Veillard4255d502002-04-16 15:50:10 +000019865 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019866 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000019867 ctxt->error = err;
19868 ctxt->warning = warn;
19869 ctxt->userData = ctx;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019870 if (ctxt->pctxt != NULL)
19871 xmlSchemaSetParserErrors(ctxt->pctxt, err, warn, ctx);
Daniel Veillard4255d502002-04-16 15:50:10 +000019872}
19873
19874/**
Daniel Veillard259f0df2004-08-18 09:13:18 +000019875 * xmlSchemaGetValidErrors:
19876 * @ctxt: a XML-Schema validation context
19877 * @err: the error function result
19878 * @warn: the warning function result
19879 * @ctx: the functions context result
19880 *
19881 * Get the error and warning callback informations
19882 *
19883 * Returns -1 in case of error and 0 otherwise
19884 */
19885int
19886xmlSchemaGetValidErrors(xmlSchemaValidCtxtPtr ctxt,
19887 xmlSchemaValidityErrorFunc * err,
19888 xmlSchemaValidityWarningFunc * warn, void **ctx)
19889{
19890 if (ctxt == NULL)
19891 return (-1);
19892 if (err != NULL)
19893 *err = ctxt->error;
19894 if (warn != NULL)
19895 *warn = ctxt->warning;
19896 if (ctx != NULL)
19897 *ctx = ctxt->userData;
19898 return (0);
19899}
19900
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019901
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019902/**
Daniel Veillard6927b102004-10-27 17:29:04 +000019903 * xmlSchemaSetValidOptions:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019904 * @ctxt: a schema validation context
19905 * @options: a combination of xmlSchemaValidOption
19906 *
19907 * Sets the options to be used during the validation.
19908 *
19909 * Returns 0 in case of success, -1 in case of an
19910 * API error.
19911 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019912int
19913xmlSchemaSetValidOptions(xmlSchemaValidCtxtPtr ctxt,
19914 int options)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019915
19916{
19917 int i;
19918
19919 if (ctxt == NULL)
19920 return (-1);
19921 /*
19922 * WARNING: Change the start value if adding to the
19923 * xmlSchemaValidOption.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019924 * TODO: Is there an other, more easy to maintain,
19925 * way?
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019926 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019927 for (i = 1; i < (int) sizeof(int) * 8; i++) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019928 if (options & 1<<i) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019929 xmlSchemaVErr(ctxt, NULL,
19930 XML_SCHEMAV_INTERNAL,
19931 "Internal error: xmlSchemaSetValidOptions, "
19932 "invalid option argument.\n", NULL, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019933 return (-1);
19934 }
19935 }
19936 ctxt->options = options;
19937 return (0);
19938}
19939
19940/**
Daniel Veillard6927b102004-10-27 17:29:04 +000019941 * xmlSchemaValidCtxtGetOptions:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019942 * @ctxt: a schema validation context
19943 *
William M. Brack21e4ef22005-01-02 09:53:13 +000019944 * Get the validation context options.
19945 *
19946 * Returns the option combination or -1 on error.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019947 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019948int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019949xmlSchemaValidCtxtGetOptions(xmlSchemaValidCtxtPtr ctxt)
19950
19951{
19952 if (ctxt == NULL)
19953 return (-1);
19954 else
19955 return (ctxt->options);
19956}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019957
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019958
Daniel Veillard259f0df2004-08-18 09:13:18 +000019959/**
Daniel Veillard4255d502002-04-16 15:50:10 +000019960 * xmlSchemaValidateDoc:
19961 * @ctxt: a schema validation context
19962 * @doc: a parsed document tree
19963 *
19964 * Validate a document tree in memory.
19965 *
19966 * Returns 0 if the document is schemas valid, a positive error code
19967 * number otherwise and -1 in case of internal or API error.
19968 */
19969int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019970xmlSchemaValidateDoc(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
19971{
Daniel Veillard4255d502002-04-16 15:50:10 +000019972 int ret;
19973
19974 if ((ctxt == NULL) || (doc == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019975 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000019976
19977 ctxt->doc = doc;
William M. Brack2f2a6632004-08-20 23:09:47 +000019978 ctxt->err = 0;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019979 ctxt->nberrors = 0;
19980
19981 /*
19982 if (ctxt->schema == NULL) {
19983 xmlSchemaVErr(ctxt, NULL,
19984 XML_SCHEMAV_INTERNAL,
19985 "API error: xmlSchemaValidateDoc, "
19986 "no schema specified and assembling of schemata "
19987 "using xsi:schemaLocation and xsi:noNamespaceSchemaLocation "
19988 "is not enabled.\n", NULL, NULL);
19989 return (-1);
19990 }
19991 */
Daniel Veillard4255d502002-04-16 15:50:10 +000019992 ret = xmlSchemaValidateDocument(ctxt, doc);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019993 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000019994}
19995
19996/**
19997 * xmlSchemaValidateStream:
19998 * @ctxt: a schema validation context
19999 * @input: the input to use for reading the data
20000 * @enc: an optional encoding information
20001 * @sax: a SAX handler for the resulting events
20002 * @user_data: the context to provide to the SAX handler.
20003 *
20004 * Validate a document tree in memory.
20005 *
20006 * Returns 0 if the document is schemas valid, a positive error code
20007 * number otherwise and -1 in case of internal or API error.
20008 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020009int
Daniel Veillard4255d502002-04-16 15:50:10 +000020010xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020011 xmlParserInputBufferPtr input, xmlCharEncoding enc,
20012 xmlSAXHandlerPtr sax, void *user_data)
20013{
Daniel Veillard4255d502002-04-16 15:50:10 +000020014 if ((ctxt == NULL) || (input == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020015 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000020016 ctxt->input = input;
20017 ctxt->enc = enc;
20018 ctxt->sax = sax;
20019 ctxt->user_data = user_data;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020020 TODO return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000020021}
20022
20023#endif /* LIBXML_SCHEMAS_ENABLED */