blob: da1f0dfa9b888934a1d2a3f7ac752671a91b070f [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. Buchcike8a550b2005-01-27 12:49:31 +000037#include <libxml/xpath.h>
Daniel Veillard4255d502002-04-16 15:50:10 +000038
Daniel Veillarda84c0b32003-06-02 16:58:46 +000039/* #define DEBUG 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000040
Daniel Veillard82bbbd42003-05-11 20:16:09 +000041/* #define DEBUG_CONTENT 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000042
Daniel Veillard82bbbd42003-05-11 20:16:09 +000043/* #define DEBUG_TYPE 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000044
Daniel Veillard118aed72002-09-24 14:13:13 +000045/* #define DEBUG_CONTENT_REGEXP 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000046
Daniel Veillard4255d502002-04-16 15:50:10 +000047/* #define DEBUG_AUTOMATA 1 */
48
Daniel Veillard3646d642004-06-02 19:19:14 +000049/* #define DEBUG_ATTR_VALIDATION 1 */
50
Daniel Veillardc0826a72004-08-10 14:17:33 +000051/* #define DEBUG_UNION_VALIDATION 1 */
52
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000053#define ELEM_INFO_ENABLED 1
54
55/* #define IDC_ENABLED 1 */
56
57/* #define IDC_VALUE_SUPPORT 1 */
58
59/* #define IDC_XPATH_SUPPORT 1 */
60
61/* #define DEBUG_IDC 1 */
62
Daniel Veillardc0826a72004-08-10 14:17:33 +000063
Daniel Veillard4255d502002-04-16 15:50:10 +000064#define UNBOUNDED (1 << 30)
65#define TODO \
66 xmlGenericError(xmlGenericErrorContext, \
67 "Unimplemented block at %s:%d\n", \
68 __FILE__, __LINE__);
69
William M. Brack2f2a6632004-08-20 23:09:47 +000070#define XML_SCHEMAS_NO_NAMESPACE (const xmlChar *) "##"
Daniel Veillardc0826a72004-08-10 14:17:33 +000071
Daniel Veillard4255d502002-04-16 15:50:10 +000072/*
73 * The XML Schemas namespaces
74 */
75static const xmlChar *xmlSchemaNs = (const xmlChar *)
76 "http://www.w3.org/2001/XMLSchema";
77
78static const xmlChar *xmlSchemaInstanceNs = (const xmlChar *)
79 "http://www.w3.org/2001/XMLSchema-instance";
80
Daniel Veillardc0826a72004-08-10 14:17:33 +000081static const xmlChar *xmlSchemaElemDesElemDecl = (const xmlChar *)
82 "Element decl.";
83static const xmlChar *xmlSchemaElemDesElemRef = (const xmlChar *)
84 "Element ref.";
85static const xmlChar *xmlSchemaElemDesAttrDecl = (const xmlChar *)
86 "Attribute decl.";
87static const xmlChar *xmlSchemaElemDesAttrRef = (const xmlChar *)
88 "Attribute ref.";
89static const xmlChar *xmlSchemaElemDesST = (const xmlChar *)
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000090 "simple type";
Daniel Veillardc0826a72004-08-10 14:17:33 +000091static const xmlChar *xmlSchemaElemDesCT = (const xmlChar *)
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000092 "complex type";
Daniel Veillardc0826a72004-08-10 14:17:33 +000093
Daniel Veillard4255d502002-04-16 15:50:10 +000094#define IS_SCHEMA(node, type) \
95 ((node != NULL) && (node->ns != NULL) && \
96 (xmlStrEqual(node->name, (const xmlChar *) type)) && \
97 (xmlStrEqual(node->ns->href, xmlSchemaNs)))
98
Daniel Veillardc0826a72004-08-10 14:17:33 +000099#define FREE_AND_NULL(str) \
100 if (str != NULL) { \
101 xmlFree(str); \
102 str = NULL; \
103 }
104
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000105#define IS_ANYTYPE(item) \
106 ((item->type == XML_SCHEMA_TYPE_BASIC) && \
107 (item->builtInType == XML_SCHEMAS_ANYTYPE))
108
109#define IS_COMPLEX_TYPE(item) \
110 ((item->type == XML_SCHEMA_TYPE_COMPLEX) || \
111 (item->builtInType == XML_SCHEMAS_ANYTYPE))
112
113#define IS_SIMPLE_TYPE(item) \
114 ((item->type == XML_SCHEMA_TYPE_SIMPLE) || \
115 ((item->type == XML_SCHEMA_TYPE_BASIC) && \
116 (item->builtInType != XML_SCHEMAS_ANYTYPE)))
117
Daniel Veillardc0826a72004-08-10 14:17:33 +0000118#define XML_SCHEMAS_VAL_WTSP_PRESERVE 0
119#define XML_SCHEMAS_VAL_WTSP_REPLACE 1
120#define XML_SCHEMAS_VAL_WTSP_COLLAPSE 2
121
Daniel Veillard4255d502002-04-16 15:50:10 +0000122#define XML_SCHEMAS_PARSE_ERROR 1
123
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000124#define SCHEMAS_PARSE_OPTIONS XML_PARSE_NOENT
125
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000126
127/*
128* XML_SCHEMA_VAL_XSI_ASSEMBLE_TNS_COMPOSE
129* allow to assemble schemata with
130* the same target namespace from
131* different sources; otherwise, the first
132* encountered schema with a specific target
133* namespace will be used only *
134
135*
136* XML_SCHEMA_VAL_LOCATE_BY_NSNAME = 1<<2
137* locate schemata to be imported
138* using the namespace name; otherwise
139* the location URI will be used */
140
141/*
142* xmlSchemaParserOption:
143*
144* This is the set of XML Schema parser options.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000145*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000146typedef enum {
147 XML_SCHEMA_PAR_LOCATE_BY_NSNAME = 1<<0
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000148 * locate schemata to be imported
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000149 * using the namespace name; otherwise
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000150 * the location URI will be used *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000151} xmlSchemaParserOption;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000152*/
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000153
154/*
155XMLPUBFUN int XMLCALL
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000156 xmlSchemaParserCtxtSetOptions(xmlSchemaParserCtxtPtr ctxt,
157 int options);
158XMLPUBFUN int XMLCALL
159 xmlSchemaParserCtxtGetOptions(xmlSchemaParserCtxtPtr ctxt);
160
161*/
162
163typedef struct _xmlSchemaAssemble xmlSchemaAssemble;
164typedef xmlSchemaAssemble *xmlSchemaAssemblePtr;
165struct _xmlSchemaAssemble {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000166 void **items; /* used for dynamic addition of schemata */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000167 int nbItems; /* used for dynamic addition of schemata */
168 int sizeItems; /* used for dynamic addition of schemata */
169};
170
Daniel Veillard4255d502002-04-16 15:50:10 +0000171struct _xmlSchemaParserCtxt {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000172 void *userData; /* user specific data block */
173 xmlSchemaValidityErrorFunc error; /* the callback in case of errors */
174 xmlSchemaValidityWarningFunc warning; /* the callback in case of warning */
Daniel Veillarde19fc232002-04-22 16:01:24 +0000175 xmlSchemaValidError err;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000176 int nberrors;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000177 xmlStructuredErrorFunc serror;
Daniel Veillard4255d502002-04-16 15:50:10 +0000178
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000179 xmlSchemaPtr topschema; /* The main schema */
180 xmlHashTablePtr namespaces; /* Hash table of namespaces to schemas */
181
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000182 xmlSchemaPtr schema; /* The schema in use */
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000183 const xmlChar *container; /* the current element, group, ... */
Daniel Veillard4255d502002-04-16 15:50:10 +0000184 int counter;
185
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000186 const xmlChar *URL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000187 xmlDocPtr doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +0000188 int preserve; /* Whether the doc should be freed */
Daniel Veillard4255d502002-04-16 15:50:10 +0000189
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000190 const char *buffer;
191 int size;
Daniel Veillard6045c902002-10-09 21:13:59 +0000192
Daniel Veillard4255d502002-04-16 15:50:10 +0000193 /*
194 * Used to build complex element content models
195 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000196 xmlAutomataPtr am;
Daniel Veillard4255d502002-04-16 15:50:10 +0000197 xmlAutomataStatePtr start;
198 xmlAutomataStatePtr end;
199 xmlAutomataStatePtr state;
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000200
201 xmlDictPtr dict; /* dictionnary for interned string names */
Daniel Veillardb0f397e2003-12-23 23:30:53 +0000202 int includes; /* the inclusion level, 0 for root or imports */
Daniel Veillard01fa6152004-06-29 17:04:39 +0000203 xmlSchemaTypePtr ctxtType; /* The current context simple/complex type */
204 xmlSchemaTypePtr parentItem; /* The current parent schema item */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000205 xmlSchemaAssemblePtr assemble;
206 int options;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000207 xmlSchemaValidCtxtPtr vctxt;
Daniel Veillard4255d502002-04-16 15:50:10 +0000208};
209
210
211#define XML_SCHEMAS_ATTR_UNKNOWN 1
212#define XML_SCHEMAS_ATTR_CHECKED 2
Daniel Veillard3646d642004-06-02 19:19:14 +0000213#define XML_SCHEMAS_ATTR_PROHIBITED 3
214#define XML_SCHEMAS_ATTR_MISSING 4
215#define XML_SCHEMAS_ATTR_INVALID_VALUE 5
216#define XML_SCHEMAS_ATTR_TYPE_NOT_RESOLVED 6
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000217#define XML_SCHEMAS_ATTR_INVALID_FIXED_VALUE 7
218#define XML_SCHEMAS_ATTR_DEFAULT 8
Daniel Veillard4255d502002-04-16 15:50:10 +0000219
220typedef struct _xmlSchemaAttrState xmlSchemaAttrState;
221typedef xmlSchemaAttrState *xmlSchemaAttrStatePtr;
222struct _xmlSchemaAttrState {
Daniel Veillard3646d642004-06-02 19:19:14 +0000223 xmlSchemaAttrStatePtr next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000224 xmlAttrPtr attr;
225 int state;
Daniel Veillard3646d642004-06-02 19:19:14 +0000226 xmlSchemaAttributePtr decl;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000227 const xmlChar *value;
Daniel Veillard4255d502002-04-16 15:50:10 +0000228};
229
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000230typedef struct _xmlSchemaBasicItem xmlSchemaBasicItem;
231typedef xmlSchemaBasicItem *xmlSchemaBasicItemPtr;
232struct _xmlSchemaBasicItem {
233 xmlSchemaTypeType type;
234 xmlSchemaAnnotPtr annot;
235};
236
237typedef struct _xmlSchemaItemQNRef xmlSchemaItemQNRef;
238typedef xmlSchemaItemQNRef *xmlSchemaItemQNRefPtr;
239struct _xmlSchemaItemQNRef {
240 xmlSchemaBasicItemPtr item;
241 const xmlChar *name;
242 const xmlChar *targetNamespace;
243};
244
245typedef struct _xmlSchemaIDC xmlSchemaIDC;
246typedef xmlSchemaIDC *xmlSchemaIDCPtr;
247
248/**
249 * xmlSchemaIDCSelect:
250 *
251 * The identity-constraint "field" and "selector" item, holding the
252 * XPath expression.
253 */
254typedef struct _xmlSchemaIDCSelect xmlSchemaIDCSelect;
255typedef xmlSchemaIDCSelect *xmlSchemaIDCSelectPtr;
256struct _xmlSchemaIDCSelect {
257 xmlSchemaIDCSelectPtr next;
258 xmlSchemaIDCPtr idc;
259 int index; /* an index position if significant for IDC key-sequences */
260 const xmlChar *xpath; /* the XPath expression */
261 xmlXPathCompExprPtr xpathComp; /* the compiled XPath expression */
262};
263
264/**
265 * xmlSchemaIDC:
266 *
267 * The identity-constraint definition component.
268 */
269
270struct _xmlSchemaIDC {
271 xmlSchemaTypeType type;
272 xmlSchemaAnnotPtr annot;
273 xmlSchemaIDCPtr next;
274 xmlNodePtr node;
275 const xmlChar *name;
276 const xmlChar *targetNamespace;
277 xmlSchemaIDCSelectPtr selector;
278 xmlSchemaIDCSelectPtr fields;
279 int nbFields;
280 xmlSchemaItemQNRefPtr ref;
281};
282
283/**
284 * xmlSchemaIDCAug:
285 *
286 * The augmented IDC information used for validation.
287 */
288typedef struct _xmlSchemaIDCAug xmlSchemaIDCAug;
289typedef xmlSchemaIDCAug *xmlSchemaIDCAugPtr;
290struct _xmlSchemaIDCAug {
291 xmlSchemaIDCAugPtr next; /* next in a list */
292 xmlSchemaIDCPtr def; /* the IDC definition */
293 int bubbleDepth; /* the lowest level to which IDC
294 tables need to be bubbled upwards */
295};
296
297/**
298 * xmlSchemaPSVIIDCKeySequence:
299 *
300 * The key sequence of a node table item.
301 */
302typedef struct _xmlSchemaPSVIIDCKey xmlSchemaPSVIIDCKey;
303typedef xmlSchemaPSVIIDCKey *xmlSchemaPSVIIDCKeyPtr;
304struct _xmlSchemaPSVIIDCKey {
305 xmlSchemaTypePtr type;
306 xmlSchemaValPtr compValue;
307};
308
309/**
310 * xmlSchemaPSVIIDCNode:
311 *
312 * The node table item of a node table.
313 */
314typedef struct _xmlSchemaPSVIIDCNode xmlSchemaPSVIIDCNode;
315typedef xmlSchemaPSVIIDCNode *xmlSchemaPSVIIDCNodePtr;
316struct _xmlSchemaPSVIIDCNode {
317 xmlNodePtr node;
318 xmlSchemaPSVIIDCKeyPtr *keys;
319};
320
321/**
322 * xmlSchemaPSVIIDCBinding:
323 *
324 * The identity-constraint binding item of the [identity-constraint table].
325 */
326typedef struct _xmlSchemaPSVIIDCBinding xmlSchemaPSVIIDCBinding;
327typedef xmlSchemaPSVIIDCBinding *xmlSchemaPSVIIDCBindingPtr;
328struct _xmlSchemaPSVIIDCBinding {
329 xmlSchemaPSVIIDCBindingPtr next; /* next binding of a specific node */
330 xmlSchemaIDCPtr definition; /* the IDC definition */
331 xmlSchemaPSVIIDCNodePtr *nodeTable; /* array of key-sequences */
332 int nbNodes; /* number of entries in the node table */
333 int sizeNodes; /* size of the node table */
334 int nbDupls; /* number of already identified duplicates in the node
335 table */
336 /* int nbKeys; number of keys in each key-sequence */
337};
338
339#define XPATH_STATE_OBJ_TYPE_IDC_SELECTOR 1
340#define XPATH_STATE_OBJ_TYPE_IDC_FIELD 2
341
342#define XPATH_STATE_OBJ_MATCHES -2
343#define XPATH_STATE_OBJ_BLOCKED -3
344
345typedef struct _xmlSchemaIDCMatcher xmlSchemaIDCMatcher;
346typedef xmlSchemaIDCMatcher *xmlSchemaIDCMatcherPtr;
347
348/**
349 * xmlSchemaIDCStateObj:
350 *
351 * The state object used to evaluate XPath expressions.
352 */
353typedef struct _xmlSchemaIDCStateObj xmlSchemaIDCStateObj;
354typedef xmlSchemaIDCStateObj *xmlSchemaIDCStateObjPtr;
355struct _xmlSchemaIDCStateObj {
356 int type;
357 xmlSchemaIDCStateObjPtr parent; /* the parent selector state object */
358 xmlSchemaIDCStateObjPtr next; /* next if in a list */
359 int topDown;
360 int **history; /* list of (depth, state-id) tuples */
361 int nbHistory;
362 int sizeHistory;
363 xmlSchemaIDCMatcherPtr matcher; /* the correspondent field/selector
364 matcher */
365 xmlSchemaIDCSelectPtr sel;
366};
367
368#define IDC_MATCHER 0
369
370/**
371 * xmlSchemaIDCMatcher:
372 *
373 * Used to IDC selectors (and fields) successively.
374 */
375struct _xmlSchemaIDCMatcher {
376 int type;
377 int depth; /* the tree depth at creation time */
378 xmlSchemaIDCMatcherPtr next; /* next in the list */
379 xmlSchemaIDCAugPtr aidc; /* the augmented IDC item */
380 xmlSchemaPSVIIDCKeyPtr **keySeqs; /* the key-sequences of the target
381 elements */
382 int sizeKeySeqs;
383 xmlSchemaPSVIIDCKeyPtr **refKeySeqs;
384 int nbRefKeySeqs;
385 int sizeRefKeySeqs;
386 int targetDepth;
387};
388
389/*
390* Element info flags.
391*/
392#define XML_SCHEMA_ELEM_INFO_VALUE_NEEDED 1<<0
393
394/**
395 * xmlSchemaElemInfo:
396 *
397 * Holds information of an element node.
398 */
399typedef struct _xmlSchemaElemInfo xmlSchemaElemInfo;
400typedef xmlSchemaElemInfo *xmlSchemaElemInfoPtr;
401struct _xmlSchemaElemInfo {
402 int depth;
403 int flags; /* combination of element info flags */
404 xmlNodePtr node;
405 const xmlChar *localName;
406 const xmlChar *namespaceName;
407 xmlSchemaTypePtr typeDef; /* the complex/simple type definition if any */
408 xmlSchemaValPtr value; /* the pre-computed value if any */
409 xmlSchemaPSVIIDCBindingPtr idcTable; /* the table of PSVI IDC bindings
410 for the scope element*/
411 xmlSchemaIDCMatcherPtr idcMatchers; /* the IDC matchers for the scope
412 element */
413};
414
Daniel Veillard4255d502002-04-16 15:50:10 +0000415/**
416 * xmlSchemaValidCtxt:
417 *
418 * A Schemas validation context
419 */
420
421struct _xmlSchemaValidCtxt {
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000422 void *userData; /* user specific data block */
423 xmlSchemaValidityErrorFunc error; /* the callback in case of errors */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000424 xmlSchemaValidityWarningFunc warning; /* the callback in case of warning */
Daniel Veillard659e71e2003-10-10 14:10:40 +0000425 xmlStructuredErrorFunc serror;
Daniel Veillard4255d502002-04-16 15:50:10 +0000426
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000427 xmlSchemaPtr schema; /* The schema in use */
428 xmlDocPtr doc;
Daniel Veillard4255d502002-04-16 15:50:10 +0000429 xmlParserInputBufferPtr input;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000430 xmlCharEncoding enc;
431 xmlSAXHandlerPtr sax;
432 void *user_data;
Daniel Veillard4255d502002-04-16 15:50:10 +0000433
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000434 xmlDocPtr myDoc;
435 int err;
436 int nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +0000437
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000438 xmlNodePtr node;
439 xmlNodePtr cur;
440 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +0000441
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000442 xmlRegExecCtxtPtr regexp;
443 xmlSchemaValPtr value;
Daniel Veillard4255d502002-04-16 15:50:10 +0000444
Daniel Veillard3646d642004-06-02 19:19:14 +0000445 xmlSchemaAttrStatePtr attrTop;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000446 xmlSchemaAttrStatePtr attr;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000447 /* xmlNodePtr scope; not used */
Daniel Veillardc0826a72004-08-10 14:17:33 +0000448 int valueWS;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000449 int options;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000450 xmlNodePtr validationRoot;
451 xmlSchemaParserCtxtPtr pctxt;
452 int xsiAssemble;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000453#ifdef ELEM_INFO_ENABLED
454 int depth;
455 xmlSchemaElemInfoPtr *elemInfos; /* array of element informations */
456 int sizeElemInfos;
457 xmlSchemaElemInfoPtr elemInfo; /* the current element information */
458#endif
459#ifdef IDC_ENABLED
460 xmlSchemaIDCAugPtr aidcs; /* a list of augmented IDC informations */
461
462 xmlSchemaIDCStateObjPtr xpathStates; /* first active state object. */
463 xmlSchemaIDCStateObjPtr xpathStatePool; /* first stored state object. */
464
465 xmlSchemaPSVIIDCNodePtr *idcNodes; /* list of all IDC node-table entries*/
466 int nbIdcNodes;
467 int sizeIdcNodes;
468
469 xmlSchemaPSVIIDCKeyPtr *idcKeys; /* list of all IDC node-table entries */
470 int nbIdcKeys;
471 int sizeIdcKeys;
472#endif
Daniel Veillard4255d502002-04-16 15:50:10 +0000473};
474
Daniel Veillard1d913862003-11-21 00:28:39 +0000475/*
476 * These are the entries in the schemas importSchemas hash table
477 */
478typedef struct _xmlSchemaImport xmlSchemaImport;
479typedef xmlSchemaImport *xmlSchemaImportPtr;
480struct _xmlSchemaImport {
481 const xmlChar *schemaLocation;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000482 xmlSchemaPtr schema; /* not used any more */
William M. Brack2f2a6632004-08-20 23:09:47 +0000483 xmlDocPtr doc;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000484 int isMain;
Daniel Veillard1d913862003-11-21 00:28:39 +0000485};
Daniel Veillard4255d502002-04-16 15:50:10 +0000486
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000487/*
488 * These are the entries associated to includes in a schemas
489 */
490typedef struct _xmlSchemaInclude xmlSchemaInclude;
491typedef xmlSchemaInclude *xmlSchemaIncludePtr;
492struct _xmlSchemaInclude {
493 xmlSchemaIncludePtr next;
494
495 const xmlChar *schemaLocation;
496 xmlDocPtr doc;
497};
498
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000499typedef struct _xmlSchemaParticle xmlSchemaParticle;
500typedef xmlSchemaParticle *xmlSchemaParticlePtr;
501struct _xmlSchemaParticle {
502 xmlSchemaTypeType type;
503 xmlSchemaParticlePtr next; /* the next particle if in a list */
504 int minOccurs;
505 int maxOccurs;
506 xmlSchemaTypePtr term;
507};
508
509
510typedef struct _xmlSchemaModelGroup xmlSchemaModelGroup;
511typedef xmlSchemaModelGroup *xmlSchemaModelGroupPtr;
512struct _xmlSchemaModelGroup {
513 xmlSchemaTypeType type;
514 int compositor; /* one of all, choice or sequence */
515 xmlSchemaParticlePtr particles; /* list of particles */
516 xmlSchemaAnnotPtr annot;
517};
518
519typedef struct _xmlSchemaModelGroupDef xmlSchemaModelGroupDef;
520typedef xmlSchemaModelGroupDef *xmlSchemaModelGroupDefPtr;
521struct _xmlSchemaModelGroupDef {
522 xmlSchemaTypeType type;
523 const xmlChar *name;
524 const xmlChar *targetNamespace;
525 xmlSchemaModelGroupPtr modelGroup;
526 xmlSchemaAnnotPtr annot;
527};
528
Daniel Veillard4255d502002-04-16 15:50:10 +0000529/************************************************************************
530 * *
531 * Some predeclarations *
532 * *
533 ************************************************************************/
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000534
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000535static int xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt,
536 xmlSchemaPtr schema,
537 xmlNodePtr node);
Daniel Veillard01fa6152004-06-29 17:04:39 +0000538static void
539xmlSchemaTypeFixup(xmlSchemaTypePtr typeDecl,
540 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name);
541static const char *
542xmlSchemaFacetTypeToString(xmlSchemaTypeType type);
543static int
544xmlSchemaValidateSimpleTypeValue(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000545 xmlSchemaTypePtr type,
Daniel Veillard01fa6152004-06-29 17:04:39 +0000546 const xmlChar *value,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000547 int fireErrors,
Daniel Veillardc0826a72004-08-10 14:17:33 +0000548 int applyFacets,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000549 int normalize,
550 int checkNodes);
551static int
552xmlSchemaValidateElementByDeclaration(xmlSchemaValidCtxtPtr ctxt,
553 xmlSchemaElementPtr elemDecl);
554static int
555xmlSchemaValidateElementByWildcard(xmlSchemaValidCtxtPtr ctxt,
556 xmlSchemaTypePtr type);
557static int
558xmlSchemaHasElemOrCharContent(xmlNodePtr node);
William M. Brack2f2a6632004-08-20 23:09:47 +0000559static int
560xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
561 xmlNodePtr node);
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +0000562static void
563xmlSchemaCheckDefaults(xmlSchemaTypePtr typeDecl,
564 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name);
William M. Brack87640d52004-04-17 14:58:15 +0000565
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000566/************************************************************************
567 * *
568 * Datatype error handlers *
569 * *
570 ************************************************************************/
571
572/**
573 * xmlSchemaPErrMemory:
574 * @node: a context node
575 * @extra: extra informations
576 *
577 * Handle an out of memory condition
578 */
579static void
580xmlSchemaPErrMemory(xmlSchemaParserCtxtPtr ctxt,
581 const char *extra, xmlNodePtr node)
582{
583 if (ctxt != NULL)
584 ctxt->nberrors++;
585 __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, node, NULL,
586 extra);
587}
588
589/**
590 * xmlSchemaPErr:
591 * @ctxt: the parsing context
592 * @node: the context node
593 * @error: the error code
594 * @msg: the error message
595 * @str1: extra data
596 * @str2: extra data
597 *
598 * Handle a parser error
599 */
600static void
601xmlSchemaPErr(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
602 const char *msg, const xmlChar * str1, const xmlChar * str2)
603{
604 xmlGenericErrorFunc channel = NULL;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000605 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000606 void *data = NULL;
607
608 if (ctxt != NULL) {
609 ctxt->nberrors++;
610 channel = ctxt->error;
611 data = ctxt->userData;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000612 schannel = ctxt->serror;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000613 }
Daniel Veillard659e71e2003-10-10 14:10:40 +0000614 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000615 error, XML_ERR_ERROR, NULL, 0,
616 (const char *) str1, (const char *) str2, NULL, 0, 0,
617 msg, str1, str2);
618}
619
620/**
621 * xmlSchemaPErr2:
622 * @ctxt: the parsing context
623 * @node: the context node
624 * @node: the current child
625 * @error: the error code
626 * @msg: the error message
627 * @str1: extra data
628 * @str2: extra data
629 *
630 * Handle a parser error
631 */
632static void
633xmlSchemaPErr2(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
634 xmlNodePtr child, int error,
635 const char *msg, const xmlChar * str1, const xmlChar * str2)
636{
637 if (child != NULL)
638 xmlSchemaPErr(ctxt, child, error, msg, str1, str2);
639 else
640 xmlSchemaPErr(ctxt, node, error, msg, str1, str2);
641}
642
Daniel Veillard01fa6152004-06-29 17:04:39 +0000643
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000644/**
Daniel Veillard3646d642004-06-02 19:19:14 +0000645 * xmlSchemaPErrExt:
646 * @ctxt: the parsing context
647 * @node: the context node
648 * @error: the error code
649 * @strData1: extra data
650 * @strData2: extra data
651 * @strData3: extra data
652 * @msg: the message
653 * @str1: extra parameter for the message display
654 * @str2: extra parameter for the message display
655 * @str3: extra parameter for the message display
656 * @str4: extra parameter for the message display
657 * @str5: extra parameter for the message display
658 *
659 * Handle a parser error
660 */
661static void
662xmlSchemaPErrExt(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
663 const xmlChar * strData1, const xmlChar * strData2,
664 const xmlChar * strData3, const char *msg, const xmlChar * str1,
665 const xmlChar * str2, const xmlChar * str3, const xmlChar * str4,
666 const xmlChar * str5)
667{
668
669 xmlGenericErrorFunc channel = NULL;
670 xmlStructuredErrorFunc schannel = NULL;
671 void *data = NULL;
672
673 if (ctxt != NULL) {
674 ctxt->nberrors++;
675 channel = ctxt->error;
676 data = ctxt->userData;
677 schannel = ctxt->serror;
678 }
679 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
680 error, XML_ERR_ERROR, NULL, 0,
681 (const char *) strData1, (const char *) strData2,
William M. Brack803812b2004-06-03 02:11:24 +0000682 (const char *) strData3, 0, 0, msg, str1, str2,
683 str3, str4, str5);
Daniel Veillard3646d642004-06-02 19:19:14 +0000684}
Daniel Veillard01fa6152004-06-29 17:04:39 +0000685
Daniel Veillard3646d642004-06-02 19:19:14 +0000686
687/**
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000688 * xmlSchemaVTypeErrMemory:
689 * @node: a context node
690 * @extra: extra informations
691 *
692 * Handle an out of memory condition
693 */
694static void
695xmlSchemaVErrMemory(xmlSchemaValidCtxtPtr ctxt,
696 const char *extra, xmlNodePtr node)
697{
698 if (ctxt != NULL) {
699 ctxt->nberrors++;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +0000700 ctxt->err = XML_SCHEMAV_INTERNAL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000701 }
702 __xmlSimpleError(XML_FROM_SCHEMASV, XML_ERR_NO_MEMORY, node, NULL,
703 extra);
704}
705
706/**
707 * xmlSchemaVErr3:
708 * @ctxt: the validation context
709 * @node: the context node
710 * @error: the error code
711 * @msg: the error message
712 * @str1: extra data
713 * @str2: extra data
714 * @str3: extra data
715 *
716 * Handle a validation error
717 */
718static void
719xmlSchemaVErr3(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node, int error,
720 const char *msg, const xmlChar *str1, const xmlChar *str2,
721 const xmlChar *str3)
722{
Daniel Veillard659e71e2003-10-10 14:10:40 +0000723 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000724 xmlGenericErrorFunc channel = NULL;
725 void *data = NULL;
726
727 if (ctxt != NULL) {
728 ctxt->nberrors++;
729 ctxt->err = error;
730 channel = ctxt->error;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000731 schannel = ctxt->serror;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000732 data = ctxt->userData;
733 }
734 /* reajust to global error numbers */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +0000735 /* Removed, since the old schema error codes have been
736 * substituted for the global error codes.
737 *
738 * error += XML_SCHEMAV_NOROOT - XML_SCHEMAS_ERR_NOROOT;
739 */
Daniel Veillard659e71e2003-10-10 14:10:40 +0000740 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASV,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000741 error, XML_ERR_ERROR, NULL, 0,
742 (const char *) str1, (const char *) str2,
743 (const char *) str3, 0, 0,
744 msg, str1, str2, str3);
745}
Daniel Veillardc0826a72004-08-10 14:17:33 +0000746
747/**
748 * xmlSchemaVErrExt:
749 * @ctxt: the validation context
750 * @node: the context node
751 * @error: the error code
752 * @msg: the message
753 * @str1: extra parameter for the message display
754 * @str2: extra parameter for the message display
755 * @str3: extra parameter for the message display
756 * @str4: extra parameter for the message display
757 * @str5: extra parameter for the message display
758 *
759 * Handle a validation error
760 */
761static void
762xmlSchemaVErrExt(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node, int error,
763 const char *msg, const xmlChar * str1,
764 const xmlChar * str2, const xmlChar * str3,
765 const xmlChar * str4, const xmlChar * str5)
766{
767 xmlStructuredErrorFunc schannel = NULL;
768 xmlGenericErrorFunc channel = NULL;
769 void *data = NULL;
770
771 if (ctxt != NULL) {
772 ctxt->nberrors++;
773 ctxt->err = error;
774 channel = ctxt->error;
775 schannel = ctxt->serror;
776 data = ctxt->userData;
777 }
778 /* reajust to global error numbers */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +0000779 /* Removed, since the old schema error codes have been
780 * substituted for the global error codes.
781 *
782 * error += XML_SCHEMAV_NOROOT - XML_SCHEMAS_ERR_NOROOT;
783 */
Daniel Veillardc0826a72004-08-10 14:17:33 +0000784 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
785 error, XML_ERR_ERROR, NULL, 0, NULL, NULL, NULL, 0, 0,
786 msg, str1, str2, str3, str4, str5);
787}
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000788/**
789 * xmlSchemaVErr:
790 * @ctxt: the validation context
791 * @node: the context node
792 * @error: the error code
793 * @msg: the error message
794 * @str1: extra data
795 * @str2: extra data
796 *
797 * Handle a validation error
798 */
799static void
800xmlSchemaVErr(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr node, int error,
801 const char *msg, const xmlChar * str1, const xmlChar * str2)
802{
Daniel Veillard659e71e2003-10-10 14:10:40 +0000803 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000804 xmlGenericErrorFunc channel = NULL;
805 void *data = NULL;
806
807 if (ctxt != NULL) {
808 ctxt->nberrors++;
809 ctxt->err = error;
810 channel = ctxt->error;
811 data = ctxt->userData;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000812 schannel = ctxt->serror;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000813 }
814 /* reajust to global error numbers */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +0000815 /* Removed, since the old schema error codes have been
816 * substituted for the global error codes.
817 *
818 * error += XML_SCHEMAV_NOROOT - XML_SCHEMAS_ERR_NOROOT;
819 */
Daniel Veillard659e71e2003-10-10 14:10:40 +0000820 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASV,
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000821 error, XML_ERR_ERROR, NULL, 0,
822 (const char *) str1, (const char *) str2, NULL, 0, 0,
823 msg, str1, str2);
824}
Daniel Veillard4255d502002-04-16 15:50:10 +0000825
Daniel Veillardc0826a72004-08-10 14:17:33 +0000826/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000827 * xmlSchemaGetAttrName:
Daniel Veillardc0826a72004-08-10 14:17:33 +0000828 * @attr: the attribute declaration/use
829 *
830 * Returns the name of the attribute; if the attribute
831 * is a reference, the name of the referenced global type will be returned.
832 */
833static const xmlChar *
834xmlSchemaGetAttrName(xmlSchemaAttributePtr attr)
835{
836 if (attr->ref != NULL)
837 return(attr->ref);
838 else
839 return(attr->name);
840}
841
842/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000843 * xmlSchemaGetAttrTargetNsURI:
Daniel Veillardc0826a72004-08-10 14:17:33 +0000844 * @type: the type (element or attribute)
845 *
846 * Returns the target namespace URI of the type; if the type is a reference,
847 * the target namespace of the referenced type will be returned.
848 */
849static const xmlChar *
850xmlSchemaGetAttrTargetNsURI(xmlSchemaAttributePtr attr)
851{
852 if (attr->ref != NULL)
853 return (attr->refNs);
854 else
855 return(attr->targetNamespace);
856}
857
858/**
859 * xmlSchemaFormatNsUriLocal:
860 * @buf: the string buffer
861 * @uri: the namespace URI
862 * @local: the local name
863 *
864 * Returns a representation of the given URI used
865 * for error reports.
866 *
867 * Returns an empty string, if @ns is NULL, a formatted
868 * string otherwise.
869 */
870static const xmlChar*
871xmlSchemaFormatNsUriLocal(xmlChar **buf,
872 const xmlChar *uri, const xmlChar *local)
873{
874 if (*buf != NULL)
875 xmlFree(*buf);
876 if (uri == NULL) {
877 *buf = xmlStrdup(BAD_CAST "{'");
878 *buf = xmlStrcat(*buf, local);
879 } else {
880 *buf = xmlStrdup(BAD_CAST "{'");
881 *buf = xmlStrcat(*buf, uri);
882 *buf = xmlStrcat(*buf, BAD_CAST "', '");
883 *buf = xmlStrcat(*buf, local);
884 }
885 *buf = xmlStrcat(*buf, BAD_CAST "'}");
886 return ((const xmlChar *) *buf);
887}
888
889/**
890 * xmlSchemaFormatNsPrefixLocal:
891 * @buf: the string buffer
892 * @ns: the namespace
893 * @local: the local name
894 *
895 * Returns a representation of the given URI used
896 * for error reports.
897 *
898 * Returns an empty string, if @ns is NULL, a formatted
899 * string otherwise.
900 */
901static const xmlChar*
902xmlSchemaFormatNsPrefixLocal(xmlChar **buf,
903 xmlNsPtr ns, const xmlChar *local)
904{
905 if (*buf != NULL) {
906 xmlFree(*buf);
907 *buf = NULL;
908 }
909 if ((ns == NULL) || (ns->prefix == NULL))
910 return(local);
911 else {
912 *buf = xmlStrdup(ns->prefix);
913 *buf = xmlStrcat(*buf, BAD_CAST ":");
914 *buf = xmlStrcat(*buf, local);
915 }
916 return ((const xmlChar *) *buf);
917}
918
919/**
920 * xmlSchemaFormatItemForReport:
921 * @buf: the string buffer
922 * @itemDes: the designation of the item
923 * @itemName: the name of the item
924 * @item: the item as an object
925 * @itemNode: the node of the item
926 * @local: the local name
927 * @parsing: if the function is used during the parse
928 *
929 * Returns a representation of the given item used
930 * for error reports.
931 *
932 * The following order is used to build the resulting
933 * designation if the arguments are not NULL:
934 * 1a. If itemDes not NULL -> itemDes
935 * 1b. If (itemDes not NULL) and (itemName not NULL)
936 * -> itemDes + itemName
937 * 2. If the preceding was NULL and (item not NULL) -> item
938 * 3. If the preceding was NULL and (itemNode not NULL) -> itemNode
939 *
940 * If the itemNode is an attribute node, the name of the attribute
941 * will be appended to the result.
942 *
943 * Returns the formatted string and sets @buf to the resulting value.
944 */
945static xmlChar*
946xmlSchemaFormatItemForReport(xmlChar **buf,
947 const xmlChar *itemDes,
948 xmlSchemaTypePtr item,
949 xmlNodePtr itemNode,
950 int parsing)
951{
952 xmlChar *str = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +0000953 int named = 1;
Daniel Veillardc0826a72004-08-10 14:17:33 +0000954
955 if (*buf != NULL) {
956 xmlFree(*buf);
957 *buf = NULL;
958 }
959
William M. Brack2f2a6632004-08-20 23:09:47 +0000960 if (itemDes != NULL) {
961 *buf = xmlStrdup(itemDes);
962 } else if (item != NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000963 switch (item->type) {
964 case XML_SCHEMA_TYPE_BASIC:
Daniel Veillardc0826a72004-08-10 14:17:33 +0000965 if (item->builtInType == XML_SCHEMAS_ANYTYPE)
966 *buf = xmlStrdup(BAD_CAST "'anyType'");
967 else if (item->builtInType == XML_SCHEMAS_ANYSIMPLETYPE)
968 *buf = xmlStrdup(BAD_CAST "'anySimpleType'");
969 else {
970 /* *buf = xmlStrdup(BAD_CAST "bi "); */
971 /* *buf = xmlStrcat(*buf, xmlSchemaElemDesST); */
972 *buf = xmlStrdup(BAD_CAST "'");
973 *buf = xmlStrcat(*buf, item->name);
974 *buf = xmlStrcat(*buf, BAD_CAST "'");
975 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000976 break;
977 case XML_SCHEMA_TYPE_SIMPLE:
Daniel Veillardc0826a72004-08-10 14:17:33 +0000978 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL) {
979 *buf = xmlStrdup(xmlSchemaElemDesST);
980 *buf = xmlStrcat(*buf, BAD_CAST " '");
981 *buf = xmlStrcat(*buf, item->name);
982 *buf = xmlStrcat(*buf, BAD_CAST "'");
983 } else {
984 *buf = xmlStrdup(xmlSchemaElemDesST);
Daniel Veillardc0826a72004-08-10 14:17:33 +0000985 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000986 break;
987 case XML_SCHEMA_TYPE_COMPLEX:
Daniel Veillardc0826a72004-08-10 14:17:33 +0000988 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL) {
989 *buf = xmlStrdup(xmlSchemaElemDesCT);
990 *buf = xmlStrcat(*buf, BAD_CAST " '");
991 *buf = xmlStrcat(*buf, item->name);
992 *buf = xmlStrcat(*buf, BAD_CAST "'");
993 } else {
994 *buf = xmlStrdup(xmlSchemaElemDesCT);
Daniel Veillardc0826a72004-08-10 14:17:33 +0000995 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000996 break;
997 case XML_SCHEMA_TYPE_ATTRIBUTE: {
998 xmlSchemaAttributePtr attr;
999
1000 attr = (xmlSchemaAttributePtr) item;
1001 if ((attr->flags & XML_SCHEMAS_TYPE_GLOBAL) ||
1002 (attr->ref == NULL)) {
1003 *buf = xmlStrdup(xmlSchemaElemDesAttrDecl);
1004 *buf = xmlStrcat(*buf, BAD_CAST " '");
1005 *buf = xmlStrcat(*buf, attr->name);
1006 *buf = xmlStrcat(*buf, BAD_CAST "'");
1007 } else {
1008 *buf = xmlStrdup(xmlSchemaElemDesAttrRef);
1009 *buf = xmlStrcat(*buf, BAD_CAST " '");
1010 *buf = xmlStrcat(*buf, attr->refPrefix);
1011 *buf = xmlStrcat(*buf, BAD_CAST ":");
1012 *buf = xmlStrcat(*buf, attr->ref);
1013 *buf = xmlStrcat(*buf, BAD_CAST "'");
1014 }
1015 }
1016 break;
1017 case XML_SCHEMA_TYPE_ELEMENT: {
1018 xmlSchemaElementPtr elem;
Daniel Veillardc0826a72004-08-10 14:17:33 +00001019
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001020 elem = (xmlSchemaElementPtr) item;
1021 if ((elem->flags & XML_SCHEMAS_TYPE_GLOBAL) ||
1022 (elem->ref == NULL)) {
1023 *buf = xmlStrdup(xmlSchemaElemDesElemDecl);
1024 *buf = xmlStrcat(*buf, BAD_CAST " '");
1025 *buf = xmlStrcat(*buf, elem->name);
1026 *buf = xmlStrcat(*buf, BAD_CAST "'");
1027 } else {
1028 *buf = xmlStrdup(xmlSchemaElemDesElemRef);
1029 *buf = xmlStrcat(*buf, BAD_CAST " '");
1030 *buf = xmlStrcat(*buf, elem->refPrefix);
1031 *buf = xmlStrcat(*buf, BAD_CAST ":");
1032 *buf = xmlStrcat(*buf, elem->ref);
1033 *buf = xmlStrcat(*buf, BAD_CAST "'");
1034 }
1035 }
1036 break;
1037 case XML_SCHEMA_TYPE_IDC_UNIQUE:
1038 case XML_SCHEMA_TYPE_IDC_KEY:
1039 case XML_SCHEMA_TYPE_IDC_KEYREF:
1040 if (item->type == XML_SCHEMA_TYPE_IDC_UNIQUE)
1041 *buf = xmlStrdup(BAD_CAST "unique '");
1042 else if (item->type == XML_SCHEMA_TYPE_IDC_KEY)
1043 *buf = xmlStrdup(BAD_CAST "key '");
1044 else
1045 *buf = xmlStrdup(BAD_CAST "keyRef '");
1046 *buf = xmlStrcat(*buf, ((xmlSchemaIDCPtr) item)->name);
1047 *buf = xmlStrcat(*buf, BAD_CAST "'");
1048 break;
1049 default:
William M. Brack2f2a6632004-08-20 23:09:47 +00001050 named = 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001051 }
William M. Brack2f2a6632004-08-20 23:09:47 +00001052 } else
1053 named = 0;
1054
1055 if ((named == 0) && (itemNode != NULL)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00001056 xmlNodePtr elem;
1057
1058 if (itemNode->type == XML_ATTRIBUTE_NODE)
1059 elem = itemNode->parent;
1060 else
1061 elem = itemNode;
1062 *buf = xmlStrdup(BAD_CAST "Element '");
1063 if (parsing)
1064 *buf = xmlStrcat(*buf, elem->name);
1065 else
1066 *buf = xmlStrcat(*buf,
1067 xmlSchemaFormatNsPrefixLocal(&str, elem->ns, elem->name));
1068 *buf = xmlStrcat(*buf, BAD_CAST "'");
1069 }
1070 if ((itemNode != NULL) && (itemNode->type == XML_ATTRIBUTE_NODE)) {
1071 *buf = xmlStrcat(*buf, BAD_CAST ", attribute '");
1072 *buf = xmlStrcat(*buf, xmlSchemaFormatNsPrefixLocal(&str,
1073 itemNode->ns, itemNode->name));
1074 *buf = xmlStrcat(*buf, BAD_CAST "'");
1075 }
1076 FREE_AND_NULL(str);
1077
1078 return (*buf);
1079}
1080
1081/**
1082 * xmlSchemaPFormatItemDes:
1083 * @buf: the string buffer
1084 * @item: the item as a schema object
1085 * @itemNode: the item as a node
1086 *
1087 * If the pointer to @buf is not NULL and @but holds no value,
1088 * the value is set to a item designation using
1089 * xmlSchemaFormatItemForReport. This one avoids adding
1090 * an attribute designation postfix.
1091 *
1092 * Returns a string of all enumeration elements.
1093 */
1094static void
1095xmlSchemaPRequestItemDes(xmlChar **buf,
1096 xmlSchemaTypePtr item,
1097 xmlNodePtr itemNode)
1098{
1099 if ((buf == 0) || (*buf != NULL))
1100 return;
1101 if (itemNode->type == XML_ATTRIBUTE_NODE)
1102 itemNode = itemNode->parent;
1103 xmlSchemaFormatItemForReport(buf, NULL, item, itemNode, 1);
1104}
1105
1106/**
1107 * xmlSchemaFormatFacetEnumSet:
1108 * @buf: the string buffer
1109 * @type: the type holding the enumeration facets
1110 *
1111 * Builds a string consisting of all enumeration elements.
1112 *
1113 * Returns a string of all enumeration elements.
1114 */
1115static const xmlChar *
1116xmlSchemaFormatFacetEnumSet(xmlChar **buf, xmlSchemaTypePtr type)
1117{
1118 xmlSchemaFacetLinkPtr link;
1119
1120 if (*buf != NULL)
1121 xmlFree(*buf);
1122 *buf = NULL;
1123 for (link = type->facetSet; link != NULL; link = link->next) {
1124 if (link->facet->type == XML_SCHEMA_FACET_ENUMERATION) {
1125 if (*buf == NULL) {
1126 *buf = xmlStrdup(BAD_CAST "'");
1127 *buf = xmlStrcat(*buf, link->facet->value);
1128 *buf = xmlStrcat(*buf, BAD_CAST "'");
1129 } else {
1130 *buf = xmlStrcat(*buf, BAD_CAST ", '");
1131 *buf = xmlStrcat(*buf, link->facet->value);
1132 *buf = xmlStrcat(*buf, BAD_CAST "'");
1133 }
1134 }
1135 }
1136 return ((const xmlChar *) *buf);
1137}
1138
1139/**
1140 * xmlSchemaVFacetErr:
1141 * @ctxt: the schema validation context
1142 * @error: the error code
1143 * @node: the node to be validated
1144 * @value: the value of the node
1145 * @type: the type holding the facet
1146 * @facet: the facet
1147 * @message: the error message of NULL
1148 * @str1: extra data
1149 * @str2: extra data
1150 * @str3: extra data
1151 *
1152 * Reports a facet validation error.
1153 * TODO: Should this report the value of an element as well?
1154 */
1155static void
1156xmlSchemaVFacetErr(xmlSchemaValidCtxtPtr ctxt,
1157 xmlParserErrors error,
1158 xmlNodePtr node,
1159 const xmlChar *value,
1160 unsigned long length,
1161 xmlSchemaTypePtr type,
1162 xmlSchemaFacetPtr facet,
1163 const char *message,
1164 const xmlChar *str1,
1165 const xmlChar *str2,
1166 const xmlChar *str3)
1167{
1168 xmlChar *str = NULL, *msg = NULL;
1169 xmlSchemaTypeType facetType;
1170
1171 xmlSchemaFormatItemForReport(&msg, NULL, NULL, node, 0);
1172 msg = xmlStrcat(msg, BAD_CAST " [");
1173 msg = xmlStrcat(msg, xmlSchemaFormatItemForReport(&str, NULL, type, NULL, 0));
1174 msg = xmlStrcat(msg, BAD_CAST ", facet '");
1175 if (error == XML_SCHEMAV_CVC_ENUMERATION_VALID) {
1176 facetType = XML_SCHEMA_FACET_ENUMERATION;
1177 /*
1178 * If enumerations are validated, one must not expect the
1179 * facet to be given.
1180 */
1181 } else
1182 facetType = facet->type;
1183 msg = xmlStrcat(msg, BAD_CAST xmlSchemaFacetTypeToString(facetType));
1184 msg = xmlStrcat(msg, BAD_CAST "']: ");
1185 if (message == NULL) {
1186 /*
1187 * Use a default message.
1188 */
1189 if ((facetType == XML_SCHEMA_FACET_LENGTH) ||
1190 (facetType == XML_SCHEMA_FACET_MINLENGTH) ||
1191 (facetType == XML_SCHEMA_FACET_MAXLENGTH)) {
1192
1193 char len[25], actLen[25];
1194
1195 /* FIXME, TODO: What is the max expected string length of the
1196 * this value?
1197 */
1198 if (node->type == XML_ATTRIBUTE_NODE)
1199 msg = xmlStrcat(msg, BAD_CAST "The value '%s' has a length of '%s'; ");
1200 else
1201 msg = xmlStrcat(msg, BAD_CAST "The value has a length of '%s'; ");
1202
1203 snprintf(len, 24, "%lu", xmlSchemaGetFacetValueAsULong(facet));
1204 snprintf(actLen, 24, "%lu", length);
1205
1206 if (facetType == XML_SCHEMA_FACET_LENGTH)
1207 msg = xmlStrcat(msg,
1208 BAD_CAST "this differs from the allowed length of '%s'.\n");
1209 else if (facetType == XML_SCHEMA_FACET_MAXLENGTH)
1210 msg = xmlStrcat(msg,
1211 BAD_CAST "this exceeds the allowed maximum length of '%s'.\n");
1212 else if (facetType == XML_SCHEMA_FACET_MINLENGTH)
1213 msg = xmlStrcat(msg,
1214 BAD_CAST "this underruns the allowed minimum length of '%s'.\n");
1215
1216 if (node->type == XML_ATTRIBUTE_NODE)
1217 xmlSchemaVErrExt(ctxt, node, error,
1218 (const char *) msg,
1219 value, (const xmlChar *) actLen, (const xmlChar *) len,
1220 NULL, NULL);
1221 else
1222 xmlSchemaVErr(ctxt, node, error,
1223 (const char *) msg,
1224 (const xmlChar *) actLen, (const xmlChar *) len);
1225
1226 } else if (facetType == XML_SCHEMA_FACET_ENUMERATION) {
1227 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not an element "
1228 "of the set {%s}.\n");
1229 xmlSchemaVErr(ctxt, node, error, (const char *) msg, value,
1230 xmlSchemaFormatFacetEnumSet(&str, type));
1231 } else if (facetType == XML_SCHEMA_FACET_PATTERN) {
1232 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not accepted "
1233 "by the pattern '%s'.\n");
1234 xmlSchemaVErr(ctxt, node, error, (const char *) msg, value,
1235 facet->value);
1236 } else if (node->type == XML_ATTRIBUTE_NODE) {
1237 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not facet-valid.\n");
1238 xmlSchemaVErr(ctxt, node, error, (const char *) msg, value, NULL);
1239 } else {
1240 msg = xmlStrcat(msg, BAD_CAST "The value is not facet-valid.\n");
1241 xmlSchemaVErr(ctxt, node, error, (const char *) msg, NULL, NULL);
1242 }
1243 } else {
1244 msg = xmlStrcat(msg, (const xmlChar *) message);
1245 msg = xmlStrcat(msg, BAD_CAST ".\n");
1246 xmlSchemaVErr3(ctxt, node, error, (const char *) msg, str1, str2, str3);
1247 }
1248 FREE_AND_NULL(str)
1249 xmlFree(msg);
1250}
1251
1252/**
1253 * xmlSchemaVSimpleTypeErr:
1254 * @ctxt: the schema validation context
1255 * @error: the error code
1256 * @type: the type used for validation
1257 * @node: the node containing the validated value
1258 * @value: the validated value
1259 *
1260 * Reports a simple type validation error.
1261 * TODO: Should this report the value of an element as well?
1262 */
1263static void
1264xmlSchemaVSimpleTypeErr(xmlSchemaValidCtxtPtr ctxt,
1265 xmlParserErrors error,
1266 xmlNodePtr node,
1267 const xmlChar *value,
1268 xmlSchemaTypePtr type)
1269{
1270 xmlChar *str = NULL, *msg = NULL;
1271
1272 xmlSchemaFormatItemForReport(&msg, NULL, NULL, node, 0);
1273 msg = xmlStrcat(msg, BAD_CAST " [");
1274 msg = xmlStrcat(msg, xmlSchemaFormatItemForReport(&str, NULL, type, NULL, 0));
1275 if (node->type == XML_ATTRIBUTE_NODE) {
1276 msg = xmlStrcat(msg, BAD_CAST "]: The value '%s' is not valid.\n");
1277 xmlSchemaVErr(ctxt, node, error, (const char *) msg, value, NULL);
1278 } else {
1279 msg = xmlStrcat(msg, BAD_CAST "]: The character content is not valid.\n");
1280 xmlSchemaVErr(ctxt, node, error, (const char *) msg, NULL, NULL);
1281 }
1282 FREE_AND_NULL(str)
1283 xmlFree(msg);
1284}
1285
1286/**
William M. Brack2f2a6632004-08-20 23:09:47 +00001287 * xmlSchemaVComplexTypeErr:
1288 * @ctxt: the schema validation context
1289 * @error: the error code
1290 * @node: the node containing the validated value
1291 * @type: the complex type used for validation
1292 * @message: the error message
1293 *
1294 * Reports a complex type validation error.
1295 */
1296static void
1297xmlSchemaVComplexTypeErr(xmlSchemaValidCtxtPtr ctxt,
1298 xmlParserErrors error,
1299 xmlNodePtr node,
1300 xmlSchemaTypePtr type,
1301 const char *message)
1302{
1303 xmlChar *str = NULL, *msg = NULL;
1304
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00001305 xmlSchemaFormatItemForReport(&msg, NULL, NULL, node, 0);
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +00001306 /* Specify the complex type only if it is global. */
1307 if ((type != NULL) && (type->flags & XML_SCHEMAS_TYPE_GLOBAL)) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00001308 msg = xmlStrcat(msg, BAD_CAST " [");
1309 msg = xmlStrcat(msg, xmlSchemaFormatItemForReport(&str, NULL, type, NULL, 0));
1310 msg = xmlStrcat(msg, BAD_CAST "]");
1311 }
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001312 msg = xmlStrcat(msg, BAD_CAST ": %s.\n");
1313 xmlSchemaVErr(ctxt, node, error, (const char *) msg,
William M. Brack2f2a6632004-08-20 23:09:47 +00001314 (const xmlChar *) message, NULL);
1315 FREE_AND_NULL(str)
1316 xmlFree(msg);
1317}
1318
1319/**
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001320 * xmlSchemaVComplexTypeElemErr:
1321 * @ctxt: the schema validation context
1322 * @error: the error code
1323 * @node: the node containing the validated value
1324 * @type: the complex type used for validation
1325 * @message: the error message
1326 *
1327 * Reports a complex type validation error.
1328 */
1329static void
1330xmlSchemaVComplexTypeElemErr(xmlSchemaValidCtxtPtr ctxt,
1331 xmlParserErrors error,
1332 xmlNodePtr node,
1333 xmlSchemaTypePtr type,
1334 const char *message,
1335 int nbval,
1336 int nbneg,
1337 xmlChar **values)
1338{
1339 xmlChar *str = NULL, *msg = NULL;
1340 xmlChar *localName, *nsName;
1341 const xmlChar *cur, *end;
1342 int i;
1343
1344 xmlSchemaFormatItemForReport(&msg, NULL, NULL, node, 0);
1345 /* Specify the complex type only if it is global. */
1346 if ((type != NULL) && (type->flags & XML_SCHEMAS_TYPE_GLOBAL)) {
1347 msg = xmlStrcat(msg, BAD_CAST " [");
1348 msg = xmlStrcat(msg, xmlSchemaFormatItemForReport(&str, NULL, type, NULL, 0));
1349 msg = xmlStrcat(msg, BAD_CAST "]");
1350 FREE_AND_NULL(str)
1351 }
1352 msg = xmlStrcat(msg, BAD_CAST ": ");
1353 msg = xmlStrcat(msg, (const xmlChar *) message);
1354 /*
1355 * Note that is does not make sense to report that we have a
1356 * wildcard here, since the wildcard might be unfolded into
1357 * multiple transitions.
1358 */
1359 if (nbval + nbneg > 0) {
1360 if (nbval + nbneg > 1) {
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00001361 str = xmlStrdup(BAD_CAST ". Expected is one of ( ");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001362 } else
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00001363 str = xmlStrdup(BAD_CAST ". Expected is ( ");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001364 nsName = NULL;
1365
1366 for (i = 0; i < nbval + nbneg; i++) {
1367 cur = values[i];
1368 /*
1369 * Get the local name.
1370 */
1371 localName = NULL;
1372
1373 end = cur;
1374 if (*end == '*') {
1375 localName = xmlStrdup(BAD_CAST "*");
1376 *end++;
1377 } else {
1378 while ((*end != 0) && (*end != '|'))
1379 end++;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001380 localName = xmlStrncat(localName, BAD_CAST cur, end - cur);
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001381 }
1382 if (*end != 0) {
1383 *end++;
1384 /*
1385 * Skip "*|*" if they come with negated expressions, since
1386 * they represent the same negated wildcard.
1387 */
1388 if ((nbneg == 0) || (*end != '*') || (*localName != '*')) {
1389 /*
1390 * Get the namespace name.
1391 */
1392 cur = end;
1393 if (*end == '*') {
1394 nsName = xmlStrdup(BAD_CAST "{*}");
1395 } else {
1396 while (*end != 0)
1397 end++;
1398
1399 if (i >= nbval)
1400 nsName = xmlStrdup(BAD_CAST "{##other:");
1401 else
1402 nsName = xmlStrdup(BAD_CAST "{");
1403
1404 nsName = xmlStrncat(nsName, BAD_CAST cur, end - cur);
1405 nsName = xmlStrcat(nsName, BAD_CAST "}");
1406 }
1407 str = xmlStrcat(str, BAD_CAST nsName);
1408 FREE_AND_NULL(nsName)
1409 } else {
1410 FREE_AND_NULL(localName);
1411 continue;
1412 }
1413 }
1414 str = xmlStrcat(str, BAD_CAST localName);
1415 FREE_AND_NULL(localName);
1416
1417 if (i < nbval + nbneg -1)
1418 str = xmlStrcat(str, BAD_CAST ", ");
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00001419 }
1420 str = xmlStrcat(str, BAD_CAST " )");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00001421 msg = xmlStrcat(msg, BAD_CAST str);
1422 FREE_AND_NULL(str)
1423 }
1424 msg = xmlStrcat(msg, BAD_CAST ".\n");
1425 xmlSchemaVErr(ctxt, node, error, (const char *) msg, NULL, NULL);
1426 xmlFree(msg);
1427}
1428
1429/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00001430 * xmlSchemaPMissingAttrErr:
1431 * @ctxt: the schema validation context
1432 * @ownerDes: the designation of the owner
1433 * @ownerName: the name of the owner
1434 * @ownerItem: the owner as a schema object
1435 * @ownerElem: the owner as an element node
1436 * @node: the parent element node of the missing attribute node
1437 * @type: the corresponding type of the attribute node
1438 *
1439 * Reports an illegal attribute.
1440 */
1441static void
1442xmlSchemaPMissingAttrErr(xmlSchemaParserCtxtPtr ctxt,
1443 xmlParserErrors error,
1444 xmlChar **ownerDes,
1445 xmlSchemaTypePtr ownerItem,
1446 xmlNodePtr ownerElem,
1447 const char *name,
1448 const char *message)
1449{
1450 xmlChar *des = NULL;
1451
1452 if (ownerDes == NULL)
1453 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem, 1);
1454 else if (*ownerDes == NULL) {
1455 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, ownerElem, 1);
1456 des = *ownerDes;
1457 } else
1458 des = *ownerDes;
1459 if (message != NULL)
1460 xmlSchemaPErr(ctxt, ownerElem, error, "%s: %s.\n", BAD_CAST des, BAD_CAST message);
1461 else
1462 xmlSchemaPErr(ctxt, ownerElem, error,
1463 "%s: The attribute '%s' is required but missing.\n",
1464 BAD_CAST des, BAD_CAST name);
1465 if (ownerDes == NULL)
1466 FREE_AND_NULL(des);
1467}
1468
William M. Brack2f2a6632004-08-20 23:09:47 +00001469/**
1470 * xmlSchemaCompTypeToString:
1471 * @type: the type of the schema item
1472 *
1473 * Returns the component name of a schema item.
1474 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001475static const char *
1476xmlSchemaCompTypeToString(xmlSchemaTypeType type)
1477{
1478 switch (type) {
1479 case XML_SCHEMA_TYPE_SIMPLE:
1480 return("simple type definition");
1481 case XML_SCHEMA_TYPE_COMPLEX:
1482 return("complex type definition");
1483 case XML_SCHEMA_TYPE_ELEMENT:
1484 return("element declaration");
1485 case XML_SCHEMA_TYPE_ATTRIBUTE:
1486 return("attribute declaration");
1487 case XML_SCHEMA_TYPE_GROUP:
1488 return("model group definition");
1489 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1490 return("attribute group definition");
1491 case XML_SCHEMA_TYPE_NOTATION:
1492 return("notation declaration");
1493 default:
1494 return("Not a schema component");
1495 }
1496}
1497/**
1498 * xmlSchemaPResCompAttrErr:
1499 * @ctxt: the schema validation context
1500 * @error: the error code
1501 * @ownerDes: the designation of the owner
1502 * @ownerItem: the owner as a schema object
1503 * @ownerElem: the owner as an element node
1504 * @name: the name of the attribute holding the QName
1505 * @refName: the referenced local name
1506 * @refURI: the referenced namespace URI
1507 * @message: optional message
1508 *
1509 * Used to report QName attribute values that failed to resolve
1510 * to schema components.
1511 */
1512static void
1513xmlSchemaPResCompAttrErr(xmlSchemaParserCtxtPtr ctxt,
1514 xmlParserErrors error,
1515 xmlChar **ownerDes,
1516 xmlSchemaTypePtr ownerItem,
1517 xmlNodePtr ownerElem,
1518 const char *name,
1519 const xmlChar *refName,
1520 const xmlChar *refURI,
1521 xmlSchemaTypeType refType,
1522 const char *refTypeStr)
1523{
1524 xmlChar *des = NULL, *strA = NULL;
1525
1526 if (ownerDes == NULL)
1527 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem, 1);
1528 else if (*ownerDes == NULL) {
1529 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, ownerElem, 1);
1530 des = *ownerDes;
1531 } else
1532 des = *ownerDes;
Daniel Veillardc0826a72004-08-10 14:17:33 +00001533 if (refTypeStr == NULL)
1534 refTypeStr = xmlSchemaCompTypeToString(refType);
1535 xmlSchemaPErrExt(ctxt, ownerElem, error,
1536 NULL, NULL, NULL,
1537 "%s, attribute '%s': The QName value %s does not resolve to a(n) "
1538 "%s.\n", BAD_CAST des, BAD_CAST name,
1539 xmlSchemaFormatNsUriLocal(&strA, refURI, refName),
1540 BAD_CAST refTypeStr, NULL);
1541 if (ownerDes == NULL)
1542 FREE_AND_NULL(des)
1543 FREE_AND_NULL(strA)
1544}
1545
William M. Brack2f2a6632004-08-20 23:09:47 +00001546/**
1547 * xmlSchemaPCustomAttrErr:
1548 * @ctxt: the schema parser context
1549 * @error: the error code
1550 * @ownerDes: the designation of the owner
1551 * @ownerItem: the owner as a schema object
1552 * @attr: the illegal attribute node
1553 *
1554 * Reports an illegal attribute during the parse.
1555 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001556static void
1557xmlSchemaPCustomAttrErr(xmlSchemaParserCtxtPtr ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00001558 xmlParserErrors error,
1559 xmlChar **ownerDes,
1560 xmlSchemaTypePtr ownerItem,
1561 xmlAttrPtr attr,
1562 const char *msg)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001563{
1564 xmlChar *des = NULL;
1565
1566 if (ownerDes == NULL)
1567 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent, 1);
1568 else if (*ownerDes == NULL) {
1569 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent, 1);
1570 des = *ownerDes;
1571 } else
1572 des = *ownerDes;
1573 xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
1574 "%s, attribute '%s': %s.\n",
1575 BAD_CAST des, attr->name, (const xmlChar *) msg, NULL, NULL);
1576 if (ownerDes == NULL)
1577 FREE_AND_NULL(des);
1578}
1579
1580/**
1581 * xmlSchemaPIllegalAttrErr:
William M. Brack2f2a6632004-08-20 23:09:47 +00001582 * @ctxt: the schema parser context
Daniel Veillardc0826a72004-08-10 14:17:33 +00001583 * @error: the error code
William M. Brack2f2a6632004-08-20 23:09:47 +00001584 * @ownerDes: the designation of the attribute's owner
1585 * @ownerItem: the attribute's owner item
Daniel Veillardc0826a72004-08-10 14:17:33 +00001586 * @attr: the illegal attribute node
1587 *
William M. Brack2f2a6632004-08-20 23:09:47 +00001588 * Reports an illegal attribute during the parse.
Daniel Veillardc0826a72004-08-10 14:17:33 +00001589 */
1590static void
1591xmlSchemaPIllegalAttrErr(xmlSchemaParserCtxtPtr ctxt,
1592 xmlParserErrors error,
1593 xmlChar **ownerDes,
1594 xmlSchemaTypePtr ownerItem,
1595 xmlAttrPtr attr)
1596{
1597 xmlChar *des = NULL, *strA = NULL;
1598
1599 if (ownerDes == NULL)
1600 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent, 1);
1601 else if (*ownerDes == NULL) {
1602 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent, 1);
1603 des = *ownerDes;
1604 } else
1605 des = *ownerDes;
1606 xmlSchemaPErr(ctxt, (xmlNodePtr) attr, error,
1607 "%s: The attribute '%s' is not allowed.\n", BAD_CAST des,
1608 xmlSchemaFormatNsPrefixLocal(&strA, attr->ns, attr->name));
1609 if (ownerDes == NULL)
1610 FREE_AND_NULL(des);
1611 FREE_AND_NULL(strA);
1612}
1613
William M. Brack2f2a6632004-08-20 23:09:47 +00001614/**
1615 * xmlSchemaPAquireDes:
1616 * @des: the first designation
1617 * @itemDes: the second designation
1618 * @item: the schema item
1619 * @itemElem: the node of the schema item
1620 *
1621 * Creates a designation for an item.
1622 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001623static void
1624xmlSchemaPAquireDes(xmlChar **des,
1625 xmlChar **itemDes,
1626 xmlSchemaTypePtr item,
1627 xmlNodePtr itemElem)
1628{
1629 if (itemDes == NULL)
1630 xmlSchemaFormatItemForReport(des, NULL, item, itemElem, 1);
1631 else if (*itemDes == NULL) {
1632 xmlSchemaFormatItemForReport(itemDes, NULL, item, itemElem, 1);
1633 *des = *itemDes;
1634 } else
1635 *des = *itemDes;
1636}
1637
William M. Brack2f2a6632004-08-20 23:09:47 +00001638/**
1639 * xmlSchemaPCustomErr:
1640 * @ctxt: the schema parser context
1641 * @error: the error code
1642 * @itemDes: the designation of the schema item
1643 * @item: the schema item
1644 * @itemElem: the node of the schema item
1645 * @message: the error message
1646 * @str1: an optional param for the error message
1647 * @str2: an optional param for the error message
1648 * @str3: an optional param for the error message
1649 *
1650 * Reports an error during parsing.
1651 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001652static void
1653xmlSchemaPCustomErrExt(xmlSchemaParserCtxtPtr ctxt,
1654 xmlParserErrors error,
1655 xmlChar **itemDes,
1656 xmlSchemaTypePtr item,
1657 xmlNodePtr itemElem,
1658 const char *message,
1659 const xmlChar *str1,
1660 const xmlChar *str2,
1661 const xmlChar *str3)
1662{
1663 xmlChar *des = NULL, *msg = NULL;
1664
1665 xmlSchemaPAquireDes(&des, itemDes, item, itemElem);
1666 msg = xmlStrdup(BAD_CAST "%s: ");
1667 msg = xmlStrcat(msg, (const xmlChar *) message);
1668 msg = xmlStrcat(msg, BAD_CAST ".\n");
1669 if ((itemElem == NULL) && (item != NULL))
1670 itemElem = item->node;
1671 xmlSchemaPErrExt(ctxt, itemElem, error, NULL, NULL, NULL,
1672 (const char *) msg, BAD_CAST des, str1, str2, str3, NULL);
1673 if (itemDes == NULL)
1674 FREE_AND_NULL(des);
1675 FREE_AND_NULL(msg);
1676}
1677
William M. Brack2f2a6632004-08-20 23:09:47 +00001678/**
1679 * xmlSchemaPCustomErr:
1680 * @ctxt: the schema parser context
1681 * @error: the error code
1682 * @itemDes: the designation of the schema item
1683 * @item: the schema item
1684 * @itemElem: the node of the schema item
1685 * @message: the error message
1686 * @str1: the optional param for the error message
1687 *
1688 * Reports an error during parsing.
1689 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001690static void
1691xmlSchemaPCustomErr(xmlSchemaParserCtxtPtr ctxt,
1692 xmlParserErrors error,
1693 xmlChar **itemDes,
1694 xmlSchemaTypePtr item,
1695 xmlNodePtr itemElem,
1696 const char *message,
1697 const xmlChar *str1)
1698{
1699 xmlSchemaPCustomErrExt(ctxt, error, itemDes, item, itemElem, message,
1700 str1, NULL, NULL);
1701}
1702
William M. Brack2f2a6632004-08-20 23:09:47 +00001703/**
1704 * xmlSchemaPAttrUseErr:
1705 * @ctxt: the schema parser context
1706 * @error: the error code
1707 * @itemDes: the designation of the schema type
1708 * @item: the schema type
1709 * @itemElem: the node of the schema type
1710 * @attr: the invalid schema attribute
1711 * @message: the error message
1712 * @str1: the optional param for the error message
1713 *
1714 * Reports an attribute use error during parsing.
1715 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001716static void
1717xmlSchemaPAttrUseErr(xmlSchemaParserCtxtPtr ctxt,
1718 xmlParserErrors error,
1719 xmlChar **itemDes,
1720 xmlSchemaTypePtr item,
1721 xmlNodePtr itemElem,
1722 const xmlSchemaAttributePtr attr,
1723 const char *message,
1724 const xmlChar *str1)
1725{
1726 xmlChar *des = NULL, *strA = NULL, *msg = NULL;
1727
1728 xmlSchemaPAquireDes(&des, itemDes, item, itemElem);
1729 xmlSchemaFormatNsUriLocal(&strA, xmlSchemaGetAttrTargetNsURI(attr),
1730 xmlSchemaGetAttrName(attr));
1731 msg = xmlStrdup(BAD_CAST "%s, attr. use %s: ");
1732 msg = xmlStrcat(msg, (const xmlChar *) message);
1733 msg = xmlStrcat(msg, BAD_CAST ".\n");
1734 if ((itemElem == NULL) && (item != NULL))
1735 itemElem = item->node;
1736 xmlSchemaPErrExt(ctxt, itemElem, error, NULL, NULL, NULL,
1737 (const char *) msg, BAD_CAST des, BAD_CAST strA, str1, NULL, NULL);
1738 if (itemDes == NULL)
1739 FREE_AND_NULL(des);
1740 FREE_AND_NULL(strA);
1741 xmlFree(msg);
1742}
1743
William M. Brack2f2a6632004-08-20 23:09:47 +00001744/**
1745 * xmlSchemaPIllegalFacetAtomicErr:
1746 * @ctxt: the schema parser context
1747 * @error: the error code
1748 * @itemDes: the designation of the type
1749 * @item: the schema type
1750 * @baseItem: the base type of type
1751 * @facet: the illegal facet
1752 *
1753 * Reports an illegal facet for atomic simple types.
1754 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001755static void
1756xmlSchemaPIllegalFacetAtomicErr(xmlSchemaParserCtxtPtr ctxt,
1757 xmlParserErrors error,
1758 xmlChar **itemDes,
1759 xmlSchemaTypePtr item,
1760 xmlSchemaTypePtr baseItem,
1761 xmlSchemaFacetPtr facet)
1762{
1763 xmlChar *des = NULL, *strT = NULL;
1764
1765 xmlSchemaPAquireDes(&des, itemDes, item, item->node);
1766 xmlSchemaPErrExt(ctxt, item->node, error, NULL, NULL, NULL,
1767 "%s: The facet '%s' is not allowed on types derived from the "
1768 "type %s.\n",
1769 BAD_CAST des, BAD_CAST xmlSchemaFacetTypeToString(facet->type),
1770 xmlSchemaFormatItemForReport(&strT, NULL, baseItem, NULL, 1),
1771 NULL, NULL);
1772 if (itemDes == NULL)
1773 FREE_AND_NULL(des);
1774 FREE_AND_NULL(strT);
1775}
1776
William M. Brack2f2a6632004-08-20 23:09:47 +00001777/**
1778 * xmlSchemaPIllegalFacetListUnionErr:
1779 * @ctxt: the schema parser context
1780 * @error: the error code
1781 * @itemDes: the designation of the schema item involved
1782 * @item: the schema item involved
1783 * @facet: the illegal facet
1784 *
1785 * Reports an illegal facet for <list> and <union>.
1786 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001787static void
1788xmlSchemaPIllegalFacetListUnionErr(xmlSchemaParserCtxtPtr ctxt,
1789 xmlParserErrors error,
1790 xmlChar **itemDes,
1791 xmlSchemaTypePtr item,
1792 xmlSchemaFacetPtr facet)
1793{
1794 xmlChar *des = NULL, *strT = NULL;
1795
1796 xmlSchemaPAquireDes(&des, itemDes, item, item->node);
1797 xmlSchemaPErr(ctxt, item->node, error,
1798 "%s: The facet '%s' is not allowed.\n",
1799 BAD_CAST des, BAD_CAST xmlSchemaFacetTypeToString(facet->type));
1800 if (itemDes == NULL)
1801 FREE_AND_NULL(des);
1802 FREE_AND_NULL(strT);
1803}
1804
1805/**
1806 * xmlSchemaPMutualExclAttrErr:
1807 * @ctxt: the schema validation context
1808 * @error: the error code
1809 * @elemDes: the designation of the parent element node
1810 * @attr: the bad attribute node
1811 * @type: the corresponding type of the attribute node
1812 *
1813 * Reports an illegal attribute.
1814 */
1815static void
1816xmlSchemaPMutualExclAttrErr(xmlSchemaParserCtxtPtr ctxt,
1817 xmlParserErrors error,
1818 xmlChar **ownerDes,
1819 xmlSchemaTypePtr ownerItem,
1820 xmlAttrPtr attr,
1821 const char *name1,
1822 const char *name2)
1823{
1824 xmlChar *des = NULL;
1825
1826 if (ownerDes == NULL)
1827 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent, 1);
1828 else if (*ownerDes == NULL) {
1829 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent, 1);
1830 des = *ownerDes;
1831 } else
1832 des = *ownerDes;
1833 xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
1834 "%s: The attributes '%s' and '%s' are mutually exclusive.\n",
1835 BAD_CAST des, BAD_CAST name1, BAD_CAST name2, NULL, NULL);
1836 if (ownerDes == NULL)
1837 FREE_AND_NULL(des)
1838}
1839
1840/**
1841 * xmlSchemaPSimpleTypeErr:
1842 * @ctxt: the schema validation context
1843 * @error: the error code
William M. Brack2f2a6632004-08-20 23:09:47 +00001844 * @type: the type specifier
Daniel Veillardc0826a72004-08-10 14:17:33 +00001845 * @ownerDes: the designation of the owner
1846 * @ownerItem: the schema object if existent
1847 * @node: the validated node
1848 * @value: the validated value
1849 *
1850 * Reports a simple type validation error.
1851 * TODO: Should this report the value of an element as well?
1852 */
1853static void
1854xmlSchemaPSimpleTypeErr(xmlSchemaParserCtxtPtr ctxt,
1855 xmlParserErrors error,
1856 xmlChar **ownerDes,
1857 xmlSchemaTypePtr ownerItem,
1858 xmlNodePtr node,
William M. Brack2f2a6632004-08-20 23:09:47 +00001859 xmlSchemaTypePtr type,
Daniel Veillardc0826a72004-08-10 14:17:33 +00001860 const char *typeDes,
1861 const xmlChar *value,
1862 const char *message,
1863 const xmlChar *str1,
1864 const xmlChar *str2)
1865{
William M. Brack2f2a6632004-08-20 23:09:47 +00001866 xmlChar *des = NULL, *strA = NULL, *strT = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00001867
1868 if (ownerDes == NULL)
1869 xmlSchemaPRequestItemDes(&des, ownerItem, node);
1870 else if (*ownerDes == NULL) {
1871 xmlSchemaPRequestItemDes(ownerDes, ownerItem, node);
1872 des = *ownerDes;
1873 } else
1874 des = *ownerDes;
William M. Brack2f2a6632004-08-20 23:09:47 +00001875 if (type != NULL)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001876 typeDes = (const char *) xmlSchemaFormatItemForReport(&strT, NULL, type, NULL, 1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00001877 if (message == NULL) {
1878 /*
1879 * Use default messages.
1880 */
1881 if (node->type == XML_ATTRIBUTE_NODE) {
1882 xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL,
1883 "%s, attribute '%s' [%s]: The value '%s' is not "
1884 "valid.\n",
1885 BAD_CAST des, xmlSchemaFormatNsPrefixLocal(&strA, node->ns,
1886 node->name), BAD_CAST typeDes, value, NULL);
1887 } else {
1888 xmlSchemaPErr(ctxt, node, error,
1889 "%s [%s]: The character content is not valid.\n",
1890 BAD_CAST des, BAD_CAST typeDes);
1891 }
1892 } else {
1893 xmlChar *msg;
1894
1895 msg = xmlStrdup(BAD_CAST "%s");
1896 if (node->type == XML_ATTRIBUTE_NODE)
1897 msg = xmlStrcat(msg, BAD_CAST ", attribute '%s'");
1898 msg = xmlStrcat(msg, BAD_CAST " [%s]: ");
1899 msg = xmlStrcat(msg, (const xmlChar *) message);
1900 msg = xmlStrcat(msg, BAD_CAST ".\n");
1901 if (node->type == XML_ATTRIBUTE_NODE) {
1902 xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL,
1903 (const char *) msg,
1904 BAD_CAST des, xmlSchemaFormatNsPrefixLocal(&strA,
1905 node->ns, node->name), BAD_CAST typeDes, str1, str2);
1906 } else {
1907 xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL,
1908 (const char *) msg,
1909 BAD_CAST des, BAD_CAST typeDes, str1, str2, NULL);
1910 }
1911 xmlFree(msg);
1912 }
1913 /* Cleanup. */
1914 FREE_AND_NULL(strA)
1915 FREE_AND_NULL(strT)
1916 if (ownerDes == NULL)
1917 FREE_AND_NULL(des)
1918}
1919
William M. Brack2f2a6632004-08-20 23:09:47 +00001920/**
1921 * xmlSchemaPContentErr:
1922 * @ctxt: the schema parser context
1923 * @error: the error code
1924 * @onwerDes: the designation of the holder of the content
1925 * @ownerItem: the owner item of the holder of the content
1926 * @ownerElem: the node of the holder of the content
1927 * @child: the invalid child node
1928 * @message: the optional error message
1929 * @content: the optional string describing the correct content
1930 *
1931 * Reports an error concerning the content of a schema element.
1932 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001933static void
1934xmlSchemaPContentErr(xmlSchemaParserCtxtPtr ctxt,
1935 xmlParserErrors error,
1936 xmlChar **ownerDes,
1937 xmlSchemaTypePtr ownerItem,
1938 xmlNodePtr ownerElem,
1939 xmlNodePtr child,
1940 const char *message,
1941 const char *content)
1942{
1943 xmlChar *des = NULL;
1944
1945 if (ownerDes == NULL)
1946 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem, 1);
1947 else if (*ownerDes == NULL) {
1948 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, ownerElem, 1);
1949 des = *ownerDes;
1950 } else
1951 des = *ownerDes;
1952 if (message != NULL)
1953 xmlSchemaPErr2(ctxt, ownerElem, child, error,
1954 "%s: %s.\n",
1955 BAD_CAST des, BAD_CAST message);
1956 else {
1957 if (content != NULL) {
1958 xmlSchemaPErr2(ctxt, ownerElem, child, error,
1959 "%s: The content is not valid. Expected is %s.\n",
1960 BAD_CAST des, BAD_CAST content);
1961 } else {
1962 xmlSchemaPErr2(ctxt, ownerElem, child, error,
1963 "%s: The content is not valid.\n",
1964 BAD_CAST des, NULL);
1965 }
1966 }
1967 if (ownerDes == NULL)
1968 FREE_AND_NULL(des)
1969}
1970
1971/**
1972 * xmlSchemaVIllegalAttrErr:
1973 * @ctxt: the schema validation context
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00001974 * @error: the error code
Daniel Veillardc0826a72004-08-10 14:17:33 +00001975 * @attr: the illegal attribute node
1976 *
1977 * Reports an illegal attribute.
1978 */
1979static void
1980xmlSchemaVIllegalAttrErr(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00001981 xmlParserErrors error,
William M. Brack2f2a6632004-08-20 23:09:47 +00001982 xmlAttrPtr attr)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001983{
1984 xmlChar *strE = NULL, *strA = NULL;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00001985
1986 xmlSchemaVErr(ctxt, (xmlNodePtr) attr,
1987 error,
1988 /* XML_SCHEMAS_ERR_ATTRUNKNOWN, */
Daniel Veillardc0826a72004-08-10 14:17:33 +00001989 "%s: The attribute '%s' is not allowed.\n",
1990 xmlSchemaFormatItemForReport(&strE, NULL, NULL, attr->parent, 0),
1991 xmlSchemaFormatNsPrefixLocal(&strA, attr->ns, attr->name));
1992 FREE_AND_NULL(strE)
1993 FREE_AND_NULL(strA)
1994}
1995
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +00001996
1997static int
1998xmlSchemaIsGlobalItem(xmlSchemaTypePtr item)
1999{
2000 switch (item->type) {
2001 case XML_SCHEMA_TYPE_COMPLEX:
2002 case XML_SCHEMA_TYPE_SIMPLE:
2003 case XML_SCHEMA_TYPE_GROUP:
2004 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL)
2005 return(1);
2006 break;
2007 case XML_SCHEMA_TYPE_ELEMENT:
2008 if ( ((xmlSchemaElementPtr) item)->flags &
2009 XML_SCHEMAS_ELEM_GLOBAL)
2010 return(1);
2011 break;
2012 case XML_SCHEMA_TYPE_ATTRIBUTE:
2013 if ( ((xmlSchemaAttributePtr) item)->flags &
2014 XML_SCHEMAS_ATTR_GLOBAL)
2015 return(1);
2016 break;
2017 /* Note that attribute groups are always global. */
2018 default:
2019 return(1);
2020 }
2021 return (0);
2022}
2023
William M. Brack2f2a6632004-08-20 23:09:47 +00002024/**
2025 * xmlSchemaVCustomErr:
2026 * @ctxt: the schema validation context
2027 * @error: the error code
2028 * @node: the validated node
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002029 * @type: the schema type of the validated node
William M. Brack2f2a6632004-08-20 23:09:47 +00002030 * @message: the error message
2031 * @str1: the optional param for the message
2032 *
2033 * Reports a validation error.
2034 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002035static void
2036xmlSchemaVCustomErr(xmlSchemaValidCtxtPtr ctxt,
2037 xmlParserErrors error,
2038 xmlNodePtr node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002039 xmlSchemaTypePtr type,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002040 const char *message,
2041 const xmlChar *str1)
2042{
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002043 xmlChar *msg = NULL, *str = NULL;
2044
2045 if (node == NULL) {
2046 xmlSchemaVErr(ctxt, NULL,
2047 XML_SCHEMAV_INTERNAL,
2048 "Internal error: xmlSchemaVCustomErr, no node "
2049 "given.\n", NULL, NULL);
2050 return;
2051 }
2052 /* TODO: Are the HTML and DOCB doc nodes expected here? */
2053 if (node->type != XML_DOCUMENT_NODE) {
2054 xmlSchemaFormatItemForReport(&msg, NULL, NULL, node, 0);
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +00002055 if ((type != NULL) && (xmlSchemaIsGlobalItem(type))) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002056 msg = xmlStrcat(msg, BAD_CAST " [");
2057 msg = xmlStrcat(msg, xmlSchemaFormatItemForReport(&str, NULL, type, NULL, 0));
2058 msg = xmlStrcat(msg, BAD_CAST "]");
2059 }
2060 msg = xmlStrcat(msg, BAD_CAST ": ");
2061 } else
2062 msg = xmlStrdup((const xmlChar *) "");
Daniel Veillardc0826a72004-08-10 14:17:33 +00002063 msg = xmlStrcat(msg, (const xmlChar *) message);
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002064 msg = xmlStrcat(msg, BAD_CAST ".\n");
2065 xmlSchemaVErr(ctxt, node, error, (const char *) msg, str1, NULL);
2066 FREE_AND_NULL(msg)
2067 FREE_AND_NULL(str)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002068}
2069
William M. Brack2f2a6632004-08-20 23:09:47 +00002070/**
2071 * xmlSchemaWildcardPCToString:
2072 * @pc: the type of processContents
2073 *
2074 * Returns a string representation of the type of
2075 * processContents.
2076 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002077static const char *
2078xmlSchemaWildcardPCToString(int pc)
2079{
2080 switch (pc) {
2081 case XML_SCHEMAS_ANY_SKIP:
2082 return ("skip");
2083 case XML_SCHEMAS_ANY_LAX:
2084 return ("lax");
2085 case XML_SCHEMAS_ANY_STRICT:
2086 return ("strict");
2087 default:
2088 return ("invalid process contents");
2089 }
2090}
2091
William M. Brack2f2a6632004-08-20 23:09:47 +00002092/**
2093 * xmlSchemaVWildcardErr:
2094 * @ctxt: the schema validation context
2095 * @error: the error code
2096 * @node: the validated node
2097 * @wild: the wildcard used
2098 * @message: the error message
2099 *
2100 * Reports an validation-by-wildcard error.
2101 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002102static void
2103xmlSchemaVWildcardErr(xmlSchemaValidCtxtPtr ctxt,
2104 xmlParserErrors error,
2105 xmlNodePtr node,
2106 xmlSchemaWildcardPtr wild,
2107 const char *message)
2108{
2109 xmlChar *des = NULL, *msg = NULL;
2110
2111 xmlSchemaFormatItemForReport(&des, NULL, NULL, node, 0);
2112 msg = xmlStrdup(BAD_CAST "%s, [");
2113 msg = xmlStrcat(msg, BAD_CAST xmlSchemaWildcardPCToString(wild->processContents));
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +00002114 msg = xmlStrcat(msg, BAD_CAST " wildcard]: ");
Daniel Veillardc0826a72004-08-10 14:17:33 +00002115 msg = xmlStrcat(msg, (const xmlChar *) message);
2116 msg = xmlStrcat(msg, BAD_CAST ".\n");
2117 xmlSchemaVErr(ctxt, node, error, (const char *) msg, BAD_CAST des, NULL);
2118 FREE_AND_NULL(des);
2119 FREE_AND_NULL(msg);
2120}
2121
2122/**
2123 * xmlSchemaVMissingAttrErr:
2124 * @ctxt: the schema validation context
2125 * @node: the parent element node of the missing attribute node
2126 * @type: the corresponding type of the attribute node
2127 *
2128 * Reports an illegal attribute.
2129 */
2130static void
2131xmlSchemaVMissingAttrErr(xmlSchemaValidCtxtPtr ctxt,
2132 xmlNodePtr elem,
2133 xmlSchemaAttributePtr type)
2134{
2135 const xmlChar *name, *uri;
2136 xmlChar *strE = NULL, *strA = NULL;
2137
2138 if (type->ref != NULL) {
2139 name = type->ref;
2140 uri = type->refNs;
2141 } else {
2142 name = type->name;
2143 uri = type->targetNamespace;
2144 }
2145 xmlSchemaVErr(ctxt, elem,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00002146 XML_SCHEMAV_CVC_COMPLEX_TYPE_4,
2147 /* XML_SCHEMAS_ERR_MISSING, */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002148 "%s: The attribute %s is required but missing.\n",
2149 xmlSchemaFormatItemForReport(&strE, NULL, NULL, elem, 0),
2150 xmlSchemaFormatNsUriLocal(&strA, uri, name));
2151 FREE_AND_NULL(strE)
2152 FREE_AND_NULL(strA)
2153}
2154
Daniel Veillard4255d502002-04-16 15:50:10 +00002155/************************************************************************
2156 * *
2157 * Allocation functions *
2158 * *
2159 ************************************************************************/
2160
2161/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00002162 * xmlSchemaNewSchemaForParserCtxt:
William M. Brack08171912003-12-29 02:52:11 +00002163 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00002164 *
2165 * Allocate a new Schema structure.
2166 *
2167 * Returns the newly allocated structure or NULL in case or error
2168 */
2169static xmlSchemaPtr
2170xmlSchemaNewSchema(xmlSchemaParserCtxtPtr ctxt)
2171{
2172 xmlSchemaPtr ret;
2173
2174 ret = (xmlSchemaPtr) xmlMalloc(sizeof(xmlSchema));
2175 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002176 xmlSchemaPErrMemory(ctxt, "allocating schema", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002177 return (NULL);
2178 }
2179 memset(ret, 0, sizeof(xmlSchema));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002180 ret->dict = ctxt->dict;
Daniel Veillard500a1de2004-03-22 15:22:58 +00002181 xmlDictReference(ret->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00002182
2183 return (ret);
2184}
2185
2186/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002187 * xmlSchemaNewSchema:
2188 * @ctxt: a schema validation context
2189 *
2190 * Allocate a new Schema structure.
2191 *
2192 * Returns the newly allocated structure or NULL in case or error
2193 */
2194static xmlSchemaAssemblePtr
2195xmlSchemaNewAssemble(void)
2196{
2197 xmlSchemaAssemblePtr ret;
2198
2199 ret = (xmlSchemaAssemblePtr) xmlMalloc(sizeof(xmlSchemaAssemble));
2200 if (ret == NULL) {
2201 /* xmlSchemaPErrMemory(ctxt, "allocating assemble info", NULL); */
2202 return (NULL);
2203 }
2204 memset(ret, 0, sizeof(xmlSchemaAssemble));
2205 ret->items = NULL;
2206 return (ret);
2207}
2208
2209/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002210 * xmlSchemaNewFacet:
Daniel Veillard4255d502002-04-16 15:50:10 +00002211 *
2212 * Allocate a new Facet structure.
2213 *
2214 * Returns the newly allocated structure or NULL in case or error
2215 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00002216xmlSchemaFacetPtr
2217xmlSchemaNewFacet(void)
Daniel Veillard4255d502002-04-16 15:50:10 +00002218{
2219 xmlSchemaFacetPtr ret;
2220
2221 ret = (xmlSchemaFacetPtr) xmlMalloc(sizeof(xmlSchemaFacet));
2222 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002223 return (NULL);
2224 }
2225 memset(ret, 0, sizeof(xmlSchemaFacet));
2226
2227 return (ret);
2228}
2229
2230/**
2231 * xmlSchemaNewAnnot:
William M. Brack08171912003-12-29 02:52:11 +00002232 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00002233 * @node: a node
2234 *
2235 * Allocate a new annotation structure.
2236 *
2237 * Returns the newly allocated structure or NULL in case or error
2238 */
2239static xmlSchemaAnnotPtr
2240xmlSchemaNewAnnot(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
2241{
2242 xmlSchemaAnnotPtr ret;
2243
2244 ret = (xmlSchemaAnnotPtr) xmlMalloc(sizeof(xmlSchemaAnnot));
2245 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002246 xmlSchemaPErrMemory(ctxt, "allocating annotation", node);
Daniel Veillard4255d502002-04-16 15:50:10 +00002247 return (NULL);
2248 }
2249 memset(ret, 0, sizeof(xmlSchemaAnnot));
2250 ret->content = node;
2251 return (ret);
2252}
2253
2254/**
Daniel Veillardfdc91562002-07-01 21:52:03 +00002255 * xmlSchemaFreeAnnot:
2256 * @annot: a schema type structure
2257 *
2258 * Deallocate a annotation structure
2259 */
2260static void
2261xmlSchemaFreeAnnot(xmlSchemaAnnotPtr annot)
2262{
2263 if (annot == NULL)
2264 return;
2265 xmlFree(annot);
2266}
2267
2268/**
Daniel Veillard1d913862003-11-21 00:28:39 +00002269 * xmlSchemaFreeImport:
2270 * @import: a schema import structure
2271 *
2272 * Deallocate an import structure
2273 */
2274static void
2275xmlSchemaFreeImport(xmlSchemaImportPtr import)
2276{
2277 if (import == NULL)
2278 return;
2279
2280 xmlSchemaFree(import->schema);
William M. Brack2f2a6632004-08-20 23:09:47 +00002281 xmlFreeDoc(import->doc);
Daniel Veillard1d913862003-11-21 00:28:39 +00002282 xmlFree(import);
2283}
2284
2285/**
Daniel Veillardbd2904b2003-11-25 15:38:59 +00002286 * xmlSchemaFreeInclude:
2287 * @include: a schema include structure
2288 *
2289 * Deallocate an include structure
2290 */
2291static void
2292xmlSchemaFreeInclude(xmlSchemaIncludePtr include)
2293{
2294 if (include == NULL)
2295 return;
2296
2297 xmlFreeDoc(include->doc);
2298 xmlFree(include);
2299}
2300
2301/**
2302 * xmlSchemaFreeIncludeList:
2303 * @includes: a schema include list
2304 *
2305 * Deallocate an include structure
2306 */
2307static void
2308xmlSchemaFreeIncludeList(xmlSchemaIncludePtr includes)
2309{
2310 xmlSchemaIncludePtr next;
2311
2312 while (includes != NULL) {
2313 next = includes->next;
2314 xmlSchemaFreeInclude(includes);
2315 includes = next;
2316 }
2317}
2318
2319/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002320 * xmlSchemaFreeNotation:
2321 * @schema: a schema notation structure
2322 *
2323 * Deallocate a Schema Notation structure.
2324 */
2325static void
2326xmlSchemaFreeNotation(xmlSchemaNotationPtr nota)
2327{
2328 if (nota == NULL)
2329 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00002330 xmlFree(nota);
2331}
2332
2333/**
2334 * xmlSchemaFreeAttribute:
2335 * @schema: a schema attribute structure
2336 *
2337 * Deallocate a Schema Attribute structure.
2338 */
2339static void
2340xmlSchemaFreeAttribute(xmlSchemaAttributePtr attr)
2341{
2342 if (attr == NULL)
2343 return;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002344 if (attr->annot != NULL)
2345 xmlSchemaFreeAnnot(attr->annot);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00002346 if (attr->defVal != NULL)
2347 xmlSchemaFreeValue(attr->defVal);
Daniel Veillard4255d502002-04-16 15:50:10 +00002348 xmlFree(attr);
2349}
2350
2351/**
Daniel Veillard3646d642004-06-02 19:19:14 +00002352 * xmlSchemaFreeWildcardNsSet:
2353 * set: a schema wildcard namespace
2354 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00002355 * Deallocates a list of wildcard constraint structures.
Daniel Veillard3646d642004-06-02 19:19:14 +00002356 */
2357static void
2358xmlSchemaFreeWildcardNsSet(xmlSchemaWildcardNsPtr set)
2359{
2360 xmlSchemaWildcardNsPtr next;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002361
Daniel Veillard3646d642004-06-02 19:19:14 +00002362 while (set != NULL) {
2363 next = set->next;
2364 xmlFree(set);
2365 set = next;
2366 }
2367}
2368
2369/**
2370 * xmlSchemaFreeWildcard:
Daniel Veillard01fa6152004-06-29 17:04:39 +00002371 * @wildcard: a wildcard structure
Daniel Veillard3646d642004-06-02 19:19:14 +00002372 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00002373 * Deallocates a wildcard structure.
Daniel Veillard3646d642004-06-02 19:19:14 +00002374 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00002375void
Daniel Veillard3646d642004-06-02 19:19:14 +00002376xmlSchemaFreeWildcard(xmlSchemaWildcardPtr wildcard)
2377{
2378 if (wildcard == NULL)
2379 return;
2380 if (wildcard->annot != NULL)
2381 xmlSchemaFreeAnnot(wildcard->annot);
2382 if (wildcard->nsSet != NULL)
2383 xmlSchemaFreeWildcardNsSet(wildcard->nsSet);
2384 if (wildcard->negNsSet != NULL)
2385 xmlFree(wildcard->negNsSet);
2386 xmlFree(wildcard);
2387}
2388
2389/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002390 * xmlSchemaFreeAttributeGroup:
2391 * @schema: a schema attribute group structure
2392 *
2393 * Deallocate a Schema Attribute Group structure.
2394 */
2395static void
2396xmlSchemaFreeAttributeGroup(xmlSchemaAttributeGroupPtr attr)
2397{
2398 if (attr == NULL)
2399 return;
Daniel Veillard3646d642004-06-02 19:19:14 +00002400 if (attr->annot != NULL)
2401 xmlSchemaFreeAnnot(attr->annot);
2402 if ((attr->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL) &&
2403 (attr->attributeWildcard != NULL))
2404 xmlSchemaFreeWildcard(attr->attributeWildcard);
2405
Daniel Veillard4255d502002-04-16 15:50:10 +00002406 xmlFree(attr);
2407}
2408
2409/**
Daniel Veillard3646d642004-06-02 19:19:14 +00002410 * xmlSchemaFreeAttributeUseList:
Daniel Veillard01fa6152004-06-29 17:04:39 +00002411 * @attrUse: an attribute link
Daniel Veillard3646d642004-06-02 19:19:14 +00002412 *
2413 * Deallocate a list of schema attribute uses.
2414 */
2415static void
2416xmlSchemaFreeAttributeUseList(xmlSchemaAttributeLinkPtr attrUse)
2417{
2418 xmlSchemaAttributeLinkPtr next;
2419
2420 while (attrUse != NULL) {
2421 next = attrUse->next;
2422 xmlFree(attrUse);
2423 attrUse = next;
2424 }
2425}
2426
2427/**
Daniel Veillard01fa6152004-06-29 17:04:39 +00002428 * xmlSchemaFreeTypeLinkList:
2429 * @alink: a type link
2430 *
2431 * Deallocate a list of types.
2432 */
2433static void
2434xmlSchemaFreeTypeLinkList(xmlSchemaTypeLinkPtr link)
2435{
2436 xmlSchemaTypeLinkPtr next;
2437
2438 while (link != NULL) {
2439 next = link->next;
2440 xmlFree(link);
2441 link = next;
2442 }
2443}
2444
2445/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002446 * xmlSchemaFreeElement:
2447 * @schema: a schema element structure
2448 *
2449 * Deallocate a Schema Element structure.
2450 */
2451static void
2452xmlSchemaFreeElement(xmlSchemaElementPtr elem)
2453{
2454 if (elem == NULL)
2455 return;
Daniel Veillard32370232002-10-16 14:08:14 +00002456 if (elem->annot != NULL)
2457 xmlSchemaFreeAnnot(elem->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00002458 if (elem->contModel != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002459 xmlRegFreeRegexp(elem->contModel);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00002460 if (elem->defVal != NULL)
2461 xmlSchemaFreeValue(elem->defVal);
Daniel Veillard4255d502002-04-16 15:50:10 +00002462 xmlFree(elem);
2463}
2464
2465/**
2466 * xmlSchemaFreeFacet:
2467 * @facet: a schema facet structure
2468 *
2469 * Deallocate a Schema Facet structure.
2470 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00002471void
Daniel Veillard4255d502002-04-16 15:50:10 +00002472xmlSchemaFreeFacet(xmlSchemaFacetPtr facet)
2473{
2474 if (facet == NULL)
2475 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00002476 if (facet->val != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002477 xmlSchemaFreeValue(facet->val);
Daniel Veillard4255d502002-04-16 15:50:10 +00002478 if (facet->regexp != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002479 xmlRegFreeRegexp(facet->regexp);
Daniel Veillardfdc91562002-07-01 21:52:03 +00002480 if (facet->annot != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002481 xmlSchemaFreeAnnot(facet->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00002482 xmlFree(facet);
2483}
2484
2485/**
2486 * xmlSchemaFreeType:
2487 * @type: a schema type structure
2488 *
2489 * Deallocate a Schema Type structure.
2490 */
2491void
2492xmlSchemaFreeType(xmlSchemaTypePtr type)
2493{
2494 if (type == NULL)
2495 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00002496 if (type->annot != NULL)
Daniel Veillard32370232002-10-16 14:08:14 +00002497 xmlSchemaFreeAnnot(type->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00002498 if (type->facets != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002499 xmlSchemaFacetPtr facet, next;
Daniel Veillard4255d502002-04-16 15:50:10 +00002500
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002501 facet = type->facets;
2502 while (facet != NULL) {
2503 next = facet->next;
2504 xmlSchemaFreeFacet(facet);
2505 facet = next;
2506 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002507 }
Daniel Veillard3646d642004-06-02 19:19:14 +00002508 if (type->type != XML_SCHEMA_TYPE_BASIC) {
2509 if (type->attributeUses != NULL)
2510 xmlSchemaFreeAttributeUseList(type->attributeUses);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002511 if ((type->attributeWildcard != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +00002512 ((type->type != XML_SCHEMA_TYPE_COMPLEX) ||
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002513 (type->flags & XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD))) {
2514 /*
2515 * NOTE: The only case where an attribute wildcard
2516 * is not owned, is if a complex type inherits it
2517 * from a base type.
2518 */
Daniel Veillard3646d642004-06-02 19:19:14 +00002519 xmlSchemaFreeWildcard(type->attributeWildcard);
2520 }
2521 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00002522 if (type->memberTypes != NULL)
2523 xmlSchemaFreeTypeLinkList(type->memberTypes);
2524 if (type->facetSet != NULL) {
2525 xmlSchemaFacetLinkPtr next, link;
2526
2527 link = type->facetSet;
2528 do {
2529 next = link->next;
2530 xmlFree(link);
2531 link = next;
2532 } while (link != NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002533 }
2534 if (type->contModel != NULL)
2535 xmlRegFreeRegexp(type->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +00002536 xmlFree(type);
2537}
2538
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00002539static void
2540xmlSchemaFreeIDCStateObjList(xmlSchemaIDCStateObjPtr sto)
2541{
2542 xmlSchemaIDCStateObjPtr next;
2543 while (sto != NULL) {
2544 next = sto->next;
2545 if (sto->history != NULL) {
2546 int i;
2547 for (i = 0; i < sto->sizeHistory; i++) {
2548 if (sto->history[i] != NULL)
2549 xmlFree(sto->history[i]);
2550 else
2551 break;
2552 }
2553 xmlFree(sto->history);
2554 }
2555 xmlFree(sto);
2556 sto = next;
2557 }
2558}
2559
2560/**
2561 * xmlSchemaFreeIDC:
2562 * @idc: a identity-constraint definition
2563 *
2564 * Deallocates an identity-constraint definition.
2565 */
2566void
2567xmlSchemaFreeIDC(xmlSchemaIDCPtr idc)
2568{
2569 xmlSchemaIDCSelectPtr cur, prev;
2570
2571 if (idc == NULL)
2572 return;
2573 if (idc->annot != NULL)
2574 xmlSchemaFreeAnnot(idc->annot);
2575 if (idc->ref != NULL)
2576 xmlFree(idc->ref);
2577 /* Selector */
2578 if (idc->selector != NULL) {
2579 if (idc->selector->xpathComp != NULL)
2580 xmlXPathFreeCompExpr(idc->selector->xpathComp);
2581 xmlFree(idc->selector);
2582 }
2583 /* Fields */
2584 if (idc->fields != NULL) {
2585 cur = idc->fields;
2586 do {
2587 prev = cur;
2588 cur = cur->next;
2589 if (prev->xpathComp != NULL)
2590 xmlXPathFreeCompExpr(prev->xpathComp);
2591 xmlFree(prev);
2592 } while (cur != NULL);
2593 }
2594 xmlFree(idc);
2595}
2596
Daniel Veillard4255d502002-04-16 15:50:10 +00002597/**
Daniel Veillardb0f397e2003-12-23 23:30:53 +00002598 * xmlSchemaFreeTypeList:
2599 * @type: a schema type structure
2600 *
2601 * Deallocate a Schema Type structure.
2602 */
2603static void
2604xmlSchemaFreeTypeList(xmlSchemaTypePtr type)
2605{
2606 xmlSchemaTypePtr next;
2607
2608 while (type != NULL) {
2609 next = type->redef;
2610 xmlSchemaFreeType(type);
2611 type = next;
2612 }
2613}
2614
2615/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002616 * xmlSchemaFree:
2617 * @schema: a schema structure
2618 *
2619 * Deallocate a Schema structure.
2620 */
2621void
2622xmlSchemaFree(xmlSchemaPtr schema)
2623{
2624 if (schema == NULL)
2625 return;
2626
Daniel Veillard4255d502002-04-16 15:50:10 +00002627 if (schema->notaDecl != NULL)
2628 xmlHashFree(schema->notaDecl,
2629 (xmlHashDeallocator) xmlSchemaFreeNotation);
2630 if (schema->attrDecl != NULL)
2631 xmlHashFree(schema->attrDecl,
2632 (xmlHashDeallocator) xmlSchemaFreeAttribute);
2633 if (schema->attrgrpDecl != NULL)
2634 xmlHashFree(schema->attrgrpDecl,
2635 (xmlHashDeallocator) xmlSchemaFreeAttributeGroup);
2636 if (schema->elemDecl != NULL)
2637 xmlHashFree(schema->elemDecl,
2638 (xmlHashDeallocator) xmlSchemaFreeElement);
2639 if (schema->typeDecl != NULL)
2640 xmlHashFree(schema->typeDecl,
Daniel Veillardb0f397e2003-12-23 23:30:53 +00002641 (xmlHashDeallocator) xmlSchemaFreeTypeList);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00002642 if (schema->groupDecl != NULL)
2643 xmlHashFree(schema->groupDecl,
2644 (xmlHashDeallocator) xmlSchemaFreeType);
Daniel Veillard1d913862003-11-21 00:28:39 +00002645 if (schema->schemasImports != NULL)
2646 xmlHashFree(schema->schemasImports,
2647 (xmlHashDeallocator) xmlSchemaFreeImport);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00002648 if (schema->includes != NULL) {
2649 xmlSchemaFreeIncludeList((xmlSchemaIncludePtr) schema->includes);
2650 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002651 if (schema->annot != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002652 xmlSchemaFreeAnnot(schema->annot);
Daniel Veillarddda22c12004-01-24 08:31:30 +00002653 if (schema->doc != NULL && !schema->preserve)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002654 xmlFreeDoc(schema->doc);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002655 xmlDictFree(schema->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00002656 xmlFree(schema);
2657}
2658
2659/************************************************************************
2660 * *
Daniel Veillard4255d502002-04-16 15:50:10 +00002661 * Debug functions *
2662 * *
2663 ************************************************************************/
2664
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00002665#ifdef LIBXML_OUTPUT_ENABLED
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002666
Daniel Veillard4255d502002-04-16 15:50:10 +00002667/**
2668 * xmlSchemaElementDump:
2669 * @elem: an element
2670 * @output: the file output
2671 *
2672 * Dump the element
2673 */
2674static void
2675xmlSchemaElementDump(xmlSchemaElementPtr elem, FILE * output,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002676 const xmlChar * name ATTRIBUTE_UNUSED,
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002677 const xmlChar * namespace ATTRIBUTE_UNUSED,
2678 const xmlChar * context ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +00002679{
2680 if (elem == NULL)
2681 return;
2682
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002683 if (elem->flags & XML_SCHEMAS_ELEM_REF) {
2684 fprintf(output, "Particle: %s", name);
2685 fprintf(output, ", term element: %s", elem->ref);
2686 if (elem->refNs != NULL)
2687 fprintf(output, " ns %s", elem->refNs);
2688 } else {
2689 fprintf(output, "Element");
2690 if (elem->flags & XML_SCHEMAS_ELEM_GLOBAL)
2691 fprintf(output, " (global)");
2692 fprintf(output, ": %s ", elem->name);
2693 if (namespace != NULL)
2694 fprintf(output, "ns %s", namespace);
2695 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002696 fprintf(output, "\n");
2697 if ((elem->minOccurs != 1) || (elem->maxOccurs != 1)) {
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002698 fprintf(output, " min %d ", elem->minOccurs);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002699 if (elem->maxOccurs >= UNBOUNDED)
2700 fprintf(output, "max: unbounded\n");
2701 else if (elem->maxOccurs != 1)
2702 fprintf(output, "max: %d\n", elem->maxOccurs);
2703 else
2704 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00002705 }
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002706 /*
2707 * Misc other properties.
2708 */
2709 if ((elem->flags & XML_SCHEMAS_ELEM_NILLABLE) ||
2710 (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT) ||
2711 (elem->flags & XML_SCHEMAS_ELEM_FIXED) ||
2712 (elem->flags & XML_SCHEMAS_ELEM_DEFAULT) ||
2713 (elem->id != NULL)) {
2714 fprintf(output, " props: ");
2715 if (elem->flags & XML_SCHEMAS_ELEM_FIXED)
2716 fprintf(output, "[fixed] ");
2717 if (elem->flags & XML_SCHEMAS_ELEM_DEFAULT)
2718 fprintf(output, "[default] ");
2719 if (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT)
2720 fprintf(output, "[abstract] ");
2721 if (elem->flags & XML_SCHEMAS_ELEM_NILLABLE)
2722 fprintf(output, "[nillable] ");
2723 if (elem->id != NULL)
2724 fprintf(output, "[id: '%s'] ", elem->id);
2725 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00002726 }
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002727 /*
2728 * Default/fixed value.
2729 */
Daniel Veillard4255d502002-04-16 15:50:10 +00002730 if (elem->value != NULL)
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002731 fprintf(output, " value: '%s'\n", elem->value);
2732 /*
2733 * Type.
2734 */
2735 if (elem->namedType != NULL) {
2736 fprintf(output, " type: %s ", elem->namedType);
2737 if (elem->namedTypeNs != NULL)
2738 fprintf(output, "ns %s\n", elem->namedTypeNs);
2739 else
2740 fprintf(output, "\n");
2741 }
2742 /*
2743 * Substitution group.
2744 */
2745 if (elem->substGroup != NULL) {
2746 fprintf(output, " substitutionGroup: %s ", elem->substGroup);
2747 if (elem->substGroupNs != NULL)
2748 fprintf(output, "ns %s\n", elem->substGroupNs);
2749 else
2750 fprintf(output, "\n");
2751 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002752}
2753
2754/**
2755 * xmlSchemaAnnotDump:
2756 * @output: the file output
2757 * @annot: a annotation
2758 *
2759 * Dump the annotation
2760 */
2761static void
2762xmlSchemaAnnotDump(FILE * output, xmlSchemaAnnotPtr annot)
2763{
2764 xmlChar *content;
2765
2766 if (annot == NULL)
2767 return;
2768
2769 content = xmlNodeGetContent(annot->content);
2770 if (content != NULL) {
2771 fprintf(output, " Annot: %s\n", content);
2772 xmlFree(content);
2773 } else
2774 fprintf(output, " Annot: empty\n");
2775}
2776
2777/**
2778 * xmlSchemaTypeDump:
2779 * @output: the file output
2780 * @type: a type structure
2781 *
2782 * Dump a SchemaType structure
2783 */
2784static void
2785xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output)
2786{
2787 if (type == NULL) {
2788 fprintf(output, "Type: NULL\n");
2789 return;
2790 }
2791 fprintf(output, "Type: ");
2792 if (type->name != NULL)
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002793 fprintf(output, "%s ", type->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00002794 else
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002795 fprintf(output, "no name ");
2796 if (type->targetNamespace != NULL)
2797 fprintf(output, "ns %s ", type->targetNamespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00002798 switch (type->type) {
2799 case XML_SCHEMA_TYPE_BASIC:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002800 fprintf(output, "[basic] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002801 break;
2802 case XML_SCHEMA_TYPE_SIMPLE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002803 fprintf(output, "[simple] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002804 break;
2805 case XML_SCHEMA_TYPE_COMPLEX:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002806 fprintf(output, "[complex] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002807 break;
2808 case XML_SCHEMA_TYPE_SEQUENCE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002809 fprintf(output, "[sequence] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002810 break;
2811 case XML_SCHEMA_TYPE_CHOICE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002812 fprintf(output, "[choice] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002813 break;
2814 case XML_SCHEMA_TYPE_ALL:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002815 fprintf(output, "[all] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002816 break;
2817 case XML_SCHEMA_TYPE_UR:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002818 fprintf(output, "[ur] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002819 break;
2820 case XML_SCHEMA_TYPE_RESTRICTION:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002821 fprintf(output, "[restriction] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002822 break;
2823 case XML_SCHEMA_TYPE_EXTENSION:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002824 fprintf(output, "[extension] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002825 break;
2826 default:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002827 fprintf(output, "[unknown type %d] ", type->type);
Daniel Veillard4255d502002-04-16 15:50:10 +00002828 break;
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002829 }
2830 fprintf(output, "content: ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002831 switch (type->contentType) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002832 case XML_SCHEMA_CONTENT_UNKNOWN:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002833 fprintf(output, "[unknown] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002834 break;
2835 case XML_SCHEMA_CONTENT_EMPTY:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002836 fprintf(output, "[empty] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002837 break;
2838 case XML_SCHEMA_CONTENT_ELEMENTS:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002839 fprintf(output, "[element] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002840 break;
2841 case XML_SCHEMA_CONTENT_MIXED:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002842 fprintf(output, "[mixed] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002843 break;
2844 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00002845 /* not used. */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002846 break;
2847 case XML_SCHEMA_CONTENT_BASIC:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002848 fprintf(output, "[basic] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002849 break;
2850 case XML_SCHEMA_CONTENT_SIMPLE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002851 fprintf(output, "[simple] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002852 break;
2853 case XML_SCHEMA_CONTENT_ANY:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002854 fprintf(output, "[any] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002855 break;
Daniel Veillard4255d502002-04-16 15:50:10 +00002856 }
2857 fprintf(output, "\n");
2858 if ((type->minOccurs != 1) || (type->maxOccurs != 1)) {
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002859 fprintf(output, " min: %d ", type->minOccurs);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002860 if (type->maxOccurs >= UNBOUNDED)
2861 fprintf(output, "max: unbounded\n");
2862 else if (type->maxOccurs != 1)
2863 fprintf(output, "max: %d\n", type->maxOccurs);
2864 else
2865 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00002866 }
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002867 if (type->base != NULL) {
2868 fprintf(output, " base type: %s", type->base);
2869 if (type->baseNs != NULL)
2870 fprintf(output, " ns %s\n", type->baseNs);
2871 else
2872 fprintf(output, "\n");
2873 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002874 if (type->annot != NULL)
2875 xmlSchemaAnnotDump(output, type->annot);
2876 if (type->subtypes != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002877 xmlSchemaTypePtr sub = type->subtypes;
Daniel Veillard4255d502002-04-16 15:50:10 +00002878
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002879 fprintf(output, " subtypes: ");
2880 while (sub != NULL) {
2881 fprintf(output, "%s ", sub->name);
2882 sub = sub->next;
2883 }
2884 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00002885 }
2886
2887}
2888
2889/**
2890 * xmlSchemaDump:
2891 * @output: the file output
2892 * @schema: a schema structure
2893 *
2894 * Dump a Schema structure.
2895 */
2896void
2897xmlSchemaDump(FILE * output, xmlSchemaPtr schema)
2898{
Daniel Veillardce682bc2004-11-05 17:22:25 +00002899 if (output == NULL)
2900 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00002901 if (schema == NULL) {
2902 fprintf(output, "Schemas: NULL\n");
2903 return;
2904 }
2905 fprintf(output, "Schemas: ");
2906 if (schema->name != NULL)
2907 fprintf(output, "%s, ", schema->name);
2908 else
2909 fprintf(output, "no name, ");
2910 if (schema->targetNamespace != NULL)
Daniel Veillard580ced82003-03-21 21:22:48 +00002911 fprintf(output, "%s", (const char *) schema->targetNamespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00002912 else
2913 fprintf(output, "no target namespace");
2914 fprintf(output, "\n");
2915 if (schema->annot != NULL)
2916 xmlSchemaAnnotDump(output, schema->annot);
2917
2918 xmlHashScan(schema->typeDecl, (xmlHashScanner) xmlSchemaTypeDump,
2919 output);
2920 xmlHashScanFull(schema->elemDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002921 (xmlHashScannerFull) xmlSchemaElementDump, output);
Daniel Veillard4255d502002-04-16 15:50:10 +00002922}
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00002923
2924/**
2925 * xmlSchemaDebugDumpIDCTable:
2926 * @vctxt: the WXS validation context
2927 *
2928 * Displays the current IDC table for debug purposes.
2929 */
2930static void
2931xmlSchemaDebugDumpIDCTable(FILE * output,
2932 const xmlChar *namespaceName,
2933 const xmlChar *localName,
2934 xmlSchemaPSVIIDCBindingPtr bind)
2935{
2936 xmlChar *str = NULL, *value;
2937 xmlSchemaPSVIIDCNodePtr tab;
2938 xmlSchemaPSVIIDCKeyPtr key;
2939 int i, j, res;
2940
2941 fprintf(output, "IDC: TABLES on %s\n",
2942 xmlSchemaFormatNsUriLocal(&str, namespaceName, localName));
2943 FREE_AND_NULL(str)
2944
2945 if (bind == NULL)
2946 return;
2947 do {
2948 fprintf(output, "IDC: BINDING %s\n",
2949 xmlSchemaFormatNsUriLocal(&str, bind->definition->targetNamespace,
2950 bind->definition->name));
2951 FREE_AND_NULL(str)
2952 for (i = 0; i < bind->nbNodes; i++) {
2953 tab = bind->nodeTable[i];
2954 fprintf(output, " ( ");
2955 for (j = 0; j < bind->definition->nbFields; j++) {
2956 key = tab->keys[j];
2957 if ((key != NULL) && (key->compValue != NULL)) {
2958#ifdef IDC_VALUE_SUPPORT
2959 res = xmlSchemaGetCanonValue(key->compValue, &value);
2960#else
2961 value = xmlStrdup(BAD_CAST "dummy-value");
2962 res = 0;
2963#endif
2964 if (res == 0)
2965 fprintf(output, "\"%s\" ", value);
2966 else
2967 fprintf(output, "CANON-VALUE-FAILED ", value);
2968 if (value != NULL) {
2969 xmlFree(value);
2970 value = NULL;
2971 }
2972 } else if (key != NULL)
2973 fprintf(output, "(no val), ", key->compValue);
2974 else
2975 fprintf(output, "(key missing), ");
2976 }
2977 fprintf(output, ")\n");
2978 }
2979 bind = bind->next;
2980 } while (bind != NULL);
2981}
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00002982#endif /* LIBXML_OUTPUT_ENABLED */
Daniel Veillard4255d502002-04-16 15:50:10 +00002983
2984/************************************************************************
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002985 * *
2986 * Utilities *
2987 * *
2988 ************************************************************************/
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002989
Daniel Veillardc0826a72004-08-10 14:17:33 +00002990/**
2991 * xmlSchemaGetPropNode:
2992 * @node: the element node
2993 * @name: the name of the attribute
2994 *
2995 * Seeks an attribute with a name of @name in
2996 * no namespace.
2997 *
2998 * Returns the attribute or NULL if not present.
2999 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00003000static xmlAttrPtr
Daniel Veillardc0826a72004-08-10 14:17:33 +00003001xmlSchemaGetPropNode(xmlNodePtr node, const char *name)
Daniel Veillard01fa6152004-06-29 17:04:39 +00003002{
3003 xmlAttrPtr prop;
3004
Daniel Veillardc0826a72004-08-10 14:17:33 +00003005 if ((node == NULL) || (name == NULL))
3006 return(NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00003007 prop = node->properties;
3008 while (prop != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00003009 if ((prop->ns == NULL) && xmlStrEqual(prop->name, BAD_CAST name))
3010 return(prop);
3011 prop = prop->next;
3012 }
3013 return (NULL);
3014}
3015
3016/**
3017 * xmlSchemaGetPropNodeNs:
3018 * @node: the element node
3019 * @uri: the uri
3020 * @name: the name of the attribute
3021 *
3022 * Seeks an attribute with a local name of @name and
3023 * a namespace URI of @uri.
3024 *
3025 * Returns the attribute or NULL if not present.
3026 */
3027static xmlAttrPtr
3028xmlSchemaGetPropNodeNs(xmlNodePtr node, const char *uri, const char *name)
3029{
3030 xmlAttrPtr prop;
3031
3032 if ((node == NULL) || (name == NULL))
3033 return(NULL);
3034 prop = node->properties;
3035 while (prop != NULL) {
3036 if ((prop->ns != NULL) &&
3037 xmlStrEqual(prop->name, BAD_CAST name) &&
3038 xmlStrEqual(prop->ns->href, BAD_CAST uri))
Daniel Veillard01fa6152004-06-29 17:04:39 +00003039 return(prop);
3040 prop = prop->next;
3041 }
3042 return (NULL);
3043}
3044
3045static const xmlChar *
3046xmlSchemaGetNodeContent(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
3047{
3048 xmlChar *val;
3049 const xmlChar *ret;
3050
3051 val = xmlNodeGetContent(node);
3052 if (val == NULL)
3053 return(NULL);
3054 ret = xmlDictLookup(ctxt->dict, val, -1);
3055 xmlFree(val);
3056 return(ret);
3057}
3058
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003059/**
3060 * xmlSchemaGetProp:
3061 * @ctxt: the parser context
3062 * @node: the node
3063 * @name: the property name
3064 *
3065 * Read a attribute value and internalize the string
3066 *
3067 * Returns the string or NULL if not present.
3068 */
3069static const xmlChar *
3070xmlSchemaGetProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
3071 const char *name)
3072{
3073 xmlChar *val;
3074 const xmlChar *ret;
3075
3076 val = xmlGetProp(node, BAD_CAST name);
3077 if (val == NULL)
3078 return(NULL);
3079 ret = xmlDictLookup(ctxt->dict, val, -1);
3080 xmlFree(val);
3081 return(ret);
3082}
3083
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003084/************************************************************************
Daniel Veillard4255d502002-04-16 15:50:10 +00003085 * *
3086 * Parsing functions *
3087 * *
3088 ************************************************************************/
3089
3090/**
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003091 * xmlSchemaGetElem:
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003092 * @schema: the schema context
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003093 * @name: the element name
3094 * @ns: the element namespace
3095 *
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003096 * Lookup a global element declaration in the schema.
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003097 *
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003098 * Returns the element declaration or NULL if not found.
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003099 */
3100static xmlSchemaElementPtr
3101xmlSchemaGetElem(xmlSchemaPtr schema, const xmlChar * name,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003102 const xmlChar * namespace)
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003103{
3104 xmlSchemaElementPtr ret;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003105
3106 if ((name == NULL) || (schema == NULL))
3107 return (NULL);
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003108
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003109 ret = xmlHashLookup2(schema->elemDecl, name, namespace);
Daniel Veillardf2a12832003-11-24 13:04:35 +00003110 if ((ret != NULL) &&
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003111 (ret->flags & XML_SCHEMAS_ELEM_GLOBAL)) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003112 return (ret);
Daniel Veillard3646d642004-06-02 19:19:14 +00003113 } else
3114 ret = NULL;
William M. Bracke7091952004-05-11 15:09:58 +00003115 /*
3116 * This one was removed, since top level element declarations have
3117 * the target namespace specified in targetNamespace of the <schema>
3118 * information element, even if elementFormDefault is "unqualified".
3119 */
3120
3121 /* else if ((schema->flags & XML_SCHEMAS_QUALIF_ELEM) == 0) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003122 if (xmlStrEqual(namespace, schema->targetNamespace))
3123 ret = xmlHashLookup2(schema->elemDecl, name, NULL);
3124 else
3125 ret = xmlHashLookup2(schema->elemDecl, name, namespace);
Daniel Veillardf2a12832003-11-24 13:04:35 +00003126 if ((ret != NULL) &&
3127 ((level == 0) || (ret->flags & XML_SCHEMAS_ELEM_TOPLEVEL))) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003128 return (ret);
Daniel Veillardf2a12832003-11-24 13:04:35 +00003129 }
William M. Bracke7091952004-05-11 15:09:58 +00003130 */
Daniel Veillard3646d642004-06-02 19:19:14 +00003131
William M. Brack2f2a6632004-08-20 23:09:47 +00003132 /*
3133 * Removed since imported components will be hold by the main schema only.
3134 *
Daniel Veillard3646d642004-06-02 19:19:14 +00003135 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00003136 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00003137 else
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003138 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00003139 if (import != NULL) {
Daniel Veillardf2a12832003-11-24 13:04:35 +00003140 ret = xmlSchemaGetElem(import->schema, name, namespace, level + 1);
Daniel Veillard3646d642004-06-02 19:19:14 +00003141 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ELEM_GLOBAL)) {
3142 return (ret);
3143 } else
3144 ret = NULL;
3145 }
William M. Brack2f2a6632004-08-20 23:09:47 +00003146 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003147#ifdef DEBUG
3148 if (ret == NULL) {
3149 if (namespace == NULL)
3150 fprintf(stderr, "Unable to lookup type %s", name);
3151 else
3152 fprintf(stderr, "Unable to lookup type %s:%s", name,
3153 namespace);
3154 }
3155#endif
3156 return (ret);
3157}
3158
3159/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003160 * xmlSchemaGetType:
3161 * @schema: the schemas context
3162 * @name: the type name
3163 * @ns: the type namespace
3164 *
3165 * Lookup a type in the schemas or the predefined types
3166 *
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003167 * Returns the group definition or NULL if not found.
Daniel Veillard4255d502002-04-16 15:50:10 +00003168 */
3169static xmlSchemaTypePtr
3170xmlSchemaGetType(xmlSchemaPtr schema, const xmlChar * name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003171 const xmlChar * namespace)
3172{
Daniel Veillard4255d502002-04-16 15:50:10 +00003173 xmlSchemaTypePtr ret;
3174
3175 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003176 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003177 if (schema != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003178 ret = xmlHashLookup2(schema->typeDecl, name, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00003179 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003180 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003181 }
3182 ret = xmlSchemaGetPredefinedType(name, namespace);
Daniel Veillard1d913862003-11-21 00:28:39 +00003183 if (ret != NULL)
3184 return (ret);
William M. Brack2f2a6632004-08-20 23:09:47 +00003185 /*
3186 * Removed, since the imported components will be grafted on the
3187 * main schema only.
Daniel Veillard3646d642004-06-02 19:19:14 +00003188 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00003189 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00003190 else
Daniel Veillard1d913862003-11-21 00:28:39 +00003191 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00003192 if (import != NULL) {
Daniel Veillard1d913862003-11-21 00:28:39 +00003193 ret = xmlSchemaGetType(import->schema, name, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00003194 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL)) {
3195 return (ret);
3196 } else
3197 ret = NULL;
3198 }
William M. Brack2f2a6632004-08-20 23:09:47 +00003199 */
Daniel Veillard4255d502002-04-16 15:50:10 +00003200#ifdef DEBUG
3201 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003202 if (namespace == NULL)
3203 fprintf(stderr, "Unable to lookup type %s", name);
3204 else
3205 fprintf(stderr, "Unable to lookup type %s:%s", name,
3206 namespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00003207 }
3208#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003209 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003210}
3211
Daniel Veillard3646d642004-06-02 19:19:14 +00003212/**
3213 * xmlSchemaGetAttribute:
3214 * @schema: the context of the schema
3215 * @name: the name of the attribute
3216 * @ns: the target namespace of the attribute
3217 *
3218 * Lookup a an attribute in the schema or imported schemas
3219 *
3220 * Returns the attribute declaration or NULL if not found.
3221 */
3222static xmlSchemaAttributePtr
3223xmlSchemaGetAttribute(xmlSchemaPtr schema, const xmlChar * name,
3224 const xmlChar * namespace)
3225{
3226 xmlSchemaAttributePtr ret;
Daniel Veillard3646d642004-06-02 19:19:14 +00003227
3228 if ((name == NULL) || (schema == NULL))
3229 return (NULL);
3230
3231
3232 ret = xmlHashLookup2(schema->attrDecl, name, namespace);
3233 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTR_GLOBAL))
3234 return (ret);
3235 else
3236 ret = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00003237 /*
3238 * Removed, since imported components will be hold by the main schema only.
3239 *
Daniel Veillard3646d642004-06-02 19:19:14 +00003240 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00003241 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00003242 else
3243 import = xmlHashLookup(schema->schemasImports, namespace);
3244 if (import != NULL) {
3245 ret = xmlSchemaGetAttribute(import->schema, name, namespace);
3246 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTR_GLOBAL)) {
3247 return (ret);
3248 } else
3249 ret = NULL;
3250 }
William M. Brack2f2a6632004-08-20 23:09:47 +00003251 */
Daniel Veillard3646d642004-06-02 19:19:14 +00003252#ifdef DEBUG
3253 if (ret == NULL) {
3254 if (namespace == NULL)
3255 fprintf(stderr, "Unable to lookup attribute %s", name);
3256 else
3257 fprintf(stderr, "Unable to lookup attribute %s:%s", name,
3258 namespace);
3259 }
3260#endif
3261 return (ret);
3262}
3263
3264/**
3265 * xmlSchemaGetAttributeGroup:
3266 * @schema: the context of the schema
3267 * @name: the name of the attribute group
3268 * @ns: the target namespace of the attribute group
3269 *
3270 * Lookup a an attribute group in the schema or imported schemas
3271 *
3272 * Returns the attribute group definition or NULL if not found.
3273 */
3274static xmlSchemaAttributeGroupPtr
3275xmlSchemaGetAttributeGroup(xmlSchemaPtr schema, const xmlChar * name,
3276 const xmlChar * namespace)
3277{
3278 xmlSchemaAttributeGroupPtr ret;
Daniel Veillard3646d642004-06-02 19:19:14 +00003279
3280 if ((name == NULL) || (schema == NULL))
3281 return (NULL);
3282
3283
3284 ret = xmlHashLookup2(schema->attrgrpDecl, name, namespace);
3285 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL))
3286 return (ret);
3287 else
3288 ret = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00003289 /*
3290 * Removed since imported components will be hold by the main schema only.
3291 *
Daniel Veillard3646d642004-06-02 19:19:14 +00003292 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00003293 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00003294 else
3295 import = xmlHashLookup(schema->schemasImports, namespace);
3296 if (import != NULL) {
3297 ret = xmlSchemaGetAttributeGroup(import->schema, name, namespace);
3298 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL))
3299 return (ret);
3300 else
3301 ret = NULL;
3302 }
William M. Brack2f2a6632004-08-20 23:09:47 +00003303 */
Daniel Veillard3646d642004-06-02 19:19:14 +00003304#ifdef DEBUG
3305 if (ret == NULL) {
3306 if (namespace == NULL)
3307 fprintf(stderr, "Unable to lookup attribute group %s", name);
3308 else
3309 fprintf(stderr, "Unable to lookup attribute group %s:%s", name,
3310 namespace);
3311 }
3312#endif
3313 return (ret);
3314}
3315
3316/**
3317 * xmlSchemaGetGroup:
3318 * @schema: the context of the schema
3319 * @name: the name of the group
3320 * @ns: the target namespace of the group
3321 *
3322 * Lookup a group in the schema or imported schemas
3323 *
3324 * Returns the group definition or NULL if not found.
3325 */
3326static xmlSchemaTypePtr
3327xmlSchemaGetGroup(xmlSchemaPtr schema, const xmlChar * name,
3328 const xmlChar * namespace)
3329{
3330 xmlSchemaTypePtr ret;
Daniel Veillard3646d642004-06-02 19:19:14 +00003331
3332 if ((name == NULL) || (schema == NULL))
3333 return (NULL);
3334
3335
3336 ret = xmlHashLookup2(schema->groupDecl, name, namespace);
3337 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL))
3338 return (ret);
3339 else
3340 ret = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00003341 /*
3342 * Removed since imported components will be hold by the main schema only.
3343 *
Daniel Veillard3646d642004-06-02 19:19:14 +00003344 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00003345 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00003346 else
3347 import = xmlHashLookup(schema->schemasImports, namespace);
3348 if (import != NULL) {
3349 ret = xmlSchemaGetGroup(import->schema, name, namespace);
3350 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL))
3351 return (ret);
3352 else
3353 ret = NULL;
3354 }
William M. Brack2f2a6632004-08-20 23:09:47 +00003355 */
Daniel Veillard3646d642004-06-02 19:19:14 +00003356#ifdef DEBUG
3357 if (ret == NULL) {
3358 if (namespace == NULL)
3359 fprintf(stderr, "Unable to lookup group %s", name);
3360 else
3361 fprintf(stderr, "Unable to lookup group %s:%s", name,
3362 namespace);
3363 }
3364#endif
3365 return (ret);
3366}
3367
Daniel Veillard4255d502002-04-16 15:50:10 +00003368/************************************************************************
3369 * *
3370 * Parsing functions *
3371 * *
3372 ************************************************************************/
3373
3374#define IS_BLANK_NODE(n) \
3375 (((n)->type == XML_TEXT_NODE) && (xmlSchemaIsBlank((n)->content)))
3376
3377/**
3378 * xmlSchemaIsBlank:
3379 * @str: a string
3380 *
3381 * Check if a string is ignorable
3382 *
3383 * Returns 1 if the string is NULL or made of blanks chars, 0 otherwise
3384 */
3385static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003386xmlSchemaIsBlank(xmlChar * str)
3387{
Daniel Veillard4255d502002-04-16 15:50:10 +00003388 if (str == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003389 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003390 while (*str != 0) {
William M. Brack76e95df2003-10-18 16:20:14 +00003391 if (!(IS_BLANK_CH(*str)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003392 return (0);
3393 str++;
Daniel Veillard4255d502002-04-16 15:50:10 +00003394 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003395 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003396}
3397
3398/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003399 * xmlSchemaAddAssembledItem:
3400 * @ctxt: a schema parser context
3401 * @schema: the schema being built
3402 * @item: the item
3403 *
3404 * Add a item to the schema's list of current items.
3405 * This is used if the schema was already constructed and
3406 * new schemata need to be added to it.
3407 * *WARNING* this interface is highly subject to change.
3408 *
3409 * Returns 0 if suceeds and -1 if an internal error occurs.
3410 */
3411static int
3412xmlSchemaAddAssembledItem(xmlSchemaParserCtxtPtr ctxt,
3413 xmlSchemaTypePtr item)
3414{
3415 static int growSize = 100;
3416 xmlSchemaAssemblePtr ass;
3417
3418 ass = ctxt->assemble;
3419 if (ass->sizeItems < 0) {
3420 /* If disabled. */
3421 return (0);
3422 }
3423 if (ass->sizeItems <= 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00003424 ass->items = (void **) xmlMalloc(growSize * sizeof(xmlSchemaTypePtr));
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003425 if (ass->items == NULL) {
3426 xmlSchemaPErrMemory(ctxt,
3427 "allocating new item buffer", NULL);
3428 return (-1);
3429 }
3430 ass->sizeItems = growSize;
3431 } else if (ass->sizeItems <= ass->nbItems) {
3432 ass->sizeItems *= 2;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00003433 ass->items = (void **) xmlRealloc(ass->items,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003434 ass->sizeItems * sizeof(xmlSchemaTypePtr));
3435 if (ass->items == NULL) {
3436 xmlSchemaPErrMemory(ctxt,
3437 "growing item buffer", NULL);
3438 ass->sizeItems = 0;
3439 return (-1);
3440 }
3441 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00003442 /* ass->items[ass->nbItems++] = (void *) item; */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003443 ((xmlSchemaTypePtr *) ass->items)[ass->nbItems++] = (void *) item;
3444 return (0);
3445}
3446
3447/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003448 * xmlSchemaAddNotation:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003449 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00003450 * @schema: the schema being built
3451 * @name: the item name
3452 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00003453 * Add an XML schema annotation declaration
Daniel Veillard4255d502002-04-16 15:50:10 +00003454 * *WARNING* this interface is highly subject to change
3455 *
3456 * Returns the new struture or NULL in case of error
3457 */
3458static xmlSchemaNotationPtr
3459xmlSchemaAddNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003460 const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +00003461{
3462 xmlSchemaNotationPtr ret = NULL;
3463 int val;
3464
3465 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
3466 return (NULL);
3467
3468 if (schema->notaDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00003469 schema->notaDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00003470 if (schema->notaDecl == NULL)
3471 return (NULL);
3472
3473 ret = (xmlSchemaNotationPtr) xmlMalloc(sizeof(xmlSchemaNotation));
3474 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003475 xmlSchemaPErrMemory(ctxt, "add annotation", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003476 return (NULL);
3477 }
3478 memset(ret, 0, sizeof(xmlSchemaNotation));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003479 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003480 val = xmlHashAddEntry2(schema->notaDecl, name, schema->targetNamespace,
3481 ret);
3482 if (val != 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00003483 /*
3484 * TODO: This should never happen, since a unique name will be computed.
3485 * If it fails, then an other internal error must have occured.
3486 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003487 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
3488 XML_SCHEMAP_REDEFINED_NOTATION,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003489 "Annotation declaration '%s' is already declared.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003490 name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003491 xmlFree(ret);
3492 return (NULL);
3493 }
3494 return (ret);
3495}
3496
3497
3498/**
3499 * xmlSchemaAddAttribute:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003500 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00003501 * @schema: the schema being built
3502 * @name: the item name
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003503 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00003504 *
3505 * Add an XML schema Attrribute declaration
3506 * *WARNING* this interface is highly subject to change
3507 *
3508 * Returns the new struture or NULL in case of error
3509 */
3510static xmlSchemaAttributePtr
3511xmlSchemaAddAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00003512 const xmlChar * name, const xmlChar * namespace,
3513 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00003514{
3515 xmlSchemaAttributePtr ret = NULL;
3516 int val;
3517
3518 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
3519 return (NULL);
3520
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003521#ifdef DEBUG
3522 fprintf(stderr, "Adding attribute %s\n", name);
3523 if (namespace != NULL)
3524 fprintf(stderr, " target namespace %s\n", namespace);
3525#endif
3526
Daniel Veillard4255d502002-04-16 15:50:10 +00003527 if (schema->attrDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00003528 schema->attrDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00003529 if (schema->attrDecl == NULL)
3530 return (NULL);
3531
3532 ret = (xmlSchemaAttributePtr) xmlMalloc(sizeof(xmlSchemaAttribute));
3533 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003534 xmlSchemaPErrMemory(ctxt, "allocating attribute", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003535 return (NULL);
3536 }
3537 memset(ret, 0, sizeof(xmlSchemaAttribute));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003538 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00003539 ret->targetNamespace = namespace;
Daniel Veillard4255d502002-04-16 15:50:10 +00003540 val = xmlHashAddEntry3(schema->attrDecl, name,
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00003541 namespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003542 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00003543 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003544 XML_SCHEMAP_REDEFINED_ATTR,
William M. Brack2f2a6632004-08-20 23:09:47 +00003545 NULL, NULL, node,
3546 "A global attribute declaration with the name '%s' does already exist", name);
Daniel Veillard4255d502002-04-16 15:50:10 +00003547 xmlFree(ret);
3548 return (NULL);
3549 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003550 if (ctxt->assemble != NULL)
3551 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003552 return (ret);
3553}
3554
3555/**
3556 * xmlSchemaAddAttributeGroup:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003557 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00003558 * @schema: the schema being built
3559 * @name: the item name
3560 *
3561 * Add an XML schema Attrribute Group declaration
3562 *
3563 * Returns the new struture or NULL in case of error
3564 */
3565static xmlSchemaAttributeGroupPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003566xmlSchemaAddAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00003567 xmlSchemaPtr schema, const xmlChar * name,
3568 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00003569{
3570 xmlSchemaAttributeGroupPtr ret = NULL;
3571 int val;
3572
3573 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
3574 return (NULL);
3575
3576 if (schema->attrgrpDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00003577 schema->attrgrpDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00003578 if (schema->attrgrpDecl == NULL)
3579 return (NULL);
3580
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003581 ret =
3582 (xmlSchemaAttributeGroupPtr)
3583 xmlMalloc(sizeof(xmlSchemaAttributeGroup));
Daniel Veillard4255d502002-04-16 15:50:10 +00003584 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003585 xmlSchemaPErrMemory(ctxt, "allocating attribute group", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003586 return (NULL);
3587 }
3588 memset(ret, 0, sizeof(xmlSchemaAttributeGroup));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003589 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003590 val = xmlHashAddEntry3(schema->attrgrpDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003591 schema->targetNamespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003592 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00003593 xmlSchemaPCustomErr(ctxt,
3594 XML_SCHEMAP_REDEFINED_ATTRGROUP,
3595 NULL, NULL, node,
3596 "A global attribute group definition with the name '%s' does already exist", name);
Daniel Veillard4255d502002-04-16 15:50:10 +00003597 xmlFree(ret);
3598 return (NULL);
3599 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003600 if (ctxt->assemble != NULL)
3601 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003602 return (ret);
3603}
3604
3605/**
3606 * xmlSchemaAddElement:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003607 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00003608 * @schema: the schema being built
3609 * @name: the type name
3610 * @namespace: the type namespace
3611 *
3612 * Add an XML schema Element declaration
3613 * *WARNING* this interface is highly subject to change
3614 *
3615 * Returns the new struture or NULL in case of error
3616 */
3617static xmlSchemaElementPtr
3618xmlSchemaAddElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00003619 const xmlChar * name, const xmlChar * namespace,
3620 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00003621{
3622 xmlSchemaElementPtr ret = NULL;
3623 int val;
3624
3625 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
3626 return (NULL);
3627
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003628#ifdef DEBUG
3629 fprintf(stderr, "Adding element %s\n", name);
3630 if (namespace != NULL)
3631 fprintf(stderr, " target namespace %s\n", namespace);
3632#endif
3633
Daniel Veillard4255d502002-04-16 15:50:10 +00003634 if (schema->elemDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00003635 schema->elemDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00003636 if (schema->elemDecl == NULL)
3637 return (NULL);
3638
3639 ret = (xmlSchemaElementPtr) xmlMalloc(sizeof(xmlSchemaElement));
3640 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003641 xmlSchemaPErrMemory(ctxt, "allocating element", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003642 return (NULL);
3643 }
3644 memset(ret, 0, sizeof(xmlSchemaElement));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003645 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003646 val = xmlHashAddEntry3(schema->elemDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003647 namespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003648 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00003649 if (topLevel) {
3650 xmlSchemaPCustomErr(ctxt,
3651 XML_SCHEMAP_REDEFINED_ELEMENT,
3652 NULL, NULL, node,
3653 "A global element declaration with the name '%s' does "
3654 "already exist", name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003655 xmlFree(ret);
3656 return (NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +00003657 } else {
3658 char buf[30];
3659
3660 snprintf(buf, 29, "#eCont %d", ctxt->counter++ + 1);
3661 val = xmlHashAddEntry3(schema->elemDecl, name, (xmlChar *) buf,
3662 namespace, ret);
3663 if (val != 0) {
3664 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003665 XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +00003666 NULL, NULL, node,
3667 "Internal error: xmlSchemaAddElement, "
3668 "a dublicate element declaration with the name '%s' "
3669 "could not be added to the hash.", name);
3670 xmlFree(ret);
3671 return (NULL);
3672 }
3673 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00003674
Daniel Veillard4255d502002-04-16 15:50:10 +00003675 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003676 if (ctxt->assemble != NULL)
3677 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003678 return (ret);
3679}
3680
3681/**
3682 * xmlSchemaAddType:
Daniel Veillard01fa6152004-06-29 17:04:39 +00003683 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00003684 * @schema: the schema being built
3685 * @name: the item name
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003686 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00003687 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00003688 * Add an XML schema item
Daniel Veillard4255d502002-04-16 15:50:10 +00003689 * *WARNING* this interface is highly subject to change
3690 *
3691 * Returns the new struture or NULL in case of error
3692 */
3693static xmlSchemaTypePtr
3694xmlSchemaAddType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00003695 const xmlChar * name, const xmlChar * namespace,
3696 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00003697{
3698 xmlSchemaTypePtr ret = NULL;
3699 int val;
3700
3701 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
3702 return (NULL);
3703
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003704#ifdef DEBUG
3705 fprintf(stderr, "Adding type %s\n", name);
3706 if (namespace != NULL)
3707 fprintf(stderr, " target namespace %s\n", namespace);
3708#endif
3709
Daniel Veillard4255d502002-04-16 15:50:10 +00003710 if (schema->typeDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00003711 schema->typeDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00003712 if (schema->typeDecl == NULL)
3713 return (NULL);
3714
3715 ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
3716 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003717 xmlSchemaPErrMemory(ctxt, "allocating type", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003718 return (NULL);
3719 }
3720 memset(ret, 0, sizeof(xmlSchemaType));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003721 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00003722 ret->redef = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003723 val = xmlHashAddEntry2(schema->typeDecl, name, namespace, ret);
William M. Brack2f2a6632004-08-20 23:09:47 +00003724 if (val != 0) {
3725 if (ctxt->includes == 0) {
3726 xmlSchemaPCustomErr(ctxt,
3727 XML_SCHEMAP_REDEFINED_TYPE,
3728 NULL, NULL, node,
3729 "A global type definition with the name '%s' does already exist", name);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00003730 xmlFree(ret);
3731 return (NULL);
3732 } else {
3733 xmlSchemaTypePtr prev;
3734
3735 prev = xmlHashLookup2(schema->typeDecl, name, namespace);
3736 if (prev == NULL) {
3737 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003738 XML_ERR_INTERNAL_ERROR,
3739 "Internal error: xmlSchemaAddType, on type "
3740 "'%s'.\n",
3741 name, NULL);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00003742 xmlFree(ret);
3743 return (NULL);
3744 }
3745 ret->redef = prev->redef;
3746 prev->redef = ret;
3747 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003748 }
3749 ret->minOccurs = 1;
3750 ret->maxOccurs = 1;
Daniel Veillard3646d642004-06-02 19:19:14 +00003751 ret->attributeUses = NULL;
3752 ret->attributeWildcard = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003753 if (ctxt->assemble != NULL)
3754 xmlSchemaAddAssembledItem(ctxt,ret);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003755 return (ret);
3756}
3757
3758/**
3759 * xmlSchemaAddGroup:
3760 * @ctxt: a schema validation context
3761 * @schema: the schema being built
3762 * @name: the group name
3763 *
3764 * Add an XML schema Group definition
3765 *
3766 * Returns the new struture or NULL in case of error
3767 */
3768static xmlSchemaTypePtr
3769xmlSchemaAddGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00003770 const xmlChar *name, const xmlChar *namespaceName,
3771 xmlNodePtr node)
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003772{
3773 xmlSchemaTypePtr ret = NULL;
3774 int val;
3775
3776 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
3777 return (NULL);
3778
3779 if (schema->groupDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00003780 schema->groupDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003781 if (schema->groupDecl == NULL)
3782 return (NULL);
3783
3784 ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
3785 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003786 xmlSchemaPErrMemory(ctxt, "adding group", NULL);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003787 return (NULL);
3788 }
3789 memset(ret, 0, sizeof(xmlSchemaType));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003790 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003791 val =
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00003792 xmlHashAddEntry2(schema->groupDecl, name, namespaceName,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003793 ret);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003794 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00003795 xmlSchemaPCustomErr(ctxt,
3796 XML_SCHEMAP_REDEFINED_GROUP,
3797 NULL, NULL, node,
3798 "A global model group definition with the name '%s' does already exist", name);
Daniel Veillard4255d502002-04-16 15:50:10 +00003799 xmlFree(ret);
3800 return (NULL);
3801 }
3802 ret->minOccurs = 1;
3803 ret->maxOccurs = 1;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003804 if (ctxt->assemble != NULL)
3805 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003806 return (ret);
3807}
3808
Daniel Veillard3646d642004-06-02 19:19:14 +00003809/**
3810 * xmlSchemaNewWildcardNs:
3811 * @ctxt: a schema validation context
3812 *
3813 * Creates a new wildcard namespace constraint.
3814 *
3815 * Returns the new struture or NULL in case of error
3816 */
3817static xmlSchemaWildcardNsPtr
3818xmlSchemaNewWildcardNsConstraint(xmlSchemaParserCtxtPtr ctxt)
3819{
3820 xmlSchemaWildcardNsPtr ret;
3821
3822 ret = (xmlSchemaWildcardNsPtr)
3823 xmlMalloc(sizeof(xmlSchemaWildcardNs));
3824 if (ret == NULL) {
3825 xmlSchemaPErrMemory(ctxt, "creating wildcard namespace constraint", NULL);
3826 return (NULL);
3827 }
3828 ret->value = NULL;
3829 ret->next = NULL;
3830 return (ret);
3831}
3832
3833/**
3834 * xmlSchemaAddWildcard:
3835 * @ctxt: a schema validation context
Daniel Veillardc0826a72004-08-10 14:17:33 +00003836 * Adds a wildcard. It corresponds to a
3837 * xsd:anyAttribute and is used as storage for namespace
3838 * constraints on a xsd:any.
Daniel Veillard3646d642004-06-02 19:19:14 +00003839 *
3840 * Returns the new struture or NULL in case of error
3841 */
3842static xmlSchemaWildcardPtr
3843xmlSchemaAddWildcard(xmlSchemaParserCtxtPtr ctxt)
3844{
3845 xmlSchemaWildcardPtr ret = NULL;
3846
3847 if (ctxt == NULL)
3848 return (NULL);
3849
3850 ret = (xmlSchemaWildcardPtr) xmlMalloc(sizeof(xmlSchemaWildcard));
3851 if (ret == NULL) {
3852 xmlSchemaPErrMemory(ctxt, "adding wildcard", NULL);
3853 return (NULL);
3854 }
3855 memset(ret, 0, sizeof(xmlSchemaWildcard));
3856 ret->minOccurs = 1;
3857 ret->maxOccurs = 1;
3858
3859 return (ret);
3860}
3861
Daniel Veillard4255d502002-04-16 15:50:10 +00003862/************************************************************************
3863 * *
3864 * Utilities for parsing *
3865 * *
3866 ************************************************************************/
3867
3868/**
3869 * xmlGetQNameProp:
3870 * @ctxt: a schema validation context
3871 * @node: a subtree containing XML Schema informations
3872 * @name: the attribute name
3873 * @namespace: the result namespace if any
3874 *
3875 * Extract a QName Attribute value
3876 *
3877 * Returns the NCName or NULL if not found, and also update @namespace
3878 * with the namespace URI
3879 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003880static const xmlChar *
Daniel Veillard4255d502002-04-16 15:50:10 +00003881xmlGetQNameProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003882 const char *name, const xmlChar ** namespace)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003883{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003884 const xmlChar *val;
Daniel Veillard4255d502002-04-16 15:50:10 +00003885 xmlNsPtr ns;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003886 const xmlChar *ret, *prefix;
3887 int len;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00003888 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00003889
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003890 *namespace = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00003891 attr = xmlSchemaGetPropNode(node, name);
3892 if (attr == NULL)
3893 return (NULL);
3894 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00003895
Daniel Veillard4255d502002-04-16 15:50:10 +00003896 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003897 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003898
Daniel Veillardba0153a2004-04-01 10:42:31 +00003899 if (!strchr((char *) val, ':')) {
Daniel Veillardebcdebd2004-03-05 00:15:50 +00003900 ns = xmlSearchNs(node->doc, node, 0);
3901 if (ns) {
3902 *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
3903 return (val);
3904 }
3905 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003906 ret = xmlSplitQName3(val, &len);
3907 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003908 return (val);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003909 }
3910 ret = xmlDictLookup(ctxt->dict, ret, -1);
3911 prefix = xmlDictLookup(ctxt->dict, val, len);
Daniel Veillard4255d502002-04-16 15:50:10 +00003912
3913 ns = xmlSearchNs(node->doc, node, prefix);
3914 if (ns == NULL) {
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00003915 xmlSchemaPSimpleTypeErr(ctxt, XML_SCHEMAP_PREFIX_UNDEFINED,
3916 NULL, NULL, (xmlNodePtr) attr,
3917 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), NULL, val,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003918 "The QName value '%s' has no corresponding namespace "
3919 "declaration in scope", val, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003920 } else {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003921 *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003922 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003923 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003924}
3925
3926/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00003927 * xmlSchemaPValAttrNodeQNameValue:
3928 * @ctxt: a schema parser context
3929 * @schema: the schema context
3930 * @ownerDes: the designation of the parent element
3931 * @ownerItem: the parent as a schema object
3932 * @value: the QName value
3933 * @local: the resulting local part if found, the attribute value otherwise
3934 * @uri: the resulting namespace URI if found
3935 *
3936 * Extracts the local name and the URI of a QName value and validates it.
3937 * This one is intended to be used on attribute values that
3938 * should resolve to schema components.
3939 *
3940 * Returns 0, in case the QName is valid, a positive error code
3941 * if not valid and -1 if an internal error occurs.
3942 */
3943static int
3944xmlSchemaPValAttrNodeQNameValue(xmlSchemaParserCtxtPtr ctxt,
3945 xmlSchemaPtr schema,
3946 xmlChar **ownerDes,
3947 xmlSchemaTypePtr ownerItem,
3948 xmlAttrPtr attr,
3949 const xmlChar *value,
3950 const xmlChar **uri,
3951 const xmlChar **prefix,
3952 const xmlChar **local)
3953{
3954 const xmlChar *pref;
3955 xmlNsPtr ns;
3956 int len, ret;
3957
3958 *uri = NULL;
3959 *local = NULL;
3960 if (prefix != 0)
3961 *prefix = NULL;
3962 ret = xmlValidateQName(value, 1);
3963 if (ret > 0) {
3964 xmlSchemaPSimpleTypeErr(ctxt,
3965 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
3966 ownerDes, ownerItem, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00003967 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
3968 "QName", value,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003969 NULL, NULL, NULL);
3970 *local = value;
3971 return (ctxt->err);
3972 } else if (ret < 0)
3973 return (-1);
3974
3975 if (!strchr((char *) value, ':')) {
3976 ns = xmlSearchNs(attr->doc, attr->parent, 0);
3977 if (ns)
3978 *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
3979 else if (schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) {
3980 /*
3981 * This one takes care of included schemas with no
3982 * target namespace.
3983 */
3984 *uri = schema->targetNamespace;
3985 }
3986 *local = value;
3987 return (0);
3988 }
3989 /*
3990 * At this point xmlSplitQName3 has to return a local name.
3991 */
3992 *local = xmlSplitQName3(value, &len);
3993 *local = xmlDictLookup(ctxt->dict, *local, -1);
3994 pref = xmlDictLookup(ctxt->dict, value, len);
3995 if (prefix != 0)
3996 *prefix = pref;
3997 ns = xmlSearchNs(attr->doc, attr->parent, pref);
3998 if (ns == NULL) {
3999 xmlSchemaPSimpleTypeErr(ctxt,
4000 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
4001 ownerDes, ownerItem, (xmlNodePtr) attr,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004002 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), "QName", value,
4003 "The QName value '%s' has no corresponding namespace "
4004 "declaration in scope", value, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004005 return (ctxt->err);
4006 } else {
4007 *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
4008 }
4009 return (0);
4010}
4011
4012/**
4013 * xmlSchemaPValAttrNodeQName:
4014 * @ctxt: a schema parser context
4015 * @schema: the schema context
4016 * @ownerDes: the designation of the owner element
4017 * @ownerItem: the owner as a schema object
4018 * @attr: the attribute node
4019 * @local: the resulting local part if found, the attribute value otherwise
4020 * @uri: the resulting namespace URI if found
4021 *
4022 * Extracts and validates the QName of an attribute value.
4023 * This one is intended to be used on attribute values that
4024 * should resolve to schema components.
4025 *
4026 * Returns 0, in case the QName is valid, a positive error code
4027 * if not valid and -1 if an internal error occurs.
4028 */
4029static int
4030xmlSchemaPValAttrNodeQName(xmlSchemaParserCtxtPtr ctxt,
4031 xmlSchemaPtr schema,
4032 xmlChar **ownerDes,
4033 xmlSchemaTypePtr ownerItem,
4034 xmlAttrPtr attr,
4035 const xmlChar **uri,
4036 const xmlChar **prefix,
4037 const xmlChar **local)
4038{
4039 const xmlChar *value;
4040
4041 value = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
4042 return (xmlSchemaPValAttrNodeQNameValue(ctxt, schema,
4043 ownerDes, ownerItem, attr, value, uri, prefix, local));
4044}
4045
4046/**
4047 * xmlSchemaPValAttrQName:
4048 * @ctxt: a schema parser context
4049 * @schema: the schema context
4050 * @ownerDes: the designation of the parent element
4051 * @ownerItem: the owner as a schema object
4052 * @ownerElem: the parent node of the attribute
4053 * @name: the name of the attribute
4054 * @local: the resulting local part if found, the attribute value otherwise
4055 * @uri: the resulting namespace URI if found
4056 *
4057 * Extracts and validates the QName of an attribute value.
4058 *
4059 * Returns 0, in case the QName is valid, a positive error code
4060 * if not valid and -1 if an internal error occurs.
4061 */
4062static int
4063xmlSchemaPValAttrQName(xmlSchemaParserCtxtPtr ctxt,
4064 xmlSchemaPtr schema,
4065 xmlChar **ownerDes,
4066 xmlSchemaTypePtr ownerItem,
4067 xmlNodePtr ownerElem,
4068 const char *name,
4069 const xmlChar **uri,
4070 const xmlChar **prefix,
4071 const xmlChar **local)
4072{
4073 xmlAttrPtr attr;
4074
4075 attr = xmlSchemaGetPropNode(ownerElem, name);
4076 if (attr == NULL) {
4077 *local = NULL;
4078 *uri = NULL;
4079 return (0);
4080 }
4081 return (xmlSchemaPValAttrNodeQName(ctxt, schema,
4082 ownerDes, ownerItem, attr, uri, prefix, local));
4083}
4084
4085/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004086 * xmlGetMaxOccurs:
4087 * @ctxt: a schema validation context
4088 * @node: a subtree containing XML Schema informations
4089 *
4090 * Get the maxOccurs property
4091 *
4092 * Returns the default if not found, or the value
4093 */
4094static int
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004095xmlGetMaxOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
4096 int min, int max, int def, const char *expected)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004097{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004098 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00004099 int ret = 0;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004100 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00004101
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004102 attr = xmlSchemaGetPropNode(node, "maxOccurs");
4103 if (attr == NULL)
4104 return (def);
4105 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Daniel Veillard4255d502002-04-16 15:50:10 +00004106
4107 if (xmlStrEqual(val, (const xmlChar *) "unbounded")) {
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004108 if (max != UNBOUNDED) {
4109 xmlSchemaPSimpleTypeErr(ctxt,
4110 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
4111 /* XML_SCHEMAP_INVALID_MINOCCURS, */
4112 NULL, NULL, (xmlNodePtr) attr, NULL, expected,
4113 val, NULL, NULL, NULL);
4114 return (def);
4115 } else
4116 return (UNBOUNDED); /* encoding it with -1 might be another option */
Daniel Veillard4255d502002-04-16 15:50:10 +00004117 }
4118
4119 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00004120 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004121 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004122 if (*cur == 0) {
4123 xmlSchemaPSimpleTypeErr(ctxt,
4124 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
4125 /* XML_SCHEMAP_INVALID_MINOCCURS, */
4126 NULL, NULL, (xmlNodePtr) attr, NULL, expected,
4127 val, NULL, NULL, NULL);
4128 return (def);
4129 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004130 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004131 ret = ret * 10 + (*cur - '0');
4132 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00004133 }
William M. Brack76e95df2003-10-18 16:20:14 +00004134 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004135 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004136 /*
4137 * TODO: Restrict the maximal value to Integer.
4138 */
4139 if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
4140 xmlSchemaPSimpleTypeErr(ctxt,
4141 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
4142 /* XML_SCHEMAP_INVALID_MINOCCURS, */
4143 NULL, NULL, (xmlNodePtr) attr, NULL, expected,
4144 val, NULL, NULL, NULL);
4145 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00004146 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004147 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004148}
4149
4150/**
4151 * xmlGetMinOccurs:
4152 * @ctxt: a schema validation context
4153 * @node: a subtree containing XML Schema informations
4154 *
4155 * Get the minOccurs property
4156 *
4157 * Returns the default if not found, or the value
4158 */
4159static int
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004160xmlGetMinOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
4161 int min, int max, int def, const char *expected)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004162{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004163 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00004164 int ret = 0;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004165 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00004166
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004167 attr = xmlSchemaGetPropNode(node, "minOccurs");
4168 if (attr == NULL)
4169 return (def);
4170 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Daniel Veillard4255d502002-04-16 15:50:10 +00004171 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00004172 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004173 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004174 if (*cur == 0) {
4175 xmlSchemaPSimpleTypeErr(ctxt,
4176 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
4177 /* XML_SCHEMAP_INVALID_MINOCCURS, */
4178 NULL, NULL, (xmlNodePtr) attr, NULL, expected,
4179 val, NULL, NULL, NULL);
4180 return (def);
4181 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004182 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004183 ret = ret * 10 + (*cur - '0');
4184 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00004185 }
William M. Brack76e95df2003-10-18 16:20:14 +00004186 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004187 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004188 /*
4189 * TODO: Restrict the maximal value to Integer.
4190 */
4191 if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
4192 xmlSchemaPSimpleTypeErr(ctxt,
4193 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
4194 /* XML_SCHEMAP_INVALID_MINOCCURS, */
4195 NULL, NULL, (xmlNodePtr) attr, NULL, expected,
4196 val, NULL, NULL, NULL);
4197 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00004198 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004199 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004200}
4201
4202/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00004203 * xmlSchemaPGetBoolNodeValue:
4204 * @ctxt: a schema validation context
4205 * @ownerDes: owner designation
4206 * @ownerItem: the owner as a schema item
4207 * @node: the node holding the value
4208 *
4209 * Converts a boolean string value into 1 or 0.
4210 *
4211 * Returns 0 or 1.
4212 */
4213static int
4214xmlSchemaPGetBoolNodeValue(xmlSchemaParserCtxtPtr ctxt,
4215 xmlChar **ownerDes,
4216 xmlSchemaTypePtr ownerItem,
4217 xmlNodePtr node)
4218{
4219 xmlChar *value = NULL;
4220 int res = 0;
4221
4222 value = xmlNodeGetContent(node);
4223 /*
4224 * 3.2.2.1 Lexical representation
4225 * An instance of a datatype that is defined as ·boolean·
4226 * can have the following legal literals {true, false, 1, 0}.
4227 */
4228 if (xmlStrEqual(BAD_CAST value, BAD_CAST "true"))
4229 res = 1;
4230 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "false"))
4231 res = 0;
4232 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "1"))
4233 res = 1;
4234 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "0"))
4235 res = 0;
4236 else {
4237 xmlSchemaPSimpleTypeErr(ctxt,
4238 XML_SCHEMAP_INVALID_BOOLEAN,
4239 ownerDes, ownerItem, node,
4240 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
4241 "(1 | 0 | true | false)", BAD_CAST value,
4242 NULL, NULL, NULL);
4243 }
4244 if (value != NULL)
4245 xmlFree(value);
4246 return (res);
4247}
4248
4249/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004250 * xmlGetBooleanProp:
4251 * @ctxt: a schema validation context
4252 * @node: a subtree containing XML Schema informations
4253 * @name: the attribute name
4254 * @def: the default value
4255 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00004256 * Evaluate if a boolean property is set
Daniel Veillard4255d502002-04-16 15:50:10 +00004257 *
4258 * Returns the default if not found, 0 if found to be false,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004259 * 1 if found to be true
Daniel Veillard4255d502002-04-16 15:50:10 +00004260 */
4261static int
Daniel Veillardc0826a72004-08-10 14:17:33 +00004262xmlGetBooleanProp(xmlSchemaParserCtxtPtr ctxt,
4263 xmlChar **ownerDes,
4264 xmlSchemaTypePtr ownerItem,
4265 xmlNodePtr node,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004266 const char *name, int def)
4267{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004268 const xmlChar *val;
Daniel Veillard4255d502002-04-16 15:50:10 +00004269
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004270 val = xmlSchemaGetProp(ctxt, node, name);
Daniel Veillard4255d502002-04-16 15:50:10 +00004271 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004272 return (def);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004273 /*
4274 * 3.2.2.1 Lexical representation
4275 * An instance of a datatype that is defined as ·boolean·
4276 * can have the following legal literals {true, false, 1, 0}.
4277 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004278 if (xmlStrEqual(val, BAD_CAST "true"))
4279 def = 1;
4280 else if (xmlStrEqual(val, BAD_CAST "false"))
4281 def = 0;
Daniel Veillardc0826a72004-08-10 14:17:33 +00004282 else if (xmlStrEqual(val, BAD_CAST "1"))
4283 def = 1;
4284 else if (xmlStrEqual(val, BAD_CAST "0"))
4285 def = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00004286 else {
Daniel Veillardc0826a72004-08-10 14:17:33 +00004287 xmlSchemaPSimpleTypeErr(ctxt,
4288 XML_SCHEMAP_INVALID_BOOLEAN,
William M. Brack2f2a6632004-08-20 23:09:47 +00004289 ownerDes, ownerItem, node,
4290 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
4291 "(1 | 0 | true | false)", val, NULL, NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004292 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004293 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00004294}
4295
4296/************************************************************************
4297 * *
4298 * Shema extraction from an Infoset *
4299 * *
4300 ************************************************************************/
4301static xmlSchemaTypePtr xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr
4302 ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00004303 xmlNodePtr node,
4304 int topLevel);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004305static xmlSchemaTypePtr xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr
4306 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00004307 xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00004308 xmlNodePtr node,
4309 int topLevel);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004310static xmlSchemaTypePtr xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr
4311 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00004312 xmlSchemaPtr schema,
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00004313 xmlNodePtr node);
Daniel Veillard4255d502002-04-16 15:50:10 +00004314static xmlSchemaTypePtr xmlSchemaParseSequence(xmlSchemaParserCtxtPtr ctxt,
4315 xmlSchemaPtr schema,
4316 xmlNodePtr node);
4317static xmlSchemaTypePtr xmlSchemaParseAll(xmlSchemaParserCtxtPtr ctxt,
4318 xmlSchemaPtr schema,
4319 xmlNodePtr node);
4320static xmlSchemaAttributePtr xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr
4321 ctxt,
4322 xmlSchemaPtr schema,
William M. Bracke7091952004-05-11 15:09:58 +00004323 xmlNodePtr node,
4324 int topLevel);
Daniel Veillard4255d502002-04-16 15:50:10 +00004325static xmlSchemaAttributeGroupPtr
4326xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +00004327 xmlSchemaPtr schema, xmlNodePtr node,
4328 int topLevel);
Daniel Veillard4255d502002-04-16 15:50:10 +00004329static xmlSchemaTypePtr xmlSchemaParseChoice(xmlSchemaParserCtxtPtr ctxt,
4330 xmlSchemaPtr schema,
4331 xmlNodePtr node);
4332static xmlSchemaTypePtr xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt,
4333 xmlSchemaPtr schema,
4334 xmlNodePtr node);
Daniel Veillard3646d642004-06-02 19:19:14 +00004335static xmlSchemaWildcardPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004336xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
4337 xmlSchemaPtr schema, xmlNodePtr node);
Daniel Veillard4255d502002-04-16 15:50:10 +00004338
4339/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004340 * xmlSchemaPValAttrNodeValue:
Daniel Veillard01fa6152004-06-29 17:04:39 +00004341 *
4342 * @ctxt: a schema parser context
Daniel Veillardc0826a72004-08-10 14:17:33 +00004343 * @ownerDes: the designation of the parent element
4344 * @ownerItem: the schema object owner if existent
4345 * @attr: the schema attribute node being validated
4346 * @value: the value
4347 * @type: the built-in type to be validated against
Daniel Veillard01fa6152004-06-29 17:04:39 +00004348 *
4349 * Validates a value against the given built-in type.
4350 * This one is intended to be used internally for validation
4351 * of schema attribute values during parsing of the schema.
4352 *
4353 * Returns 0 if the value is valid, a positive error code
4354 * number otherwise and -1 in case of an internal or API error.
4355 */
4356static int
Daniel Veillardc0826a72004-08-10 14:17:33 +00004357xmlSchemaPValAttrNodeValue(xmlSchemaParserCtxtPtr ctxt,
4358 xmlChar **ownerDes,
4359 xmlSchemaTypePtr ownerItem,
4360 xmlAttrPtr attr,
4361 const xmlChar *value,
4362 xmlSchemaTypePtr type)
Daniel Veillard01fa6152004-06-29 17:04:39 +00004363{
Daniel Veillard01fa6152004-06-29 17:04:39 +00004364
Daniel Veillardc0826a72004-08-10 14:17:33 +00004365 int ret = 0;
4366
4367 /*
4368 * NOTE: Should we move this to xmlschematypes.c? Hmm, but this
4369 * one is really meant to be used internally, so better not.
4370 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00004371 if ((ctxt == NULL) || (type == NULL) || (attr == NULL))
Daniel Veillardc0826a72004-08-10 14:17:33 +00004372 return (-1);
4373 if (type->type != XML_SCHEMA_TYPE_BASIC) {
4374 xmlSchemaPErr(ctxt, (xmlNodePtr) attr,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00004375 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00004376 "Internal error: xmlSchemaPValAttrNodeValue, the given "
Daniel Veillardc0826a72004-08-10 14:17:33 +00004377 "type '%s' is not a built-in type.\n",
4378 type->name, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00004379 return (-1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004380 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00004381 switch (type->builtInType) {
4382 case XML_SCHEMAS_NCNAME:
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00004383 case XML_SCHEMAS_QNAME:
4384 case XML_SCHEMAS_ANYURI:
4385 case XML_SCHEMAS_TOKEN:
4386 case XML_SCHEMAS_LANGUAGE:
4387 ret = xmlSchemaValPredefTypeNode(type, value, NULL, (xmlNodePtr) attr);
4388 break;
4389
4390 /*
4391 case XML_SCHEMAS_NCNAME:
Daniel Veillard01fa6152004-06-29 17:04:39 +00004392 ret = xmlValidateNCName(value, 1);
4393 break;
4394 case XML_SCHEMAS_QNAME:
Daniel Veillardc0826a72004-08-10 14:17:33 +00004395 xmlSchemaPErr(ctxt, (xmlNodePtr) attr,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00004396 XML_SCHEMAP_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004397 "Internal error: xmlSchemaPvalueAttrNode, use "
4398 "the function xmlSchemaExtractSchemaQNamePropvalueidated "
4399 "for extracting QName valueues instead.\n",
4400 NULL, NULL);
4401 return (-1);
4402 case XML_SCHEMAS_ANYURI:
4403 if (value != NULL) {
4404 xmlURIPtr uri = xmlParseURI((const char *) value);
4405 if (uri == NULL)
4406 ret = 1;
4407 else
4408 xmlFreeURI(uri);
Daniel Veillard01fa6152004-06-29 17:04:39 +00004409 }
4410 break;
Daniel Veillardc0826a72004-08-10 14:17:33 +00004411 case XML_SCHEMAS_TOKEN: {
4412 const xmlChar *cur = value;
4413
4414 if (IS_BLANK_CH(*cur)) {
4415 ret = 1;
4416 } else while (*cur != 0) {
4417 if ((*cur == 0xd) || (*cur == 0xa) || (*cur == 0x9)) {
4418 ret = 1;
4419 break;
4420 } else if (*cur == ' ') {
4421 cur++;
4422 if ((*cur == 0) || (*cur == ' ')) {
4423 ret = 1;
4424 break;
4425 }
4426 } else {
4427 cur++;
4428 }
4429 }
4430 }
4431 break;
4432 case XML_SCHEMAS_LANGUAGE:
4433 if (xmlCheckLanguageID(value) != 1)
4434 ret = 1;
4435 break;
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00004436 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00004437 default: {
4438 xmlSchemaPErr(ctxt, (xmlNodePtr) attr,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00004439 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00004440 "Internal error: xmlSchemaPValAttrNodeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +00004441 "valueidation using the type '%s' is not implemented "
4442 "yet.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +00004443 type->name, NULL);
4444 return (-1);
4445 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00004446 }
4447 /*
4448 * TODO: Should we use the S4S error codes instead?
4449 */
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00004450 if (ret < 0) {
4451 xmlSchemaPErr(ctxt, (xmlNodePtr) attr,
4452 XML_SCHEMAP_INTERNAL,
4453 "Internal error: xmlSchemaPValAttrNodeValue, "
4454 "failed to validate a schema attribute value.\n",
4455 NULL, NULL);
4456 return (-1);
4457 } else if (ret > 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00004458 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
4459 xmlSchemaPSimpleTypeErr(ctxt,
4460 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2,
4461 ownerDes, ownerItem, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00004462 type, NULL, value,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004463 NULL, NULL, NULL);
4464 return(XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2);
4465 } else {
4466 xmlSchemaPSimpleTypeErr(ctxt,
4467 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1,
4468 ownerDes, ownerItem, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00004469 type, NULL, value,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004470 NULL, NULL, NULL);
4471 return(XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1);
4472 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00004473 }
4474 return (ret);
4475}
4476
4477/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00004478 * xmlSchemaPValAttrNode:
4479 *
4480 * @ctxt: a schema parser context
4481 * @ownerDes: the designation of the parent element
4482 * @ownerItem: the schema object owner if existent
4483 * @attr: the schema attribute node being validated
4484 * @type: the built-in type to be validated against
4485 * @value: the resulting value if any
4486 *
4487 * Extracts and validates a value against the given built-in type.
4488 * This one is intended to be used internally for validation
4489 * of schema attribute values during parsing of the schema.
4490 *
4491 * Returns 0 if the value is valid, a positive error code
4492 * number otherwise and -1 in case of an internal or API error.
4493 */
4494static int
4495xmlSchemaPValAttrNode(xmlSchemaParserCtxtPtr ctxt,
4496 xmlChar **ownerDes,
4497 xmlSchemaTypePtr ownerItem,
4498 xmlAttrPtr attr,
4499 xmlSchemaTypePtr type,
4500 const xmlChar **value)
4501{
4502 const xmlChar *val;
4503
4504 if ((ctxt == NULL) || (type == NULL) || (attr == NULL))
4505 return (-1);
4506
4507 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
4508 if (value != NULL)
4509 *value = val;
4510
4511 return (xmlSchemaPValAttrNodeValue(ctxt, ownerDes, ownerItem, attr,
4512 val, type));
4513}
4514
4515/**
4516 * xmlSchemaPValAttr:
4517 *
4518 * @ctxt: a schema parser context
4519 * @node: the element node of the attribute
4520 * @ownerDes: the designation of the parent element
4521 * @ownerItem: the schema object owner if existent
4522 * @ownerElem: the owner element node
4523 * @name: the name of the schema attribute node
4524 * @type: the built-in type to be validated against
4525 * @value: the resulting value if any
4526 *
4527 * Extracts and validates a value against the given built-in type.
4528 * This one is intended to be used internally for validation
4529 * of schema attribute values during parsing of the schema.
4530 *
4531 * Returns 0 if the value is valid, a positive error code
4532 * number otherwise and -1 in case of an internal or API error.
4533 */
4534static int
4535xmlSchemaPValAttr(xmlSchemaParserCtxtPtr ctxt,
4536 xmlChar **ownerDes,
4537 xmlSchemaTypePtr ownerItem,
4538 xmlNodePtr ownerElem,
4539 const char *name,
4540 xmlSchemaTypePtr type,
4541 const xmlChar **value)
4542{
4543 xmlAttrPtr attr;
4544
4545 if ((ctxt == NULL) || (type == NULL)) {
4546 if (value != NULL)
4547 *value = NULL;
4548 return (-1);
4549 }
4550 if (type->type != XML_SCHEMA_TYPE_BASIC) {
4551 if (value != NULL)
4552 *value = NULL;
4553 xmlSchemaPErr(ctxt, ownerElem,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00004554 XML_SCHEMAP_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004555 "Internal error: xmlSchemaPValAttr, the given "
4556 "type '%s' is not a built-in type.\n",
4557 type->name, NULL);
4558 return (-1);
4559 }
4560 attr = xmlSchemaGetPropNode(ownerElem, name);
4561 if (attr == NULL) {
4562 if (value != NULL)
4563 *value = NULL;
4564 return (0);
4565 }
4566 return (xmlSchemaPValAttrNode(ctxt, ownerDes, ownerItem, attr,
4567 type, value));
4568}
4569/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004570 * xmlSchemaParseAttrDecls:
4571 * @ctxt: a schema validation context
4572 * @schema: the schema being built
4573 * @node: a subtree containing XML Schema informations
4574 * @type: the hosting type
4575 *
4576 * parse a XML schema attrDecls declaration corresponding to
4577 * <!ENTITY % attrDecls
4578 * '((%attribute;| %attributeGroup;)*,(%anyAttribute;)?)'>
4579 */
4580static xmlNodePtr
4581xmlSchemaParseAttrDecls(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
4582 xmlNodePtr child, xmlSchemaTypePtr type)
4583{
4584 xmlSchemaAttributePtr lastattr, attr;
4585
4586 lastattr = NULL;
4587 while ((IS_SCHEMA(child, "attribute")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004588 (IS_SCHEMA(child, "attributeGroup"))) {
4589 attr = NULL;
4590 if (IS_SCHEMA(child, "attribute")) {
William M. Bracke7091952004-05-11 15:09:58 +00004591 attr = xmlSchemaParseAttribute(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004592 } else if (IS_SCHEMA(child, "attributeGroup")) {
4593 attr = (xmlSchemaAttributePtr)
Daniel Veillard3646d642004-06-02 19:19:14 +00004594 xmlSchemaParseAttributeGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004595 }
4596 if (attr != NULL) {
4597 if (lastattr == NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +00004598 if (type->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP)
4599 ((xmlSchemaAttributeGroupPtr) type)->attributes = attr;
4600 else
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004601 type->attributes = attr;
4602 lastattr = attr;
4603 } else {
4604 lastattr->next = attr;
4605 lastattr = attr;
4606 }
4607 }
4608 child = child->next;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004609 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004610 return (child);
Daniel Veillard4255d502002-04-16 15:50:10 +00004611}
4612
4613/**
4614 * xmlSchemaParseAnnotation:
4615 * @ctxt: a schema validation context
4616 * @schema: the schema being built
4617 * @node: a subtree containing XML Schema informations
4618 *
4619 * parse a XML schema Attrribute declaration
4620 * *WARNING* this interface is highly subject to change
4621 *
William M. Bracke7091952004-05-11 15:09:58 +00004622 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00004623 * 1 in case of success.
4624 */
4625static xmlSchemaAnnotPtr
4626xmlSchemaParseAnnotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
4627 xmlNodePtr node)
4628{
4629 xmlSchemaAnnotPtr ret;
Daniel Veillardc0826a72004-08-10 14:17:33 +00004630 xmlNodePtr child = NULL;
4631 xmlAttrPtr attr;
4632 int barked = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00004633
Daniel Veillardc0826a72004-08-10 14:17:33 +00004634 /*
4635 * INFO: S4S completed.
4636 */
4637 /*
4638 * id = ID
4639 * {any attributes with non-schema namespace . . .}>
4640 * Content: (appinfo | documentation)*
4641 */
Daniel Veillard4255d502002-04-16 15:50:10 +00004642 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
4643 return (NULL);
4644 ret = xmlSchemaNewAnnot(ctxt, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004645 attr = node->properties;
4646 while (attr != NULL) {
4647 if (((attr->ns == NULL) &&
4648 (!xmlStrEqual(attr->name, BAD_CAST "id"))) ||
4649 ((attr->ns != NULL) &&
4650 xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
4651
4652 xmlSchemaPIllegalAttrErr(ctxt,
4653 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4654 NULL, NULL, attr);
4655 }
4656 attr = attr->next;
4657 }
4658 /* TODO: Check id. */
4659
4660 /*
4661 * And now for the children...
4662 */
4663 child = node->children;
4664 while (child != NULL) {
4665 if (IS_SCHEMA(child, "appinfo")) {
4666 /* TODO: make available the content of "appinfo". */
4667 /*
4668 * source = anyURI
4669 * {any attributes with non-schema namespace . . .}>
4670 * Content: ({any})*
4671 */
4672 attr = child->properties;
4673 while (attr != NULL) {
4674 if (((attr->ns == NULL) &&
4675 (!xmlStrEqual(attr->name, BAD_CAST "source"))) ||
4676 ((attr->ns != NULL) &&
4677 xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004678
Daniel Veillardc0826a72004-08-10 14:17:33 +00004679 xmlSchemaPIllegalAttrErr(ctxt,
4680 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4681 NULL, NULL, attr);
4682 }
4683 attr = attr->next;
4684 }
4685 xmlSchemaPValAttr(ctxt, NULL, NULL, child, "source",
4686 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), NULL);
4687 child = child->next;
4688 } else if (IS_SCHEMA(child, "documentation")) {
4689 /* TODO: make available the content of "documentation". */
4690 /*
4691 * source = anyURI
4692 * {any attributes with non-schema namespace . . .}>
4693 * Content: ({any})*
4694 */
4695 attr = child->properties;
4696 while (attr != NULL) {
4697 if (attr->ns == NULL) {
4698 if (!xmlStrEqual(attr->name, BAD_CAST "source")) {
4699 xmlSchemaPIllegalAttrErr(ctxt,
4700 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4701 NULL, NULL, attr);
4702 }
4703 } else {
4704 if (xmlStrEqual(attr->ns->href, xmlSchemaNs) ||
4705 (xmlStrEqual(attr->name, BAD_CAST "lang") &&
4706 (!xmlStrEqual(attr->ns->href, XML_XML_NAMESPACE)))) {
4707
4708 xmlSchemaPIllegalAttrErr(ctxt,
4709 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4710 NULL, NULL, attr);
4711 }
4712 }
4713 attr = attr->next;
4714 }
4715 /*
4716 * Attribute "xml:lang".
4717 */
4718 attr = xmlSchemaGetPropNodeNs(child, (const char *) XML_XML_NAMESPACE, "lang");
4719 if (attr != NULL)
4720 xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
4721 xmlSchemaGetBuiltInType(XML_SCHEMAS_LANGUAGE), NULL);
4722 child = child->next;
4723 } else {
4724 if (!barked)
4725 xmlSchemaPContentErr(ctxt,
4726 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
4727 NULL, NULL, node, child, NULL, "(appinfo | documentation)*");
4728 barked = 1;
4729 child = child->next;
4730 }
4731 }
4732
Daniel Veillard4255d502002-04-16 15:50:10 +00004733 return (ret);
4734}
4735
4736/**
4737 * xmlSchemaParseFacet:
4738 * @ctxt: a schema validation context
4739 * @schema: the schema being built
4740 * @node: a subtree containing XML Schema informations
4741 *
4742 * parse a XML schema Facet declaration
4743 * *WARNING* this interface is highly subject to change
4744 *
4745 * Returns the new type structure or NULL in case of error
4746 */
4747static xmlSchemaFacetPtr
4748xmlSchemaParseFacet(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004749 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00004750{
4751 xmlSchemaFacetPtr facet;
4752 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004753 const xmlChar *value;
Daniel Veillard4255d502002-04-16 15:50:10 +00004754
4755 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
4756 return (NULL);
4757
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00004758 facet = xmlSchemaNewFacet();
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004759 if (facet == NULL) {
4760 xmlSchemaPErrMemory(ctxt, "allocating facet", node);
4761 return (NULL);
4762 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004763 facet->node = node;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004764 value = xmlSchemaGetProp(ctxt, node, "value");
Daniel Veillard4255d502002-04-16 15:50:10 +00004765 if (value == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004766 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_FACET_NO_VALUE,
4767 "Facet %s has no value\n", node->name, NULL);
4768 xmlSchemaFreeFacet(facet);
Daniel Veillard4255d502002-04-16 15:50:10 +00004769 return (NULL);
4770 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004771 if (IS_SCHEMA(node, "minInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004772 facet->type = XML_SCHEMA_FACET_MININCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004773 } else if (IS_SCHEMA(node, "minExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004774 facet->type = XML_SCHEMA_FACET_MINEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004775 } else if (IS_SCHEMA(node, "maxInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004776 facet->type = XML_SCHEMA_FACET_MAXINCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004777 } else if (IS_SCHEMA(node, "maxExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004778 facet->type = XML_SCHEMA_FACET_MAXEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004779 } else if (IS_SCHEMA(node, "totalDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004780 facet->type = XML_SCHEMA_FACET_TOTALDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004781 } else if (IS_SCHEMA(node, "fractionDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004782 facet->type = XML_SCHEMA_FACET_FRACTIONDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004783 } else if (IS_SCHEMA(node, "pattern")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004784 facet->type = XML_SCHEMA_FACET_PATTERN;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004785 } else if (IS_SCHEMA(node, "enumeration")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004786 facet->type = XML_SCHEMA_FACET_ENUMERATION;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004787 } else if (IS_SCHEMA(node, "whiteSpace")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004788 facet->type = XML_SCHEMA_FACET_WHITESPACE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004789 } else if (IS_SCHEMA(node, "length")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004790 facet->type = XML_SCHEMA_FACET_LENGTH;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004791 } else if (IS_SCHEMA(node, "maxLength")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004792 facet->type = XML_SCHEMA_FACET_MAXLENGTH;
4793 } else if (IS_SCHEMA(node, "minLength")) {
4794 facet->type = XML_SCHEMA_FACET_MINLENGTH;
4795 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004796 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_TYPE,
4797 "Unknown facet type %s\n", node->name, NULL);
4798 xmlSchemaFreeFacet(facet);
4799 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004800 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004801 facet->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00004802 facet->value = value;
Daniel Veillard01fa6152004-06-29 17:04:39 +00004803 if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
4804 (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
4805 const xmlChar *fixed;
4806
4807 fixed = xmlSchemaGetProp(ctxt, node, "fixed");
4808 if (fixed != NULL) {
4809 if (xmlStrEqual(fixed, BAD_CAST "true"))
4810 facet->fixed = 1;
4811 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004812 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004813 child = node->children;
4814
4815 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004816 facet->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
4817 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004818 }
4819 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004820 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_CHILD,
4821 "Facet %s has unexpected child content\n",
4822 node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004823 }
4824 return (facet);
4825}
4826
4827/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00004828 * xmlSchemaParseWildcardNs:
4829 * @ctxt: a schema parser context
4830 * @wildc: the wildcard, already created
4831 * @node: a subtree containing XML Schema informations
4832 *
4833 * Parses the attribute "processContents" and "namespace"
4834 * of a xsd:anyAttribute and xsd:any.
4835 * *WARNING* this interface is highly subject to change
4836 *
4837 * Returns 0 if everything goes fine, a positive error code
4838 * if something is not valid and -1 if an internal error occurs.
4839 */
4840static int
4841xmlSchemaParseWildcardNs(xmlSchemaParserCtxtPtr ctxt,
4842 xmlSchemaPtr schema,
4843 xmlSchemaWildcardPtr wildc,
4844 xmlNodePtr node)
4845{
4846 const xmlChar *pc, *ns, *dictnsItem;
4847 int ret = 0;
4848 xmlChar *nsItem;
4849 xmlSchemaWildcardNsPtr tmp, lastNs = NULL;
4850 xmlAttrPtr attr;
4851
4852 pc = xmlSchemaGetProp(ctxt, node, "processContents");
4853 if ((pc == NULL)
4854 || (xmlStrEqual(pc, (const xmlChar *) "strict"))) {
4855 wildc->processContents = XML_SCHEMAS_ANY_STRICT;
4856 } else if (xmlStrEqual(pc, (const xmlChar *) "skip")) {
4857 wildc->processContents = XML_SCHEMAS_ANY_SKIP;
4858 } else if (xmlStrEqual(pc, (const xmlChar *) "lax")) {
4859 wildc->processContents = XML_SCHEMAS_ANY_LAX;
4860 } else {
4861 xmlSchemaPSimpleTypeErr(ctxt,
4862 XML_SCHEMAP_UNKNOWN_PROCESSCONTENT_CHILD,
4863 NULL, NULL, node,
William M. Brack2f2a6632004-08-20 23:09:47 +00004864 NULL, "(strict | skip | lax)", pc,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004865 NULL, NULL, NULL);
4866 wildc->processContents = XML_SCHEMAS_ANY_STRICT;
4867 ret = XML_SCHEMAP_UNKNOWN_PROCESSCONTENT_CHILD;
4868 }
4869 /*
4870 * Build the namespace constraints.
4871 */
4872 attr = xmlSchemaGetPropNode(node, "namespace");
4873 ns = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
4874 if ((ns == NULL) || (xmlStrEqual(ns, BAD_CAST "##any")))
4875 wildc->any = 1;
4876 else if (xmlStrEqual(ns, BAD_CAST "##other")) {
4877 wildc->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
4878 if (wildc->negNsSet == NULL) {
4879 return (-1);
4880 }
4881 wildc->negNsSet->value = schema->targetNamespace;
4882 } else {
4883 const xmlChar *end, *cur;
4884
4885 cur = ns;
4886 do {
4887 while (IS_BLANK_CH(*cur))
4888 cur++;
4889 end = cur;
4890 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
4891 end++;
4892 if (end == cur)
4893 break;
4894 nsItem = xmlStrndup(cur, end - cur);
4895 if ((xmlStrEqual(nsItem, BAD_CAST "##other")) ||
4896 (xmlStrEqual(nsItem, BAD_CAST "##any"))) {
4897 xmlSchemaPSimpleTypeErr(ctxt,
4898 XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER,
4899 NULL, NULL, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00004900 NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004901 "((##any | ##other) | List of (anyURI | "
4902 "(##targetNamespace | ##local)))",
4903 nsItem, NULL, NULL, NULL);
4904 ret = XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER;
4905 } else {
4906 if (xmlStrEqual(nsItem, BAD_CAST "##targetNamespace")) {
4907 dictnsItem = schema->targetNamespace;
4908 } else if (xmlStrEqual(nsItem, BAD_CAST "##local")) {
4909 dictnsItem = NULL;
4910 } else {
4911 /*
4912 * Validate the item (anyURI).
4913 */
4914 xmlSchemaPValAttrNodeValue(ctxt, NULL, NULL, attr,
4915 nsItem, xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI));
4916 dictnsItem = xmlDictLookup(ctxt->dict, nsItem, -1);
4917 }
4918 /*
4919 * Avoid dublicate namespaces.
4920 */
4921 tmp = wildc->nsSet;
4922 while (tmp != NULL) {
4923 if (dictnsItem == tmp->value)
4924 break;
4925 tmp = tmp->next;
4926 }
4927 if (tmp == NULL) {
4928 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
4929 if (tmp == NULL) {
4930 xmlFree(nsItem);
4931 return (-1);
4932 }
4933 tmp->value = dictnsItem;
4934 tmp->next = NULL;
4935 if (wildc->nsSet == NULL)
4936 wildc->nsSet = tmp;
4937 else
4938 lastNs->next = tmp;
4939 lastNs = tmp;
4940 }
4941
4942 }
4943 xmlFree(nsItem);
4944 cur = end;
4945 } while (*cur != 0);
4946 }
4947 return (ret);
4948}
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004949
4950static int
4951xmlSchemaPCheckParticleCorrect_2(xmlSchemaParserCtxtPtr ctxt,
4952 xmlSchemaTypePtr item,
4953 xmlNodePtr node,
4954 int minOccurs,
4955 int maxOccurs) {
4956
4957 if (maxOccurs != UNBOUNDED) {
4958 /*
4959 * TODO: Maby we should better not create the particle,
4960 * if min/max is invalid, since it could confuse the build of the
4961 * content model.
4962 */
4963 /*
4964 * 3.9.6 Schema Component Constraint: Particle Correct
4965 *
4966 */
4967 if (maxOccurs < 1) {
4968 /*
4969 * 2.2 {max occurs} must be greater than or equal to 1.
4970 */
4971 xmlSchemaPCustomAttrErr(ctxt,
4972 XML_SCHEMAP_P_PROPS_CORRECT_2_2,
4973 NULL, item, xmlSchemaGetPropNode(node, "maxOccurs"),
4974 "The value must be greater than or equal to 1");
4975 return (XML_SCHEMAP_P_PROPS_CORRECT_2_2);
4976 } else if (minOccurs > maxOccurs) {
4977 /*
4978 * 2.1 {min occurs} must not be greater than {max occurs}.
4979 */
4980 xmlSchemaPCustomAttrErr(ctxt,
4981 XML_SCHEMAP_P_PROPS_CORRECT_2_1,
4982 NULL, item, xmlSchemaGetPropNode(node, "minOccurs"),
4983 "The value must not be greater than the value of 'maxOccurs'");
4984 return (XML_SCHEMAP_P_PROPS_CORRECT_2_1);
4985 }
4986 }
4987 return (0);
4988}
4989
Daniel Veillardc0826a72004-08-10 14:17:33 +00004990/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004991 * xmlSchemaParseAny:
4992 * @ctxt: a schema validation context
4993 * @schema: the schema being built
4994 * @node: a subtree containing XML Schema informations
4995 *
4996 * parse a XML schema Any declaration
4997 * *WARNING* this interface is highly subject to change
4998 *
4999 * Returns the new type structure or NULL in case of error
5000 */
5001static xmlSchemaTypePtr
5002xmlSchemaParseAny(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5003 xmlNodePtr node)
5004{
5005 xmlSchemaTypePtr type;
5006 xmlNodePtr child = NULL;
5007 xmlChar name[30];
Daniel Veillardc0826a72004-08-10 14:17:33 +00005008 xmlSchemaWildcardPtr wildc;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005009 int minOccurs, maxOccurs;
Daniel Veillard4255d502002-04-16 15:50:10 +00005010
5011 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5012 return (NULL);
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005013 maxOccurs = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
5014 "(nonNegativeInteger | unbounded)");
5015 minOccurs = xmlGetMinOccurs(ctxt, node, 0, -1, 1,
5016 "nonNegativeInteger");
5017 if ((minOccurs == 0) && (maxOccurs == 0))
5018 return (NULL);
5019
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005020 snprintf((char *) name, 30, "any %d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00005021 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00005022 if (type == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005023 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005024 type->node = node;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005025 type->type = XML_SCHEMA_TYPE_ANY;
5026
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00005027 /*
5028 * TODO: Use a particle component here.
5029 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00005030 wildc = xmlSchemaAddWildcard(ctxt);
5031 /*
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005032 * Check min/max sanity.
5033 */
5034 type->maxOccurs = maxOccurs;
5035 type->minOccurs = minOccurs;
5036 xmlSchemaPCheckParticleCorrect_2(ctxt, type,
5037 node, type->minOccurs, type->maxOccurs);
5038 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00005039 * This is not nice, since it is won't be used as a attribute wildcard,
5040 * but better than adding a field to the structure.
5041 */
5042 type->attributeWildcard = wildc;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005043 xmlSchemaParseWildcardNs(ctxt, schema, wildc, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005044 child = node->children;
Daniel Veillard4255d502002-04-16 15:50:10 +00005045 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005046 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5047 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005048 }
5049 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005050 xmlSchemaPErr2(ctxt, node, child,
5051 XML_SCHEMAP_UNKNOWN_SEQUENCE_CHILD,
5052 "Sequence %s has unexpected content\n", type->name,
5053 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005054 }
5055
5056 return (type);
5057}
5058
5059/**
5060 * xmlSchemaParseNotation:
5061 * @ctxt: a schema validation context
5062 * @schema: the schema being built
5063 * @node: a subtree containing XML Schema informations
5064 *
5065 * parse a XML schema Notation declaration
5066 *
5067 * Returns the new structure or NULL in case of error
5068 */
5069static xmlSchemaNotationPtr
5070xmlSchemaParseNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005071 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00005072{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005073 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00005074 xmlSchemaNotationPtr ret;
5075 xmlNodePtr child = NULL;
5076
5077 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5078 return (NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005079 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00005080 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005081 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_NOTATION_NO_NAME,
5082 "Notation has no name\n", NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005083 return (NULL);
5084 }
5085 ret = xmlSchemaAddNotation(ctxt, schema, name);
5086 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005087 return (NULL);
5088 }
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00005089 ret->targetNamespace = schema->targetNamespace;
Daniel Veillard4255d502002-04-16 15:50:10 +00005090 child = node->children;
5091 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005092 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5093 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005094 }
5095 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005096 xmlSchemaPErr2(ctxt, node, child,
5097 XML_SCHEMAP_UNKNOWN_NOTATION_CHILD,
5098 "notation %s has unexpected content\n", name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005099 }
5100
5101 return (ret);
5102}
5103
5104/**
5105 * xmlSchemaParseAnyAttribute:
5106 * @ctxt: a schema validation context
5107 * @schema: the schema being built
5108 * @node: a subtree containing XML Schema informations
5109 *
5110 * parse a XML schema AnyAttrribute declaration
5111 * *WARNING* this interface is highly subject to change
5112 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005113 * Returns a wildcard or NULL.
Daniel Veillard4255d502002-04-16 15:50:10 +00005114 */
Daniel Veillard3646d642004-06-02 19:19:14 +00005115static xmlSchemaWildcardPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005116xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
5117 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00005118{
Daniel Veillard3646d642004-06-02 19:19:14 +00005119 xmlSchemaWildcardPtr ret;
Daniel Veillard4255d502002-04-16 15:50:10 +00005120 xmlNodePtr child = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005121 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005122
5123 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5124 return (NULL);
5125
Daniel Veillard3646d642004-06-02 19:19:14 +00005126 ret = xmlSchemaAddWildcard(ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +00005127 if (ret == NULL) {
5128 return (NULL);
5129 }
William M. Bracke7091952004-05-11 15:09:58 +00005130 ret->type = XML_SCHEMA_TYPE_ANY_ATTRIBUTE;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005131 /*
5132 * Check for illegal attributes.
5133 */
5134 attr = node->properties;
5135 while (attr != NULL) {
5136 if (attr->ns == NULL) {
5137 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
5138 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
5139 (!xmlStrEqual(attr->name, BAD_CAST "processContents"))) {
5140 xmlSchemaPIllegalAttrErr(ctxt,
5141 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5142 NULL, NULL, attr);
5143 }
5144 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5145 xmlSchemaPIllegalAttrErr(ctxt,
5146 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5147 NULL, NULL, attr);
5148 }
5149 attr = attr->next;
5150 }
5151 /* ret->id = xmlSchemaGetProp(ctxt, node, "id"); */
5152 /*
5153 * Parse the namespace list.
5154 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00005155 if (xmlSchemaParseWildcardNs(ctxt, schema, ret, node) != 0) {
5156 xmlSchemaFreeWildcard(ret);
5157 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005158 }
5159 /*
5160 * And now for the children...
5161 */
Daniel Veillard4255d502002-04-16 15:50:10 +00005162 child = node->children;
5163 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005164 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5165 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005166 }
5167 if (child != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005168 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005169 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
5170 NULL, NULL, node, child,
5171 NULL, "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00005172 }
5173
5174 return (ret);
5175}
5176
5177
5178/**
5179 * xmlSchemaParseAttribute:
5180 * @ctxt: a schema validation context
5181 * @schema: the schema being built
5182 * @node: a subtree containing XML Schema informations
5183 *
5184 * parse a XML schema Attrribute declaration
5185 * *WARNING* this interface is highly subject to change
5186 *
William M. Bracke7091952004-05-11 15:09:58 +00005187 * Returns the attribute declaration.
Daniel Veillard4255d502002-04-16 15:50:10 +00005188 */
5189static xmlSchemaAttributePtr
5190xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Bracke7091952004-05-11 15:09:58 +00005191 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00005192{
Daniel Veillardc0826a72004-08-10 14:17:33 +00005193 const xmlChar *name, *attrValue;
5194 xmlChar *repName = NULL; /* The reported designation. */
Daniel Veillard4255d502002-04-16 15:50:10 +00005195 xmlSchemaAttributePtr ret;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005196 xmlNodePtr child = NULL;
5197 xmlAttrPtr attr, nameAttr;
5198 int isRef = 0;
William M. Bracke7091952004-05-11 15:09:58 +00005199
5200 /*
5201 * Note that the w3c spec assumes the schema to be validated with schema
5202 * for schemas beforehand.
5203 *
5204 * 3.2.3 Constraints on XML Representations of Attribute Declarations
William M. Bracke7091952004-05-11 15:09:58 +00005205 */
Daniel Veillard4255d502002-04-16 15:50:10 +00005206
5207 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5208 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005209 attr = xmlSchemaGetPropNode(node, "ref");
5210 nameAttr = xmlSchemaGetPropNode(node, "name");
5211
5212 if ((attr == NULL) && (nameAttr == NULL)) {
5213 /*
5214 * 3.2.3 : 3.1
5215 * One of ref or name must be present, but not both
5216 */
5217 xmlSchemaPMissingAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_1,
5218 (xmlChar **) &xmlSchemaElemDesAttrDecl, NULL, node, NULL,
5219 "One of the attributes 'ref' or 'name' must be present");
5220 return (NULL);
5221 }
5222 if ((topLevel) || (attr == NULL)) {
5223 if (nameAttr == NULL) {
5224 xmlSchemaPMissingAttrErr(ctxt, XML_SCHEMAP_S4S_ATTR_MISSING,
5225 (xmlChar **) &xmlSchemaElemDesAttrDecl, NULL, node,
5226 "name", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00005227 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005228 }
5229 } else
5230 isRef = 1;
5231
5232 if (isRef) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005233 char buf[50];
Daniel Veillardc0826a72004-08-10 14:17:33 +00005234 const xmlChar *refNs = NULL, *ref = NULL, *refPrefix = NULL;
5235
5236 /*
5237 * Parse as attribute reference.
5238 */
5239 if (xmlSchemaPValAttrNodeQName(ctxt, schema,
5240 (xmlChar **) &xmlSchemaElemDesAttrRef, NULL, attr, &refNs,
5241 &refPrefix, &ref) != 0) {
5242 return (NULL);
5243 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005244 snprintf(buf, 49, "#aRef %d", ctxt->counter++ + 1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005245 name = (const xmlChar *) buf;
William M. Brack2f2a6632004-08-20 23:09:47 +00005246 ret = xmlSchemaAddAttribute(ctxt, schema, name, NULL, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005247 if (ret == NULL) {
5248 if (repName != NULL)
5249 xmlFree(repName);
5250 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00005251 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005252 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
5253 ret->node = node;
5254 ret->refNs = refNs;
5255 ret->refPrefix = refPrefix;
5256 ret->ref = ref;
5257 /*
5258 xmlSchemaFormatTypeRep(&repName, (xmlSchemaTypePtr) ret, NULL, NULL);
5259 */
5260 if (nameAttr != NULL)
5261 xmlSchemaPMutualExclAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_1,
5262 &repName, (xmlSchemaTypePtr) ret, nameAttr,
5263 "ref", "name");
5264 /*
5265 * Check for illegal attributes.
5266 */
5267 attr = node->properties;
5268 while (attr != NULL) {
5269 if (attr->ns == NULL) {
5270 if (xmlStrEqual(attr->name, BAD_CAST "type") ||
5271 xmlStrEqual(attr->name, BAD_CAST "form")) {
5272 /*
5273 * 3.2.3 : 3.2
5274 * If ref is present, then all of <simpleType>,
5275 * form and type must be absent.
5276 */
5277 xmlSchemaPIllegalAttrErr(ctxt,
5278 XML_SCHEMAP_SRC_ATTRIBUTE_3_2, &repName,
5279 (xmlSchemaTypePtr) ret, attr);
5280 } else if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
5281 (!xmlStrEqual(attr->name, BAD_CAST "use")) &&
5282 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
5283 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
5284 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
5285 (!xmlStrEqual(attr->name, BAD_CAST "default"))) {
5286 xmlSchemaPIllegalAttrErr(ctxt,
5287 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5288 &repName, (xmlSchemaTypePtr) ret, attr);
5289 }
5290 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5291 xmlSchemaPIllegalAttrErr(ctxt,
5292 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5293 &repName, (xmlSchemaTypePtr) ret, attr);
5294 }
5295 attr = attr->next;
5296 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005297 } else {
William M. Bracke7091952004-05-11 15:09:58 +00005298 const xmlChar *ns = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005299
5300 /*
5301 * Parse as attribute declaration.
5302 */
5303 if (xmlSchemaPValAttrNode(ctxt,
5304 (xmlChar **) &xmlSchemaElemDesAttrDecl, NULL, nameAttr,
5305 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
5306 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00005307 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005308 /*
5309 xmlSchemaFormatTypeRep(&repName, NULL, xmlSchemaElemDesAttrDecl, name);
5310 */
5311 /*
5312 * 3.2.6 Schema Component Constraint: xmlns Not Allowed
5313 */
5314 if (xmlStrEqual(name, BAD_CAST "xmlns")) {
5315 xmlSchemaPSimpleTypeErr(ctxt,
5316 XML_SCHEMAP_NO_XMLNS,
5317 &repName, NULL, (xmlNodePtr) nameAttr,
William M. Brack2f2a6632004-08-20 23:09:47 +00005318 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), "NCName", NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005319 "The value must not match 'xmlns'",
5320 NULL, NULL);
5321 if (repName != NULL)
5322 xmlFree(repName);
5323 return (NULL);
5324 }
5325 /*
5326 * Evaluate the target namespace
5327 */
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005328 if (topLevel) {
5329 ns = schema->targetNamespace;
5330 } else {
5331 attr = xmlSchemaGetPropNode(node, "form");
5332 if (attr != NULL) {
5333 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5334 if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
5335 ns = schema->targetNamespace;
5336 } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) {
5337 xmlSchemaPSimpleTypeErr(ctxt,
5338 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5339 &repName, NULL, (xmlNodePtr) attr,
5340 NULL, "(qualified | unqualified)",
5341 attrValue, NULL, NULL, NULL);
5342 }
5343 } else if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
5344 ns = schema->targetNamespace;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005345 }
William M. Brack2f2a6632004-08-20 23:09:47 +00005346 ret = xmlSchemaAddAttribute(ctxt, schema, name, ns, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005347 if (ret == NULL) {
5348 if (repName != NULL)
5349 xmlFree(repName);
Daniel Veillard3646d642004-06-02 19:19:14 +00005350 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00005351 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005352 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00005353 ret->node = node;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005354 if (topLevel)
5355 ret->flags |= XML_SCHEMAS_ATTR_GLOBAL;
5356 /*
5357 * 3.2.6 Schema Component Constraint: xsi: Not Allowed
5358 */
5359 if (xmlStrEqual(ret->targetNamespace, xmlSchemaInstanceNs)) {
5360 xmlSchemaPCustomErr(ctxt,
5361 XML_SCHEMAP_NO_XSI,
5362 &repName, (xmlSchemaTypePtr) ret, node,
5363 "The target namespace must not match '%s'",
5364 xmlSchemaInstanceNs);
5365 }
5366 /*
5367 * Check for illegal attributes.
5368 */
5369 attr = node->properties;
5370 while (attr != NULL) {
5371 if (attr->ns == NULL) {
5372 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
5373 (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
5374 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
5375 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
5376 (!xmlStrEqual(attr->name, BAD_CAST "type"))) {
5377 if ((topLevel) ||
5378 ((!xmlStrEqual(attr->name, BAD_CAST "form")) &&
5379 (!xmlStrEqual(attr->name, BAD_CAST "use")))) {
5380 xmlSchemaPIllegalAttrErr(ctxt,
5381 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5382 &repName, (xmlSchemaTypePtr) ret, attr);
5383 }
5384 }
5385 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5386 xmlSchemaPIllegalAttrErr(ctxt, XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5387 &repName, (xmlSchemaTypePtr) ret, attr);
5388 }
5389 attr = attr->next;
5390 }
5391 xmlSchemaPValAttrQName(ctxt, schema, &repName, (xmlSchemaTypePtr) ret,
5392 node, "type", &ret->typeNs, NULL, &ret->typeName);
William M. Bracke7091952004-05-11 15:09:58 +00005393 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005394 /* TODO: Check ID. */
5395 ret->id = xmlSchemaGetProp(ctxt, node, "id");
William M. Bracke7091952004-05-11 15:09:58 +00005396 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00005397 * Attribute "fixed".
William M. Bracke7091952004-05-11 15:09:58 +00005398 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00005399 ret->defValue = xmlSchemaGetProp(ctxt, node, "fixed");
5400 if (ret->defValue != NULL)
5401 ret->flags |= XML_SCHEMAS_ATTR_FIXED;
5402 /*
5403 * Attribute "default".
5404 */
5405 attr = xmlSchemaGetPropNode(node, "default");
5406 if (attr != NULL) {
5407 /*
5408 * 3.2.3 : 1
5409 * default and fixed must not both be present.
5410 */
5411 if (ret->flags & XML_SCHEMAS_ATTR_FIXED) {
5412 xmlSchemaPMutualExclAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_1,
5413 &repName, (xmlSchemaTypePtr) ret, attr, "default", "fixed");
5414 } else
5415 ret->defValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5416 }
5417 if (topLevel == 0) {
5418 /*
5419 * Attribute "use".
5420 */
5421 attr = xmlSchemaGetPropNode(node, "use");
5422 if (attr != NULL) {
5423 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5424 if (xmlStrEqual(attrValue, BAD_CAST "optional"))
5425 ret->occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
5426 else if (xmlStrEqual(attrValue, BAD_CAST "prohibited"))
5427 ret->occurs = XML_SCHEMAS_ATTR_USE_PROHIBITED;
5428 else if (xmlStrEqual(attrValue, BAD_CAST "required"))
5429 ret->occurs = XML_SCHEMAS_ATTR_USE_REQUIRED;
5430 else
5431 xmlSchemaPSimpleTypeErr(ctxt,
5432 XML_SCHEMAP_INVALID_ATTR_USE,
5433 &repName, (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00005434 NULL, "(optional | prohibited | required)",
Daniel Veillardc0826a72004-08-10 14:17:33 +00005435 attrValue, NULL, NULL, NULL);
5436 } else
5437 ret->occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
5438 /*
5439 * 3.2.3 : 2
5440 * If default and use are both present, use must have
5441 * the actual value optional.
5442 */
5443 if ((ret->occurs != XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
5444 (ret->defValue != NULL) &&
5445 ((ret->flags & XML_SCHEMAS_ATTR_FIXED) == 0)) {
5446 xmlSchemaPSimpleTypeErr(ctxt,
5447 XML_SCHEMAP_SRC_ATTRIBUTE_2,
5448 &repName, (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00005449 NULL, "(optional | prohibited | required)", NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005450 "The value must be 'optional' if the attribute "
5451 "'default' is present as well", NULL, NULL);
5452 }
5453 }
5454 /*
5455 * And now for the children...
5456 */
Daniel Veillard4255d502002-04-16 15:50:10 +00005457 child = node->children;
5458 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005459 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5460 child = child->next;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005461 }
5462 if (isRef) {
5463 if (child != NULL) {
5464 if (IS_SCHEMA(child, "simpleType"))
5465 /*
5466 * 3.2.3 : 3.2
5467 * If ref is present, then all of <simpleType>,
5468 * form and type must be absent.
5469 */
5470 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_2,
5471 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
5472 "(annotation?)");
5473 else
5474 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
5475 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
5476 "(annotation?)");
5477 }
5478 } else {
5479 if (IS_SCHEMA(child, "simpleType")) {
5480 if (ret->typeName != NULL) {
5481 /*
5482 * 3.2.3 : 4
5483 * type and <simpleType> must not both be present.
5484 */
5485 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_4,
5486 &repName, (xmlSchemaTypePtr) ret, node, child,
5487 "The attribute 'type' and the <simpleType> child "
5488 "are mutually exclusive", NULL);
5489 } else
5490 ret->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
5491 child = child->next;
5492 }
5493 if (child != NULL)
5494 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
5495 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
5496 "(annotation?, simpleType?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00005497 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005498 /*
5499 * Cleanup.
5500 */
5501 if (repName != NULL)
5502 xmlFree(repName);
Daniel Veillard4255d502002-04-16 15:50:10 +00005503 return (ret);
5504}
5505
5506/**
5507 * xmlSchemaParseAttributeGroup:
5508 * @ctxt: a schema validation context
5509 * @schema: the schema being built
5510 * @node: a subtree containing XML Schema informations
5511 *
5512 * parse a XML schema Attribute Group declaration
5513 * *WARNING* this interface is highly subject to change
5514 *
5515 * Returns the attribute group or NULL in case of error.
5516 */
5517static xmlSchemaAttributeGroupPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005518xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +00005519 xmlSchemaPtr schema, xmlNodePtr node,
5520 int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00005521{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005522 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00005523 xmlSchemaAttributeGroupPtr ret;
Daniel Veillard4255d502002-04-16 15:50:10 +00005524 xmlNodePtr child = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005525 const xmlChar *oldcontainer;
5526 xmlAttrPtr attr, nameAttr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005527
5528 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5529 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005530
5531 nameAttr = xmlSchemaGetPropNode(node, "name");
5532 attr = xmlSchemaGetPropNode(node, "ref");
5533 if ((topLevel) || (attr == NULL)) {
5534 /*
5535 * Parse as an attribute group definition.
5536 * Note that those are allowed at top level only.
5537 */
5538 if (nameAttr == NULL) {
5539 xmlSchemaPMissingAttrErr(ctxt,
5540 XML_SCHEMAP_S4S_ATTR_MISSING,
5541 NULL, NULL, node, "name", NULL);
5542 return (NULL);
5543 }
5544 name = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) nameAttr);
5545 /*
5546 * The name is crucial, exit if invalid.
5547 */
5548 if (xmlSchemaPValAttrNode(ctxt,
5549 NULL, NULL, nameAttr,
5550 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
5551 return (NULL);
5552 }
5553 ret = xmlSchemaAddAttributeGroup(ctxt, schema, name, node);
5554 if (ret == NULL)
5555 return (NULL);
5556 ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
5557 ret->flags |= XML_SCHEMAS_ATTRGROUP_GLOBAL;
5558 ret->node = node;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00005559 ret->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005560 } else {
5561 char buf[50];
5562 const xmlChar *refNs = NULL, *ref = NULL, *refPrefix;
5563
5564 /*
5565 * Parse as an attribute group definition reference.
5566 */
5567 if (attr == NULL) {
5568 xmlSchemaPMissingAttrErr(ctxt,
5569 XML_SCHEMAP_S4S_ATTR_MISSING,
5570 NULL, NULL, node, "ref", NULL);
5571 }
5572 xmlSchemaPValAttrNodeQName(ctxt, schema,
5573 NULL, NULL, attr, &refNs, &refPrefix, &ref);
5574
5575 snprintf(buf, 49, "#aGrRef %d", ctxt->counter++ + 1);
5576 name = (const xmlChar *) buf;
5577 if (name == NULL) {
5578 xmlSchemaPErrMemory(ctxt, "creating internal name for an "
5579 "attribute group definition reference", node);
5580 return (NULL);
5581 }
5582 ret = xmlSchemaAddAttributeGroup(ctxt, schema, name, node);
5583 if (ret == NULL)
5584 return (NULL);
5585 ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
5586 ret->ref = ref;
5587 ret->refNs = refNs;
5588 /* TODO: Is @refPrefix currently used? */
5589 ret->refPrefix = refPrefix;
5590 ret->node = node;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00005591 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005592 /*
5593 * Check for illegal attributes.
5594 */
5595 attr = node->properties;
5596 while (attr != NULL) {
5597 if (attr->ns == NULL) {
5598 if ((((topLevel == 0) && (!xmlStrEqual(attr->name, BAD_CAST "ref"))) ||
5599 (topLevel && (!xmlStrEqual(attr->name, BAD_CAST "name")))) &&
5600 (!xmlStrEqual(attr->name, BAD_CAST "id")))
5601 {
5602 xmlSchemaPIllegalAttrErr(ctxt,
5603 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5604 NULL, NULL, attr);
5605 }
5606 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5607 xmlSchemaPIllegalAttrErr(ctxt,
5608 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5609 NULL, NULL, attr);
5610 }
5611 attr = attr->next;
5612 }
5613 /* TODO: Validate "id" ? */
5614 /*
5615 * And now for the children...
5616 */
Daniel Veillard4255d502002-04-16 15:50:10 +00005617 oldcontainer = ctxt->container;
Daniel Veillard4255d502002-04-16 15:50:10 +00005618 ctxt->container = name;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005619 child = node->children;
Daniel Veillard4255d502002-04-16 15:50:10 +00005620 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005621 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5622 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005623 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005624 if (topLevel) {
5625 child = xmlSchemaParseAttrDecls(ctxt, schema, child, (xmlSchemaTypePtr) ret);
5626 if (IS_SCHEMA(child, "anyAttribute")) {
5627 ret->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
5628 child = child->next;
5629 }
5630 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005631 if (child != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005632 xmlSchemaPContentErr(ctxt,
5633 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
5634 NULL, NULL, node, child, NULL,
5635 "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00005636 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005637 ctxt->container = oldcontainer;
5638 return (ret);
5639}
5640
5641/**
William M. Brack2f2a6632004-08-20 23:09:47 +00005642 * xmlSchemaPValAttrFormDefault:
5643 * @value: the value
5644 * @flags: the flags to be modified
5645 * @flagQualified: the specific flag for "qualified"
5646 *
5647 * Returns 0 if the value is valid, 1 otherwise.
5648 */
5649static int
5650xmlSchemaPValAttrFormDefault(const xmlChar *value,
5651 int *flags,
5652 int flagQualified)
5653{
5654 if (xmlStrEqual(value, BAD_CAST "qualified")) {
5655 if ((*flags & flagQualified) == 0)
5656 *flags |= flagQualified;
5657 } else if (!xmlStrEqual(value, BAD_CAST "unqualified"))
5658 return (1);
5659
5660 return (0);
5661}
5662
5663/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00005664 * xmlSchemaPValAttrBlockFinal:
5665 * @value: the value
5666 * @flags: the flags to be modified
5667 * @flagAll: the specific flag for "#all"
5668 * @flagExtension: the specific flag for "extension"
5669 * @flagRestriction: the specific flag for "restriction"
5670 * @flagSubstitution: the specific flag for "substitution"
5671 * @flagList: the specific flag for "list"
5672 * @flagUnion: the specific flag for "union"
5673 *
5674 * Validates the value of the attribute "final" and "block". The value
5675 * is converted into the specified flag values and returned in @flags.
5676 *
5677 * Returns 0 if the value is valid, 1 otherwise.
5678 */
5679
5680static int
5681xmlSchemaPValAttrBlockFinal(const xmlChar *value,
5682 int *flags,
5683 int flagAll,
5684 int flagExtension,
5685 int flagRestriction,
5686 int flagSubstitution,
5687 int flagList,
5688 int flagUnion)
5689{
5690 int ret = 0;
5691
5692 /*
5693 * TODO: This does not check for dublicate entries.
5694 */
William M. Brack2f2a6632004-08-20 23:09:47 +00005695 if (value == NULL)
5696 return (1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005697 if (xmlStrEqual(value, BAD_CAST "#all")) {
5698 if (flagAll != -1)
5699 *flags |= flagAll;
5700 else {
5701 if (flagExtension != -1)
5702 *flags |= flagExtension;
5703 if (flagRestriction != -1)
5704 *flags |= flagRestriction;
5705 if (flagSubstitution != -1)
5706 *flags |= flagSubstitution;
5707 if (flagList != -1)
5708 *flags |= flagList;
5709 if (flagUnion != -1)
5710 *flags |= flagUnion;
5711 }
5712 } else {
5713 const xmlChar *end, *cur = value;
5714 xmlChar *item;
5715
5716 do {
5717 while (IS_BLANK_CH(*cur))
5718 cur++;
5719 end = cur;
5720 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
5721 end++;
5722 if (end == cur)
5723 break;
5724 item = xmlStrndup(cur, end - cur);
5725 if (xmlStrEqual(item, BAD_CAST "extension")) {
5726 if (flagExtension != -1) {
5727 if ((*flags & flagExtension) == 0)
5728 *flags |= flagExtension;
5729 } else
5730 ret = 1;
5731 } else if (xmlStrEqual(item, BAD_CAST "restriction")) {
5732 if (flagRestriction != -1) {
5733 if ((*flags & flagRestriction) == 0)
5734 *flags |= flagRestriction;
5735 } else
5736 ret = 1;
5737 } else if (xmlStrEqual(item, BAD_CAST "substitution")) {
5738 if (flagSubstitution != -1) {
5739 if ((*flags & flagSubstitution) == 0)
5740 *flags |= flagSubstitution;
5741 } else
5742 ret = 1;
5743 } else if (xmlStrEqual(item, BAD_CAST "list")) {
5744 if (flagList != -1) {
5745 if ((*flags & flagList) == 0)
5746 *flags |= flagList;
5747 } else
5748 ret = 1;
5749 } else if (xmlStrEqual(item, BAD_CAST "union")) {
5750 if (flagUnion != -1) {
5751 if ((*flags & flagUnion) == 0)
5752 *flags |= flagUnion;
5753 } else
5754 ret = 1;
5755 } else
5756 ret = 1;
5757 if (item != NULL)
5758 xmlFree(item);
5759 cur = end;
5760 } while ((ret == 0) && (*cur != 0));
5761 }
5762
5763 return (ret);
5764}
5765
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00005766static int
5767xmlSchemaCheckCSelectorXPath(xmlSchemaParserCtxtPtr ctxt,
5768 xmlSchemaPtr schema,
5769 xmlSchemaIDCPtr idc,
5770 xmlSchemaIDCSelectPtr selector,
5771 xmlNodePtr parNode,
5772 xmlAttrPtr attr,
5773 int isField)
5774{
5775 xmlNodePtr node;
5776
5777 /*
5778 * c-selector-xpath:
5779 * Schema Component Constraint: Selector Value OK
5780 *
5781 * TODO: 1 The {selector} must be a valid XPath expression, as defined
5782 * in [XPath].
5783 */
5784 if (selector == NULL) {
5785 xmlSchemaPErr(ctxt, idc->node,
5786 XML_SCHEMAP_INTERNAL,
5787 "Internal error: xmlSchemaCheckCSelectorXPath, "
5788 "the selector is not specified.\n", NULL, NULL);
5789 return (-1);
5790 }
5791 if (attr == NULL)
5792 node = idc->node;
5793 else
5794 node = (xmlNodePtr) attr;
5795 if (selector->xpath == NULL) {
5796 xmlSchemaPCustomErr(ctxt,
5797 /* TODO: Adjust error code. */
5798 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5799 NULL, NULL, node,
5800 "The XPath expression of the selector is not valid", NULL);
5801 return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE);
5802 } else {
5803 /*
5804 * Compile the XPath expression.
5805 */
5806 /*
5807 * TODO: We need the array of in-scope namespaces for compilation.
5808 */
5809 selector->xpathComp = xmlXPathCompile(selector->xpath);
5810#ifdef IDC_XPATH_SUPPORT
5811 if ((selector->xpathComp == NULL) ||
5812 (xmlXPathWXSIDCValid(selector->xpathComp, isField) != 0)) {
5813 xmlSchemaPCustomErr(ctxt,
5814 /* TODO: Adjust error code? */
5815 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5816 NULL, NULL, node,
5817 "The XPath expression '%s' could not be "
5818 "compiled", selector->xpath);
5819 return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE);
5820 }
5821#endif
5822 }
5823 return (0);
5824}
5825
5826/**
5827 * xmlSchemaAssignAnnotation:
5828 * @item: the schema component
5829 * @annot: the annotation
5830 *
5831 * Adds the annotation to the given schema component.
5832 *
5833 * Returns the given annotaion.
5834 */
5835static xmlSchemaAnnotPtr
5836xmlSchemaAssignAnnotation(xmlSchemaBasicItemPtr item,
5837 xmlSchemaAnnotPtr annot)
5838{
5839 xmlSchemaAnnotPtr cur = item->annot;
5840
5841 if (item->annot == NULL) {
5842 item->annot = annot;
5843 return (annot);
5844 }
5845 cur = item->annot;
5846 if (cur->next != NULL) {
5847 cur = cur->next;
5848 }
5849 cur->next = annot;
5850 return (annot);
5851}
5852
5853/**
5854 * xmlSchemaParseIDCSelectorAndField:
5855 * @ctxt: a schema validation context
5856 * @schema: the schema being built
5857 * @node: a subtree containing XML Schema informations
5858 *
5859 * Parses a XML Schema identity-contraint definition's
5860 * <selector> and <field> elements.
5861 *
5862 * Returns the parsed identity-constraint definition.
5863 */
5864static xmlSchemaIDCSelectPtr
5865xmlSchemaParseIDCSelectorAndField(xmlSchemaParserCtxtPtr ctxt,
5866 xmlSchemaPtr schema,
5867 xmlSchemaIDCPtr idc,
5868 xmlNodePtr node,
5869 int isField)
5870{
5871 xmlSchemaIDCSelectPtr item;
5872 xmlNodePtr child = NULL;
5873 xmlAttrPtr attr;
5874
5875 /*
5876 * Check for illegal attributes.
5877 */
5878 attr = node->properties;
5879 while (attr != NULL) {
5880 if (attr->ns == NULL) {
5881 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
5882 (!xmlStrEqual(attr->name, BAD_CAST "xpath"))) {
5883 xmlSchemaPIllegalAttrErr(ctxt,
5884 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5885 NULL, NULL, attr);
5886 }
5887 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5888 xmlSchemaPIllegalAttrErr(ctxt,
5889 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5890 NULL, NULL, attr);
5891 }
5892 attr = attr->next;
5893 }
5894 /*
5895 * Create the item.
5896 */
5897 item = (xmlSchemaIDCSelectPtr) xmlMalloc(sizeof(xmlSchemaIDCSelect));
5898 if (item == NULL) {
5899 xmlSchemaPErrMemory(ctxt,
5900 "allocating a 'selector' of an identity-constraint definition",
5901 NULL);
5902 return (NULL);
5903 }
5904 memset(item, 0, sizeof(xmlSchemaIDCSelect));
5905 /*
5906 * Attribute "xpath" (mandatory).
5907 */
5908 attr = xmlSchemaGetPropNode(node, "xpath");
5909 if (attr == NULL) {
5910 xmlSchemaPMissingAttrErr(ctxt,
5911 XML_SCHEMAP_S4S_ATTR_MISSING,
5912 NULL, NULL, node,
5913 "name", NULL);
5914 } else {
5915 item->xpath = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5916 /*
5917 * URGENT TODO: "field"s have an other syntax than "selector"s.
5918 */
5919
5920 if (xmlSchemaCheckCSelectorXPath(ctxt, schema,
5921 idc, item, node, attr, isField) == -1)
5922 {
5923 xmlSchemaPErr(ctxt,
5924 (xmlNodePtr) attr,
5925 XML_SCHEMAP_INTERNAL,
5926 "Internal error: xmlSchemaParseIDCSelectorAndField, "
5927 "validating the XPath expression of a IDC selector.\n",
5928 NULL, NULL);
5929 }
5930
5931 }
5932 /*
5933 * And now for the children...
5934 */
5935 child = node->children;
5936 if (IS_SCHEMA(child, "annotation")) {
5937 /*
5938 * Add the annotation to the parent IDC.
5939 */
5940 xmlSchemaAssignAnnotation((xmlSchemaBasicItemPtr) idc,
5941 xmlSchemaParseAnnotation(ctxt, schema, child));
5942 child = child->next;
5943 }
5944 if (child != NULL) {
5945 xmlSchemaPContentErr(ctxt,
5946 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
5947 NULL, NULL, node, child,
5948 NULL, "(annotation?)");
5949 }
5950
5951 return (item);
5952}
5953
5954/**
5955 * xmlSchemaParseIDC:
5956 * @ctxt: a schema validation context
5957 * @schema: the schema being built
5958 * @node: a subtree containing XML Schema informations
5959 *
5960 * Parses a XML Schema identity-contraint definition.
5961 *
5962 * Returns the parsed identity-constraint definition.
5963 */
5964static xmlSchemaIDCPtr
5965xmlSchemaParseIDC(xmlSchemaParserCtxtPtr ctxt,
5966 xmlSchemaPtr schema,
5967 xmlNodePtr node,
5968 xmlSchemaTypeType idcCategory,
5969 const xmlChar *targetNamespace)
5970{
5971 xmlSchemaIDCPtr item = NULL;
5972 xmlNodePtr child = NULL;
5973 xmlAttrPtr attr;
5974 const xmlChar *name = NULL;
5975 xmlSchemaIDCSelectPtr field = NULL, lastField = NULL;
5976 int resAdd;
5977
5978 /*
5979 * Check for illegal attributes.
5980 */
5981 attr = node->properties;
5982 while (attr != NULL) {
5983 if (attr->ns == NULL) {
5984 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
5985 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
5986 ((idcCategory != XML_SCHEMA_TYPE_IDC_KEYREF) ||
5987 (!xmlStrEqual(attr->name, BAD_CAST "refer")))) {
5988 xmlSchemaPIllegalAttrErr(ctxt,
5989 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5990 NULL, NULL, attr);
5991 }
5992 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5993 xmlSchemaPIllegalAttrErr(ctxt,
5994 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5995 NULL, NULL, attr);
5996 }
5997 attr = attr->next;
5998 }
5999 /*
6000 * Attribute "name" (mandatory).
6001 */
6002 attr = xmlSchemaGetPropNode(node, "name");
6003 if (attr == NULL) {
6004 xmlSchemaPMissingAttrErr(ctxt,
6005 XML_SCHEMAP_S4S_ATTR_MISSING,
6006 NULL, NULL, node,
6007 "name", NULL);
6008 return (NULL);
6009 } else if (xmlSchemaPValAttrNode(ctxt,
6010 NULL, NULL, attr,
6011 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
6012 return (NULL);
6013 }
6014 /*
6015 * Create the component.
6016 */
6017 if (schema->idcDef == NULL)
6018 schema->idcDef = xmlHashCreateDict(10, ctxt->dict);
6019 if (schema->idcDef == NULL)
6020 return (NULL);
6021
6022 item = (xmlSchemaIDCPtr) xmlMalloc(sizeof(xmlSchemaIDC));
6023 if (item == NULL) {
6024 xmlSchemaPErrMemory(ctxt,
6025 "allocating an identity-constraint definition", NULL);
6026 return (NULL);
6027 }
6028 /*
6029 * Add the IDC to the list of IDCs on the schema component.
6030 */
6031 resAdd = xmlHashAddEntry2(schema->idcDef, name, targetNamespace, item);
6032 if (resAdd != 0) {
6033 xmlSchemaPCustomErrExt(ctxt,
6034 XML_SCHEMAP_REDEFINED_TYPE,
6035 NULL, NULL, node,
6036 "An identity-constraint definition with the name '%s' "
6037 "and targetNamespace '%s' does already exist",
6038 name, targetNamespace, NULL);
6039 xmlFree(item);
6040 return (NULL);
6041 }
6042
6043 memset(item, 0, sizeof(xmlSchemaIDC));
6044 item->name = name;
6045 item->type = idcCategory;
6046 item->node = node;
6047 /*
6048 * The target namespace of the parent element declaration.
6049 */
6050 item->targetNamespace = targetNamespace;
6051 /* TODO: Handle attribute "id". */
6052 if (idcCategory == XML_SCHEMA_TYPE_IDC_KEYREF) {
6053 /*
6054 * Attribute "refer" (mandatory).
6055 */
6056 attr = xmlSchemaGetPropNode(node, "refer");
6057 if (attr == NULL) {
6058 xmlSchemaPMissingAttrErr(ctxt,
6059 XML_SCHEMAP_S4S_ATTR_MISSING,
6060 NULL, NULL, node,
6061 "refer", NULL);
6062 } else {
6063 /*
6064 * Create a reference item.
6065 */
6066 item->ref = (xmlSchemaItemQNRefPtr) xmlMalloc(
6067 sizeof(xmlSchemaItemQNRef));
6068 if (item->ref == NULL) {
6069 xmlSchemaPErrMemory(ctxt,
6070 "allocating a QName reference item", NULL);
6071 return (NULL);
6072 }
6073 memset(item->ref, 0, sizeof(xmlSchemaItemQNRef));
6074 xmlSchemaPValAttrNodeQName(ctxt, schema,
6075 NULL, NULL, attr,
6076 &(item->ref->targetNamespace), 0,
6077 &(item->ref->name));
6078 }
6079 }
6080 /*
6081 * And now for the children...
6082 */
6083 child = node->children;
6084 if (IS_SCHEMA(child, "annotation")) {
6085 item->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6086 child = child->next;
6087 }
6088 /*
6089 * Child element <selector>.
6090 */
6091 if (IS_SCHEMA(child, "selector")) {
6092 item->selector = xmlSchemaParseIDCSelectorAndField(ctxt, schema,
6093 item, child, 0);
6094 child = child->next;
6095 /*
6096 * Child elements <field>.
6097 */
6098 if (IS_SCHEMA(child, "field")) {
6099 do {
6100 field = xmlSchemaParseIDCSelectorAndField(ctxt, schema,
6101 item, child, 1);
6102 if (field != NULL) {
6103 field->index = item->nbFields;
6104 item->nbFields++;
6105 if (lastField != NULL)
6106 lastField->next = field;
6107 else
6108 item->fields = field;
6109 lastField = field;
6110 }
6111 child = child->next;
6112 } while (IS_SCHEMA(child, "field"));
6113 } else {
6114 xmlSchemaPContentErr(ctxt,
6115 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6116 NULL, NULL, node, child,
6117 NULL, "(annotation?, (selector, field+))");
6118 }
6119 }
6120 if (child != NULL) {
6121 xmlSchemaPContentErr(ctxt,
6122 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6123 NULL, NULL, node, child,
6124 NULL, "(annotation?, (selector, field+))");
6125 }
6126
6127 return (item);
6128}
6129
Daniel Veillardc0826a72004-08-10 14:17:33 +00006130/**
Daniel Veillard4255d502002-04-16 15:50:10 +00006131 * xmlSchemaParseElement:
6132 * @ctxt: a schema validation context
6133 * @schema: the schema being built
6134 * @node: a subtree containing XML Schema informations
6135 *
6136 * parse a XML schema Element declaration
6137 * *WARNING* this interface is highly subject to change
6138 *
William M. Bracke7091952004-05-11 15:09:58 +00006139 * Returns the parsed element declaration.
Daniel Veillard4255d502002-04-16 15:50:10 +00006140 */
6141static xmlSchemaElementPtr
6142xmlSchemaParseElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00006143 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00006144{
Daniel Veillardc0826a72004-08-10 14:17:33 +00006145 const xmlChar *name = NULL;
6146 const xmlChar *attrValue;
6147 xmlChar *repName = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00006148 xmlSchemaElementPtr ret;
6149 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006150 const xmlChar *oldcontainer;
6151 xmlAttrPtr attr, nameAttr;
6152 int minOccurs, maxOccurs;
6153 int isRef = 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006154#ifdef IDC_ENABLED
6155 xmlSchemaIDCPtr curIDC, lastIDC = NULL;
6156#endif
William M. Bracke7091952004-05-11 15:09:58 +00006157
6158 /* 3.3.3 Constraints on XML Representations of Element Declarations */
6159 /* TODO: Complete implementation of 3.3.6 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00006160
Daniel Veillard4255d502002-04-16 15:50:10 +00006161 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6162 return (NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006163
Daniel Veillardc0826a72004-08-10 14:17:33 +00006164 oldcontainer = ctxt->container;
6165
6166 nameAttr = xmlSchemaGetPropNode(node, "name");
6167 attr = xmlSchemaGetPropNode(node, "ref");
6168 if ((topLevel) || (attr == NULL)) {
6169 if (nameAttr == NULL) {
6170 xmlSchemaPMissingAttrErr(ctxt,
6171 XML_SCHEMAP_S4S_ATTR_MISSING,
6172 (xmlChar **) &xmlSchemaElemDesElemDecl, NULL, node,
6173 "name", NULL);
6174 return (NULL);
6175 }
6176 name = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) nameAttr);
6177 } else {
6178 isRef = 1;
6179
6180 }
6181 /*
6182 * ... unless minOccurs=maxOccurs=0, in which case the item corresponds
6183 * to no component at all
6184 * TODO: It might be better to validate the element, even if it won't be
6185 * used.
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006186 */
6187 minOccurs = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "nonNegativeInteger");
6188 maxOccurs = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1, "(nonNegativeInteger | unbounded)");
Daniel Veillardc0826a72004-08-10 14:17:33 +00006189 if ((minOccurs == 0) && (maxOccurs == 0))
6190 return (NULL);
6191 /*
6192 * If we get a "ref" attribute on a local <element> we will assume it's
6193 * a reference - even if there's a "name" attribute; this seems to be more
6194 * robust.
6195 */
6196 if (isRef) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006197 char buf[50];
Daniel Veillardc0826a72004-08-10 14:17:33 +00006198 const xmlChar *refNs = NULL, *ref = NULL, *refPrefix;
6199
6200 /*
6201 * Parse as a particle.
6202 */
6203 xmlSchemaPValAttrNodeQName(ctxt, schema,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006204 (xmlChar **) &xmlSchemaElemDesElemRef,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006205 NULL, attr, &refNs, &refPrefix, &ref);
6206
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006207 snprintf(buf, 49, "#eRef %d", ctxt->counter++ + 1);
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00006208 ret = xmlSchemaAddElement(ctxt, schema, (const xmlChar *) buf, NULL, node, 0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006209 if (ret == NULL) {
6210 if (repName != NULL)
6211 xmlFree(repName);
6212 return (NULL);
6213 }
6214 ret->type = XML_SCHEMA_TYPE_ELEMENT;
6215 ret->node = node;
6216 ret->ref = ref;
6217 ret->refNs = refNs;
6218 ret->refPrefix = refPrefix;
6219 ret->flags |= XML_SCHEMAS_ELEM_REF;
6220 /*
6221 * Check for illegal attributes.
6222 */
6223 /*
6224 * 3.3.3 : 2.1
6225 * One of ref or name must be present, but not both
6226 */
6227 if (nameAttr != NULL) {
6228 xmlSchemaPMutualExclAttrErr(ctxt,
6229 XML_SCHEMAP_SRC_ELEMENT_2_1,
6230 &repName, (xmlSchemaTypePtr) ret, nameAttr,
6231 "ref", "name");
6232 }
6233 /* 3.3.3 : 2.2 */
6234 attr = node->properties;
6235 while (attr != NULL) {
6236 if (attr->ns == NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006237 if (xmlStrEqual(attr->name, BAD_CAST "ref") ||
6238 xmlStrEqual(attr->name, BAD_CAST "name") ||
6239 xmlStrEqual(attr->name, BAD_CAST "id") ||
6240 xmlStrEqual(attr->name, BAD_CAST "maxOccurs") ||
6241 xmlStrEqual(attr->name, BAD_CAST "minOccurs"))
6242 {
6243 attr = attr->next;
6244 continue;
6245 } else {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006246 xmlSchemaPCustomAttrErr(ctxt,
6247 XML_SCHEMAP_SRC_ELEMENT_2_2,
6248 &repName, (xmlSchemaTypePtr) ret, attr,
6249 "Only the attributes 'minOccurs', 'maxOccurs' and "
6250 "'id' are allowed in addition to 'ref'");
6251 break;
6252 }
6253 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6254 xmlSchemaPIllegalAttrErr(ctxt,
6255 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6256 &repName, (xmlSchemaTypePtr) ret, attr);
6257 }
6258 attr = attr->next;
6259 }
6260 } else {
6261 const xmlChar *ns = NULL, *fixed;
6262
6263 /*
6264 * Parse as an element declaration.
6265 */
6266 if (xmlSchemaPValAttrNode(ctxt,
6267 (xmlChar **) &xmlSchemaElemDesElemDecl, NULL, nameAttr,
6268 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0)
6269 return (NULL);
6270 /*
6271 * Evaluate the target namespace.
6272 */
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006273 if (topLevel) {
6274 ns = schema->targetNamespace;
6275 } else {
6276 attr = xmlSchemaGetPropNode(node, "form");
6277 if (attr != NULL) {
6278 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6279 if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
William M. Bracke7091952004-05-11 15:09:58 +00006280 ns = schema->targetNamespace;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006281 } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) {
6282 xmlSchemaPSimpleTypeErr(ctxt,
6283 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6284 &repName, NULL, (xmlNodePtr) attr,
6285 NULL, "(qualified | unqualified)",
6286 attrValue, NULL, NULL, NULL);
6287 }
6288 } else if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
6289 ns = schema->targetNamespace;
William M. Brack2f2a6632004-08-20 23:09:47 +00006290 }
6291 ret = xmlSchemaAddElement(ctxt, schema, name, ns, node, topLevel);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006292 if (ret == NULL) {
6293 if (repName != NULL)
6294 xmlFree(repName);
6295 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00006296 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006297 ret->type = XML_SCHEMA_TYPE_ELEMENT;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006298 ret->node = node;
6299 ret->targetNamespace = ns;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006300 /*
6301 * Check for illegal attributes.
6302 */
William M. Bracke7091952004-05-11 15:09:58 +00006303 attr = node->properties;
6304 while (attr != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006305 if (attr->ns == NULL) {
6306 if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
6307 (!xmlStrEqual(attr->name, BAD_CAST "type")) &&
6308 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6309 (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
6310 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
6311 (!xmlStrEqual(attr->name, BAD_CAST "block")) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006312 (!xmlStrEqual(attr->name, BAD_CAST "nillable")))
6313 {
6314 if (topLevel == 0) {
6315 if ((!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00006316 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006317 (!xmlStrEqual(attr->name, BAD_CAST "form")))
6318 {
6319 if (xmlStrEqual(attr->name, BAD_CAST "substitutionGroup")) {
6320 /*
6321 * 3.3.6 : 3 If there is a non-·absent· {substitution
6322 * group affiliation}, then {scope} must be global.
6323 * TODO: This one is redundant, since the S4S does
6324 * prohibit this attribute on local declarations already;
6325 * so why an explicit error code? Weird spec.
6326 * TODO: Move this to the proper constraint layer.
6327 * TODO: Or better wait for spec 1.1 to come.
6328 */
6329 xmlSchemaPIllegalAttrErr(ctxt,
6330 XML_SCHEMAP_E_PROPS_CORRECT_3,
6331 &repName, (xmlSchemaTypePtr) ret, attr);
6332 } else {
6333 xmlSchemaPIllegalAttrErr(ctxt,
6334 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6335 &repName, (xmlSchemaTypePtr) ret, attr);
6336 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006337 }
6338 } else if ((!xmlStrEqual(attr->name, BAD_CAST "final")) &&
6339 (!xmlStrEqual(attr->name, BAD_CAST "abstract")) &&
6340 (!xmlStrEqual(attr->name, BAD_CAST "substitutionGroup"))) {
6341
6342 xmlSchemaPIllegalAttrErr(ctxt,
6343 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6344 &repName, (xmlSchemaTypePtr) ret, attr);
6345 }
6346 }
6347 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6348
6349 xmlSchemaPIllegalAttrErr(ctxt,
6350 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6351 &repName, (xmlSchemaTypePtr) ret, attr);
William M. Bracke7091952004-05-11 15:09:58 +00006352 }
6353 attr = attr->next;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006354 }
William M. Bracke7091952004-05-11 15:09:58 +00006355 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006356 * Extract/validate attributes.
6357 */
6358 if (topLevel) {
6359 /*
6360 * Process top attributes of global element declarations here.
6361 */
6362 ret->flags |= XML_SCHEMAS_ELEM_GLOBAL;
6363 ret->flags |= XML_SCHEMAS_ELEM_TOPLEVEL;
6364 xmlSchemaPValAttrQName(ctxt, schema, &repName,
6365 (xmlSchemaTypePtr) ret, node, "substitutionGroup",
6366 &(ret->substGroupNs), NULL, &(ret->substGroup));
6367 if (xmlGetBooleanProp(ctxt, &repName, (xmlSchemaTypePtr) ret,
6368 node, "abstract", 0))
6369 ret->flags |= XML_SCHEMAS_ELEM_ABSTRACT;
6370 /*
6371 * Attribute "final".
6372 */
6373 attr = xmlSchemaGetPropNode(node, "final");
6374 if (attr == NULL) {
6375 ret->flags |= XML_SCHEMAS_ELEM_FINAL_ABSENT;
6376 } else {
6377 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6378 if (xmlSchemaPValAttrBlockFinal(attrValue, &(ret->flags),
6379 -1,
6380 XML_SCHEMAS_ELEM_FINAL_EXTENSION,
6381 XML_SCHEMAS_ELEM_FINAL_RESTRICTION, -1, -1, -1) != 0) {
6382 xmlSchemaPSimpleTypeErr(ctxt,
6383 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6384 &repName, (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00006385 NULL, "(#all | List of (extension | restriction))",
Daniel Veillardc0826a72004-08-10 14:17:33 +00006386 attrValue, NULL, NULL, NULL);
6387 }
6388 }
6389 }
6390 /*
6391 * Attribute "block".
6392 */
6393 attr = xmlSchemaGetPropNode(node, "block");
6394 if (attr == NULL) {
6395 ret->flags |= XML_SCHEMAS_ELEM_BLOCK_ABSENT;
6396 } else {
6397 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6398 if (xmlSchemaPValAttrBlockFinal(attrValue, &(ret->flags),
6399 -1,
6400 XML_SCHEMAS_ELEM_BLOCK_EXTENSION,
6401 XML_SCHEMAS_ELEM_BLOCK_RESTRICTION,
6402 XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION, -1, -1) != 0) {
6403 xmlSchemaPSimpleTypeErr(ctxt,
6404 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6405 &repName, (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00006406 NULL, "(#all | List of (extension | "
Daniel Veillardc0826a72004-08-10 14:17:33 +00006407 "restriction | substitution))", attrValue,
6408 NULL, NULL, NULL);
6409 }
6410 }
6411 if (xmlGetBooleanProp(ctxt, &repName, (xmlSchemaTypePtr) ret,
6412 node, "nillable", 0))
6413 ret->flags |= XML_SCHEMAS_ELEM_NILLABLE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006414
Daniel Veillardc0826a72004-08-10 14:17:33 +00006415 xmlSchemaPValAttrQName(ctxt, schema,
6416 &repName, (xmlSchemaTypePtr) ret, node,
6417 "type", &(ret->namedTypeNs), NULL, &(ret->namedType));
Daniel Veillard4255d502002-04-16 15:50:10 +00006418
Daniel Veillardc0826a72004-08-10 14:17:33 +00006419 ret->value = xmlSchemaGetProp(ctxt, node, "default");
6420 attr = xmlSchemaGetPropNode(node, "fixed");
6421 if (attr != NULL) {
6422 fixed = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6423 if (ret->value != NULL) {
6424 /*
6425 * 3.3.3 : 1
6426 * default and fixed must not both be present.
6427 */
6428 xmlSchemaPMutualExclAttrErr(ctxt,
6429 XML_SCHEMAP_SRC_ELEMENT_1,
6430 &repName, (xmlSchemaTypePtr) ret, attr,
6431 "default", "fixed");
6432 } else {
6433 ret->flags |= XML_SCHEMAS_ELEM_FIXED;
6434 ret->value = fixed;
6435 }
6436 }
6437 }
6438 /*
6439 * Extract/validate common attributes.
6440 */
6441 /* TODO: Check ID: */
6442 ret->id = xmlSchemaGetProp(ctxt, node, "id");
6443 ret->minOccurs = minOccurs;
6444 ret->maxOccurs = maxOccurs;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006445 if (topLevel != 1)
6446 xmlSchemaPCheckParticleCorrect_2(ctxt, (xmlSchemaTypePtr) ret,
6447 node, minOccurs, maxOccurs);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006448 /*
6449 * And now for the children...
6450 */
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00006451 ctxt->container = ret->name;
Daniel Veillard4255d502002-04-16 15:50:10 +00006452 child = node->children;
6453 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006454 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6455 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006456 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006457 if (isRef) {
6458 if (child != NULL) {
6459 xmlSchemaPContentErr(ctxt,
6460 XML_SCHEMAP_SRC_ELEMENT_2_2,
6461 &repName, (xmlSchemaTypePtr) ret, node, child,
6462 NULL, "(annotation?)");
William M. Bracke7091952004-05-11 15:09:58 +00006463 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006464 } else {
William M. Bracke7091952004-05-11 15:09:58 +00006465 if (IS_SCHEMA(child, "complexType")) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006466 /*
6467 * 3.3.3 : 3
6468 * "type" and either <simpleType> or <complexType> are mutually
6469 * exclusive
6470 */
William M. Bracke7091952004-05-11 15:09:58 +00006471 if (ret->namedType != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006472 xmlSchemaPContentErr(ctxt,
6473 XML_SCHEMAP_SRC_ELEMENT_3,
6474 &repName, (xmlSchemaTypePtr) ret, node, child,
6475 "The attribute 'type' and the <complexType> child are "
6476 "mutually exclusive", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00006477 } else
Daniel Veillard3646d642004-06-02 19:19:14 +00006478 ret->subtypes = xmlSchemaParseComplexType(ctxt, schema, child, 0);
William M. Bracke7091952004-05-11 15:09:58 +00006479 child = child->next;
6480 } else if (IS_SCHEMA(child, "simpleType")) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006481 /*
6482 * 3.3.3 : 3
6483 * "type" and either <simpleType> or <complexType> are
6484 * mutually exclusive
6485 */
William M. Bracke7091952004-05-11 15:09:58 +00006486 if (ret->namedType != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006487 xmlSchemaPContentErr(ctxt,
6488 XML_SCHEMAP_SRC_ELEMENT_3,
6489 &repName, (xmlSchemaTypePtr) ret, node, child,
6490 "The attribute 'type' and the <simpleType> child are "
6491 "mutually exclusive", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00006492 } else
Daniel Veillard3646d642004-06-02 19:19:14 +00006493 ret->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
William M. Bracke7091952004-05-11 15:09:58 +00006494 child = child->next;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006495 }
William M. Bracke7091952004-05-11 15:09:58 +00006496 while ((IS_SCHEMA(child, "unique")) ||
Daniel Veillardc0826a72004-08-10 14:17:33 +00006497 (IS_SCHEMA(child, "key")) || (IS_SCHEMA(child, "keyref"))) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006498#ifdef IDC_ENABLED
6499 if (IS_SCHEMA(child, "unique")) {
6500 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
6501 XML_SCHEMA_TYPE_IDC_UNIQUE, ret->targetNamespace);
6502 } else if (IS_SCHEMA(child, "key")) {
6503 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
6504 XML_SCHEMA_TYPE_IDC_KEY, ret->targetNamespace);
6505 } else if (IS_SCHEMA(child, "keyref")) {
6506 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
6507 XML_SCHEMA_TYPE_IDC_KEYREF, ret->targetNamespace);
6508 }
6509 if (lastIDC != NULL)
6510 lastIDC->next = curIDC;
6511 else
6512 (xmlSchemaIDCPtr) ret->idcs = curIDC;
6513 lastIDC = curIDC;
6514#endif
6515 child = child->next;
William M. Bracke7091952004-05-11 15:09:58 +00006516 }
6517 if (child != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006518 xmlSchemaPContentErr(ctxt,
6519 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6520 &repName, (xmlSchemaTypePtr) ret, node, child,
6521 NULL, "(annotation?, ((simpleType | complexType)?, "
6522 "(unique | key | keyref)*))");
6523 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006524
Daniel Veillardc0826a72004-08-10 14:17:33 +00006525 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006526 ctxt->container = oldcontainer;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006527 /*
6528 * Cleanup.
6529 */
6530 if (repName != NULL)
6531 xmlFree(repName);
6532 /*
6533 * NOTE: Element Declaration Representation OK 4. will be checked at a
6534 * different layer.
6535 */
Daniel Veillard4255d502002-04-16 15:50:10 +00006536 return (ret);
6537}
6538
6539/**
6540 * xmlSchemaParseUnion:
6541 * @ctxt: a schema validation context
6542 * @schema: the schema being built
6543 * @node: a subtree containing XML Schema informations
6544 *
6545 * parse a XML schema Union definition
6546 * *WARNING* this interface is highly subject to change
6547 *
William M. Bracke7091952004-05-11 15:09:58 +00006548 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00006549 * 1 in case of success.
6550 */
6551static xmlSchemaTypePtr
6552xmlSchemaParseUnion(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006553 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00006554{
6555 xmlSchemaTypePtr type, subtype, last = NULL;
6556 xmlNodePtr child = NULL;
6557 xmlChar name[30];
William M. Brack2f2a6632004-08-20 23:09:47 +00006558 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00006559
6560 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6561 return (NULL);
6562
William M. Brack2f2a6632004-08-20 23:09:47 +00006563 snprintf((char *) name, 30, "#union %d", ctxt->counter++ + 1);
6564 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00006565 if (type == NULL)
6566 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00006567 type->type = XML_SCHEMA_TYPE_UNION;
Daniel Veillard4255d502002-04-16 15:50:10 +00006568 type->node = node;
William M. Brack2f2a6632004-08-20 23:09:47 +00006569 /*
6570 * Check for illegal attributes.
6571 */
6572 attr = node->properties;
6573 while (attr != NULL) {
6574 if (attr->ns == NULL) {
6575 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6576 (!xmlStrEqual(attr->name, BAD_CAST "memberTypes"))) {
6577 xmlSchemaPIllegalAttrErr(ctxt,
6578 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6579 NULL, type, attr);
6580 }
6581 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6582 xmlSchemaPIllegalAttrErr(ctxt,
6583 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6584 NULL, type, attr);
6585 }
6586 attr = attr->next;
6587 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006588 type->id = xmlSchemaGetProp(ctxt, node, "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00006589 /*
6590 * Attribute "memberTypes". This is a list of QNames.
6591 * TODO: Validate the QNames.
6592 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00006593 type->base = xmlSchemaGetProp(ctxt, node, "memberTypes");
William M. Brack2f2a6632004-08-20 23:09:47 +00006594 /*
6595 * And now for the children...
6596 */
Daniel Veillard4255d502002-04-16 15:50:10 +00006597 child = node->children;
6598 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006599 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6600 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006601 }
William M. Brack2f2a6632004-08-20 23:09:47 +00006602 while (IS_SCHEMA(child, "simpleType")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006603 subtype = (xmlSchemaTypePtr)
Daniel Veillard3646d642004-06-02 19:19:14 +00006604 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006605 if (subtype != NULL) {
6606 if (last == NULL) {
6607 type->subtypes = subtype;
6608 last = subtype;
6609 } else {
6610 last->next = subtype;
6611 last = subtype;
6612 }
6613 last->next = NULL;
6614 }
6615 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006616 }
6617 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00006618 /* TODO: Think about the error code. */
6619 xmlSchemaPContentErr(ctxt,
6620 XML_SCHEMAP_UNKNOWN_UNION_CHILD,
6621 NULL, type, node, child, NULL, "(annotation?, simpleType*)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006622 }
6623 return (type);
6624}
6625
6626/**
6627 * xmlSchemaParseList:
6628 * @ctxt: a schema validation context
6629 * @schema: the schema being built
6630 * @node: a subtree containing XML Schema informations
6631 *
6632 * parse a XML schema List definition
6633 * *WARNING* this interface is highly subject to change
6634 *
William M. Bracke7091952004-05-11 15:09:58 +00006635 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00006636 * 1 in case of success.
6637 */
6638static xmlSchemaTypePtr
6639xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006640 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00006641{
6642 xmlSchemaTypePtr type, subtype;
6643 xmlNodePtr child = NULL;
6644 xmlChar name[30];
William M. Brack2f2a6632004-08-20 23:09:47 +00006645 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00006646
6647 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6648 return (NULL);
6649
William M. Brack2f2a6632004-08-20 23:09:47 +00006650 snprintf((char *) name, 30, "#list %d", ctxt->counter++ + 1);
6651 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00006652 if (type == NULL)
6653 return (NULL);
6654 type->node = node;
6655 type->type = XML_SCHEMA_TYPE_LIST;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006656 type->id = xmlSchemaGetProp(ctxt, node, "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00006657 /*
6658 * Check for illegal attributes.
6659 */
6660 attr = node->properties;
6661 while (attr != NULL) {
6662 if (attr->ns == NULL) {
6663 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6664 (!xmlStrEqual(attr->name, BAD_CAST "itemType"))) {
6665 xmlSchemaPIllegalAttrErr(ctxt,
6666 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6667 NULL, type, attr);
6668 }
6669 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6670 xmlSchemaPIllegalAttrErr(ctxt,
6671 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6672 NULL, type, attr);
6673 }
6674 attr = attr->next;
6675 }
6676 /*
6677 * Attribute "itemType".
6678 */
6679 xmlSchemaPValAttrQName(ctxt, schema, NULL, NULL,
6680 node, "itemType", &(type->baseNs), NULL, &(type->base));
6681 /*
6682 * And now for the children...
6683 */
Daniel Veillard4255d502002-04-16 15:50:10 +00006684 child = node->children;
6685 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006686 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6687 child = child->next;
William M. Brack2f2a6632004-08-20 23:09:47 +00006688 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006689 subtype = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00006690 if (IS_SCHEMA(child, "simpleType")) {
6691 if (type->base != NULL) {
6692 xmlSchemaPCustomErr(ctxt,
6693 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
6694 NULL, type, node,
6695 "The attribute 'itemType' and the <simpleType> child "
6696 "are mutually exclusive", NULL);
6697 } else {
6698 subtype = (xmlSchemaTypePtr)
6699 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
6700 type->subtypes = subtype;
6701 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00006702 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006703 }
6704 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00006705 /* TODO: Think about the error code. */
6706 xmlSchemaPContentErr(ctxt,
6707 XML_SCHEMAP_UNKNOWN_LIST_CHILD,
6708 NULL, type, node, child, NULL, "(annotation?, simpleType?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006709 }
6710 return (type);
6711}
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006712
Daniel Veillard4255d502002-04-16 15:50:10 +00006713/**
6714 * xmlSchemaParseSimpleType:
6715 * @ctxt: a schema validation context
6716 * @schema: the schema being built
6717 * @node: a subtree containing XML Schema informations
6718 *
6719 * parse a XML schema Simple Type definition
6720 * *WARNING* this interface is highly subject to change
6721 *
William M. Bracke7091952004-05-11 15:09:58 +00006722 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillardc0826a72004-08-10 14:17:33 +00006723 * 1 in case of success.
Daniel Veillard4255d502002-04-16 15:50:10 +00006724 */
6725static xmlSchemaTypePtr
6726xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00006727 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00006728{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006729 xmlSchemaTypePtr type, subtype, oldCtxtType, oldParentItem;
Daniel Veillard4255d502002-04-16 15:50:10 +00006730 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006731 const xmlChar *attrValue = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006732 xmlChar *des = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006733 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00006734
6735 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6736 return (NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006737
Daniel Veillardc0826a72004-08-10 14:17:33 +00006738 if (topLevel) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006739 attr = xmlSchemaGetPropNode(node, "name");
Daniel Veillardc0826a72004-08-10 14:17:33 +00006740 if (attr == NULL) {
6741 xmlSchemaPMissingAttrErr(ctxt,
6742 XML_SCHEMAP_S4S_ATTR_MISSING,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006743 (xmlChar **) &xmlSchemaElemDesST, NULL, node,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006744 "name", NULL);
6745 return (NULL);
6746 } else if (xmlSchemaPValAttrNode(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006747 (xmlChar **) &xmlSchemaElemDesST, NULL, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006748 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &attrValue) != 0) {
Daniel Veillard01fa6152004-06-29 17:04:39 +00006749 return (NULL);
6750 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006751 }
6752
6753 if (topLevel == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006754 char buf[40];
Daniel Veillardc0826a72004-08-10 14:17:33 +00006755
Daniel Veillard01fa6152004-06-29 17:04:39 +00006756 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006757 * Parse as local simple type definition.
Daniel Veillard01fa6152004-06-29 17:04:39 +00006758 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006759 snprintf(buf, 39, "#ST %d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00006760 type = xmlSchemaAddType(ctxt, schema, (const xmlChar *)buf, NULL, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006761 if (type == NULL)
6762 return (NULL);
6763 type->node = node;
6764 type->type = XML_SCHEMA_TYPE_SIMPLE;
6765 /*
6766 * Check for illegal attributes.
6767 */
6768 attr = node->properties;
6769 while (attr != NULL) {
6770 if (attr->ns == NULL) {
6771 if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
6772 xmlSchemaPIllegalAttrErr(ctxt,
6773 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006774 &des, type, attr);
Daniel Veillard01fa6152004-06-29 17:04:39 +00006775 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006776 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6777 xmlSchemaPIllegalAttrErr(ctxt,
6778 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006779 &des, type, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006780 }
6781 attr = attr->next;
Daniel Veillard01fa6152004-06-29 17:04:39 +00006782 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006783 } else {
6784 /*
6785 * Parse as global simple type definition.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006786 *
6787 * Note that attrValue is the value of the attribute "name" here.
Daniel Veillardc0826a72004-08-10 14:17:33 +00006788 */
William M. Brack2f2a6632004-08-20 23:09:47 +00006789 type = xmlSchemaAddType(ctxt, schema, attrValue, schema->targetNamespace, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006790 if (type == NULL)
6791 return (NULL);
6792 type->node = node;
6793 type->type = XML_SCHEMA_TYPE_SIMPLE;
6794 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
6795 /*
6796 * Check for illegal attributes.
6797 */
6798 attr = node->properties;
6799 while (attr != NULL) {
6800 if (attr->ns == NULL) {
6801 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6802 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006803 (!xmlStrEqual(attr->name, BAD_CAST "final"))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006804 xmlSchemaPIllegalAttrErr(ctxt,
6805 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006806 &des, type, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006807 }
6808 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6809 xmlSchemaPIllegalAttrErr(ctxt,
6810 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006811 &des, type, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006812 }
6813 attr = attr->next;
6814 }
6815 /*
6816 * Attribute "final".
6817 */
6818 attr = xmlSchemaGetPropNode(node, "final");
6819 if (attr == NULL) {
6820 type->flags |= XML_SCHEMAS_TYPE_FINAL_DEFAULT;
6821 } else {
6822 attrValue = xmlSchemaGetProp(ctxt, node, "final");
6823 if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
6824 -1, -1, XML_SCHEMAS_TYPE_FINAL_RESTRICTION, -1,
6825 XML_SCHEMAS_TYPE_FINAL_LIST,
6826 XML_SCHEMAS_TYPE_FINAL_UNION) != 0) {
6827
6828 xmlSchemaPSimpleTypeErr(ctxt,
6829 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006830 &des, type, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00006831 NULL, "(#all | List of (list | union | restriction)",
Daniel Veillardc0826a72004-08-10 14:17:33 +00006832 attrValue, NULL, NULL, NULL);
6833 }
6834 }
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006835 }
6836 type->targetNamespace = schema->targetNamespace;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006837 /* TODO: Check id. */
6838 type->id = xmlSchemaGetProp(ctxt, node, "id");
6839 /*
6840 * And now for the children...
6841 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006842 oldCtxtType = ctxt->ctxtType;
6843 oldParentItem = ctxt->parentItem;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006844 ctxt->ctxtType = type;
6845 ctxt->parentItem = type;
Daniel Veillard4255d502002-04-16 15:50:10 +00006846 child = node->children;
6847 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006848 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6849 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006850 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006851 subtype = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00006852 if (IS_SCHEMA(child, "restriction")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006853 subtype = (xmlSchemaTypePtr)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00006854 xmlSchemaParseRestriction(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006855 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006856 } else if (IS_SCHEMA(child, "list")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006857 subtype = (xmlSchemaTypePtr)
6858 xmlSchemaParseList(ctxt, schema, child);
6859 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006860 } else if (IS_SCHEMA(child, "union")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006861 subtype = (xmlSchemaTypePtr)
6862 xmlSchemaParseUnion(ctxt, schema, child);
6863 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006864 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006865 type->subtypes = subtype;
6866 if ((child != NULL) || (subtype == NULL)) {
6867 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006868 &des, type, node, child, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006869 "(annotation?, (restriction | list | union))");
Daniel Veillard4255d502002-04-16 15:50:10 +00006870 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006871 ctxt->parentItem = oldParentItem;
6872 ctxt->ctxtType = oldCtxtType;
6873 FREE_AND_NULL(des)
Daniel Veillard01fa6152004-06-29 17:04:39 +00006874
Daniel Veillard4255d502002-04-16 15:50:10 +00006875 return (type);
6876}
6877
6878
6879/**
6880 * xmlSchemaParseGroup:
6881 * @ctxt: a schema validation context
6882 * @schema: the schema being built
6883 * @node: a subtree containing XML Schema informations
6884 *
6885 * parse a XML schema Group definition
6886 * *WARNING* this interface is highly subject to change
6887 *
William M. Bracke7091952004-05-11 15:09:58 +00006888 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00006889 * 1 in case of success.
6890 */
6891static xmlSchemaTypePtr
6892xmlSchemaParseGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00006893 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00006894{
6895 xmlSchemaTypePtr type, subtype;
6896 xmlNodePtr child = NULL;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006897 const xmlChar *name, *ns = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006898 const xmlChar *ref = NULL, *refNs = NULL;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006899 char buf[50];
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00006900 int minOccurs, maxOccurs;
Daniel Veillard4255d502002-04-16 15:50:10 +00006901
6902 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6903 return (NULL);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00006904 /*
6905 * TODO: Validate the element even if no item is created
6906 * (i.e. min/maxOccurs == 0).
6907 */
6908 minOccurs = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "nonNegativeInteger");
6909 maxOccurs = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1, "(nonNegativeInteger | unbounded)");
6910 if ((minOccurs == 0) && (maxOccurs == 0)) {
6911 return (NULL);
6912 }
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006913 if (topLevel)
6914 ns = schema->targetNamespace;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006915 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00006916 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006917 ref = xmlGetQNameProp(ctxt, node, "ref", &refNs);
6918 if (ref == NULL) {
6919 xmlSchemaPErr2(ctxt, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006920 XML_SCHEMAP_GROUP_NONAME_NOREF,
6921 "Group definition or particle: One of the attributes \"name\" "
6922 "or \"ref\" must be present.\n", NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006923 return (NULL);
6924 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006925 if (refNs == NULL)
6926 refNs = schema->targetNamespace;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006927 snprintf(buf, 49, "#GrRef %d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006928 name = (const xmlChar *) buf;
Daniel Veillard4255d502002-04-16 15:50:10 +00006929 }
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006930 type = xmlSchemaAddGroup(ctxt, schema, name, ns, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00006931 if (type == NULL)
6932 return (NULL);
6933 type->node = node;
6934 type->type = XML_SCHEMA_TYPE_GROUP;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006935 if (topLevel)
6936 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006937 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00006938 type->ref = ref;
6939 type->refNs = refNs;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00006940 type->minOccurs = minOccurs;
6941 type->maxOccurs = maxOccurs;
6942 xmlSchemaPCheckParticleCorrect_2(ctxt, type,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006943 node, type->minOccurs, type->maxOccurs);
Daniel Veillard4255d502002-04-16 15:50:10 +00006944
6945 child = node->children;
6946 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006947 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6948 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006949 }
6950 subtype = NULL;
6951 if (IS_SCHEMA(child, "all")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006952 subtype = (xmlSchemaTypePtr)
6953 xmlSchemaParseAll(ctxt, schema, child);
6954 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006955 } else if (IS_SCHEMA(child, "choice")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006956 subtype = xmlSchemaParseChoice(ctxt, schema, child);
6957 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006958 } else if (IS_SCHEMA(child, "sequence")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006959 subtype = (xmlSchemaTypePtr)
6960 xmlSchemaParseSequence(ctxt, schema, child);
6961 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006962 }
6963 if (subtype != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006964 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00006965 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006966 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_GROUP_CHILD,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006967 "Group definition \"%s\" has unexpected content.\n", type->name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006968 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006969 }
6970
6971 return (type);
6972}
6973
6974/**
6975 * xmlSchemaParseAll:
6976 * @ctxt: a schema validation context
6977 * @schema: the schema being built
6978 * @node: a subtree containing XML Schema informations
6979 *
6980 * parse a XML schema All definition
6981 * *WARNING* this interface is highly subject to change
6982 *
William M. Bracke7091952004-05-11 15:09:58 +00006983 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00006984 * 1 in case of success.
6985 */
6986static xmlSchemaTypePtr
6987xmlSchemaParseAll(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006988 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00006989{
6990 xmlSchemaTypePtr type, subtype, last = NULL;
6991 xmlNodePtr child = NULL;
6992 xmlChar name[30];
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00006993 const xmlChar *oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00006994
6995 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6996 return (NULL);
6997
6998
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006999 snprintf((char *) name, 30, "all%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00007000 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00007001 if (type == NULL)
7002 return (NULL);
7003 type->node = node;
Daniel Veillard7646b182002-04-20 06:41:40 +00007004 type->type = XML_SCHEMA_TYPE_ALL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007005 type->id = xmlSchemaGetProp(ctxt, node, "id");
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00007006
7007 type->minOccurs = xmlGetMinOccurs(ctxt, node, 0, 1, 1, "(0 | 1)");
7008 type->maxOccurs = xmlGetMaxOccurs(ctxt, node, 1, 1, 1, "1");
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00007009
7010 oldcontainer = ctxt->container;
7011 ctxt->container = (const xmlChar *) name;
Daniel Veillard4255d502002-04-16 15:50:10 +00007012 child = node->children;
7013 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007014 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7015 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007016 }
7017 while (IS_SCHEMA(child, "element")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007018 subtype = (xmlSchemaTypePtr)
7019 xmlSchemaParseElement(ctxt, schema, child, 0);
7020 if (subtype != NULL) {
William M. Brackb15351e2003-12-27 04:34:42 +00007021 if (subtype->minOccurs > 1)
7022 xmlSchemaPErr(ctxt, child, XML_SCHEMAP_INVALID_MINOCCURS,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007023 "invalid value for minOccurs (must be 0 or 1).\n",
William M. Brackb15351e2003-12-27 04:34:42 +00007024 NULL, NULL);
7025 if (subtype->maxOccurs > 1)
7026 xmlSchemaPErr(ctxt, child, XML_SCHEMAP_INVALID_MAXOCCURS,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007027 "invalid value for maxOccurs (must be 0 or 1).\n",
William M. Brackb15351e2003-12-27 04:34:42 +00007028 NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007029 if (last == NULL) {
7030 type->subtypes = subtype;
7031 last = subtype;
7032 } else {
7033 last->next = subtype;
7034 last = subtype;
7035 }
7036 last->next = NULL;
7037 }
7038 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007039 }
7040 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007041 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_ALL_CHILD,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007042 "<all> has unexpected content.\n", type->name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007043 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007044 }
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00007045 ctxt->container = oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00007046 return (type);
7047}
7048
7049/**
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007050 * xmlSchemaCleanupDoc:
7051 * @ctxt: a schema validation context
7052 * @node: the root of the document.
7053 *
7054 * removes unwanted nodes in a schemas document tree
7055 */
7056static void
7057xmlSchemaCleanupDoc(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr root)
7058{
7059 xmlNodePtr delete, cur;
7060
7061 if ((ctxt == NULL) || (root == NULL)) return;
7062
7063 /*
7064 * Remove all the blank text nodes
7065 */
7066 delete = NULL;
7067 cur = root;
7068 while (cur != NULL) {
7069 if (delete != NULL) {
7070 xmlUnlinkNode(delete);
7071 xmlFreeNode(delete);
7072 delete = NULL;
7073 }
7074 if (cur->type == XML_TEXT_NODE) {
7075 if (IS_BLANK_NODE(cur)) {
7076 if (xmlNodeGetSpacePreserve(cur) != 1) {
7077 delete = cur;
7078 }
7079 }
7080 } else if ((cur->type != XML_ELEMENT_NODE) &&
7081 (cur->type != XML_CDATA_SECTION_NODE)) {
7082 delete = cur;
7083 goto skip_children;
7084 }
7085
7086 /*
7087 * Skip to next node
7088 */
7089 if (cur->children != NULL) {
7090 if ((cur->children->type != XML_ENTITY_DECL) &&
7091 (cur->children->type != XML_ENTITY_REF_NODE) &&
7092 (cur->children->type != XML_ENTITY_NODE)) {
7093 cur = cur->children;
7094 continue;
7095 }
7096 }
7097 skip_children:
7098 if (cur->next != NULL) {
7099 cur = cur->next;
7100 continue;
7101 }
7102
7103 do {
7104 cur = cur->parent;
7105 if (cur == NULL)
7106 break;
7107 if (cur == root) {
7108 cur = NULL;
7109 break;
7110 }
7111 if (cur->next != NULL) {
7112 cur = cur->next;
7113 break;
7114 }
7115 } while (cur != NULL);
7116 }
7117 if (delete != NULL) {
7118 xmlUnlinkNode(delete);
7119 xmlFreeNode(delete);
7120 delete = NULL;
7121 }
7122}
7123
William M. Brack2f2a6632004-08-20 23:09:47 +00007124
7125/**
7126 * xmlSchemaImportSchema
7127 *
7128 * @ctxt: a schema validation context
7129 * @schemaLocation: an URI defining where to find the imported schema
7130 *
7131 * import a XML schema
7132 * *WARNING* this interface is highly subject to change
7133 *
7134 * Returns -1 in case of error and 1 in case of success.
7135 */
7136#if 0
7137static xmlSchemaImportPtr
7138xmlSchemaImportSchema(xmlSchemaParserCtxtPtr ctxt,
7139 const xmlChar *schemaLocation)
7140{
7141 xmlSchemaImportPtr import;
7142 xmlSchemaParserCtxtPtr newctxt;
7143
7144 newctxt = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
7145 if (newctxt == NULL) {
7146 xmlSchemaPErrMemory(ctxt, "allocating schema parser context",
7147 NULL);
7148 return (NULL);
7149 }
7150 memset(newctxt, 0, sizeof(xmlSchemaParserCtxt));
7151 /* Keep the same dictionnary for parsing, really */
7152 xmlDictReference(ctxt->dict);
7153 newctxt->dict = ctxt->dict;
7154 newctxt->includes = 0;
7155 newctxt->URL = xmlDictLookup(newctxt->dict, schemaLocation, -1);
7156
7157 xmlSchemaSetParserErrors(newctxt, ctxt->error, ctxt->warning,
7158 ctxt->userData);
7159
7160 import = (xmlSchemaImport*) xmlMalloc(sizeof(xmlSchemaImport));
7161 if (import == NULL) {
7162 xmlSchemaPErrMemory(NULL, "allocating imported schema",
7163 NULL);
7164 xmlSchemaFreeParserCtxt(newctxt);
7165 return (NULL);
7166 }
7167
7168 memset(import, 0, sizeof(xmlSchemaImport));
7169 import->schemaLocation = xmlDictLookup(ctxt->dict, schemaLocation, -1);
7170 import->schema = xmlSchemaParse(newctxt);
7171
7172 if (import->schema == NULL) {
7173 /* FIXME use another error enum here ? */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00007174 xmlSchemaPErr(ctxt, NULL, XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +00007175 "Failed to import schema from location \"%s\".\n",
7176 schemaLocation, NULL);
7177
7178 xmlSchemaFreeParserCtxt(newctxt);
7179 /* The schemaLocation is held by the dictionary.
7180 if (import->schemaLocation != NULL)
7181 xmlFree((xmlChar *)import->schemaLocation);
7182 */
7183 xmlFree(import);
7184 return NULL;
7185 }
7186
7187 xmlSchemaFreeParserCtxt(newctxt);
7188 return import;
7189}
7190#endif
7191
7192static void
7193xmlSchemaClearSchemaDefaults(xmlSchemaPtr schema)
7194{
7195 if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
7196 schema->flags ^= XML_SCHEMAS_QUALIF_ELEM;
7197
7198 if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
7199 schema->flags ^= XML_SCHEMAS_QUALIF_ATTR;
7200
7201 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
7202 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_EXTENSION;
7203 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
7204 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION;
7205 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST)
7206 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_LIST;
7207 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION)
7208 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_UNION;
7209
7210 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
7211 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION;
7212 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
7213 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION;
7214 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
7215 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION;
7216}
7217
7218static void
7219xmlSchemaParseSchemaDefaults(xmlSchemaParserCtxtPtr ctxt,
7220 xmlSchemaPtr schema,
7221 xmlNodePtr node)
7222{
7223 xmlAttrPtr attr;
7224 const xmlChar *val;
7225
7226 attr = xmlSchemaGetPropNode(node, "elementFormDefault");
7227 if (attr != NULL) {
7228 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
7229 if (xmlSchemaPValAttrFormDefault(val, &schema->flags,
7230 XML_SCHEMAS_QUALIF_ELEM) != 0) {
7231 xmlSchemaPSimpleTypeErr(ctxt,
7232 XML_SCHEMAP_ELEMFORMDEFAULT_VALUE,
7233 NULL, NULL, (xmlNodePtr) attr, NULL,
7234 "(qualified | unqualified)", val, NULL, NULL, NULL);
7235 }
7236 }
7237
7238 attr = xmlSchemaGetPropNode(node, "attributeFormDefault");
7239 if (attr != NULL) {
7240 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
7241 if (xmlSchemaPValAttrFormDefault(val, &schema->flags,
7242 XML_SCHEMAS_QUALIF_ATTR) != 0) {
7243 xmlSchemaPSimpleTypeErr(ctxt,
7244 XML_SCHEMAP_ATTRFORMDEFAULT_VALUE,
7245 NULL, NULL, (xmlNodePtr) attr, NULL,
7246 "(qualified | unqualified)", val, NULL, NULL, NULL);
7247 }
7248 }
7249
7250 attr = xmlSchemaGetPropNode(node, "finalDefault");
7251 if (attr != NULL) {
7252 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
7253 if (xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
7254 XML_SCHEMAS_FINAL_DEFAULT_EXTENSION,
7255 XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION,
7256 -1,
7257 XML_SCHEMAS_FINAL_DEFAULT_LIST,
7258 XML_SCHEMAS_FINAL_DEFAULT_UNION) != 0) {
7259 xmlSchemaPSimpleTypeErr(ctxt,
7260 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
7261 NULL, NULL, (xmlNodePtr) attr, NULL,
7262 "(#all | List of (extension | restriction | list | union))",
7263 val, NULL, NULL, NULL);
7264 }
7265 }
7266
7267 attr = xmlSchemaGetPropNode(node, "blockDefault");
7268 if (attr != NULL) {
7269 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
7270 if (xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
7271 XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION,
7272 XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION,
7273 XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION, -1, -1) != 0) {
7274 xmlSchemaPSimpleTypeErr(ctxt,
7275 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
7276 NULL, NULL, (xmlNodePtr) attr, NULL,
7277 "(#all | List of (extension | restriction | substitution))",
7278 val, NULL, NULL, NULL);
7279 }
7280 }
7281}
7282
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007283/**
7284 * xmlSchemaParseSchemaTopLevel:
7285 * @ctxt: a schema validation context
7286 * @schema: the schemas
7287 * @nodes: the list of top level nodes
7288 *
7289 * Returns the internal XML Schema structure built from the resource or
7290 * NULL in case of error
7291 */
7292static void
7293xmlSchemaParseSchemaTopLevel(xmlSchemaParserCtxtPtr ctxt,
7294 xmlSchemaPtr schema, xmlNodePtr nodes)
7295{
7296 xmlNodePtr child;
7297 xmlSchemaAnnotPtr annot;
7298
7299 if ((ctxt == NULL) || (schema == NULL) || (nodes == NULL))
7300 return;
7301
7302 child = nodes;
7303 while ((IS_SCHEMA(child, "include")) ||
7304 (IS_SCHEMA(child, "import")) ||
7305 (IS_SCHEMA(child, "redefine")) ||
7306 (IS_SCHEMA(child, "annotation"))) {
7307 if (IS_SCHEMA(child, "annotation")) {
7308 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7309 if (schema->annot == NULL)
7310 schema->annot = annot;
7311 else
7312 xmlSchemaFreeAnnot(annot);
7313 } else if (IS_SCHEMA(child, "import")) {
7314 xmlSchemaParseImport(ctxt, schema, child);
7315 } else if (IS_SCHEMA(child, "include")) {
Daniel Veillardb0f397e2003-12-23 23:30:53 +00007316 ctxt->includes++;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007317 xmlSchemaParseInclude(ctxt, schema, child);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00007318 ctxt->includes--;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007319 } else if (IS_SCHEMA(child, "redefine")) {
7320 TODO
7321 }
7322 child = child->next;
7323 }
7324 while (child != NULL) {
7325 if (IS_SCHEMA(child, "complexType")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00007326 xmlSchemaParseComplexType(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007327 child = child->next;
7328 } else if (IS_SCHEMA(child, "simpleType")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00007329 xmlSchemaParseSimpleType(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007330 child = child->next;
7331 } else if (IS_SCHEMA(child, "element")) {
7332 xmlSchemaParseElement(ctxt, schema, child, 1);
7333 child = child->next;
7334 } else if (IS_SCHEMA(child, "attribute")) {
William M. Bracke7091952004-05-11 15:09:58 +00007335 xmlSchemaParseAttribute(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007336 child = child->next;
7337 } else if (IS_SCHEMA(child, "attributeGroup")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00007338 xmlSchemaParseAttributeGroup(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007339 child = child->next;
7340 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00007341 xmlSchemaParseGroup(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007342 child = child->next;
7343 } else if (IS_SCHEMA(child, "notation")) {
7344 xmlSchemaParseNotation(ctxt, schema, child);
7345 child = child->next;
7346 } else {
7347 xmlSchemaPErr2(ctxt, NULL, child,
7348 XML_SCHEMAP_UNKNOWN_SCHEMAS_CHILD,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007349 "Unexpected element \"%s\" as child of <schema>.\n",
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007350 child->name, NULL);
7351 child = child->next;
7352 }
7353 while (IS_SCHEMA(child, "annotation")) {
7354 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7355 if (schema->annot == NULL)
7356 schema->annot = annot;
7357 else
7358 xmlSchemaFreeAnnot(annot);
7359 child = child->next;
7360 }
7361 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00007362 ctxt->parentItem = NULL;
7363 ctxt->ctxtType = NULL;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007364}
7365
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007366static xmlSchemaImportPtr
7367xmlSchemaAddImport(xmlSchemaParserCtxtPtr ctxt,
7368 xmlHashTablePtr *imports,
7369 const xmlChar *nsName)
7370{
7371 xmlSchemaImportPtr ret;
7372
7373 if (*imports == NULL) {
Daniel Veillardb9e2f262005-01-23 23:48:34 +00007374 *imports = xmlHashCreateDict(10, ctxt->dict);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007375 if (*imports == NULL) {
7376 xmlSchemaPCustomErr(ctxt,
7377 XML_SCHEMAP_FAILED_BUILD_IMPORT,
7378 NULL, NULL, (xmlNodePtr) ctxt->doc,
7379 "Internal error: failed to build the import table",
7380 NULL);
7381 return (NULL);
7382 }
7383 }
7384 ret = (xmlSchemaImport*) xmlMalloc(sizeof(xmlSchemaImport));
7385 if (ret == NULL) {
7386 xmlSchemaPErrMemory(NULL, "allocating import struct", NULL);
7387 return (NULL);
7388 }
7389 memset(ret, 0, sizeof(xmlSchemaImport));
7390 if (nsName == NULL)
7391 nsName = XML_SCHEMAS_NO_NAMESPACE;
7392 xmlHashAddEntry(*imports, nsName, ret);
7393
7394 return (ret);
7395}
7396
7397static int
7398xmlSchemaAcquireSchemaDoc(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007399 xmlSchemaPtr schema,
7400 xmlNodePtr node,
7401 const xmlChar *nsName,
7402 const xmlChar *location,
7403 xmlDocPtr *doc,
7404 const xmlChar **targetNamespace,
7405 int absolute)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007406{
7407 xmlParserCtxtPtr parserCtxt;
7408 xmlSchemaImportPtr import;
7409 const xmlChar *ns;
7410 xmlNodePtr root;
7411
7412 /*
7413 * NOTE: This will be used for <import>, <xsi:schemaLocation> and
7414 * <xsi:noNamespaceSchemaLocation>.
7415 */
7416 *doc = NULL;
7417 /*
7418 * Given that the schemaLocation [attribute] is only a hint, it is open
7419 * to applications to ignore all but the first <import> for a given
7420 * namespace, regardless of the ·actual value· of schemaLocation, but
7421 * such a strategy risks missing useful information when new
7422 * schemaLocations are offered.
7423 *
7424 * XSV (ver 2.5-2) does use the first <import> which resolves to a valid schema.
7425 * Xerces-J (ver 2.5.1) ignores all but the first given <import> - regardless if
7426 * valid or not.
7427 * We will follow XSV here.
7428 */
7429 if (location == NULL) {
7430 /*
7431 * Schema Document Location Strategy:
7432 *
7433 * 3 Based on the namespace name, identify an existing schema document,
7434 * either as a resource which is an XML document or a <schema> element
7435 * information item, in some local schema repository;
7436 *
7437 * 5 Attempt to resolve the namespace name to locate such a resource.
7438 *
7439 * NOTE: Those stategies are not supported, so we will skip.
7440 */
7441 return (0);
7442 }
7443 if (nsName == NULL)
7444 ns = XML_SCHEMAS_NO_NAMESPACE;
7445 else
7446 ns = nsName;
7447
7448 import = xmlHashLookup(schema->schemasImports, ns);
7449 if (import != NULL) {
7450 /*
7451 * There was a valid resource for the specified namespace already
7452 * defined, so skip.
7453 * TODO: This might be changed someday to allow import of
7454 * components from multiple documents for a single target namespace.
7455 */
7456 return (0);
7457 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007458
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007459 /*
7460 * Schema Document Location Strategy:
7461 *
7462 * 2 Based on the location URI, identify an existing schema document,
7463 * either as a resource which is an XML document or a <schema> element
7464 * information item, in some local schema repository;
7465 *
7466 * 4 Attempt to resolve the location URI, to locate a resource on the
7467 * web which is or contains or references a <schema> element;
7468 * TODO: Hmm, I don't know if the reference stuff in 4. will work.
7469 *
7470 */
7471 if ((absolute == 0) && (node != NULL)) {
7472 xmlChar *base, *URI;
7473
7474 base = xmlNodeGetBase(node->doc, node);
7475 if (base == NULL) {
7476 URI = xmlBuildURI(location, node->doc->URL);
7477 } else {
7478 URI = xmlBuildURI(location, base);
7479 xmlFree(base);
7480 }
7481 if (URI != NULL) {
7482 location = xmlDictLookup(ctxt->dict, URI, -1);
7483 xmlFree(URI);
7484 }
7485 }
7486 parserCtxt = xmlNewParserCtxt();
7487 if (parserCtxt == NULL) {
7488 xmlSchemaPErrMemory(NULL, "xmlSchemaParseImport: "
7489 "allocating a parser context", NULL);
7490 return(-1);
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00007491 }
7492
7493 if ((ctxt->dict != NULL) && (parserCtxt->dict != NULL)) {
7494 xmlDictFree(parserCtxt->dict);
7495 parserCtxt->dict = ctxt->dict;
7496 xmlDictReference(parserCtxt->dict);
7497 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007498
7499 *doc = xmlCtxtReadFile(parserCtxt, (const char *) location,
7500 NULL, SCHEMAS_PARSE_OPTIONS);
7501
7502 /*
7503 * 2.1 The referent is (a fragment of) a resource which is an
7504 * XML document (see clause 1.1), which in turn corresponds to
7505 * a <schema> element information item in a well-formed information
7506 * set, which in turn corresponds to a valid schema.
7507 * TODO: What to do with the "fragment" stuff?
7508 *
7509 * 2.2 The referent is a <schema> element information item in
7510 * a well-formed information set, which in turn corresponds
7511 * to a valid schema.
7512 * NOTE: 2.2 won't apply, since only XML documents will be processed
7513 * here.
7514 */
7515 if (*doc == NULL) {
7516 xmlErrorPtr lerr;
7517 /*
7518 * It is *not* an error for the application schema reference
7519 * strategy to fail.
7520 *
7521 * If the doc is NULL and the parser error is an IO error we
7522 * will assume that the resource could not be located or accessed.
7523 *
7524 * TODO: Try to find specific error codes to react only on
7525 * localisation failures.
7526 *
7527 * TODO, FIXME: Check the spec: is a namespace added to the imported
7528 * namespaces, even if the schemaLocation did not provide
7529 * a resource? I guess so, since omitting the "schemaLocation"
7530 * attribute, imports a namespace as well.
7531 */
7532 lerr = xmlGetLastError();
7533 if ((lerr != NULL) && (lerr->domain == XML_FROM_IO)) {
7534 xmlFreeParserCtxt(parserCtxt);
7535 return(0);
7536 }
7537
7538 xmlSchemaPCustomErr(ctxt,
7539 XML_SCHEMAP_SRC_IMPORT_2_1,
7540 NULL, NULL, node,
7541 "Failed to parse the resource '%s' for import",
7542 location);
7543 xmlFreeParserCtxt(parserCtxt);
7544 return(XML_SCHEMAP_SRC_IMPORT_2_1);
7545 }
7546 xmlFreeParserCtxt(parserCtxt);
7547
7548 root = xmlDocGetRootElement(*doc);
7549 if (root == NULL) {
7550 xmlSchemaPCustomErr(ctxt,
7551 XML_SCHEMAP_SRC_IMPORT_2_1,
7552 NULL, NULL, node,
7553 "The XML document '%s' to be imported has no document "
7554 "element", location);
7555 xmlFreeDoc(*doc);
7556 *doc = NULL;
7557 return (XML_SCHEMAP_SRC_IMPORT_2_1);
7558 }
7559
7560 xmlSchemaCleanupDoc(ctxt, root);
7561
7562 if (!IS_SCHEMA(root, "schema")) {
7563 xmlSchemaPCustomErr(ctxt,
7564 XML_SCHEMAP_SRC_IMPORT_2_1,
7565 NULL, NULL, node,
7566 "The XML document '%s' to be imported is not a XML schema document",
7567 location);
7568 xmlFreeDoc(*doc);
7569 *doc = NULL;
7570 return (XML_SCHEMAP_SRC_IMPORT_2_1);
7571 }
7572 *targetNamespace = xmlSchemaGetProp(ctxt, root, "targetNamespace");
7573 /*
7574 * Schema Representation Constraint: Import Constraints and Semantics
7575 */
7576 if (nsName == NULL) {
7577 if (*targetNamespace != NULL) {
7578 xmlSchemaPCustomErr(ctxt,
7579 XML_SCHEMAP_SRC_IMPORT_3_2,
7580 NULL, NULL, node,
7581 "The XML schema to be imported is not expected "
7582 "to have a target namespace; this differs from "
7583 "its target namespace of '%s'", *targetNamespace);
7584 xmlFreeDoc(*doc);
7585 *doc = NULL;
7586 return (XML_SCHEMAP_SRC_IMPORT_3_2);
7587 }
7588 } else {
7589 if (*targetNamespace == NULL) {
7590 xmlSchemaPCustomErr(ctxt,
7591 XML_SCHEMAP_SRC_IMPORT_3_1,
7592 NULL, NULL, node,
7593 "The XML schema to be imported is expected to have a target "
7594 "namespace of '%s'", nsName);
7595 xmlFreeDoc(*doc);
7596 *doc = NULL;
7597 return (XML_SCHEMAP_SRC_IMPORT_3_1);
7598 } else if (!xmlStrEqual(*targetNamespace, nsName)) {
7599 xmlSchemaPCustomErrExt(ctxt,
7600 XML_SCHEMAP_SRC_IMPORT_3_1,
7601 NULL, NULL, node,
7602 "The XML schema to be imported is expected to have a "
7603 "target namespace of '%s'; this differs from "
7604 "its target namespace of '%s'",
7605 nsName, *targetNamespace, NULL);
7606 xmlFreeDoc(*doc);
7607 *doc = NULL;
7608 return (XML_SCHEMAP_SRC_IMPORT_3_1);
7609 }
7610 }
7611
7612 import = xmlSchemaAddImport(ctxt, &(schema->schemasImports), nsName);
7613 if (import == NULL) {
7614 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_FAILED_BUILD_IMPORT,
7615 NULL, NULL, NULL,
7616 "Internal error: xmlSchemaAcquireSchemaDoc, "
7617 "failed to build import table", NULL);
7618 xmlFreeDoc(*doc);
7619 *doc = NULL;
7620 return (-1);
7621 }
7622 import->schemaLocation = location;
7623 import->doc = *doc;
7624 return (0);
7625}
William M. Brack2f2a6632004-08-20 23:09:47 +00007626
7627/**
7628 * xmlSchemaParseImport:
7629 * @ctxt: a schema validation context
7630 * @schema: the schema being built
7631 * @node: a subtree containing XML Schema informations
7632 *
7633 * parse a XML schema Import definition
7634 * *WARNING* this interface is highly subject to change
7635 *
7636 * Returns 0 in case of success, a positive error code if
7637 * not valid and -1 in case of an internal error.
7638 */
7639static int
7640xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
7641 xmlNodePtr node)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007642{
7643 xmlNodePtr child;
7644 const xmlChar *namespace = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00007645 const xmlChar *schemaLocation = NULL;
7646 const xmlChar *targetNamespace, *oldTNS, *url;
7647 xmlAttrPtr attr;
7648 xmlDocPtr doc;
7649 xmlNodePtr root;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007650 int flags, ret = 0;
William M. Brack2f2a6632004-08-20 23:09:47 +00007651
7652
7653 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7654 return (-1);
7655
7656 /*
7657 * Check for illegal attributes.
7658 */
7659 attr = node->properties;
7660 while (attr != NULL) {
7661 if (attr->ns == NULL) {
7662 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7663 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
7664 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
7665 xmlSchemaPIllegalAttrErr(ctxt,
7666 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7667 NULL, NULL, attr);
7668 }
7669 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7670 xmlSchemaPIllegalAttrErr(ctxt,
7671 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7672 NULL, NULL, attr);
7673 }
7674 attr = attr->next;
7675 }
7676 /*
7677 * Extract and validate attributes.
7678 */
7679 if (xmlSchemaPValAttr(ctxt, NULL, NULL, node,
7680 "namespace", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
7681 &namespace) != 0) {
7682 xmlSchemaPSimpleTypeErr(ctxt,
7683 XML_SCHEMAP_IMPORT_NAMESPACE_NOT_URI,
7684 NULL, NULL, node,
7685 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
7686 NULL, namespace, NULL, NULL, NULL);
7687 return (XML_SCHEMAP_IMPORT_NAMESPACE_NOT_URI);
7688 }
7689
7690 if (xmlSchemaPValAttr(ctxt, NULL, NULL, node,
7691 "schemaLocation", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
7692 &schemaLocation) != 0) {
7693 xmlSchemaPSimpleTypeErr(ctxt,
7694 XML_SCHEMAP_IMPORT_SCHEMA_NOT_URI,
7695 NULL, NULL, node,
7696 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
7697 NULL, namespace, NULL, NULL, NULL);
7698 return (XML_SCHEMAP_IMPORT_SCHEMA_NOT_URI);
7699 }
7700 /*
7701 * And now for the children...
7702 */
7703 child = node->children;
7704 if (IS_SCHEMA(child, "annotation")) {
7705 /*
7706 * the annotation here is simply discarded ...
7707 */
7708 child = child->next;
7709 }
7710 if (child != NULL) {
7711 xmlSchemaPContentErr(ctxt,
7712 XML_SCHEMAP_UNKNOWN_IMPORT_CHILD,
7713 NULL, NULL, node, child, NULL,
7714 "(annotation?)");
7715 }
7716 /*
7717 * Apply additional constraints.
7718 */
7719 if (namespace != NULL) {
7720 /*
7721 * 1.1 If the namespace [attribute] is present, then its ·actual value·
7722 * must not match the ·actual value· of the enclosing <schema>'s
7723 * targetNamespace [attribute].
7724 */
7725 if (xmlStrEqual(schema->targetNamespace, namespace)) {
7726 xmlSchemaPCustomErr(ctxt,
7727 XML_SCHEMAP_SRC_IMPORT_1_1,
7728 NULL, NULL, node,
7729 "The value of the attribute 'namespace' must not match "
7730 "the target namespace '%s' of the importing schema",
7731 schema->targetNamespace);
7732 return (XML_SCHEMAP_SRC_IMPORT_1_1);
7733 }
7734 } else {
7735 /*
7736 * 1.2 If the namespace [attribute] is not present, then the enclosing
7737 * <schema> must have a targetNamespace [attribute].
7738 */
7739 if (schema->targetNamespace == NULL) {
7740 xmlSchemaPCustomErr(ctxt,
7741 XML_SCHEMAP_SRC_IMPORT_1_2,
7742 NULL, NULL, node,
7743 "The attribute 'namespace' must be existent if "
7744 "the importing schema has no target namespace",
7745 NULL);
7746 return (XML_SCHEMAP_SRC_IMPORT_1_2);
7747 }
7748 }
William M. Brack2f2a6632004-08-20 23:09:47 +00007749 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007750 * Locate and aquire the schema document.
William M. Brack2f2a6632004-08-20 23:09:47 +00007751 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007752 ret = xmlSchemaAcquireSchemaDoc(ctxt, schema, node, namespace,
7753 schemaLocation, &doc, &targetNamespace, 0);
7754 if (ret != 0) {
7755 if (doc != NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00007756 xmlFreeDoc(doc);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007757 return (ret);
7758 } else if (doc != NULL) {
7759 /*
7760 * Save and reset the context & schema.
7761 */
7762 url = ctxt->URL;
7763 /* TODO: Is using the doc->URL here correct? */
7764 ctxt->URL = doc->URL;
7765 flags = schema->flags;
7766 oldTNS = schema->targetNamespace;
7767 /*
7768 * Parse the schema.
7769 */
7770 root = xmlDocGetRootElement(doc);
7771 xmlSchemaClearSchemaDefaults(schema);
7772 xmlSchemaParseSchemaDefaults(ctxt, schema, root);
7773 schema->targetNamespace = targetNamespace;
7774 xmlSchemaParseSchemaTopLevel(ctxt, schema, root->children);
7775 /*
7776 * Restore the context & schema.
7777 */
7778 schema->flags = flags;
7779 schema->targetNamespace = oldTNS;
7780 ctxt->URL = url;
William M. Brack2f2a6632004-08-20 23:09:47 +00007781 }
William M. Brack2f2a6632004-08-20 23:09:47 +00007782
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007783 return (0);
William M. Brack2f2a6632004-08-20 23:09:47 +00007784}
7785
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007786/**
7787 * xmlSchemaParseInclude:
7788 * @ctxt: a schema validation context
7789 * @schema: the schema being built
7790 * @node: a subtree containing XML Schema informations
7791 *
7792 * parse a XML schema Include definition
7793 *
William M. Bracke7091952004-05-11 15:09:58 +00007794 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007795 * 1 in case of success.
7796 */
7797static int
7798xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
7799 xmlNodePtr node)
7800{
7801 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007802 const xmlChar *schemaLocation, *targetNamespace;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007803 xmlDocPtr doc;
7804 xmlNodePtr root;
7805 xmlSchemaIncludePtr include;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007806 int wasConvertingNs = 0;
William M. Brack2f2a6632004-08-20 23:09:47 +00007807 xmlAttrPtr attr;
7808 int saveFlags;
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00007809 xmlParserCtxtPtr parserCtxt;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007810
7811
7812 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7813 return (-1);
7814
7815 /*
William M. Brack2f2a6632004-08-20 23:09:47 +00007816 * Check for illegal attributes.
7817 */
7818 attr = node->properties;
7819 while (attr != NULL) {
7820 if (attr->ns == NULL) {
7821 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7822 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
7823 xmlSchemaPIllegalAttrErr(ctxt,
7824 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7825 NULL, NULL, attr);
7826 }
7827 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7828 xmlSchemaPIllegalAttrErr(ctxt,
7829 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7830 NULL, NULL, attr);
7831 }
7832 attr = attr->next;
7833 }
7834 /*
7835 * Extract and validate attributes.
7836 */
7837 /*
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007838 * Preliminary step, extract the URI-Reference for the include and
7839 * make an URI from the base.
7840 */
William M. Brack2f2a6632004-08-20 23:09:47 +00007841 attr = xmlSchemaGetPropNode(node, "schemaLocation");
7842 if (attr != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007843 xmlChar *base = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00007844 xmlChar *uri = NULL;
7845
7846 if (xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
7847 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), &schemaLocation) != 0)
7848 return (-1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007849 base = xmlNodeGetBase(node->doc, node);
7850 if (base == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00007851 uri = xmlBuildURI(schemaLocation, node->doc->URL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007852 } else {
William M. Brack2f2a6632004-08-20 23:09:47 +00007853 uri = xmlBuildURI(schemaLocation, base);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007854 xmlFree(base);
7855 }
William M. Brack2f2a6632004-08-20 23:09:47 +00007856 if (uri != NULL) {
7857 schemaLocation = xmlDictLookup(ctxt->dict, uri, -1);
7858 xmlFree(uri);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007859 }
7860 } else {
William M. Brack2f2a6632004-08-20 23:09:47 +00007861 xmlSchemaPMissingAttrErr(ctxt,
7862 XML_SCHEMAP_INCLUDE_SCHEMA_NO_URI,
7863 NULL, NULL, node, "schemaLocation", NULL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007864 return (-1);
7865 }
William M. Brack2f2a6632004-08-20 23:09:47 +00007866 /*
7867 * And now for the children...
7868 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007869 child = node->children;
7870 while (IS_SCHEMA(child, "annotation")) {
7871 /*
7872 * the annotations here are simply discarded ...
7873 */
7874 child = child->next;
7875 }
7876 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00007877 xmlSchemaPContentErr(ctxt,
7878 XML_SCHEMAP_UNKNOWN_INCLUDE_CHILD,
7879 NULL, NULL, node, child, NULL,
7880 "(annotation?)");
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007881 }
7882
7883 /*
7884 * First step is to parse the input document into an DOM/Infoset
7885 */
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00007886 /*
7887 * TODO: Use xmlCtxtReadFile to share the dictionary.
7888 */
7889 parserCtxt = xmlNewParserCtxt();
7890 if (parserCtxt == NULL) {
7891 xmlSchemaPErrMemory(NULL, "xmlSchemaParseInclude: "
7892 "allocating a parser context", NULL);
7893 return(-1);
7894 }
7895
7896 if ((ctxt->dict != NULL) && (parserCtxt->dict != NULL)) {
7897 xmlDictFree(parserCtxt->dict);
7898 parserCtxt->dict = ctxt->dict;
7899 xmlDictReference(parserCtxt->dict);
7900 }
7901
7902 doc = xmlCtxtReadFile(parserCtxt, (const char *) schemaLocation,
7903 NULL, SCHEMAS_PARSE_OPTIONS);
7904 xmlFreeParserCtxt(parserCtxt);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007905 if (doc == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00007906 /*
7907 * TODO: It is not an error for the ·actual value· of the
7908 * schemaLocation [attribute] to fail to resolve it all, in which
7909 * case no corresponding inclusion is performed.
7910 * So do we need a warning report here?
7911 */
7912 xmlSchemaPCustomErr(ctxt,
7913 XML_SCHEMAP_FAILED_LOAD,
7914 NULL, NULL, node,
7915 "Failed to load the document '%s' for inclusion", schemaLocation);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007916 return(-1);
7917 }
7918
7919 /*
7920 * Then extract the root of the schema
7921 */
7922 root = xmlDocGetRootElement(doc);
7923 if (root == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00007924 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007925 XML_SCHEMAP_NOROOT,
William M. Brack2f2a6632004-08-20 23:09:47 +00007926 NULL, NULL, node,
7927 "The included document '%s' has no document "
7928 "element", schemaLocation);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007929 xmlFreeDoc(doc);
7930 return (-1);
7931 }
7932
7933 /*
7934 * Remove all the blank text nodes
7935 */
7936 xmlSchemaCleanupDoc(ctxt, root);
7937
7938 /*
7939 * Check the schemas top level element
7940 */
7941 if (!IS_SCHEMA(root, "schema")) {
William M. Brack2f2a6632004-08-20 23:09:47 +00007942 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007943 XML_SCHEMAP_NOT_SCHEMA,
William M. Brack2f2a6632004-08-20 23:09:47 +00007944 NULL, NULL, node,
7945 "The document '%s' to be included is not a schema document",
7946 schemaLocation);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007947 xmlFreeDoc(doc);
7948 return (-1);
7949 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00007950
William M. Brack2f2a6632004-08-20 23:09:47 +00007951 targetNamespace = xmlSchemaGetProp(ctxt, root, "targetNamespace");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007952 /*
7953 * 2.1 SII has a targetNamespace [attribute], and its ·actual
7954 * value· is identical to the ·actual value· of the targetNamespace
7955 * [attribute] of SIIÂ’ (which must have such an [attribute]).
7956 */
7957 if (targetNamespace != NULL) {
7958 if (schema->targetNamespace == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00007959 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007960 XML_SCHEMAP_SRC_INCLUDE,
William M. Brack2f2a6632004-08-20 23:09:47 +00007961 NULL, NULL, node,
7962 "The target namespace of the included schema "
7963 "'%s' has to be absent, since the including schema "
7964 "has no target namespace",
7965 schemaLocation);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007966 xmlFreeDoc(doc);
7967 return (-1);
William M. Brack2f2a6632004-08-20 23:09:47 +00007968 } else if (!xmlStrEqual(targetNamespace, schema->targetNamespace)) {
7969 xmlSchemaPCustomErrExt(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007970 XML_SCHEMAP_SRC_INCLUDE,
William M. Brack2f2a6632004-08-20 23:09:47 +00007971 NULL, NULL, node,
7972 "The target namespace '%s' of the included schema '%s' "
7973 "differs from '%s' of the including schema",
7974 targetNamespace, schemaLocation, schema->targetNamespace);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007975 xmlFreeDoc(doc);
7976 return (-1);
7977 }
7978 } else if (schema->targetNamespace != NULL) {
7979 if ((schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) == 0) {
7980 schema->flags |= XML_SCHEMAS_INCLUDING_CONVERT_NS;
7981 } else
7982 wasConvertingNs = 1;
7983 }
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007984 /*
7985 * register the include
7986 */
7987 include = (xmlSchemaIncludePtr) xmlMalloc(sizeof(xmlSchemaInclude));
7988 if (include == NULL) {
7989 xmlSchemaPErrMemory(ctxt, "allocating included schema", NULL);
7990 xmlFreeDoc(doc);
7991 return (-1);
7992 }
7993
7994 memset(include, 0, sizeof(xmlSchemaInclude));
7995 include->schemaLocation = xmlDictLookup(ctxt->dict, schemaLocation, -1);
7996 include->doc = doc;
7997 include->next = schema->includes;
7998 schema->includes = include;
7999
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008000 /*
8001 * parse the declarations in the included file like if they
8002 * were in the original file.
Daniel Veillardc0826a72004-08-10 14:17:33 +00008003 */
8004 /*
William M. Brack2f2a6632004-08-20 23:09:47 +00008005 * TODO: The complete validation of the <schema> element is not done.
Daniel Veillardc0826a72004-08-10 14:17:33 +00008006 */
William M. Brack2f2a6632004-08-20 23:09:47 +00008007 /*
8008 * The default values ("blockDefault", "elementFormDefault", etc.)
8009 * are set to the values of the included schema and restored afterwards.
8010 */
8011 saveFlags = schema->flags;
8012 xmlSchemaClearSchemaDefaults(schema);
8013 xmlSchemaParseSchemaDefaults(ctxt, schema, root);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008014 xmlSchemaParseSchemaTopLevel(ctxt, schema, root->children);
William M. Brack2f2a6632004-08-20 23:09:47 +00008015 schema->flags = saveFlags;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008016 /*
8017 * Remove the converting flag.
8018 */
William M. Brack2f2a6632004-08-20 23:09:47 +00008019 if ((wasConvertingNs == 0) &&
8020 (schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS))
Daniel Veillardc0826a72004-08-10 14:17:33 +00008021 schema->flags ^= XML_SCHEMAS_INCLUDING_CONVERT_NS;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008022 return (1);
8023}
8024
8025/**
Daniel Veillard4255d502002-04-16 15:50:10 +00008026 * xmlSchemaParseChoice:
8027 * @ctxt: a schema validation context
8028 * @schema: the schema being built
8029 * @node: a subtree containing XML Schema informations
8030 *
8031 * parse a XML schema Choice definition
8032 * *WARNING* this interface is highly subject to change
8033 *
William M. Bracke7091952004-05-11 15:09:58 +00008034 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00008035 * 1 in case of success.
8036 */
8037static xmlSchemaTypePtr
8038xmlSchemaParseChoice(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008039 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00008040{
8041 xmlSchemaTypePtr type, subtype, last = NULL;
8042 xmlNodePtr child = NULL;
8043 xmlChar name[30];
William M. Brack2f2a6632004-08-20 23:09:47 +00008044 xmlAttrPtr attr;
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00008045 const xmlChar *oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00008046
8047 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8048 return (NULL);
8049
8050
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008051 snprintf((char *) name, 30, "choice %d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00008052 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00008053 if (type == NULL)
8054 return (NULL);
8055 type->node = node;
8056 type->type = XML_SCHEMA_TYPE_CHOICE;
William M. Brack2f2a6632004-08-20 23:09:47 +00008057 /*
8058 * Check for illegal attributes.
8059 */
8060 attr = node->properties;
8061 while (attr != NULL) {
8062 if (attr->ns == NULL) {
8063 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8064 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
8065 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs"))) {
8066 xmlSchemaPIllegalAttrErr(ctxt,
8067 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8068 NULL, type, attr);
8069 }
8070 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8071 xmlSchemaPIllegalAttrErr(ctxt,
8072 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8073 NULL, type, attr);
8074 }
8075 attr = attr->next;
8076 }
8077 /*
8078 * Extract and validate attributes.
8079 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008080 type->id = xmlSchemaGetProp(ctxt, node, "id");
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00008081 type->minOccurs = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "nonNegativeInteger");
8082 type->maxOccurs = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
8083 "(nonNegativeInteger | unbounded)");
William M. Brack2f2a6632004-08-20 23:09:47 +00008084 /*
8085 * And now for the children...
8086 */
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00008087 oldcontainer = ctxt->container;
8088 ctxt->container = (const xmlChar *) name;
Daniel Veillard4255d502002-04-16 15:50:10 +00008089 child = node->children;
8090 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008091 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8092 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008093 }
8094 while ((IS_SCHEMA(child, "element")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008095 (IS_SCHEMA(child, "group")) ||
8096 (IS_SCHEMA(child, "any")) ||
8097 (IS_SCHEMA(child, "choice")) ||
8098 (IS_SCHEMA(child, "sequence"))) {
8099 subtype = NULL;
8100 if (IS_SCHEMA(child, "element")) {
8101 subtype = (xmlSchemaTypePtr)
8102 xmlSchemaParseElement(ctxt, schema, child, 0);
8103 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00008104 subtype = xmlSchemaParseGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008105 } else if (IS_SCHEMA(child, "any")) {
8106 subtype = xmlSchemaParseAny(ctxt, schema, child);
8107 } else if (IS_SCHEMA(child, "sequence")) {
8108 subtype = xmlSchemaParseSequence(ctxt, schema, child);
8109 } else if (IS_SCHEMA(child, "choice")) {
8110 subtype = xmlSchemaParseChoice(ctxt, schema, child);
8111 }
8112 if (subtype != NULL) {
8113 if (last == NULL) {
8114 type->subtypes = subtype;
8115 last = subtype;
8116 } else {
8117 last->next = subtype;
8118 last = subtype;
8119 }
8120 last->next = NULL;
8121 }
8122 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008123 }
8124 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008125 /* TODO: error code. */
8126 xmlSchemaPContentErr(ctxt,
8127 XML_SCHEMAP_UNKNOWN_CHOICE_CHILD,
8128 NULL, type, node, child, NULL,
8129 "(annotation?, (element | group | choice | sequence | any)*)");
Daniel Veillard4255d502002-04-16 15:50:10 +00008130 }
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00008131 ctxt->container = oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00008132 return (type);
8133}
8134
8135/**
8136 * xmlSchemaParseSequence:
8137 * @ctxt: a schema validation context
8138 * @schema: the schema being built
8139 * @node: a subtree containing XML Schema informations
8140 *
8141 * parse a XML schema Sequence definition
8142 * *WARNING* this interface is highly subject to change
8143 *
William M. Bracke7091952004-05-11 15:09:58 +00008144 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00008145 * 1 in case of success.
8146 */
8147static xmlSchemaTypePtr
8148xmlSchemaParseSequence(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008149 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00008150{
8151 xmlSchemaTypePtr type, subtype, last = NULL;
8152 xmlNodePtr child = NULL;
8153 xmlChar name[30];
William M. Brack2f2a6632004-08-20 23:09:47 +00008154 xmlAttrPtr attr;
8155 const xmlChar *oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00008156
8157 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8158 return (NULL);
8159
William M. Brack2f2a6632004-08-20 23:09:47 +00008160 oldcontainer = ctxt->container;
8161 snprintf((char *) name, 30, "#seq %d", ctxt->counter++ + 1);
8162 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00008163 if (type == NULL)
8164 return (NULL);
8165 type->node = node;
8166 type->type = XML_SCHEMA_TYPE_SEQUENCE;
William M. Brack2f2a6632004-08-20 23:09:47 +00008167 /*
8168 * Check for illegal attributes.
8169 */
8170 attr = node->properties;
8171 while (attr != NULL) {
8172 if (attr->ns == NULL) {
8173 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8174 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
8175 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs"))) {
8176 xmlSchemaPIllegalAttrErr(ctxt,
8177 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8178 NULL, type, attr);
8179 }
8180 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8181 xmlSchemaPIllegalAttrErr(ctxt,
8182 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8183 NULL, type, attr);
8184 }
8185 attr = attr->next;
8186 }
8187 /*
8188 * Extract and validate attributes.
8189 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008190 type->id = xmlSchemaGetProp(ctxt, node, "id");
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00008191 type->minOccurs = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "nonNegativeInteger");
8192 type->maxOccurs = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
8193 "(nonNegativeInteger | unbounded)");
William M. Brack2f2a6632004-08-20 23:09:47 +00008194 /*
8195 * And now for the children...
8196 */
8197 ctxt->container = (const xmlChar *) name;
Daniel Veillard4255d502002-04-16 15:50:10 +00008198 child = node->children;
8199 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008200 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8201 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008202 }
8203 while ((IS_SCHEMA(child, "element")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008204 (IS_SCHEMA(child, "group")) ||
8205 (IS_SCHEMA(child, "any")) ||
8206 (IS_SCHEMA(child, "choice")) ||
8207 (IS_SCHEMA(child, "sequence"))) {
8208 subtype = NULL;
8209 if (IS_SCHEMA(child, "element")) {
8210 subtype = (xmlSchemaTypePtr)
8211 xmlSchemaParseElement(ctxt, schema, child, 0);
8212 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00008213 subtype = xmlSchemaParseGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008214 } else if (IS_SCHEMA(child, "any")) {
8215 subtype = xmlSchemaParseAny(ctxt, schema, child);
8216 } else if (IS_SCHEMA(child, "choice")) {
8217 subtype = xmlSchemaParseChoice(ctxt, schema, child);
8218 } else if (IS_SCHEMA(child, "sequence")) {
8219 subtype = xmlSchemaParseSequence(ctxt, schema, child);
8220 }
8221 if (subtype != NULL) {
8222 if (last == NULL) {
8223 type->subtypes = subtype;
8224 last = subtype;
8225 } else {
8226 last->next = subtype;
8227 last = subtype;
8228 }
8229 last->next = NULL;
8230 }
8231 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008232 }
8233 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008234 xmlSchemaPContentErr(ctxt,
8235 XML_SCHEMAP_UNKNOWN_SEQUENCE_CHILD,
8236 NULL, type, node, child, NULL,
8237 "(annotation?, (element | group | choice | sequence | any)*)");
Daniel Veillard4255d502002-04-16 15:50:10 +00008238 }
William M. Brack2f2a6632004-08-20 23:09:47 +00008239 ctxt->container = oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00008240
8241 return (type);
8242}
8243
8244/**
8245 * xmlSchemaParseRestriction:
8246 * @ctxt: a schema validation context
8247 * @schema: the schema being built
8248 * @node: a subtree containing XML Schema informations
Daniel Veillard4255d502002-04-16 15:50:10 +00008249 *
8250 * parse a XML schema Restriction definition
8251 * *WARNING* this interface is highly subject to change
8252 *
8253 * Returns the type definition or NULL in case of error
8254 */
8255static xmlSchemaTypePtr
8256xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00008257 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00008258{
Daniel Veillard01fa6152004-06-29 17:04:39 +00008259 xmlSchemaTypePtr type, subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00008260 xmlNodePtr child = NULL;
8261 xmlChar name[30];
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008262 const xmlChar *oldcontainer;
William M. Brack2f2a6632004-08-20 23:09:47 +00008263 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00008264
8265 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8266 return (NULL);
8267
8268 oldcontainer = ctxt->container;
8269
William M. Brack2f2a6632004-08-20 23:09:47 +00008270 snprintf((char *) name, 30, "#restr %d", ctxt->counter++ + 1);
8271 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00008272 if (type == NULL)
8273 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00008274 type->type = XML_SCHEMA_TYPE_RESTRICTION;
Daniel Veillard4255d502002-04-16 15:50:10 +00008275 type->node = node;
William M. Brack2f2a6632004-08-20 23:09:47 +00008276 /*
8277 * Check for illegal attributes.
8278 */
8279 attr = node->properties;
8280 while (attr != NULL) {
8281 if (attr->ns == NULL) {
8282 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8283 (!xmlStrEqual(attr->name, BAD_CAST "base"))) {
8284 xmlSchemaPIllegalAttrErr(ctxt,
8285 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8286 NULL, type, attr);
8287 }
8288 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8289 xmlSchemaPIllegalAttrErr(ctxt,
8290 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8291 NULL, type, attr);
8292 }
8293 attr = attr->next;
8294 }
8295 /*
8296 * Extract and validate attributes.
8297 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008298 type->id = xmlSchemaGetProp(ctxt, node, "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00008299 /*
8300 * Attribute "base".
8301 */
Daniel Veillard4255d502002-04-16 15:50:10 +00008302 type->base = xmlGetQNameProp(ctxt, node, "base", &(type->baseNs));
Daniel Veillard01fa6152004-06-29 17:04:39 +00008303 if ((type->base == NULL) &&
William M. Brack2f2a6632004-08-20 23:09:47 +00008304 (ctxt->ctxtType->type == XML_SCHEMA_TYPE_COMPLEX)) {
8305 /* TODO: Think about the error code. */
8306 xmlSchemaPMissingAttrErr(ctxt,
8307 XML_SCHEMAP_RESTRICTION_NONAME_NOREF,
8308 NULL, type, node, "base", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00008309 }
William M. Brack2f2a6632004-08-20 23:09:47 +00008310 /*
8311 * And now for the children...
8312 */
Daniel Veillard4255d502002-04-16 15:50:10 +00008313 ctxt->container = name;
Daniel Veillard4255d502002-04-16 15:50:10 +00008314 child = node->children;
8315 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008316 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8317 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008318 }
8319 subtype = NULL;
Daniel Veillard01fa6152004-06-29 17:04:39 +00008320 if (ctxt->parentItem->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
8321 if (IS_SCHEMA(child, "all")) {
8322 subtype = (xmlSchemaTypePtr)
8323 xmlSchemaParseAll(ctxt, schema, child);
8324 child = child->next;
8325 type->subtypes = subtype;
8326 } else if (IS_SCHEMA(child, "choice")) {
8327 subtype = xmlSchemaParseChoice(ctxt, schema, child);
8328 child = child->next;
8329 type->subtypes = subtype;
8330 } else if (IS_SCHEMA(child, "sequence")) {
8331 subtype = (xmlSchemaTypePtr)
8332 xmlSchemaParseSequence(ctxt, schema, child);
8333 child = child->next;
8334 type->subtypes = subtype;
8335 } else if (IS_SCHEMA(child, "group")) {
8336 subtype = (xmlSchemaTypePtr)
8337 xmlSchemaParseGroup(ctxt, schema, child, 0);
8338 child = child->next;
8339 type->subtypes = subtype;
8340 }
William M. Brack2f2a6632004-08-20 23:09:47 +00008341 } else if (ctxt->ctxtType->type == XML_SCHEMA_TYPE_SIMPLE) {
8342 if (IS_SCHEMA(child, "simpleType")) {
8343 if (type->base != NULL) {
8344 /*
8345 * src-restriction-base-or-simpleType
8346 * Either the base [attribute] or the simpleType [child] of the
8347 * <restriction> element must be present, but not both.
8348 */
8349 xmlSchemaPContentErr(ctxt,
8350 XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
8351 NULL, NULL, type->node, child,
8352 "The attribute 'base' and the <simpleType> child are "
8353 "mutually exclusive", NULL);
8354 } else {
8355 subtype = (xmlSchemaTypePtr)
8356 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
8357 type->baseType = subtype;
8358 }
8359 child = child->next;
8360 }
8361 } else if (ctxt->parentItem->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
Daniel Veillard01fa6152004-06-29 17:04:39 +00008362 if (IS_SCHEMA(child, "simpleType")) {
8363 subtype = (xmlSchemaTypePtr)
8364 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
Daniel Veillard01fa6152004-06-29 17:04:39 +00008365 type->subtypes = subtype;
8366 child = child->next;
William M. Brack2f2a6632004-08-20 23:09:47 +00008367 }
8368 }
8369 if ((ctxt->ctxtType->type == XML_SCHEMA_TYPE_SIMPLE) ||
8370 (ctxt->parentItem->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT)) {
8371 xmlSchemaFacetPtr facet, lastfacet = NULL;
8372
Daniel Veillard01fa6152004-06-29 17:04:39 +00008373 /*
8374 * Add the facets to the parent simpleType/complexType.
8375 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00008376 /*
8377 * TODO: Datatypes: 4.1.3 Constraints on XML Representation of
8378 * Simple Type Definition Schema Representation Constraint:
8379 * *Single Facet Value*
8380 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00008381 while ((IS_SCHEMA(child, "minInclusive")) ||
8382 (IS_SCHEMA(child, "minExclusive")) ||
8383 (IS_SCHEMA(child, "maxInclusive")) ||
8384 (IS_SCHEMA(child, "maxExclusive")) ||
8385 (IS_SCHEMA(child, "totalDigits")) ||
8386 (IS_SCHEMA(child, "fractionDigits")) ||
8387 (IS_SCHEMA(child, "pattern")) ||
8388 (IS_SCHEMA(child, "enumeration")) ||
8389 (IS_SCHEMA(child, "whiteSpace")) ||
8390 (IS_SCHEMA(child, "length")) ||
8391 (IS_SCHEMA(child, "maxLength")) ||
8392 (IS_SCHEMA(child, "minLength"))) {
8393 facet = xmlSchemaParseFacet(ctxt, schema, child);
8394 if (facet != NULL) {
8395 if (lastfacet == NULL)
8396 ctxt->ctxtType->facets = facet;
8397 else
8398 lastfacet->next = facet;
8399 lastfacet = facet;
8400 lastfacet->next = NULL;
8401 }
8402 child = child->next;
8403 }
8404 /*
8405 * Create links for derivation and validation.
8406 */
8407 if (lastfacet != NULL) {
8408 xmlSchemaFacetLinkPtr facetLink, lastFacetLink = NULL;
8409
8410 facet = ctxt->ctxtType->facets;
8411 do {
8412 facetLink = (xmlSchemaFacetLinkPtr) xmlMalloc(sizeof(xmlSchemaFacetLink));
8413 if (facetLink == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008414 xmlSchemaPErrMemory(ctxt, "allocating a facet link", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00008415 xmlFree(facetLink);
8416 return (NULL);
8417 }
8418 facetLink->facet = facet;
8419 facetLink->next = NULL;
8420 if (lastFacetLink == NULL)
8421 ctxt->ctxtType->facetSet = facetLink;
8422 else
8423 lastFacetLink->next = facetLink;
8424 lastFacetLink = facetLink;
8425 facet = facet->next;
8426 } while (facet != NULL);
8427 }
8428 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008429 if (ctxt->ctxtType->type == XML_SCHEMA_TYPE_COMPLEX) {
8430 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
8431 if (IS_SCHEMA(child, "anyAttribute")) {
8432 ctxt->ctxtType->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
8433 child = child->next;
8434 }
8435 }
Daniel Veillard4255d502002-04-16 15:50:10 +00008436 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008437 /* TODO: Think about the error code. */
8438 if (ctxt->parentItem->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
8439 xmlSchemaPContentErr(ctxt,
8440 XML_SCHEMAP_UNKNOWN_RESTRICTION_CHILD,
8441 NULL, type, node, child, NULL,
8442 "annotation?, (group | all | choice | sequence)?, "
8443 "((attribute | attributeGroup)*, anyAttribute?))");
8444 } else if (ctxt->parentItem->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
8445 xmlSchemaPContentErr(ctxt,
8446 XML_SCHEMAP_UNKNOWN_RESTRICTION_CHILD,
8447 NULL, type, node, child, NULL,
8448 "(annotation?, (simpleType?, (minExclusive | minInclusive | "
8449 "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
8450 "length | minLength | maxLength | enumeration | whiteSpace | "
8451 "pattern)*)?, ((attribute | attributeGroup)*, anyAttribute?))");
8452 } else {
8453 /* Simple type */
8454 xmlSchemaPContentErr(ctxt,
8455 XML_SCHEMAP_UNKNOWN_RESTRICTION_CHILD,
8456 NULL, type, node, child, NULL,
8457 "(annotation?, (simpleType?, (minExclusive | minInclusive | "
8458 "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
8459 "length | minLength | maxLength | enumeration | whiteSpace | "
8460 "pattern)*))");
8461 }
8462 }
Daniel Veillard4255d502002-04-16 15:50:10 +00008463 ctxt->container = oldcontainer;
8464 return (type);
8465}
8466
8467/**
8468 * xmlSchemaParseExtension:
8469 * @ctxt: a schema validation context
8470 * @schema: the schema being built
8471 * @node: a subtree containing XML Schema informations
8472 *
8473 * parse a XML schema Extension definition
8474 * *WARNING* this interface is highly subject to change
8475 *
8476 * Returns the type definition or NULL in case of error
8477 */
8478static xmlSchemaTypePtr
8479xmlSchemaParseExtension(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008480 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00008481{
8482 xmlSchemaTypePtr type, subtype;
8483 xmlNodePtr child = NULL;
8484 xmlChar name[30];
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008485 const xmlChar *oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00008486
8487 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8488 return (NULL);
8489
8490 oldcontainer = ctxt->container;
8491
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008492 snprintf((char *) name, 30, "extension %d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00008493 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00008494 if (type == NULL)
8495 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00008496 type->type = XML_SCHEMA_TYPE_EXTENSION;
Daniel Veillard4255d502002-04-16 15:50:10 +00008497 type->node = node;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008498 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00008499 ctxt->container = name;
8500
8501 type->base = xmlGetQNameProp(ctxt, node, "base", &(type->baseNs));
8502 if (type->base == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008503 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_EXTENSION_NO_BASE,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008504 "<extension>: The attribute \"base\" is missing.\n",
8505 type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00008506 }
8507 child = node->children;
8508 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008509 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8510 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008511 }
8512 subtype = NULL;
8513
8514 if (IS_SCHEMA(child, "all")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008515 subtype = xmlSchemaParseAll(ctxt, schema, child);
8516 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008517 } else if (IS_SCHEMA(child, "choice")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008518 subtype = xmlSchemaParseChoice(ctxt, schema, child);
8519 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008520 } else if (IS_SCHEMA(child, "sequence")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008521 subtype = xmlSchemaParseSequence(ctxt, schema, child);
8522 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008523 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00008524 subtype = xmlSchemaParseGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008525 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008526 }
8527 if (subtype != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008528 type->subtypes = subtype;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008529 if ((ctxt->ctxtType != NULL) &&
8530 (ctxt->ctxtType->type == XML_SCHEMA_TYPE_COMPLEX)) {
8531 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
8532 if (IS_SCHEMA(child, "anyAttribute")) {
8533 ctxt->ctxtType->attributeWildcard =
8534 xmlSchemaParseAnyAttribute(ctxt, schema, child);
8535 child = child->next;
8536 }
8537 }
Daniel Veillard4255d502002-04-16 15:50:10 +00008538 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008539 xmlSchemaPErr2(ctxt, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008540 XML_SCHEMAP_UNKNOWN_EXTENSION_CHILD,
8541 "<extension> has unexpected content.\n", type->name,
8542 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00008543 }
8544 ctxt->container = oldcontainer;
8545 return (type);
8546}
8547
8548/**
8549 * xmlSchemaParseSimpleContent:
8550 * @ctxt: a schema validation context
8551 * @schema: the schema being built
8552 * @node: a subtree containing XML Schema informations
8553 *
8554 * parse a XML schema SimpleContent definition
8555 * *WARNING* this interface is highly subject to change
8556 *
8557 * Returns the type definition or NULL in case of error
8558 */
8559static xmlSchemaTypePtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008560xmlSchemaParseSimpleContent(xmlSchemaParserCtxtPtr ctxt,
8561 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00008562{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008563 xmlSchemaTypePtr type, subtype, oldParentItem;
Daniel Veillard4255d502002-04-16 15:50:10 +00008564 xmlNodePtr child = NULL;
8565 xmlChar name[30];
8566
8567 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8568 return (NULL);
8569
William M. Bracke7091952004-05-11 15:09:58 +00008570 snprintf((char *) name, 30, "simpleContent %d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00008571 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00008572 if (type == NULL)
8573 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00008574 type->type = XML_SCHEMA_TYPE_SIMPLE_CONTENT;
Daniel Veillard4255d502002-04-16 15:50:10 +00008575 type->node = node;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008576 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00008577
8578 child = node->children;
8579 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008580 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8581 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008582 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008583 oldParentItem = ctxt->parentItem;
Daniel Veillard01fa6152004-06-29 17:04:39 +00008584 ctxt->parentItem = type;
8585 subtype = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00008586 if (IS_SCHEMA(child, "restriction")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008587 subtype = (xmlSchemaTypePtr)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00008588 xmlSchemaParseRestriction(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008589 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008590 } else if (IS_SCHEMA(child, "extension")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008591 subtype = (xmlSchemaTypePtr)
8592 xmlSchemaParseExtension(ctxt, schema, child);
8593 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008594 }
8595 type->subtypes = subtype;
8596 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008597 xmlSchemaPErr2(ctxt, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008598 XML_SCHEMAP_UNKNOWN_SIMPLECONTENT_CHILD,
8599 "<simpleContent> has unexpected content.\n",
8600 NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00008601 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008602 ctxt->parentItem = oldParentItem;
Daniel Veillard4255d502002-04-16 15:50:10 +00008603 return (type);
8604}
8605
8606/**
8607 * xmlSchemaParseComplexContent:
8608 * @ctxt: a schema validation context
8609 * @schema: the schema being built
8610 * @node: a subtree containing XML Schema informations
8611 *
8612 * parse a XML schema ComplexContent definition
8613 * *WARNING* this interface is highly subject to change
8614 *
8615 * Returns the type definition or NULL in case of error
8616 */
8617static xmlSchemaTypePtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008618xmlSchemaParseComplexContent(xmlSchemaParserCtxtPtr ctxt,
8619 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00008620{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008621 xmlSchemaTypePtr type, subtype, oldParentItem;
Daniel Veillard4255d502002-04-16 15:50:10 +00008622 xmlNodePtr child = NULL;
8623 xmlChar name[30];
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008624 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00008625
8626 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8627 return (NULL);
8628
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008629 snprintf((char *) name, 30, "#CC %d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00008630 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00008631 if (type == NULL)
8632 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00008633 type->type = XML_SCHEMA_TYPE_COMPLEX_CONTENT;
Daniel Veillard01fa6152004-06-29 17:04:39 +00008634 type->node = node;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008635 /*
8636 * Check for illegal attributes.
8637 */
8638 attr = node->properties;
8639 while (attr != NULL) {
8640 if (attr->ns == NULL) {
8641 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8642 (!xmlStrEqual(attr->name, BAD_CAST "mixed")))
8643 {
8644 xmlSchemaPIllegalAttrErr(ctxt,
8645 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8646 NULL, NULL, attr);
8647 }
8648 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8649 xmlSchemaPIllegalAttrErr(ctxt,
8650 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8651 NULL, NULL, attr);
8652 }
8653 attr = attr->next;
8654 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008655 type->id = xmlSchemaGetProp(ctxt, node, "id");
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008656 /*
8657 * Handle attribute 'mixed'.
8658 */
8659 if (xmlGetBooleanProp(ctxt, NULL, type, node, "mixed", 0)) {
8660 if ((ctxt->ctxtType->flags & XML_SCHEMAS_TYPE_MIXED) == 0)
8661 ctxt->ctxtType->flags |= XML_SCHEMAS_TYPE_MIXED;
8662 }
Daniel Veillard4255d502002-04-16 15:50:10 +00008663 child = node->children;
8664 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008665 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8666 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008667 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008668 oldParentItem = ctxt->parentItem;
Daniel Veillard01fa6152004-06-29 17:04:39 +00008669 ctxt->parentItem = type;
Daniel Veillard4255d502002-04-16 15:50:10 +00008670 subtype = NULL;
8671 if (IS_SCHEMA(child, "restriction")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008672 subtype = (xmlSchemaTypePtr)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00008673 xmlSchemaParseRestriction(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008674 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008675 } else if (IS_SCHEMA(child, "extension")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008676 subtype = (xmlSchemaTypePtr)
8677 xmlSchemaParseExtension(ctxt, schema, child);
8678 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008679 }
8680 type->subtypes = subtype;
8681 if (child != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008682 xmlSchemaPContentErr(ctxt,
8683 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8684 NULL, NULL, node, child,
8685 NULL, "(annotation?, (restriction | extension))");
Daniel Veillard4255d502002-04-16 15:50:10 +00008686 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008687 ctxt->parentItem = oldParentItem;
Daniel Veillard4255d502002-04-16 15:50:10 +00008688 return (type);
8689}
8690
8691/**
8692 * xmlSchemaParseComplexType:
8693 * @ctxt: a schema validation context
8694 * @schema: the schema being built
8695 * @node: a subtree containing XML Schema informations
8696 *
8697 * parse a XML schema Complex Type definition
8698 * *WARNING* this interface is highly subject to change
8699 *
8700 * Returns the type definition or NULL in case of error
8701 */
8702static xmlSchemaTypePtr
8703xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00008704 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00008705{
Daniel Veillard01fa6152004-06-29 17:04:39 +00008706 xmlSchemaTypePtr type, subtype, ctxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +00008707 xmlNodePtr child = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008708 const xmlChar *name = NULL;
William M. Bracke7091952004-05-11 15:09:58 +00008709 const xmlChar *oldcontainer;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008710 xmlAttrPtr attr;
8711 const xmlChar *attrValue;
8712 xmlChar *des = NULL; /* The reported designation. */
Daniel Veillard1a380b82004-10-21 16:00:06 +00008713 char buf[40];
8714
Daniel Veillard4255d502002-04-16 15:50:10 +00008715
8716 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8717 return (NULL);
8718
Daniel Veillard01fa6152004-06-29 17:04:39 +00008719 ctxtType = ctxt->ctxtType;
8720
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008721 if (topLevel) {
8722 attr = xmlSchemaGetPropNode(node, "name");
8723 if (attr == NULL) {
8724 xmlSchemaPMissingAttrErr(ctxt,
8725 XML_SCHEMAP_S4S_ATTR_MISSING,
8726 (xmlChar **) &xmlSchemaElemDesCT, NULL, node,
8727 "name", NULL);
8728 return (NULL);
8729 } else if (xmlSchemaPValAttrNode(ctxt,
8730 (xmlChar **) &xmlSchemaElemDesCT, NULL, attr,
8731 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
8732 return (NULL);
8733 }
8734 }
8735
8736 if (topLevel == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008737 /*
8738 * Parse as local complex type definition.
8739 */
8740 snprintf(buf, 39, "#CT %d", ctxt->counter++ + 1);
8741 type = xmlSchemaAddType(ctxt, schema, (const xmlChar *)buf, NULL, node);
8742 if (type == NULL)
8743 return (NULL);
8744 name = (const xmlChar *) buf;
8745 type->node = node;
8746 type->type = XML_SCHEMA_TYPE_COMPLEX;
8747 /*
8748 * TODO: We need the target namespace.
8749 */
8750 } else {
8751 /*
8752 * Parse as global complex type definition.
8753 */
William M. Brack2f2a6632004-08-20 23:09:47 +00008754 type = xmlSchemaAddType(ctxt, schema, name, schema->targetNamespace, node);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008755 if (type == NULL)
8756 return (NULL);
8757 type->node = node;
8758 type->type = XML_SCHEMA_TYPE_COMPLEX;
8759 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
8760 /*
8761 * Set defaults.
8762 */
8763 type->flags |= XML_SCHEMAS_TYPE_FINAL_DEFAULT;
8764 type->flags |= XML_SCHEMAS_TYPE_BLOCK_DEFAULT;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00008765 }
8766 type->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008767 /*
8768 * Handle attributes.
8769 */
8770 attr = node->properties;
8771 while (attr != NULL) {
8772 if (attr->ns == NULL) {
8773 if (xmlStrEqual(attr->name, BAD_CAST "id")) {
8774 /*
8775 * Attribute "id".
8776 */
8777 type->id = xmlSchemaGetProp(ctxt, node, "id");
8778 } else if (xmlStrEqual(attr->name, BAD_CAST "mixed")) {
8779 /*
8780 * Attribute "mixed".
8781 */
8782 if (xmlSchemaPGetBoolNodeValue(ctxt, &des, type,
8783 (xmlNodePtr) attr))
8784 type->flags |= XML_SCHEMAS_TYPE_MIXED;
8785 } else if (topLevel) {
8786 /*
8787 * Attributes of global complex type definitions.
8788 */
8789 if (xmlStrEqual(attr->name, BAD_CAST "name")) {
8790 /* Pass. */
8791 } else if (xmlStrEqual(attr->name, BAD_CAST "abstract")) {
8792 /*
8793 * Attribute "abstract".
8794 */
8795 if (xmlSchemaPGetBoolNodeValue(ctxt, &des, type,
8796 (xmlNodePtr) attr))
8797 type->flags |= XML_SCHEMAS_TYPE_ABSTRACT;
8798 } else if (xmlStrEqual(attr->name, BAD_CAST "final")) {
8799 /*
8800 * Attribute "final".
8801 */
8802 attrValue = xmlSchemaGetNodeContent(ctxt,
8803 (xmlNodePtr) attr);
8804 if (xmlSchemaPValAttrBlockFinal(attrValue,
8805 &(type->flags),
8806 -1,
8807 XML_SCHEMAS_TYPE_FINAL_EXTENSION,
8808 XML_SCHEMAS_TYPE_FINAL_RESTRICTION,
8809 -1, -1, -1) != 0)
8810 {
8811 xmlSchemaPSimpleTypeErr(ctxt,
8812 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8813 &des, type, (xmlNodePtr) attr,
8814 NULL,
8815 "(#all | List of (extension | restriction))",
8816 attrValue, NULL, NULL, NULL);
8817 }
8818 } else if (xmlStrEqual(attr->name, BAD_CAST "block")) {
8819 /*
8820 * Attribute "block".
8821 */
8822 attrValue = xmlSchemaGetNodeContent(ctxt,
8823 (xmlNodePtr) attr);
8824 if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
8825 -1,
8826 XML_SCHEMAS_TYPE_BLOCK_EXTENSION,
8827 XML_SCHEMAS_TYPE_BLOCK_RESTRICTION,
8828 -1, -1, -1) != 0) {
8829 xmlSchemaPSimpleTypeErr(ctxt,
8830 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8831 &des, type, (xmlNodePtr) attr,
8832 NULL,
8833 "(#all | List of (extension | restriction)) ",
8834 attrValue, NULL, NULL, NULL);
8835 }
8836 } else {
8837 xmlSchemaPIllegalAttrErr(ctxt,
8838 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8839 &des, type, attr);
8840 }
8841 } else {
8842 xmlSchemaPIllegalAttrErr(ctxt,
8843 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8844 &des, type, attr);
8845 }
8846 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8847 xmlSchemaPIllegalAttrErr(ctxt,
8848 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8849 &des, type, attr);
8850 }
8851 attr = attr->next;
8852 }
8853 /*
8854 * Set as default for attribute wildcards.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008855 * This will be only changed if a complex type
8856 * inherits an attribute wildcard from a base type.
8857 */
8858 type->flags |= XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008859 /*
8860 * And now for the children...
8861 */
8862 oldcontainer = ctxt->container;
8863 ctxt->container = name;
Daniel Veillard4255d502002-04-16 15:50:10 +00008864 child = node->children;
8865 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008866 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8867 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008868 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00008869 ctxt->ctxtType = type;
Daniel Veillard4255d502002-04-16 15:50:10 +00008870 if (IS_SCHEMA(child, "simpleContent")) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008871 /*
8872 * 3.4.3 : 2.2
8873 * Specifying mixed='true' when the <simpleContent>
8874 * alternative is chosen has no effect
8875 */
William M. Bracke7091952004-05-11 15:09:58 +00008876 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
8877 type->flags ^= XML_SCHEMAS_TYPE_MIXED;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008878 type->subtypes = xmlSchemaParseSimpleContent(ctxt, schema, child);
8879 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008880 } else if (IS_SCHEMA(child, "complexContent")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008881 type->subtypes = xmlSchemaParseComplexContent(ctxt, schema, child);
8882 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008883 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008884 subtype = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008885 /*
8886 * Parse model groups.
8887 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008888 if (IS_SCHEMA(child, "all")) {
8889 subtype = xmlSchemaParseAll(ctxt, schema, child);
8890 child = child->next;
8891 } else if (IS_SCHEMA(child, "choice")) {
8892 subtype = xmlSchemaParseChoice(ctxt, schema, child);
8893 child = child->next;
8894 } else if (IS_SCHEMA(child, "sequence")) {
8895 subtype = xmlSchemaParseSequence(ctxt, schema, child);
8896 child = child->next;
8897 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00008898 subtype = xmlSchemaParseGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008899 child = child->next;
8900 }
8901 if (subtype != NULL)
8902 type->subtypes = subtype;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008903 /*
8904 * Parse attribute decls/refs.
8905 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008906 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008907 /*
8908 * Parse attribute wildcard.
8909 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008910 if (IS_SCHEMA(child, "anyAttribute")) {
8911 type->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
8912 child = child->next;
8913 }
Daniel Veillard4255d502002-04-16 15:50:10 +00008914 }
8915 if (child != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008916 xmlSchemaPContentErr(ctxt,
8917 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8918 &des, type, node, child,
8919 NULL, "(annotation?, (simpleContent | complexContent | "
8920 "((group | all | choice | sequence)?, ((attribute | "
8921 "attributeGroup)*, anyAttribute?))))");
Daniel Veillard4255d502002-04-16 15:50:10 +00008922 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008923 FREE_AND_NULL(des);
Daniel Veillard4255d502002-04-16 15:50:10 +00008924 ctxt->container = oldcontainer;
Daniel Veillard01fa6152004-06-29 17:04:39 +00008925 ctxt->ctxtType = ctxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +00008926 return (type);
8927}
8928
Daniel Veillard4255d502002-04-16 15:50:10 +00008929/**
8930 * xmlSchemaParseSchema:
8931 * @ctxt: a schema validation context
8932 * @node: a subtree containing XML Schema informations
8933 *
8934 * parse a XML schema definition from a node set
8935 * *WARNING* this interface is highly subject to change
8936 *
8937 * Returns the internal XML Schema structure built from the resource or
8938 * NULL in case of error
8939 */
8940static xmlSchemaPtr
8941xmlSchemaParseSchema(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
8942{
8943 xmlSchemaPtr schema = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008944 const xmlChar *val;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00008945 int nberrors;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008946 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00008947
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008948 /*
8949 * This one is called by xmlSchemaParse only and is used if
8950 * the schema to be parsed was specified via the API; i.e. not
8951 * automatically by the validated instance document.
8952 */
Daniel Veillard4255d502002-04-16 15:50:10 +00008953 if ((ctxt == NULL) || (node == NULL))
8954 return (NULL);
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00008955 nberrors = ctxt->nberrors;
8956 ctxt->nberrors = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00008957 if (IS_SCHEMA(node, "schema")) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008958 xmlSchemaImportPtr import;
8959
Daniel Veillard4255d502002-04-16 15:50:10 +00008960 schema = xmlSchemaNewSchema(ctxt);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008961 if (schema == NULL)
8962 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008963 /*
8964 * Disable build of list of items.
8965 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00008966 attr = xmlSchemaGetPropNode(node, "targetNamespace");
8967 if (attr != NULL) {
8968 xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
8969 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), &val);
8970 /*
8971 * TODO: Should we proceed with an invalid target namespace?
8972 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008973 schema->targetNamespace = xmlDictLookup(ctxt->dict, val, -1);
8974 } else {
8975 schema->targetNamespace = NULL;
8976 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008977 /*
8978 * Add the current ns name and location to the import table;
8979 * this is needed to have a consistent mechanism, regardless
8980 * if all schemata are constructed dynamically fired by the
8981 * instance or if the schema to be used was specified via
8982 * the API.
8983 */
8984 import = xmlSchemaAddImport(ctxt, &(schema->schemasImports),
8985 schema->targetNamespace);
8986 if (import == NULL) {
8987 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_FAILED_BUILD_IMPORT,
8988 NULL, NULL, (xmlNodePtr) ctxt->doc,
8989 "Internal error: xmlSchemaParseSchema, "
8990 "failed to add an import entry", NULL);
8991 xmlSchemaFree(schema);
8992 schema = NULL;
8993 return (NULL);
8994 }
8995 import->schemaLocation = ctxt->URL;
8996 /*
8997 * NOTE: We won't set the doc here, otherwise it will be freed
8998 * if the import struct is freed.
8999 * import->doc = ctxt->doc;
9000 */
9001
Daniel Veillardc0826a72004-08-10 14:17:33 +00009002 /* TODO: Check id. */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00009003 schema->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillardc0826a72004-08-10 14:17:33 +00009004 xmlSchemaPValAttr(ctxt, NULL, NULL, node, "version",
9005 xmlSchemaGetBuiltInType(XML_SCHEMAS_TOKEN), &(schema->version));
9006
William M. Brack2f2a6632004-08-20 23:09:47 +00009007 xmlSchemaParseSchemaDefaults(ctxt, schema, node);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009008 xmlSchemaParseSchemaTopLevel(ctxt, schema, node->children);
9009 } else {
9010 xmlDocPtr doc;
9011
9012 doc = node->doc;
9013
9014 if ((doc != NULL) && (doc->URL != NULL)) {
9015 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
9016 XML_SCHEMAP_NOT_SCHEMA,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009017 "The file \"%s\" is not a XML schema.\n", doc->URL, NULL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009018 } else {
9019 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
9020 XML_SCHEMAP_NOT_SCHEMA,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009021 "The file is not a XML schema.\n", NULL, NULL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009022 }
9023 return(NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00009024 }
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00009025 if (ctxt->nberrors != 0) {
9026 if (schema != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009027 xmlSchemaFree(schema);
9028 schema = NULL;
9029 }
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00009030 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009031 if (schema != NULL)
9032 schema->counter = ctxt->counter;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00009033 ctxt->nberrors = nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +00009034#ifdef DEBUG
9035 if (schema == NULL)
9036 xmlGenericError(xmlGenericErrorContext,
9037 "xmlSchemaParse() failed\n");
9038#endif
Daniel Veillard4255d502002-04-16 15:50:10 +00009039 return (schema);
9040}
9041
9042/************************************************************************
9043 * *
9044 * Validating using Schemas *
9045 * *
9046 ************************************************************************/
9047
9048/************************************************************************
9049 * *
9050 * Reading/Writing Schemas *
9051 * *
9052 ************************************************************************/
9053
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009054#if 0 /* Will be enabled if it is clear what options are needed. */
9055/**
9056 * xmlSchemaParserCtxtSetOptions:
9057 * @ctxt: a schema parser context
9058 * @options: a combination of xmlSchemaParserOption
9059 *
9060 * Sets the options to be used during the parse.
9061 *
9062 * Returns 0 in case of success, -1 in case of an
9063 * API error.
9064 */
9065static int
9066xmlSchemaParserCtxtSetOptions(xmlSchemaParserCtxtPtr ctxt,
9067 int options)
9068
9069{
9070 int i;
9071
9072 if (ctxt == NULL)
9073 return (-1);
9074 /*
9075 * WARNING: Change the start value if adding to the
9076 * xmlSchemaParseOption.
9077 */
9078 for (i = 1; i < (int) sizeof(int) * 8; i++) {
9079 if (options & 1<<i) {
9080 return (-1);
9081 }
9082 }
9083 ctxt->options = options;
9084 return (0);
9085}
9086
9087/**
9088 * xmlSchemaValidCtxtGetOptions:
9089 * @ctxt: a schema parser context
9090 *
9091 * Returns the option combination of the parser context.
9092 */
9093static int
9094xmlSchemaParserCtxtGetOptions(xmlSchemaParserCtxtPtr ctxt)
9095
9096{
9097 if (ctxt == NULL)
9098 return (-1);
9099 else
9100 return (ctxt->options);
9101}
9102
9103 void *curItems; /* used for dynamic addition of schemata */
9104 int nbCurItems; /* used for dynamic addition of schemata */
9105 int sizeCurItems; /* used for dynamic addition of schemata */
9106
9107#endif
9108
Daniel Veillard4255d502002-04-16 15:50:10 +00009109/**
9110 * xmlSchemaNewParserCtxt:
9111 * @URL: the location of the schema
9112 *
9113 * Create an XML Schemas parse context for that file/resource expected
9114 * to contain an XML Schemas file.
9115 *
9116 * Returns the parser context or NULL in case of error
9117 */
9118xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009119xmlSchemaNewParserCtxt(const char *URL)
9120{
Daniel Veillard4255d502002-04-16 15:50:10 +00009121 xmlSchemaParserCtxtPtr ret;
9122
9123 if (URL == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009124 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00009125
9126 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
9127 if (ret == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009128 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009129 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00009130 return (NULL);
9131 }
9132 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00009133 ret->dict = xmlDictCreate();
9134 ret->URL = xmlDictLookup(ret->dict, (const xmlChar *) URL, -1);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00009135 ret->includes = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00009136 return (ret);
9137}
9138
9139/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009140 * xmlSchemaNewParserCtxtUseDict:
9141 * @URL: the location of the schema
9142 * @dict: the dictionary to be used
9143 *
9144 * Create an XML Schemas parse context for that file/resource expected
9145 * to contain an XML Schemas file.
9146 *
9147 * Returns the parser context or NULL in case of error
9148 */
9149static xmlSchemaParserCtxtPtr
9150xmlSchemaNewParserCtxtUseDict(const char *URL, xmlDictPtr dict)
9151{
9152 xmlSchemaParserCtxtPtr ret;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009153 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009154 if (URL == NULL)
9155 return (NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009156 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009157
9158 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
9159 if (ret == NULL) {
9160 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
9161 NULL);
9162 return (NULL);
9163 }
9164 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
9165 ret->dict = dict;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009166 xmlDictReference(dict);
9167 if (URL != NULL)
9168 ret->URL = xmlDictLookup(dict, (const xmlChar *) URL, -1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009169 ret->includes = 0;
9170 return (ret);
9171}
9172
9173
9174/**
Daniel Veillard6045c902002-10-09 21:13:59 +00009175 * xmlSchemaNewMemParserCtxt:
9176 * @buffer: a pointer to a char array containing the schemas
9177 * @size: the size of the array
9178 *
9179 * Create an XML Schemas parse context for that memory buffer expected
9180 * to contain an XML Schemas file.
9181 *
9182 * Returns the parser context or NULL in case of error
9183 */
9184xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009185xmlSchemaNewMemParserCtxt(const char *buffer, int size)
9186{
Daniel Veillard6045c902002-10-09 21:13:59 +00009187 xmlSchemaParserCtxtPtr ret;
9188
9189 if ((buffer == NULL) || (size <= 0))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009190 return (NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +00009191
9192 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
9193 if (ret == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009194 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009195 NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +00009196 return (NULL);
9197 }
9198 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
9199 ret->buffer = buffer;
9200 ret->size = size;
William M. Brackcf9eadf2003-12-25 13:24:05 +00009201 ret->dict = xmlDictCreate();
Daniel Veillard6045c902002-10-09 21:13:59 +00009202 return (ret);
9203}
9204
9205/**
Daniel Veillard9d751502003-10-29 13:21:47 +00009206 * xmlSchemaNewDocParserCtxt:
9207 * @doc: a preparsed document tree
9208 *
9209 * Create an XML Schemas parse context for that document.
9210 * NB. The document may be modified during the parsing process.
9211 *
9212 * Returns the parser context or NULL in case of error
9213 */
9214xmlSchemaParserCtxtPtr
9215xmlSchemaNewDocParserCtxt(xmlDocPtr doc)
9216{
9217 xmlSchemaParserCtxtPtr ret;
9218
9219 if (doc == NULL)
9220 return (NULL);
9221
9222 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
9223 if (ret == NULL) {
9224 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
9225 NULL);
9226 return (NULL);
9227 }
9228 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
9229 ret->doc = doc;
William M. Brackcf9eadf2003-12-25 13:24:05 +00009230 ret->dict = xmlDictCreate();
Daniel Veillarddda22c12004-01-24 08:31:30 +00009231 /* The application has responsibility for the document */
9232 ret->preserve = 1;
Daniel Veillard9d751502003-10-29 13:21:47 +00009233
9234 return (ret);
9235}
9236
9237/**
Daniel Veillard4255d502002-04-16 15:50:10 +00009238 * xmlSchemaFreeParserCtxt:
9239 * @ctxt: the schema parser context
9240 *
9241 * Free the resources associated to the schema parser context
9242 */
9243void
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009244xmlSchemaFreeParserCtxt(xmlSchemaParserCtxtPtr ctxt)
9245{
Daniel Veillard4255d502002-04-16 15:50:10 +00009246 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009247 return;
Daniel Veillarddda22c12004-01-24 08:31:30 +00009248 if (ctxt->doc != NULL && !ctxt->preserve)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009249 xmlFreeDoc(ctxt->doc);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009250 if (ctxt->assemble != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009251 xmlFree((xmlSchemaTypePtr *) ctxt->assemble->items);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009252 xmlFree(ctxt->assemble);
9253 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009254 if (ctxt->vctxt != NULL) {
9255 xmlSchemaFreeValidCtxt(ctxt->vctxt);
9256 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00009257 xmlDictFree(ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00009258 xmlFree(ctxt);
9259}
9260
9261/************************************************************************
9262 * *
9263 * Building the content models *
9264 * *
9265 ************************************************************************/
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009266
Daniel Veillard4255d502002-04-16 15:50:10 +00009267/**
9268 * xmlSchemaBuildAContentModel:
9269 * @type: the schema type definition
9270 * @ctxt: the schema parser context
9271 * @name: the element name whose content is being built
9272 *
9273 * Generate the automata sequence needed for that type
9274 */
9275static void
9276xmlSchemaBuildAContentModel(xmlSchemaTypePtr type,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009277 xmlSchemaParserCtxtPtr ctxt,
9278 const xmlChar * name)
9279{
Daniel Veillard4255d502002-04-16 15:50:10 +00009280 if (type == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009281 xmlGenericError(xmlGenericErrorContext,
9282 "Found unexpected type = NULL in %s content model\n",
9283 name);
9284 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00009285 }
9286 switch (type->type) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009287 case XML_SCHEMA_TYPE_ANY: {
9288 xmlAutomataStatePtr start, end;
9289 xmlSchemaWildcardPtr wild;
9290 xmlSchemaWildcardNsPtr ns;
Daniel Veillard32370232002-10-16 14:08:14 +00009291
Daniel Veillardc0826a72004-08-10 14:17:33 +00009292 wild = type->attributeWildcard;
9293
9294 if (wild == NULL) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00009295 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009296 "Internal error: xmlSchemaBuildAContentModel, "
9297 "no wildcard on xsd:any.\n", NULL, NULL);
9298 return;
9299 }
9300
9301 start = ctxt->state;
9302 end = xmlAutomataNewState(ctxt->am);
9303
9304 if (type->maxOccurs == 1) {
9305 if (wild->any == 1) {
9306 /*
9307 * We need to add both transitions:
9308 *
9309 * 1. the {"*", "*"} for elements in a namespace.
9310 */
9311 ctxt->state =
9312 xmlAutomataNewTransition2(ctxt->am,
9313 start, NULL, BAD_CAST "*", BAD_CAST "*", type);
9314 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
9315 /*
9316 * 2. the {"*"} for elements in no namespace.
9317 */
9318 ctxt->state =
9319 xmlAutomataNewTransition2(ctxt->am,
9320 start, NULL, BAD_CAST "*", NULL, type);
9321 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
9322
9323 } else if (wild->nsSet != NULL) {
9324 ns = wild->nsSet;
9325 do {
9326 ctxt->state = start;
9327 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
9328 ctxt->state, NULL, BAD_CAST "*", ns->value, type);
9329 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
9330 ns = ns->next;
9331 } while (ns != NULL);
9332
9333 } else if (wild->negNsSet != NULL) {
9334 xmlAutomataStatePtr deadEnd;
9335
9336 deadEnd = xmlAutomataNewState(ctxt->am);
9337 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
9338 start, deadEnd, BAD_CAST "*", wild->negNsSet->value, type);
9339 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
9340 start, NULL, BAD_CAST "*", BAD_CAST "*", type);
9341 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
9342 }
9343 } else {
9344 int counter;
9345 xmlAutomataStatePtr hop;
9346 int maxOccurs =
9347 type->maxOccurs == UNBOUNDED ? UNBOUNDED : type->maxOccurs - 1;
9348 int minOccurs =
9349 type->minOccurs < 1 ? 0 : type->minOccurs - 1;
9350
9351 counter = xmlAutomataNewCounter(ctxt->am, minOccurs, maxOccurs);
9352 hop = xmlAutomataNewState(ctxt->am);
9353 if (wild->any == 1) {
9354 ctxt->state =
9355 xmlAutomataNewTransition2(ctxt->am,
9356 start, NULL, BAD_CAST "*", BAD_CAST "*", type);
9357 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
9358 ctxt->state =
9359 xmlAutomataNewTransition2(ctxt->am,
9360 start, NULL, BAD_CAST "*", NULL, type);
9361 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
9362 } else if (wild->nsSet != NULL) {
9363 ns = wild->nsSet;
9364 do {
9365 ctxt->state =
9366 xmlAutomataNewTransition2(ctxt->am,
9367 start, NULL, BAD_CAST "*", ns->value, type);
9368 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
9369 ns = ns->next;
9370 } while (ns != NULL);
9371
9372 } else if (wild->negNsSet != NULL) {
9373 xmlAutomataStatePtr deadEnd;
9374
9375 deadEnd = xmlAutomataNewState(ctxt->am);
9376 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
9377 start, deadEnd, BAD_CAST "*", wild->negNsSet->value, type);
9378 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
9379 start, NULL, BAD_CAST "*", BAD_CAST "*", type);
9380 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
9381 }
9382 xmlAutomataNewCountedTrans(ctxt->am, hop, start, counter);
9383 xmlAutomataNewCounterTrans(ctxt->am, hop, end, counter);
9384 }
9385 if (type->minOccurs == 0) {
9386 xmlAutomataNewEpsilon(ctxt->am, start, end);
9387 }
9388 ctxt->state = end;
9389 break;
9390 }
9391 case XML_SCHEMA_TYPE_ELEMENT:{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009392 xmlAutomataStatePtr oldstate;
9393 xmlSchemaElementPtr particle, elemDecl;
Daniel Veillard32370232002-10-16 14:08:14 +00009394
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009395 /*
9396 * IMPORTANT: This puts element declarations
9397 * (and never element decl. references) into the
9398 * automaton. This is crucial and should not be changed,
9399 * since validating functions rely now on it.
9400 */
9401 particle = (xmlSchemaElementPtr) type;
9402 if (particle->ref != NULL) {
9403 if (particle->refDecl == NULL) {
9404 /*
9405 * Skip content model creation if the reference
9406 * did not resolve to a declaration.
9407 */
9408 break;
9409 } else {
9410 /*
9411 * Referenced global element declaration.
9412 */
9413 elemDecl = particle->refDecl;
9414 }
9415 } else {
9416 /*
9417 * Anonymous element declaration.
9418 */
9419 elemDecl = particle;
9420 }
9421
9422 oldstate = ctxt->state;
9423
9424 if (particle->maxOccurs >= UNBOUNDED) {
9425 if (particle->minOccurs > 1) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009426 xmlAutomataStatePtr tmp;
9427 int counter;
Daniel Veillard32370232002-10-16 14:08:14 +00009428
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009429 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009430 oldstate, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009431 oldstate = ctxt->state;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009432 counter = xmlAutomataNewCounter(ctxt->am,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009433 particle->minOccurs - 1, UNBOUNDED);
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00009434 ctxt->state =
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009435 xmlAutomataNewTransition2(ctxt->am,
9436 ctxt->state, NULL,
9437 elemDecl->name,
9438 elemDecl->targetNamespace,
9439 (xmlSchemaTypePtr) elemDecl);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009440 tmp = ctxt->state;
9441 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009442 counter);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009443 ctxt->state =
9444 xmlAutomataNewCounterTrans(ctxt->am, tmp, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009445 counter);
Daniel Veillard32370232002-10-16 14:08:14 +00009446
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009447 } else {
9448 ctxt->state =
9449 xmlAutomataNewTransition2(ctxt->am,
9450 ctxt->state, NULL,
9451 elemDecl->name,
9452 elemDecl->targetNamespace,
9453 (xmlSchemaTypePtr) elemDecl);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009454 xmlAutomataNewEpsilon(ctxt->am, ctxt->state,
9455 oldstate);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009456 if (particle->minOccurs == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009457 /* basically an elem* */
9458 xmlAutomataNewEpsilon(ctxt->am, oldstate,
9459 ctxt->state);
9460 }
9461 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009462 } else if ((particle->maxOccurs > 1) || (particle->minOccurs > 1)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009463 xmlAutomataStatePtr tmp;
9464 int counter;
Daniel Veillard32370232002-10-16 14:08:14 +00009465
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009466 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
9467 oldstate, NULL);
9468 oldstate = ctxt->state;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009469 counter = xmlAutomataNewCounter(ctxt->am,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009470 particle->minOccurs - 1,
9471 particle->maxOccurs - 1);
9472 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
9473 ctxt->state,
9474 NULL,
9475 elemDecl->name,
9476 elemDecl->targetNamespace,
9477 (xmlSchemaTypePtr) elemDecl);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009478 tmp = ctxt->state;
9479 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009480 counter);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009481 ctxt->state = xmlAutomataNewCounterTrans(ctxt->am, tmp,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009482 NULL, counter);
9483 if (particle->minOccurs == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009484 /* basically an elem? */
9485 xmlAutomataNewEpsilon(ctxt->am, oldstate,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009486 ctxt->state);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009487 }
Daniel Veillardb39bc392002-10-26 19:29:51 +00009488
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009489 } else {
9490 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
9491 ctxt->state,
9492 NULL,
9493 elemDecl->name,
9494 elemDecl->targetNamespace,
9495 (xmlSchemaTypePtr) elemDecl);
9496 if (particle->minOccurs == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009497 /* basically an elem? */
9498 xmlAutomataNewEpsilon(ctxt->am, oldstate,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009499 ctxt->state);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009500 }
9501 }
9502 break;
9503 }
9504 case XML_SCHEMA_TYPE_SEQUENCE:{
9505 xmlSchemaTypePtr subtypes;
Daniel Veillardb39bc392002-10-26 19:29:51 +00009506
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009507 /*
9508 * If max and min occurances are default (1) then
9509 * simply iterate over the subtypes
9510 */
9511 if ((type->minOccurs == 1) && (type->maxOccurs == 1)) {
9512 subtypes = type->subtypes;
9513 while (subtypes != NULL) {
9514 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
9515 subtypes = subtypes->next;
9516 }
9517 } else {
9518 xmlAutomataStatePtr oldstate = ctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +00009519
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009520 if (type->maxOccurs >= UNBOUNDED) {
9521 if (type->minOccurs > 1) {
9522 xmlAutomataStatePtr tmp;
9523 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +00009524
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009525 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
9526 oldstate,
9527 NULL);
9528 oldstate = ctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +00009529
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009530 counter = xmlAutomataNewCounter(ctxt->am,
9531 type->
9532 minOccurs - 1,
9533 UNBOUNDED);
Daniel Veillardb39bc392002-10-26 19:29:51 +00009534
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009535 subtypes = type->subtypes;
9536 while (subtypes != NULL) {
9537 xmlSchemaBuildAContentModel(subtypes, ctxt,
9538 name);
9539 subtypes = subtypes->next;
9540 }
9541 tmp = ctxt->state;
9542 xmlAutomataNewCountedTrans(ctxt->am, tmp,
9543 oldstate, counter);
9544 ctxt->state =
9545 xmlAutomataNewCounterTrans(ctxt->am, tmp,
9546 NULL, counter);
Daniel Veillardb39bc392002-10-26 19:29:51 +00009547
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009548 } else {
9549 subtypes = type->subtypes;
9550 while (subtypes != NULL) {
9551 xmlSchemaBuildAContentModel(subtypes, ctxt,
9552 name);
9553 subtypes = subtypes->next;
9554 }
9555 xmlAutomataNewEpsilon(ctxt->am, ctxt->state,
9556 oldstate);
9557 if (type->minOccurs == 0) {
9558 xmlAutomataNewEpsilon(ctxt->am, oldstate,
9559 ctxt->state);
9560 }
9561 }
9562 } else if ((type->maxOccurs > 1)
9563 || (type->minOccurs > 1)) {
9564 xmlAutomataStatePtr tmp;
9565 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +00009566
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009567 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
9568 oldstate,
9569 NULL);
9570 oldstate = ctxt->state;
Daniel Veillard4255d502002-04-16 15:50:10 +00009571
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009572 counter = xmlAutomataNewCounter(ctxt->am,
9573 type->minOccurs -
9574 1,
9575 type->maxOccurs -
9576 1);
Daniel Veillard4255d502002-04-16 15:50:10 +00009577
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009578 subtypes = type->subtypes;
9579 while (subtypes != NULL) {
9580 xmlSchemaBuildAContentModel(subtypes, ctxt,
9581 name);
9582 subtypes = subtypes->next;
9583 }
9584 tmp = ctxt->state;
9585 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
9586 counter);
9587 ctxt->state =
9588 xmlAutomataNewCounterTrans(ctxt->am, tmp, NULL,
9589 counter);
9590 if (type->minOccurs == 0) {
9591 xmlAutomataNewEpsilon(ctxt->am, oldstate,
9592 ctxt->state);
9593 }
Daniel Veillardb509f152002-04-17 16:28:10 +00009594
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009595 } else {
9596 subtypes = type->subtypes;
9597 while (subtypes != NULL) {
9598 xmlSchemaBuildAContentModel(subtypes, ctxt,
9599 name);
9600 subtypes = subtypes->next;
9601 }
9602 if (type->minOccurs == 0) {
9603 xmlAutomataNewEpsilon(ctxt->am, oldstate,
9604 ctxt->state);
9605 }
9606 }
9607 }
9608 break;
9609 }
9610 case XML_SCHEMA_TYPE_CHOICE:{
9611 xmlSchemaTypePtr subtypes;
9612 xmlAutomataStatePtr start, end;
Daniel Veillardb509f152002-04-17 16:28:10 +00009613
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009614 start = ctxt->state;
9615 end = xmlAutomataNewState(ctxt->am);
Daniel Veillard7646b182002-04-20 06:41:40 +00009616
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009617 /*
9618 * iterate over the subtypes and remerge the end with an
9619 * epsilon transition
9620 */
9621 if (type->maxOccurs == 1) {
9622 subtypes = type->subtypes;
9623 while (subtypes != NULL) {
9624 ctxt->state = start;
9625 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
9626 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
9627 subtypes = subtypes->next;
9628 }
9629 } else {
9630 int counter;
9631 xmlAutomataStatePtr hop;
9632 int maxOccurs = type->maxOccurs == UNBOUNDED ?
9633 UNBOUNDED : type->maxOccurs - 1;
9634 int minOccurs =
9635 type->minOccurs < 1 ? 0 : type->minOccurs - 1;
Daniel Veillard7646b182002-04-20 06:41:40 +00009636
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009637 /*
9638 * use a counter to keep track of the number of transtions
9639 * which went through the choice.
9640 */
9641 counter =
9642 xmlAutomataNewCounter(ctxt->am, minOccurs,
9643 maxOccurs);
9644 hop = xmlAutomataNewState(ctxt->am);
Daniel Veillard6231e842002-04-18 11:54:04 +00009645
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009646 subtypes = type->subtypes;
9647 while (subtypes != NULL) {
9648 ctxt->state = start;
9649 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
9650 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
9651 subtypes = subtypes->next;
9652 }
9653 xmlAutomataNewCountedTrans(ctxt->am, hop, start,
9654 counter);
9655 xmlAutomataNewCounterTrans(ctxt->am, hop, end,
9656 counter);
9657 }
9658 if (type->minOccurs == 0) {
9659 xmlAutomataNewEpsilon(ctxt->am, start, end);
9660 }
9661 ctxt->state = end;
9662 break;
9663 }
9664 case XML_SCHEMA_TYPE_ALL:{
9665 xmlAutomataStatePtr start;
9666 xmlSchemaTypePtr subtypes;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009667
Daniel Veillard3646d642004-06-02 19:19:14 +00009668 xmlSchemaElementPtr elem;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009669 int lax;
9670
9671 subtypes = type->subtypes;
9672 if (subtypes == NULL)
9673 break;
9674 start = ctxt->state;
9675 while (subtypes != NULL) {
9676 ctxt->state = start;
William M. Brack9989c7d2004-05-12 14:39:38 +00009677 /*
9678 * the following 'if' was needed to fix bug 139897
9679 * not quite sure why it only needs to be done for
9680 * elements with a 'ref', but it seems to work ok.
9681 */
9682 if (subtypes->ref != NULL)
9683 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009684 elem = (xmlSchemaElementPtr) subtypes;
9685 /*
9686 * NOTE: The {max occurs} of all the particles in the
9687 * {particles} of the group must be 0 or 1.
9688 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009689 if ((elem->minOccurs == 1) && (elem->maxOccurs == 1)) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009690 xmlAutomataNewOnceTrans2(ctxt->am, ctxt->state,
9691 ctxt->state,
9692 elem->name,
9693 elem->targetNamespace,
9694 1, 1, subtypes);
9695 } else if ((elem->minOccurs == 0) &&
9696 (elem->maxOccurs == 1)) {
9697
9698 xmlAutomataNewCountTrans2(ctxt->am, ctxt->state,
9699 ctxt->state,
9700 elem->name,
9701 elem->targetNamespace,
9702 0,
9703 1,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009704 subtypes);
9705 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009706 /*
9707 * NOTE: if maxOccurs == 0 then no transition will be
9708 * created.
9709 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009710 subtypes = subtypes->next;
9711 }
9712 lax = type->minOccurs == 0;
9713 ctxt->state =
9714 xmlAutomataNewAllTrans(ctxt->am, ctxt->state, NULL,
9715 lax);
9716 break;
9717 }
9718 case XML_SCHEMA_TYPE_RESTRICTION:
9719 if (type->subtypes != NULL)
9720 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
9721 break;
9722 case XML_SCHEMA_TYPE_EXTENSION:
9723 if (type->baseType != NULL) {
9724 xmlSchemaTypePtr subtypes;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009725
9726 /*
9727 * TODO: Circular definitions will be checked at the
9728 * constraint level. So remove this when the complex type
9729 * constraints are implemented.
9730 */
Daniel Veillardf7627552004-04-22 07:15:40 +00009731 if (type->recurse) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009732 /* TODO: Change the error code. */
9733 xmlSchemaPCustomErr(ctxt,
9734 XML_SCHEMAP_UNKNOWN_BASE_TYPE,
9735 NULL, type, type->node,
9736 "This item is circular", NULL);
Daniel Veillardf7627552004-04-22 07:15:40 +00009737 return;
9738 }
9739 type->recurse = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009740 xmlSchemaBuildAContentModel(type->baseType, ctxt, name);
Daniel Veillardf7627552004-04-22 07:15:40 +00009741 type->recurse = 0;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009742 subtypes = type->subtypes;
9743 while (subtypes != NULL) {
9744 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
9745 subtypes = subtypes->next;
9746 }
9747 } else if (type->subtypes != NULL)
9748 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
9749 break;
9750 case XML_SCHEMA_TYPE_GROUP:
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00009751 /*
9752 * Handle model group definition references.
9753 * NOTE: type->subtypes is the referenced model grop definition;
9754 * and type->subtypes->subtypes is the model group (i.e. <all> or
9755 * <choice> or <sequence>).
9756 */
9757 if ((type->ref != NULL) && (type->subtypes != NULL) &&
9758 (type->subtypes->subtypes != NULL)) {
9759 xmlSchemaTypePtr modelGr;
9760 xmlAutomataStatePtr start, end;
9761
9762 modelGr = type->subtypes->subtypes;
9763 start = ctxt->state;
9764 end = xmlAutomataNewState(ctxt->am);
9765 if (type->maxOccurs == 1) {
9766 ctxt->state = start;
9767 xmlSchemaBuildAContentModel(modelGr, ctxt, name);
9768 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
9769 } else {
9770 int counter;
9771 xmlAutomataStatePtr hop;
9772 int maxOccurs = type->maxOccurs == UNBOUNDED ?
9773 UNBOUNDED : type->maxOccurs - 1;
9774 int minOccurs =
9775 type->minOccurs < 1 ? 0 : type->minOccurs - 1;
9776
9777 counter =
9778 xmlAutomataNewCounter(ctxt->am, minOccurs, maxOccurs);
9779 hop = xmlAutomataNewState(ctxt->am);
9780 ctxt->state = start;
9781 xmlSchemaBuildAContentModel(modelGr, ctxt, name);
9782 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
9783 xmlAutomataNewCountedTrans(ctxt->am, hop, start,
9784 counter);
9785 xmlAutomataNewCounterTrans(ctxt->am, hop, end,
9786 counter);
9787 }
9788 if (type->minOccurs == 0) {
9789 xmlAutomataNewEpsilon(ctxt->am, start, end);
9790 }
9791 ctxt->state = end;
9792 break;
9793 }
9794 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009795 case XML_SCHEMA_TYPE_COMPLEX:
9796 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:
9797 if (type->subtypes != NULL)
9798 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
9799 break;
William M. Brack2f2a6632004-08-20 23:09:47 +00009800 case XML_SCHEMA_TYPE_SIMPLE_CONTENT:
9801 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009802 default:
9803 xmlGenericError(xmlGenericErrorContext,
9804 "Found unexpected type %d in %s content model\n",
9805 type->type, name);
9806 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00009807 }
9808}
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009809
Daniel Veillard4255d502002-04-16 15:50:10 +00009810/**
9811 * xmlSchemaBuildContentModel:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009812 * @type: the type definition (or reference)
Daniel Veillard4255d502002-04-16 15:50:10 +00009813 * @ctxt: the schema parser context
Daniel Veillarda84c0b32003-06-02 16:58:46 +00009814 * @name: the element name
Daniel Veillard4255d502002-04-16 15:50:10 +00009815 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009816 * Builds the content model of the complex type.
Daniel Veillard4255d502002-04-16 15:50:10 +00009817 */
9818static void
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009819xmlSchemaBuildContentModel(xmlSchemaTypePtr type,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009820 xmlSchemaParserCtxtPtr ctxt,
9821 const xmlChar * name)
9822{
Daniel Veillard4255d502002-04-16 15:50:10 +00009823 xmlAutomataStatePtr start;
9824
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009825 if ((type->type != XML_SCHEMA_TYPE_COMPLEX) || (type->ref != NULL) ||
9826 (type->contentType == XML_SCHEMA_CONTENT_BASIC) ||
9827 (type->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
9828 (type->contModel != NULL))
9829 return;
Daniel Veillarddecd64d2002-04-18 14:41:51 +00009830
9831#ifdef DEBUG_CONTENT
9832 xmlGenericError(xmlGenericErrorContext,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009833 "Building content model for %s\n", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +00009834#endif
9835
Daniel Veillard4255d502002-04-16 15:50:10 +00009836 ctxt->am = xmlNewAutomata();
9837 if (ctxt->am == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009838 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009839 "Cannot create automata for complex tpye %s\n", name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009840 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00009841 }
9842 start = ctxt->state = xmlAutomataGetInitState(ctxt->am);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009843 xmlSchemaBuildAContentModel(type, ctxt, name);
Daniel Veillard4255d502002-04-16 15:50:10 +00009844 xmlAutomataSetFinalState(ctxt->am, ctxt->state);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009845 type->contModel = xmlAutomataCompile(ctxt->am);
9846 if (type->contModel == NULL) {
9847 xmlSchemaPCustomErr(ctxt,
9848 XML_SCHEMAP_INTERNAL,
9849 NULL, type, type->node,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009850 "Failed to compile the content model", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009851 } else if (xmlRegexpIsDeterminist(type->contModel) != 1) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00009852 xmlSchemaPCustomErr(ctxt,
9853 XML_SCHEMAP_NOT_DETERMINISTIC,
9854 /* XML_SCHEMAS_ERR_NOTDETERMINIST, */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009855 NULL, type, type->node,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009856 "The content model is not determinist", NULL);
Daniel Veillarde19fc232002-04-22 16:01:24 +00009857 } else {
Daniel Veillard118aed72002-09-24 14:13:13 +00009858#ifdef DEBUG_CONTENT_REGEXP
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009859 xmlGenericError(xmlGenericErrorContext,
9860 "Content model of %s:\n", name);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009861 xmlRegexpPrint(stderr, type->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +00009862#endif
Daniel Veillarde19fc232002-04-22 16:01:24 +00009863 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +00009864 ctxt->state = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00009865 xmlFreeAutomata(ctxt->am);
9866 ctxt->am = NULL;
9867}
9868
9869/**
9870 * xmlSchemaRefFixupCallback:
9871 * @elem: the schema element context
9872 * @ctxt: the schema parser context
9873 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00009874 * Resolves the references of an element declaration
9875 * or particle, which has an element declaration as it's
9876 * term.
Daniel Veillard4255d502002-04-16 15:50:10 +00009877 */
9878static void
9879xmlSchemaRefFixupCallback(xmlSchemaElementPtr elem,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009880 xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009881 const xmlChar * name ATTRIBUTE_UNUSED,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009882 const xmlChar * context ATTRIBUTE_UNUSED,
9883 const xmlChar * namespace ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +00009884{
Daniel Veillardc0826a72004-08-10 14:17:33 +00009885 if ((ctxt == NULL) || (elem == NULL) ||
9886 ((elem != NULL) && (elem->flags & XML_SCHEMAS_ELEM_INTERNAL_RESOLVED)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009887 return;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009888 elem->flags |= XML_SCHEMAS_ELEM_INTERNAL_RESOLVED;
Daniel Veillard4255d502002-04-16 15:50:10 +00009889 if (elem->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009890 xmlSchemaElementPtr elemDecl;
Daniel Veillard4255d502002-04-16 15:50:10 +00009891
Daniel Veillardc0826a72004-08-10 14:17:33 +00009892 /*
9893 * TODO: Evaluate, what errors could occur if the declaration is not
9894 * found. It might be possible that the "typefixup" might crash if
9895 * no ref declaration was found.
9896 */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00009897 elemDecl = xmlSchemaGetElem(ctxt->schema, elem->ref, elem->refNs);
Daniel Veillardc0826a72004-08-10 14:17:33 +00009898 if (elemDecl == NULL) {
9899 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +00009900 XML_SCHEMAP_SRC_RESOLVE,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009901 NULL, (xmlSchemaTypePtr) elem, elem->node,
9902 "ref", elem->ref, elem->refNs,
9903 XML_SCHEMA_TYPE_ELEMENT, NULL);
9904 } else
9905 elem->refDecl = elemDecl;
9906 } else {
9907 if ((elem->subtypes == NULL) && (elem->namedType != NULL)) {
9908 xmlSchemaTypePtr type;
9909
9910 /* (type definition) ... otherwise the type definition ·resolved·
9911 * to by the ·actual value· of the type [attribute] ...
9912 */
9913 type = xmlSchemaGetType(ctxt->schema, elem->namedType,
9914 elem->namedTypeNs);
9915 if (type == NULL) {
9916 xmlSchemaPResCompAttrErr(ctxt,
9917 XML_SCHEMAP_SRC_RESOLVE,
9918 NULL, (xmlSchemaTypePtr) elem, elem->node,
9919 "type", elem->namedType, elem->namedTypeNs,
9920 XML_SCHEMA_TYPE_BASIC, "type definition");
9921 } else
9922 elem->subtypes = type;
9923 }
9924 if (elem->substGroup != NULL) {
9925 xmlSchemaElementPtr substHead;
9926
9927 /*
9928 * FIXME TODO: Do we need a new field in _xmlSchemaElement for
9929 * substitutionGroup?
9930 */
9931 substHead = xmlSchemaGetElem(ctxt->schema, elem->substGroup,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00009932 elem->substGroupNs);
Daniel Veillardc0826a72004-08-10 14:17:33 +00009933 if (substHead == NULL) {
9934 xmlSchemaPResCompAttrErr(ctxt,
9935 XML_SCHEMAP_SRC_RESOLVE,
9936 NULL, (xmlSchemaTypePtr) elem, NULL,
9937 "substitutionGroup", elem->substGroup, elem->substGroupNs,
9938 XML_SCHEMA_TYPE_ELEMENT, NULL);
9939 } else {
9940 xmlSchemaRefFixupCallback(substHead, ctxt, NULL, NULL, NULL);
9941 /*
9942 * (type definition)...otherwise the {type definition} of the
9943 * element declaration ·resolved· to by the ·actual value· of
9944 * the substitutionGroup [attribute], if present
9945 */
9946 if (elem->subtypes == NULL)
9947 elem->subtypes = substHead->subtypes;
9948 }
9949 }
9950 if ((elem->subtypes == NULL) && (elem->namedType == NULL) &&
9951 (elem->substGroup == NULL))
9952 elem->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
9953 }
Daniel Veillard4255d502002-04-16 15:50:10 +00009954}
9955
William M. Bracke7091952004-05-11 15:09:58 +00009956/**
9957 * xmlSchemaParseListRefFixup:
9958 * @type: the schema type definition
9959 * @ctxt: the schema parser context
9960 *
9961 * Fixup of the itemType reference of the list type.
9962 */
Daniel Veillard377e1a92004-04-16 16:30:05 +00009963static void
William M. Bracke7091952004-05-11 15:09:58 +00009964xmlSchemaParseListRefFixup(xmlSchemaTypePtr type, xmlSchemaParserCtxtPtr ctxt)
Daniel Veillard01fa6152004-06-29 17:04:39 +00009965{
Daniel Veillardc0826a72004-08-10 14:17:33 +00009966
Daniel Veillard01fa6152004-06-29 17:04:39 +00009967 if (((type->base == NULL) &&
9968 (type->subtypes == NULL)) ||
9969 ((type->base != NULL) &&
9970 (type->subtypes != NULL))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009971 /*
9972 * src-list-itemType-or-simpleType
9973 * Either the itemType [attribute] or the <simpleType> [child] of
9974 * the <list> element must be present, but not both.
Daniel Veillard01fa6152004-06-29 17:04:39 +00009975 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00009976 /*
9977 * TODO: Move this to the parse function.
9978 */
9979 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +00009980 XML_SCHEMAP_SRC_LIST_ITEMTYPE_OR_SIMPLETYPE,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009981 NULL, type, type->node,
9982 "The attribute 'itemType' and the <simpleType> child "
9983 "are mutually exclusive", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00009984 } else if (type->base!= NULL) {
9985 type->subtypes = xmlSchemaGetType(ctxt->schema, type->base, type->baseNs);
9986 if (type->subtypes == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009987 xmlSchemaPResCompAttrErr(ctxt,
9988 XML_SCHEMAP_SRC_RESOLVE,
9989 NULL, type, type->node,
9990 "itemType", type->base, type->baseNs,
9991 XML_SCHEMA_TYPE_SIMPLE, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00009992 }
9993 }
9994 if ((type->subtypes != NULL) &&
9995 (type->subtypes->contentType == XML_SCHEMA_CONTENT_UNKNOWN))
9996 xmlSchemaTypeFixup(type->subtypes, ctxt, NULL);
William M. Bracke7091952004-05-11 15:09:58 +00009997}
9998
9999/**
10000 * xmlSchemaParseUnionRefCheck:
10001 * @typeDecl: the schema type definition
10002 * @ctxt: the schema parser context
10003 *
Daniel Veillard01fa6152004-06-29 17:04:39 +000010004 * Checks and builds the memberTypes of the union type.
10005 * Returns -1 in case of an internal error, 0 otherwise.
William M. Bracke7091952004-05-11 15:09:58 +000010006 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000010007static int
William M. Bracke7091952004-05-11 15:09:58 +000010008xmlSchemaParseUnionRefCheck(xmlSchemaTypePtr type,
Daniel Veillard377e1a92004-04-16 16:30:05 +000010009 xmlSchemaParserCtxtPtr ctxt)
10010{
Daniel Veillardc0826a72004-08-10 14:17:33 +000010011
Daniel Veillard01fa6152004-06-29 17:04:39 +000010012 xmlSchemaTypeLinkPtr link, lastLink = NULL, prevLink, subLink, newLink;
10013 xmlSchemaTypePtr memberType, ctxtType;
Daniel Veillard377e1a92004-04-16 16:30:05 +000010014
Daniel Veillard01fa6152004-06-29 17:04:39 +000010015 /* 1 If the <union> alternative is chosen, then [Definition:]
10016 * define the explicit members as the type definitions ·resolved·
10017 * to by the items in the ·actual value· of the memberTypes [attribute],
10018 * if any, followed by the type definitions corresponding to the
10019 * <simpleType>s among the [children] of <union>, if any.
10020 */
Daniel Veillard377e1a92004-04-16 16:30:05 +000010021
Daniel Veillard01fa6152004-06-29 17:04:39 +000010022 if (type->type != XML_SCHEMA_TYPE_UNION)
10023 return (-1);
10024 if (ctxt->ctxtType == NULL) {
10025 xmlSchemaPErr(ctxt, type->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000010026 XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010027 "Internal error: xmlSchemaParseUnionRefCheck, no parent type "
10028 "available", NULL, NULL);
10029 return (-1);
10030 }
10031 /*
10032 * src-union-memberTypes-or-simpleTypes
10033 * Either the memberTypes [attribute] of the <union> element must
10034 * be non-empty or there must be at least one simpleType [child].
10035 */
10036 if ((type->base == NULL) &&
10037 (type->subtypes == NULL)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010038 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010039 XML_SCHEMAP_SRC_UNION_MEMBERTYPES_OR_SIMPLETYPES,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010040 NULL, NULL, type->node,
10041 "Either the attribute 'memberTypes' must be non-empty "
10042 "or there must be at least one <simpleType> child", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010043 }
10044
10045 ctxtType = ctxt->ctxtType;
10046 if (type->base != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010047 xmlAttrPtr attr;
10048 const xmlChar *cur, *end;
10049 xmlChar *tmp;
10050 const xmlChar *localName, *uri;
10051
10052 attr = xmlSchemaGetPropNode(type->node, "memberTypes");
Daniel Veillard01fa6152004-06-29 17:04:39 +000010053 cur = type->base;
10054 do {
10055 while (IS_BLANK_CH(*cur))
10056 cur++;
10057 end = cur;
10058 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
10059 end++;
10060 if (end == cur)
10061 break;
10062 tmp = xmlStrndup(cur, end - cur);
Daniel Veillardc0826a72004-08-10 14:17:33 +000010063 xmlSchemaPValAttrNodeQNameValue(ctxt, ctxt->schema, NULL,
10064 NULL, attr, BAD_CAST tmp, &uri, NULL, &localName);
10065 memberType = xmlSchemaGetType(ctxt->schema, localName, uri);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010066 if (memberType == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010067 xmlSchemaPResCompAttrErr(ctxt,
10068 XML_SCHEMAP_UNKNOWN_MEMBER_TYPE,
10069 NULL, NULL, type->node, "memberTypes", localName, uri,
10070 XML_SCHEMA_TYPE_SIMPLE, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010071 } else {
10072 if (memberType->contentType == XML_SCHEMA_CONTENT_UNKNOWN)
10073 xmlSchemaTypeFixup(memberType, ctxt, NULL);
10074 link = (xmlSchemaTypeLinkPtr) xmlMalloc(sizeof(xmlSchemaTypeLink));
10075 if (link == NULL) {
10076 xmlSchemaPErrMemory(ctxt, "allocating a type link", NULL);
10077 return (-1);
10078 }
10079 link->type = memberType;
10080 link->next = NULL;
10081 if (lastLink == NULL)
10082 ctxtType->memberTypes = link;
10083 else
10084 lastLink->next = link;
10085 lastLink = link;
10086 }
10087 xmlFree(tmp);
10088 cur = end;
10089 } while (*cur != 0);
10090 }
10091 /*
10092 * Add local simple types,
10093 */
10094 memberType = type->subtypes;
10095 while (memberType != NULL) {
10096 if (memberType->contentType == XML_SCHEMA_CONTENT_UNKNOWN)
10097 xmlSchemaTypeFixup(memberType, ctxt, NULL);
10098 link = (xmlSchemaTypeLinkPtr) xmlMalloc(sizeof(xmlSchemaTypeLink));
10099 if (link == NULL) {
10100 xmlSchemaPErrMemory(ctxt, "allocating a type link", NULL);
10101 return (-1);
10102 }
10103 link->type = memberType;
10104 link->next = NULL;
10105 if (lastLink == NULL)
10106 ctxtType->memberTypes = link;
10107 else
10108 lastLink->next = link;
10109 lastLink = link;
10110 memberType = memberType->next;
10111 }
10112 /*
10113 * The actual value is then formed by replacing any union type
10114 * definition in the ·explicit members· with the members of their
10115 * {member type definitions}, in order.
10116 */
10117 link = ctxtType->memberTypes;
10118 while (link != NULL) {
10119 if (link->type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
10120 subLink = link->type->memberTypes;
10121 if (subLink != NULL) {
10122 link->type = subLink->type;
10123 if (subLink->next != NULL) {
10124 lastLink = link->next;
10125 subLink = subLink->next;
10126 prevLink = link;
10127 while (subLink != NULL) {
10128 newLink = (xmlSchemaTypeLinkPtr)
10129 xmlMalloc(sizeof(xmlSchemaTypeLink));
10130 if (newLink == NULL) {
10131 xmlSchemaPErrMemory(ctxt, "allocating a type link",
10132 NULL);
10133 return (-1);
10134 }
10135 newLink->type = memberType;
10136 prevLink->next = newLink;
10137 prevLink = newLink;
10138 newLink->next = lastLink;
10139
10140 subLink = subLink->next;
10141 }
10142 }
10143 }
10144 }
10145 link = link->next;
10146 }
10147
10148 return (0);
Daniel Veillard377e1a92004-04-16 16:30:05 +000010149}
10150
Daniel Veillard4255d502002-04-16 15:50:10 +000010151/**
Daniel Veillard3646d642004-06-02 19:19:14 +000010152 * xmlSchemaIsDerivedFromBuiltInType:
10153 * @ctxt: the schema parser context
10154 * @type: the type definition
10155 * @valType: the value type
10156 *
10157 *
10158 * Returns 1 if the type has the given value type, or
10159 * is derived from such a type.
10160 */
William M. Brack803812b2004-06-03 02:11:24 +000010161static int
Daniel Veillard3646d642004-06-02 19:19:14 +000010162xmlSchemaIsDerivedFromBuiltInType(xmlSchemaParserCtxtPtr ctxt,
10163 xmlSchemaTypePtr type, int valType)
10164{
10165 /* TODO: Check if this works in every case. */
Daniel Veillard01fa6152004-06-29 17:04:39 +000010166 if ((type->type == XML_SCHEMA_TYPE_BASIC) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000010167 (type->contentType == XML_SCHEMA_CONTENT_BASIC)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000010168 if (type->builtInType == valType)
Daniel Veillard3646d642004-06-02 19:19:14 +000010169 return(1);
10170 } else if (type->type == XML_SCHEMA_TYPE_ATTRIBUTE) {
10171 if (((xmlSchemaAttributePtr) type)->subtypes != NULL)
10172 return(xmlSchemaIsDerivedFromBuiltInType(ctxt,
10173 ((xmlSchemaAttributePtr) type)->subtypes, valType));
10174 } else if ((type->type == XML_SCHEMA_TYPE_RESTRICTION) ||
10175 (type->type == XML_SCHEMA_TYPE_EXTENSION)) {
10176 if (type->baseType != NULL)
10177 return(xmlSchemaIsDerivedFromBuiltInType(ctxt, type->baseType,
10178 valType));
10179 } else if ((type->subtypes != NULL) &&
10180 ((type->subtypes->type == XML_SCHEMA_TYPE_COMPLEX) ||
10181 (type->subtypes->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) ||
10182 (type->subtypes->type == XML_SCHEMA_TYPE_SIMPLE) ||
10183 (type->subtypes->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT))) {
10184 return(xmlSchemaIsDerivedFromBuiltInType(ctxt, type->subtypes,
10185 valType));
10186 }
10187
10188 return (0);
10189}
10190
10191/**
Daniel Veillard01fa6152004-06-29 17:04:39 +000010192 * xmlSchemaIsDerivedFromBuiltInType:
10193 * @type: the simpleType definition
10194 *
10195 * Returns the primitive type of the given type or
10196 * NULL in case of error.
10197 */
10198static xmlSchemaTypePtr
10199xmlSchemaGetPrimitiveType(xmlSchemaTypePtr type)
10200{
10201 while (type != NULL) {
10202 if (type->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE)
10203 return (type);
10204 type = type->baseType;
10205 }
10206
10207 return (NULL);
10208}
10209
10210
10211/**
Daniel Veillard3646d642004-06-02 19:19:14 +000010212 * xmlSchemaBuildAttributeUsesOwned:
10213 * @ctxt: the schema parser context
10214 * @type: the complex type definition
10215 * @cur: the attribute declaration list
10216 * @lastUse: the top of the attribute use list
10217 *
10218 * Builds the attribute uses list on the given complex type.
10219 * This one is supposed to be called by
10220 * xmlSchemaBuildAttributeValidation only.
10221 */
10222static int
10223xmlSchemaBuildAttributeUsesOwned(xmlSchemaParserCtxtPtr ctxt,
10224 xmlSchemaAttributePtr cur,
10225 xmlSchemaAttributeLinkPtr *uses,
10226 xmlSchemaAttributeLinkPtr *lastUse)
10227{
10228 xmlSchemaAttributeLinkPtr tmp;
10229 while (cur != NULL) {
10230 if (cur->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
10231 /*
10232 * W3C: "2 The {attribute uses} of the attribute groups ·resolved·
10233 * to by the ·actual value·s of the ref [attribute] of the
10234 * <attributeGroup> [children], if any."
10235 */
10236 if (xmlSchemaBuildAttributeUsesOwned(ctxt,
10237 ((xmlSchemaAttributeGroupPtr) cur)->attributes, uses,
10238 lastUse) == -1) {
10239 return (-1);
10240 }
10241 } else {
10242 /* W3C: "1 The set of attribute uses corresponding to the
10243 * <attribute> [children], if any."
10244 */
10245 tmp = (xmlSchemaAttributeLinkPtr)
10246 xmlMalloc(sizeof(xmlSchemaAttributeLink));
10247 if (tmp == NULL) {
10248 xmlSchemaPErrMemory(ctxt, "building attribute uses", NULL);
10249 return (-1);
10250 }
10251 tmp->attr = cur;
10252 tmp->next = NULL;
10253 if (*uses == NULL)
10254 *uses = tmp;
10255 else
10256 (*lastUse)->next = tmp;
10257 *lastUse = tmp;
10258 }
10259 cur = cur->next;
10260 }
10261 return (0);
10262}
10263
Daniel Veillard50355f02004-06-08 17:52:16 +000010264/**
10265 * xmlSchemaCloneWildcardNsConstraints:
10266 * @ctxt: the schema parser context
10267 * @dest: the destination wildcard
10268 * @source: the source wildcard
10269 *
10270 * Clones the namespace constraints of source
10271 * and assignes them to dest.
10272 * Returns -1 on internal error, 0 otherwise.
10273 */
Daniel Veillard3646d642004-06-02 19:19:14 +000010274static int
10275xmlSchemaCloneWildcardNsConstraints(xmlSchemaParserCtxtPtr ctxt,
10276 xmlSchemaWildcardPtr *dest,
10277 xmlSchemaWildcardPtr source)
10278{
10279 xmlSchemaWildcardNsPtr cur, tmp, last;
10280
10281 if ((source == NULL) || (*dest == NULL))
10282 return(-1);
10283 (*dest)->any = source->any;
10284 cur = source->nsSet;
10285 last = NULL;
10286 while (cur != NULL) {
10287 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
10288 if (tmp == NULL)
10289 return(-1);
10290 tmp->value = cur->value;
10291 if (last == NULL)
10292 (*dest)->nsSet = tmp;
10293 else
10294 last->next = tmp;
10295 last = tmp;
10296 cur = cur->next;
10297 }
10298 if ((*dest)->negNsSet != NULL)
10299 xmlSchemaFreeWildcardNsSet((*dest)->negNsSet);
10300 if (source->negNsSet != NULL) {
10301 (*dest)->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
10302 if ((*dest)->negNsSet == NULL)
10303 return(-1);
10304 (*dest)->negNsSet->value = source->negNsSet->value;
10305 } else
10306 (*dest)->negNsSet = NULL;
10307 return(0);
10308}
10309
Daniel Veillard50355f02004-06-08 17:52:16 +000010310/**
10311 * xmlSchemaUnionWildcards:
10312 * @ctxt: the schema parser context
10313 * @completeWild: the first wildcard
10314 * @curWild: the second wildcard
10315 *
10316 * Unions the namespace constraints of the given wildcards.
10317 * @completeWild will hold the resulting union.
10318 * Returns a positive error code on failure, -1 in case of an
10319 * internal error, 0 otherwise.
10320 */
Daniel Veillard3646d642004-06-02 19:19:14 +000010321static int
10322xmlSchemaUnionWildcards(xmlSchemaParserCtxtPtr ctxt,
10323 xmlSchemaWildcardPtr completeWild,
10324 xmlSchemaWildcardPtr curWild)
10325{
10326 xmlSchemaWildcardNsPtr cur, curB, tmp;
10327
10328 /*
10329 * 1 If O1 and O2 are the same value, then that value must be the
10330 * value.
10331 */
10332 if ((completeWild->any == curWild->any) &&
10333 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
10334 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
10335
10336 if ((completeWild->negNsSet == NULL) ||
10337 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
10338
10339 if (completeWild->nsSet != NULL) {
William M. Brack803812b2004-06-03 02:11:24 +000010340 int found = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000010341
10342 /*
10343 * Check equality of sets.
10344 */
10345 cur = completeWild->nsSet;
10346 while (cur != NULL) {
10347 found = 0;
10348 curB = curWild->nsSet;
10349 while (curB != NULL) {
10350 if (cur->value == curB->value) {
10351 found = 1;
10352 break;
10353 }
10354 curB = curB->next;
10355 }
10356 if (!found)
10357 break;
10358 cur = cur->next;
10359 }
10360 if (found)
10361 return(0);
10362 } else
10363 return(0);
10364 }
10365 }
10366 /*
10367 * 2 If either O1 or O2 is any, then any must be the value
10368 */
Daniel Veillard50355f02004-06-08 17:52:16 +000010369 if (completeWild->any != curWild->any) {
Daniel Veillard3646d642004-06-02 19:19:14 +000010370 if (completeWild->any == 0) {
10371 completeWild->any = 1;
10372 if (completeWild->nsSet != NULL) {
10373 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
10374 completeWild->nsSet = NULL;
10375 }
10376 if (completeWild->negNsSet != NULL) {
10377 xmlFree(completeWild->negNsSet);
10378 completeWild->negNsSet = NULL;
10379 }
10380 }
Daniel Veillard50355f02004-06-08 17:52:16 +000010381 return (0);
Daniel Veillard3646d642004-06-02 19:19:14 +000010382 }
10383 /*
10384 * 3 If both O1 and O2 are sets of (namespace names or ·absent·),
10385 * then the union of those sets must be the value.
10386 */
10387 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
10388 int found;
10389 xmlSchemaWildcardNsPtr start;
10390
10391 cur = curWild->nsSet;
10392 start = completeWild->nsSet;
10393 while (cur != NULL) {
10394 found = 0;
10395 curB = start;
10396 while (curB != NULL) {
10397 if (cur->value == curB->value) {
10398 found = 1;
10399 break;
10400 }
10401 curB = curB->next;
10402 }
10403 if (!found) {
10404 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
10405 if (tmp == NULL)
10406 return (-1);
10407 tmp->value = cur->value;
10408 tmp->next = completeWild->nsSet;
10409 completeWild->nsSet = tmp;
10410 }
10411 cur = cur->next;
10412 }
10413
10414 return(0);
10415 }
10416 /*
10417 * 4 If the two are negations of different values (namespace names
10418 * or ·absent·), then a pair of not and ·absent· must be the value.
10419 */
10420 if ((completeWild->negNsSet != NULL) &&
10421 (curWild->negNsSet != NULL) &&
10422 (completeWild->negNsSet->value != curWild->negNsSet->value)) {
10423 completeWild->negNsSet->value = NULL;
Daniel Veillard50355f02004-06-08 17:52:16 +000010424
10425 return(0);
Daniel Veillard3646d642004-06-02 19:19:14 +000010426 }
10427 /*
10428 * 5.
10429 */
10430 if (((completeWild->negNsSet != NULL) &&
10431 (completeWild->negNsSet->value != NULL) &&
10432 (curWild->nsSet != NULL)) ||
10433 ((curWild->negNsSet != NULL) &&
10434 (curWild->negNsSet->value != NULL) &&
10435 (completeWild->nsSet != NULL))) {
10436
10437 int nsFound, absentFound = 0;
10438
10439 if (completeWild->nsSet != NULL) {
10440 cur = completeWild->nsSet;
10441 curB = curWild->negNsSet;
10442 } else {
10443 cur = curWild->nsSet;
10444 curB = completeWild->negNsSet;
10445 }
10446 nsFound = 0;
10447 while (cur != NULL) {
10448 if (cur->value == NULL)
10449 absentFound = 1;
10450 else if (cur->value == curB->value)
10451 nsFound = 1;
10452 if (nsFound && absentFound)
10453 break;
10454 cur = cur->next;
10455 }
10456
10457 if (nsFound && absentFound) {
10458 /*
10459 * 5.1 If the set S includes both the negated namespace
10460 * name and ·absent·, then any must be the value.
10461 */
10462 completeWild->any = 1;
10463 if (completeWild->nsSet != NULL) {
10464 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
10465 completeWild->nsSet = NULL;
10466 }
10467 if (completeWild->negNsSet != NULL) {
10468 xmlFree(completeWild->negNsSet);
10469 completeWild->negNsSet = NULL;
10470 }
10471 } else if (nsFound && (!absentFound)) {
10472 /*
10473 * 5.2 If the set S includes the negated namespace name
10474 * but not ·absent·, then a pair of not and ·absent· must
10475 * be the value.
10476 */
10477 if (completeWild->nsSet != NULL) {
10478 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
10479 completeWild->nsSet = NULL;
10480 }
10481 if (completeWild->negNsSet == NULL) {
10482 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
10483 if (completeWild->negNsSet == NULL)
10484 return (-1);
10485 }
10486 completeWild->negNsSet->value = NULL;
10487 } else if ((!nsFound) && absentFound) {
10488 /*
10489 * 5.3 If the set S includes ·absent· but not the negated
10490 * namespace name, then the union is not expressible.
10491 */
10492 xmlSchemaPErr(ctxt, completeWild->node,
10493 XML_SCHEMAP_UNION_NOT_EXPRESSIBLE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010494 "The union of the wilcard is not expressible.\n",
Daniel Veillard3646d642004-06-02 19:19:14 +000010495 NULL, NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +000010496 return(XML_SCHEMAP_UNION_NOT_EXPRESSIBLE);
Daniel Veillard3646d642004-06-02 19:19:14 +000010497 } else if ((!nsFound) && (!absentFound)) {
10498 /*
10499 * 5.4 If the set S does not include either the negated namespace
10500 * name or ·absent·, then whichever of O1 or O2 is a pair of not
10501 * and a namespace name must be the value.
10502 */
10503 if (completeWild->negNsSet == NULL) {
10504 if (completeWild->nsSet != NULL) {
10505 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
10506 completeWild->nsSet = NULL;
10507 }
10508 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
10509 if (completeWild->negNsSet == NULL)
10510 return (-1);
10511 completeWild->negNsSet->value = curWild->negNsSet->value;
10512 }
10513 }
10514 return (0);
10515 }
10516 /*
10517 * 6.
10518 */
10519 if (((completeWild->negNsSet != NULL) &&
10520 (completeWild->negNsSet->value == NULL) &&
10521 (curWild->nsSet != NULL)) ||
10522 ((curWild->negNsSet != NULL) &&
10523 (curWild->negNsSet->value == NULL) &&
10524 (completeWild->nsSet != NULL))) {
10525
10526 if (completeWild->nsSet != NULL) {
10527 cur = completeWild->nsSet;
10528 } else {
10529 cur = curWild->nsSet;
10530 }
10531 while (cur != NULL) {
10532 if (cur->value == NULL) {
10533 /*
10534 * 6.1 If the set S includes ·absent·, then any must be the
10535 * value.
10536 */
10537 completeWild->any = 1;
10538 if (completeWild->nsSet != NULL) {
10539 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
10540 completeWild->nsSet = NULL;
10541 }
10542 if (completeWild->negNsSet != NULL) {
10543 xmlFree(completeWild->negNsSet);
10544 completeWild->negNsSet = NULL;
10545 }
10546 return (0);
10547 }
10548 cur = cur->next;
10549 }
10550 if (completeWild->negNsSet == NULL) {
10551 /*
10552 * 6.2 If the set S does not include ·absent·, then a pair of not
10553 * and ·absent· must be the value.
10554 */
10555 if (completeWild->nsSet != NULL) {
10556 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
10557 completeWild->nsSet = NULL;
10558 }
10559 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
10560 if (completeWild->negNsSet == NULL)
10561 return (-1);
10562 completeWild->negNsSet->value = NULL;
10563 }
10564 return (0);
10565 }
10566 return (0);
10567
10568}
10569
Daniel Veillard50355f02004-06-08 17:52:16 +000010570/**
10571 * xmlSchemaIntersectWildcards:
10572 * @ctxt: the schema parser context
10573 * @completeWild: the first wildcard
10574 * @curWild: the second wildcard
10575 *
10576 * Intersects the namespace constraints of the given wildcards.
10577 * @completeWild will hold the resulting intersection.
10578 * Returns a positive error code on failure, -1 in case of an
10579 * internal error, 0 otherwise.
10580 */
Daniel Veillard3646d642004-06-02 19:19:14 +000010581static int
10582xmlSchemaIntersectWildcards(xmlSchemaParserCtxtPtr ctxt,
10583 xmlSchemaWildcardPtr completeWild,
10584 xmlSchemaWildcardPtr curWild)
10585{
William M. Brack803812b2004-06-03 02:11:24 +000010586 xmlSchemaWildcardNsPtr cur, curB, prev, tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000010587
10588 /*
10589 * 1 If O1 and O2 are the same value, then that value must be the
10590 * value.
10591 */
10592 if ((completeWild->any == curWild->any) &&
10593 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
10594 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
10595
10596 if ((completeWild->negNsSet == NULL) ||
10597 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
10598
10599 if (completeWild->nsSet != NULL) {
William M. Brack803812b2004-06-03 02:11:24 +000010600 int found = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000010601
10602 /*
10603 * Check equality of sets.
10604 */
10605 cur = completeWild->nsSet;
10606 while (cur != NULL) {
10607 found = 0;
10608 curB = curWild->nsSet;
10609 while (curB != NULL) {
10610 if (cur->value == curB->value) {
10611 found = 1;
10612 break;
10613 }
10614 curB = curB->next;
10615 }
10616 if (!found)
10617 break;
10618 cur = cur->next;
10619 }
10620 if (found)
10621 return(0);
10622 } else
10623 return(0);
10624 }
10625 }
10626 /*
10627 * 2 If either O1 or O2 is any, then the other must be the value.
10628 */
10629 if ((completeWild->any != curWild->any) && (completeWild->any)) {
10630 if (xmlSchemaCloneWildcardNsConstraints(ctxt, &completeWild, curWild) == -1)
10631 return(-1);
10632 return(0);
10633 }
10634 /*
10635 * 3 If either O1 or O2 is a pair of not and a value (a namespace
10636 * name or ·absent·) and the other is a set of (namespace names or
10637 * ·absent·), then that set, minus the negated value if it was in
10638 * the set, minus ·absent· if it was in the set, must be the value.
10639 */
10640 if (((completeWild->negNsSet != NULL) && (curWild->nsSet != NULL)) ||
10641 ((curWild->negNsSet != NULL) && (completeWild->nsSet != NULL))) {
10642 const xmlChar *neg;
10643
10644 if (completeWild->nsSet == NULL) {
10645 neg = completeWild->negNsSet->value;
10646 if (xmlSchemaCloneWildcardNsConstraints(ctxt, &completeWild, curWild) == -1)
10647 return(-1);
10648 } else
10649 neg = curWild->negNsSet->value;
10650 /*
10651 * Remove absent and negated.
10652 */
10653 prev = NULL;
10654 cur = completeWild->nsSet;
10655 while (cur != NULL) {
10656 if (cur->value == NULL) {
10657 if (prev == NULL)
10658 completeWild->nsSet = cur->next;
10659 else
10660 prev->next = cur->next;
10661 xmlFree(cur);
10662 break;
10663 }
10664 prev = cur;
10665 cur = cur->next;
10666 }
10667 if (neg != NULL) {
10668 prev = NULL;
10669 cur = completeWild->nsSet;
10670 while (cur != NULL) {
10671 if (cur->value == neg) {
10672 if (prev == NULL)
10673 completeWild->nsSet = cur->next;
10674 else
10675 prev->next = cur->next;
10676 xmlFree(cur);
10677 break;
10678 }
10679 prev = cur;
10680 cur = cur->next;
10681 }
10682 }
10683
10684 return(0);
10685 }
10686 /*
10687 * 4 If both O1 and O2 are sets of (namespace names or ·absent·),
10688 * then the intersection of those sets must be the value.
10689 */
10690 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
10691 int found;
10692
10693 cur = completeWild->nsSet;
10694 prev = NULL;
10695 while (cur != NULL) {
10696 found = 0;
10697 curB = curWild->nsSet;
10698 while (curB != NULL) {
10699 if (cur->value == curB->value) {
10700 found = 1;
10701 break;
10702 }
10703 curB = curB->next;
10704 }
10705 if (!found) {
10706 if (prev == NULL)
10707 completeWild->nsSet = cur->next;
10708 else
10709 prev->next = cur->next;
10710 tmp = cur->next;
10711 xmlFree(cur);
10712 cur = tmp;
10713 continue;
10714 }
10715 prev = cur;
10716 cur = cur->next;
10717 }
10718
10719 return(0);
10720 }
10721 /* 5 If the two are negations of different namespace names,
10722 * then the intersection is not expressible
10723 */
10724 if ((completeWild->negNsSet != NULL) &&
10725 (curWild->negNsSet != NULL) &&
10726 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
10727 (completeWild->negNsSet->value != NULL) &&
10728 (curWild->negNsSet->value != NULL)) {
10729
10730 xmlSchemaPErr(ctxt, completeWild->node, XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010731 "The intersection of the wilcard is not expressible.\n",
Daniel Veillard3646d642004-06-02 19:19:14 +000010732 NULL, NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +000010733 return(XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE);
Daniel Veillard3646d642004-06-02 19:19:14 +000010734 }
10735 /*
10736 * 6 If the one is a negation of a namespace name and the other
10737 * is a negation of ·absent·, then the one which is the negation
10738 * of a namespace name must be the value.
10739 */
10740 if ((completeWild->negNsSet != NULL) && (curWild->negNsSet != NULL) &&
10741 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
10742 (completeWild->negNsSet->value == NULL)) {
10743 completeWild->negNsSet->value = curWild->negNsSet->value;
10744 }
10745 return(0);
10746}
10747
Daniel Veillard50355f02004-06-08 17:52:16 +000010748/**
10749 * xmlSchemaIsWildcardNsConstraintSubset:
10750 * @ctxt: the schema parser context
10751 * @wildA: the first wildcard
10752 * @wildB: the second wildcard
10753 *
10754 * Returns 1 if the namespace constraint of @wildA is an intensional
10755 * subset of @wildB, 0 otherwise.
10756 */
10757static int
Daniel Veillardc0826a72004-08-10 14:17:33 +000010758xmlSchemaIsWildcardNsConstraintSubset(xmlSchemaWildcardPtr wildA,
10759 xmlSchemaWildcardPtr wildB)
Daniel Veillard50355f02004-06-08 17:52:16 +000010760{
Daniel Veillard3646d642004-06-02 19:19:14 +000010761
Daniel Veillard50355f02004-06-08 17:52:16 +000010762 /*
10763 * Schema Component Constraint: Wildcard Subset
10764 */
10765 /*
10766 * 1 super must be any.
10767 */
10768 if (wildB->any)
10769 return (1);
10770 /*
10771 * 2.1 sub must be a pair of not and a namespace name or ·absent·.
10772 * 2.2 super must be a pair of not and the same value.
10773 */
10774 if ((wildA->negNsSet != NULL) &&
10775 (wildB->negNsSet != NULL) &&
10776 (wildA->negNsSet->value == wildA->negNsSet->value))
10777 return (1);
10778 /*
10779 * 3.1 sub must be a set whose members are either namespace names or ·absent·.
10780 */
10781 if (wildA->nsSet != NULL) {
10782 /*
10783 * 3.2.1 super must be the same set or a superset thereof.
10784 */
10785 if (wildB->nsSet != NULL) {
10786 xmlSchemaWildcardNsPtr cur, curB;
10787 int found = 0;
10788
10789 cur = wildA->nsSet;
10790 while (cur != NULL) {
10791 found = 0;
10792 curB = wildB->nsSet;
10793 while (curB != NULL) {
10794 if (cur->value == curB->value) {
10795 found = 1;
10796 break;
10797 }
10798 curB = curB->next;
10799 }
10800 if (!found)
10801 return (0);
10802 cur = cur->next;
10803 }
10804 if (found)
10805 return (1);
10806 } else if (wildB->negNsSet != NULL) {
10807 xmlSchemaWildcardNsPtr cur;
10808 /*
10809 * 3.2.2 super must be a pair of not and a namespace name or
10810 * ·absent· and that value must not be in sub's set.
10811 */
10812 cur = wildA->nsSet;
10813 while (cur != NULL) {
10814 if (cur->value == wildB->negNsSet->value)
10815 return (0);
10816 cur = cur->next;
10817 }
10818 return (1);
10819 }
10820 }
10821 return (0);
10822}
10823
10824/**
10825 * xmlSchemaBuildCompleteAttributeWildcard:
10826 * @ctxt: the schema parser context
10827 * @attrs: the attribute list
10828 * @completeWild: the resulting complete wildcard
10829 *
10830 * Returns -1 in case of an internal error, 0 otherwise.
10831 */
10832static int
10833xmlSchemaBuildCompleteAttributeWildcard(xmlSchemaParserCtxtPtr ctxt,
10834 xmlSchemaAttributePtr attrs,
10835 xmlSchemaWildcardPtr *completeWild)
Daniel Veillard3646d642004-06-02 19:19:14 +000010836{
10837 while (attrs != NULL) {
10838 if (attrs->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
10839 xmlSchemaAttributeGroupPtr group;
10840
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010841 group = (xmlSchemaAttributeGroupPtr) attrs;
10842 /*
10843 * Handle attribute group references.
10844 */
10845 if (group->ref != NULL) {
10846 if (group->refItem == NULL) {
10847 /*
10848 * TODO: Should we raise a warning here?
10849 */
10850 /*
10851 * The referenced attribute group definition could not
10852 * be resolved beforehand, so skip.
10853 */
10854 attrs = attrs->next;
10855 continue;
10856 } else
10857 group = group->refItem;
10858 }
10859 /*
10860 * For every attribute group definition, an intersected wildcard
10861 * will be created (assumed that a wildcard exists on the
10862 * particular attr. gr. def. or on any contained attr. gr. def
10863 * at all).
10864 * The flag XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED ensures
10865 * that the intersection will be performed only once.
10866 */
Daniel Veillard3646d642004-06-02 19:19:14 +000010867 if ((group->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED) == 0) {
10868 if (group->attributes != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000010869 if (xmlSchemaBuildCompleteAttributeWildcard(ctxt,
10870 group->attributes, &group->attributeWildcard) == -1)
10871 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000010872 }
10873 group->flags |= XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED;
10874 }
10875 if (group->attributeWildcard != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000010876 if (*completeWild == NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +000010877 /*
10878 * Copy the first encountered wildcard as context, except for the annotation.
10879 */
Daniel Veillard50355f02004-06-08 17:52:16 +000010880 *completeWild = xmlSchemaAddWildcard(ctxt);
10881 (*completeWild)->type = XML_SCHEMA_TYPE_ANY_ATTRIBUTE;
10882 if (xmlSchemaCloneWildcardNsConstraints(ctxt,
10883 completeWild, group->attributeWildcard) == -1)
10884 return (-1);
10885 (*completeWild)->processContents = group->attributeWildcard->processContents;
Daniel Veillard3646d642004-06-02 19:19:14 +000010886 /*
10887 * Although the complete wildcard might not correspond to any
10888 * node in the schema, we will save this context node.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010889 * TODO: Hmm, is this sane?
Daniel Veillard3646d642004-06-02 19:19:14 +000010890 */
Daniel Veillard50355f02004-06-08 17:52:16 +000010891 (*completeWild)->node = group->attributeWildcard->node;
10892
10893 } else if (xmlSchemaIntersectWildcards(ctxt, *completeWild, group->attributeWildcard) == -1) {
10894 xmlSchemaFreeWildcard(*completeWild);
10895 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000010896 }
10897 }
10898 }
10899 attrs = attrs->next;
10900 }
10901
Daniel Veillard50355f02004-06-08 17:52:16 +000010902 return (0);
Daniel Veillard3646d642004-06-02 19:19:14 +000010903}
10904
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010905static int
10906xmlSchemaGetEffectiveValueConstraint(xmlSchemaAttributePtr item,
10907 int *fixed,
10908 const xmlChar **value,
10909 xmlSchemaValPtr *val)
10910{
10911 *fixed = 0;
10912 *value = NULL;
10913 if (val != 0)
10914 *val = NULL;
10915
10916 if (item->defValue == NULL)
10917 item = item->refDecl;
10918
10919 if (item == NULL)
10920 return (0);
10921
10922 if (item->defValue != NULL) {
10923 *value = item->defValue;
10924 if (val != 0)
10925 *val = item->defVal;
10926 if (item->flags & XML_SCHEMAS_ATTR_FIXED)
10927 *fixed = 1;
10928 return (1);
10929 }
10930 return (0);
10931}
Daniel Veillard3646d642004-06-02 19:19:14 +000010932/**
10933 * xmlSchemaMatchesWildcardNs:
10934 * @wild: the wildcard
10935 * @ns: the namespace
10936 *
10937 *
10938 * Returns 1 if the given namespace matches the wildcard,
10939 * 0 otherwise.
10940 */
10941static int
10942xmlSchemaMatchesWildcardNs(xmlSchemaWildcardPtr wild, const xmlChar* ns)
10943{
10944 if (wild == NULL)
10945 return(0);
10946
10947 if (wild->any)
10948 return(1);
10949 else if (wild->nsSet != NULL) {
10950 xmlSchemaWildcardNsPtr cur;
10951
10952 cur = wild->nsSet;
10953 while (cur != NULL) {
10954 if (xmlStrEqual(cur->value, ns))
10955 return(1);
10956 cur = cur->next;
10957 }
10958 } else if ((wild->negNsSet != NULL) && (ns != NULL) &&
10959 (!xmlStrEqual(wild->negNsSet->value, ns)))
10960 return(1);
10961
10962 return(0);
10963}
10964
10965/**
10966 * xmlSchemaBuildAttributeValidation:
10967 * @ctxt: the schema parser context
10968 * @type: the complex type definition
10969 *
10970 *
10971 * Builds the wildcard and the attribute uses on the given complex type.
10972 * Returns -1 if an internal error occurs, 0 otherwise.
10973 */
10974static int
10975xmlSchemaBuildAttributeValidation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaTypePtr type)
10976{
10977 xmlSchemaTypePtr baseType = NULL;
10978 xmlSchemaAttributeLinkPtr cur, base, tmp, id = NULL, prev = NULL, uses = NULL,
William M. Brack803812b2004-06-03 02:11:24 +000010979 lastUse = NULL, lastBaseUse = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000010980 xmlSchemaAttributePtr attrs;
Daniel Veillard01fa6152004-06-29 17:04:39 +000010981 xmlSchemaTypePtr anyType;
Daniel Veillard50355f02004-06-08 17:52:16 +000010982 int baseIsAnyType = 0;
Daniel Veillardc0826a72004-08-10 14:17:33 +000010983 xmlChar *str = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000010984 int err = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000010985
Daniel Veillard01fa6152004-06-29 17:04:39 +000010986 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
Daniel Veillard3646d642004-06-02 19:19:14 +000010987 /*
10988 * Complex Type Definition with complex content Schema Component.
10989 *
10990 * Attribute uses.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010991 * TODO: Add checks for absent referenced attribute declarations and
10992 * simple types.
Daniel Veillard3646d642004-06-02 19:19:14 +000010993 */
10994 if (type->attributeUses != NULL) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000010995 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010996 "Internal error: xmlSchemaBuildAttributeValidation: "
Daniel Veillard3646d642004-06-02 19:19:14 +000010997 "attribute uses already builded.\n",
10998 NULL, NULL);
10999 return (-1);
11000 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000011001 if (type->baseType == NULL) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000011002 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011003 "Internal error: xmlSchemaBuildAttributeValidation: "
Daniel Veillardc0826a72004-08-10 14:17:33 +000011004 "complex type '%s' has no base type.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000011005 type->name, NULL);
11006 return (-1);
11007 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011008 baseType = type->baseType;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011009 if (baseType == anyType)
11010 baseIsAnyType = 1;
11011 /*
11012 * Inherit the attribute uses of the base type.
11013 */
11014 /*
11015 * NOTE: It is allowed to "extend" the anyType complex type.
11016 */
11017 if (!baseIsAnyType) {
11018 if (baseType != NULL) {
11019 for (cur = baseType->attributeUses; cur != NULL; cur = cur->next) {
11020 tmp = (xmlSchemaAttributeLinkPtr)
11021 xmlMalloc(sizeof(xmlSchemaAttributeLink));
11022 if (tmp == NULL) {
11023 xmlSchemaPErrMemory(ctxt,
11024 "building attribute uses of complexType", NULL);
11025 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000011026 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011027 tmp->attr = cur->attr;
11028 tmp->next = NULL;
11029 if (type->attributeUses == NULL) {
11030 type->attributeUses = tmp;
11031 } else
11032 lastBaseUse->next = tmp;
11033 lastBaseUse = tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000011034 }
11035 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011036 }
11037 if ((type->subtypes != NULL) &&
11038 ((type->subtypes->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) ||
11039 (type->subtypes->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT))) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011040 /*
11041 * type --> (<simpleContent>|<complexContent>)
11042 * --> (<restriction>|<extension>) --> attributes
11043 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011044 attrs = type->subtypes->subtypes->attributes;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011045 } else {
11046 /* Short hand form of the complexType. */
11047 attrs = type->attributes;
11048 }
11049 /*
11050 * Handle attribute wildcards.
11051 */
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000011052 err = xmlSchemaBuildCompleteAttributeWildcard(ctxt,
11053 attrs, &type->attributeWildcard);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011054 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011055 * NOTE: During the parse time, the wildcard is created on the complexType
11056 * directly, if encountered in a <restriction> or <extension> element.
Daniel Veillard01fa6152004-06-29 17:04:39 +000011057 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011058 if (err == -1) {
11059 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_INTERNAL,
11060 "Internal error: xmlSchemaBuildAttributeValidation: "
11061 "failed to build an intersected attribute wildcard.\n",
11062 NULL, NULL);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000011063 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011064 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011065
11066 if ((type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) &&
11067 ((baseIsAnyType) ||
11068 ((baseType != NULL) &&
11069 (baseType->type == XML_SCHEMA_TYPE_COMPLEX) &&
11070 (baseType->attributeWildcard != NULL)))) {
11071 if (type->attributeWildcard != NULL) {
11072 /*
11073 * Union the complete wildcard with the base wildcard.
11074 */
11075 if (xmlSchemaUnionWildcards(ctxt, type->attributeWildcard,
11076 baseType->attributeWildcard) == -1)
11077 return (-1);
11078 } else {
11079 /*
11080 * Just inherit the wildcard.
11081 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011082 /*
11083 * NOTE: This is the only case where an attribute
11084 * wildcard is shared.
11085 */
11086 if (type->flags & XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD)
11087 type->flags ^= XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011088 type->attributeWildcard = baseType->attributeWildcard;
Daniel Veillard50355f02004-06-08 17:52:16 +000011089 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011090 }
11091
11092 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
11093 if (type->attributeWildcard != NULL) {
11094 /*
11095 * Derivation Valid (Restriction, Complex)
11096 * 4.1 The {base type definition} must also have one.
11097 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000011098 if (baseType->attributeWildcard == NULL) {
11099 xmlSchemaPCustomErr(ctxt,
11100 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_1,
11101 NULL, type, NULL,
11102 "The type has an attribute wildcard, "
11103 "but the base type %s does not have one",
11104 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
11105 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011106 return (1);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011107 } else if (xmlSchemaIsWildcardNsConstraintSubset(
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011108 type->attributeWildcard, baseType->attributeWildcard) == 0) {
11109 /* 4.2 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000011110 xmlSchemaPCustomErr(ctxt,
11111 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_2,
11112 NULL, type, NULL,
11113 "The attribute wildcard is not a valid "
11114 "subset of the wildcard in the base type %s",
11115 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
11116 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011117 return (1);
11118 }
11119 /* 4.3 Unless the {base type definition} is the ·ur-type
11120 * definition·, the complex type definition's {attribute
11121 * wildcard}'s {process contents} must be identical to or
11122 * stronger than the {base type definition}'s {attribute
11123 * wildcard}'s {process contents}, where strict is stronger
11124 * than lax is stronger than skip.
11125 */
11126 if ((type->baseType != anyType) &&
11127 (type->attributeWildcard->processContents <
11128 baseType->attributeWildcard->processContents)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011129 xmlSchemaPCustomErr(ctxt,
11130 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_3,
11131 NULL, type, NULL,
11132 "The 'process contents' of the attribute wildcard is weaker than "
11133 "the one in the base type %s",
11134 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
11135 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011136 return (1);
11137 }
11138 }
11139 } else if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
11140 /*
11141 * Derivation Valid (Extension)
11142 * At this point the type and the base have both, either
11143 * no wildcard or a wildcard.
11144 */
11145 if ((baseType->attributeWildcard != NULL) &&
11146 (baseType->attributeWildcard != type->attributeWildcard)) {
11147 /* 1.3 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000011148 if (xmlSchemaIsWildcardNsConstraintSubset(
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011149 baseType->attributeWildcard, type->attributeWildcard) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011150 xmlSchemaPCustomErr(ctxt,
11151 XML_SCHEMAP_COS_CT_EXTENDS_1_3,
11152 NULL, type, NULL,
11153 "The attribute wildcard is not a valid "
11154 "superset of the one in the base type %s",
11155 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
11156 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011157 return (1);
11158 }
11159 }
11160 }
11161
Daniel Veillard3646d642004-06-02 19:19:14 +000011162 /*
11163 * Gather attribute uses defined by this type.
11164 */
11165 if (attrs != NULL) {
11166 if (xmlSchemaBuildAttributeUsesOwned(ctxt, attrs,
11167 &uses, &lastUse) == -1) {
11168 return (-1);
11169 }
11170 }
11171 /* 3.4.6 -> Complex Type Definition Properties Correct 4.
11172 * "Two distinct attribute declarations in the {attribute uses} must
11173 * not have identical {name}s and {target namespace}s."
11174 *
11175 * For "extension" this is done further down.
11176 */
11177 if ((uses != NULL) && ((type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) == 0)) {
11178 cur = uses;
11179 while (cur != NULL) {
11180 tmp = cur->next;
11181 while (tmp != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011182 if ((xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
11183 xmlSchemaGetAttrName(tmp->attr))) &&
11184 (xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr ),
11185 xmlSchemaGetAttrTargetNsURI(tmp->attr)))) {
11186
11187 xmlSchemaPAttrUseErr(ctxt,
11188 XML_SCHEMAP_CT_PROPS_CORRECT_4,
11189 NULL, type, NULL, cur->attr,
11190 "Duplicate attribute use %s specified",
11191 xmlSchemaFormatNsUriLocal(&str,
11192 xmlSchemaGetAttrTargetNsURI(tmp->attr),
11193 xmlSchemaGetAttrName(tmp->attr))
11194 );
11195 FREE_AND_NULL(str)
Daniel Veillard3646d642004-06-02 19:19:14 +000011196 break;
11197 }
11198 tmp = tmp->next;
11199 }
11200 cur = cur->next;
11201 }
11202 }
11203 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
11204 /*
11205 * Derive by restriction.
11206 */
11207 if (baseIsAnyType) {
11208 type->attributeUses = uses;
11209 } else {
11210 int found;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011211 const xmlChar *bEffValue;
11212 int effFixed;
Daniel Veillard3646d642004-06-02 19:19:14 +000011213
11214 cur = uses;
11215 while (cur != NULL) {
11216 found = 0;
11217 base = type->attributeUses;
11218 while (base != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011219 if (xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
11220 xmlSchemaGetAttrName(base->attr)) &&
11221 xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr),
11222 xmlSchemaGetAttrTargetNsURI(base->attr))) {
Daniel Veillard3646d642004-06-02 19:19:14 +000011223
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011224 found = 1;
11225
Daniel Veillard3646d642004-06-02 19:19:14 +000011226 if ((cur->attr->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
11227 (base->attr->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED)) {
11228 /*
11229 * derivation-ok-restriction 2.1.1
Daniel Veillardc0826a72004-08-10 14:17:33 +000011230 */
11231 xmlSchemaPAttrUseErr(ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +000011232 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011233 NULL, type, NULL, cur->attr,
11234 "The 'optional' use is inconsistent with a matching "
11235 "'required' use of the base type", NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +000011236 } else if ((cur->attr->occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) &&
11237 (base->attr->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED)) {
11238 /*
11239 * derivation-ok-restriction 3
11240 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000011241 xmlSchemaPCustomErr(ctxt,
11242 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_3,
11243 NULL, type, NULL,
11244 "A matching attribute use for the 'required' "
11245 "attribute use %s of the base type is missing",
11246 xmlSchemaFormatNsUriLocal(&str,
11247 xmlSchemaGetAttrTargetNsURI(base->attr),
11248 xmlSchemaGetAttrName(base->attr)));
11249 FREE_AND_NULL(str)
Daniel Veillard3646d642004-06-02 19:19:14 +000011250 } else {
11251 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011252 * 2.1.3 [Definition:] Let the effective value
11253 * constraint of an attribute use be its {value
11254 * constraint}, if present, otherwise its {attribute
11255 * declaration}'s {value constraint} .
11256 */
11257 xmlSchemaGetEffectiveValueConstraint(base->attr, &effFixed,
11258 &bEffValue, 0);
11259 /*
11260 * 2.1.3 ... one of the following must be true
11261 *
11262 * 2.1.3.1 B's ·effective value constraint· is
11263 * ·absent· or default.
11264 */
11265 if ((bEffValue != NULL) &&
11266 (effFixed == 1)) {
11267 const xmlChar *rEffValue = NULL;
11268
11269 xmlSchemaGetEffectiveValueConstraint(base->attr, &effFixed,
11270 &rEffValue, 0);
11271 /*
11272 * 2.1.3.2 R's ·effective value constraint· is
11273 * fixed with the same string as B's.
11274 */
11275 if ((effFixed == 0) ||
11276 (! xmlStrEqual(rEffValue, bEffValue))) {
11277 xmlSchemaPAttrUseErr(ctxt,
11278 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_3,
11279 NULL, type, NULL, cur->attr,
11280 "The effective value constraint of the "
11281 "attribute use is inconsistent with "
11282 "its correspondent of the base type",
11283 NULL);
11284 }
11285 }
11286 /*
11287 * TODO: derivation-ok-restriction 2.1.2 ({type definition} must be validly derived)
11288 */
11289 /*
Daniel Veillard3646d642004-06-02 19:19:14 +000011290 * Override the attribute use.
11291 */
11292 base->attr = cur->attr;
11293 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011294
Daniel Veillard3646d642004-06-02 19:19:14 +000011295 break;
11296 }
11297 base = base->next;
11298 }
11299
11300 if (!found) {
11301 if (cur->attr->occurs != XML_SCHEMAS_ATTR_USE_PROHIBITED) {
11302 /*
11303 * derivation-ok-restriction 2.2
11304 */
11305 if ((type->attributeWildcard != NULL) &&
11306 xmlSchemaMatchesWildcardNs(type->attributeWildcard,
11307 cur->attr->targetNamespace))
11308 found = 1;
11309
11310 if (!found) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011311 xmlSchemaPAttrUseErr(ctxt,
11312 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_2,
11313 NULL, type, NULL, cur->attr,
11314 "Neither a matching attribute use, "
11315 "nor a matching wildcard in the base type does exist",
11316 NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +000011317 } else {
11318 /*
11319 * Add the attribute use.
11320 *
11321 * Note that this may lead to funny derivation error reports, if
11322 * multiple equal attribute uses exist; but this is not
11323 * allowed anyway, and it will be reported beforehand.
11324 */
11325 tmp = cur;
11326 if (prev != NULL)
11327 prev->next = cur->next;
11328 else
11329 uses = cur->next;
11330 cur = cur->next;
11331 if (type->attributeUses == NULL) {
11332 type->attributeUses = tmp;
11333 } else
11334 lastBaseUse->next = tmp;
11335 lastBaseUse = tmp;
11336
11337 continue;
11338 }
11339 }
11340 }
11341 prev = cur;
11342 cur = cur->next;
11343 }
11344 if (uses != NULL)
11345 xmlSchemaFreeAttributeUseList(uses);
11346 }
11347 } else if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
11348 /*
11349 * The spec allows only appending, and not other kinds of extensions.
11350 *
11351 * This ensures: Schema Component Constraint: Derivation Valid (Extension) : 1.2
11352 */
11353 if (uses != NULL) {
11354 if (type->attributeUses == NULL) {
11355 type->attributeUses = uses;
11356 } else
11357 lastBaseUse->next = uses;
Daniel Veillard50355f02004-06-08 17:52:16 +000011358 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011359 } else {
11360 /*
Daniel Veillard50355f02004-06-08 17:52:16 +000011361 * Derive implicitely from the ur-type.
11362 */
Daniel Veillard3646d642004-06-02 19:19:14 +000011363 type->attributeUses = uses;
Daniel Veillard50355f02004-06-08 17:52:16 +000011364 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011365 /*
11366 * 3.4.6 -> Complex Type Definition Properties Correct
11367 */
11368 if (type->attributeUses != NULL) {
11369 cur = type->attributeUses;
11370 prev = NULL;
11371 while (cur != NULL) {
11372 /*
11373 * 4. Two distinct attribute declarations in the {attribute uses} must
11374 * not have identical {name}s and {target namespace}s.
Daniel Veillard50355f02004-06-08 17:52:16 +000011375 *
Daniel Veillard3646d642004-06-02 19:19:14 +000011376 * Note that this was already done for "restriction" and types derived from
11377 * the ur-type.
Daniel Veillard50355f02004-06-08 17:52:16 +000011378 */
Daniel Veillard3646d642004-06-02 19:19:14 +000011379 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
11380 tmp = cur->next;
11381 while (tmp != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011382 if ((xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
11383 xmlSchemaGetAttrName(tmp->attr))) &&
11384 (xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr ),
11385 xmlSchemaGetAttrTargetNsURI(tmp->attr)))) {
Daniel Veillard3646d642004-06-02 19:19:14 +000011386
Daniel Veillardc0826a72004-08-10 14:17:33 +000011387 xmlSchemaPAttrUseErr(ctxt,
11388 XML_SCHEMAP_CT_PROPS_CORRECT_4,
11389 NULL, type, NULL, tmp->attr,
11390 "Duplicate attribute use specified", NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +000011391 break;
11392 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011393 tmp = tmp->next;
Daniel Veillard50355f02004-06-08 17:52:16 +000011394 }
11395 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011396 /*
11397 * 5. Two distinct attribute declarations in the {attribute uses} must
11398 * not have {type definition}s which are or are derived from ID.
11399 */
11400 if ((cur->attr->subtypes != NULL) &&
Daniel Veillard01fa6152004-06-29 17:04:39 +000011401 (xmlSchemaIsDerivedFromBuiltInType(ctxt, (xmlSchemaTypePtr) cur->attr, XML_SCHEMAS_ID))) {
Daniel Veillard3646d642004-06-02 19:19:14 +000011402 if (id != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011403 xmlSchemaPAttrUseErr(ctxt,
11404 XML_SCHEMAP_CT_PROPS_CORRECT_5,
11405 NULL, type, NULL, cur->attr,
11406 "There must not exist more than one attribute use, "
11407 "declared of type 'ID' or derived from it",
11408 NULL);
11409 FREE_AND_NULL(str)
Daniel Veillard50355f02004-06-08 17:52:16 +000011410 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011411 id = cur;
11412 }
11413 /*
11414 * Remove "prohibited" attribute uses. The reason this is done at this late
11415 * stage is to be able to catch dublicate attribute uses. So we had to keep
11416 * prohibited uses in the list as well.
11417 */
11418 if (cur->attr->occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) {
11419 tmp = cur;
11420 if (prev == NULL)
11421 type->attributeUses = cur->next;
11422 else
11423 prev->next = cur->next;
11424 cur = cur->next;
Daniel Veillard50355f02004-06-08 17:52:16 +000011425 xmlFree(tmp);
Daniel Veillard3646d642004-06-02 19:19:14 +000011426 } else {
11427 prev = cur;
11428 cur = cur->next;
11429 }
11430 }
11431 }
11432 /*
11433 * TODO: This check should be removed if we are 100% sure of
11434 * the base type attribute uses already being built.
11435 */
11436 if ((baseType != NULL) && (!baseIsAnyType) &&
11437 (baseType->type == XML_SCHEMA_TYPE_COMPLEX) &&
11438 (baseType->contentType == XML_SCHEMA_CONTENT_UNKNOWN)) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000011439 xmlSchemaPErr(ctxt, baseType->node, XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011440 "Internal error: xmlSchemaBuildAttributeValidation: "
Daniel Veillardc0826a72004-08-10 14:17:33 +000011441 "attribute uses not builded on base type '%s'.\n",
Daniel Veillard3646d642004-06-02 19:19:14 +000011442 baseType->name, NULL);
11443 }
11444 return (0);
11445}
11446
11447/**
Daniel Veillard01fa6152004-06-29 17:04:39 +000011448 * xmlSchemaTypeFinalContains:
11449 * @schema: the schema
11450 * @type: the type definition
11451 * @final: the final
11452 *
11453 * Evaluates if a type definition contains the given "final".
11454 * This does take "finalDefault" into account as well.
11455 *
11456 * Returns 1 if the type does containt the given "final",
11457 * 0 otherwise.
11458 */
11459static int
11460xmlSchemaTypeFinalContains(xmlSchemaPtr schema, xmlSchemaTypePtr type, int final)
11461{
11462 int tfinal = final, tflags = type->flags;
11463
11464 if (type == NULL)
11465 return (0);
11466 if (type->flags & XML_SCHEMAS_TYPE_FINAL_DEFAULT) {
11467 switch (final) {
11468 case XML_SCHEMAS_TYPE_FINAL_RESTRICTION:
11469 tfinal = XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION;
11470 break;
11471 case XML_SCHEMAS_TYPE_FINAL_EXTENSION:
11472 tfinal = XML_SCHEMAS_FINAL_DEFAULT_EXTENSION;
11473 break;
11474 case XML_SCHEMAS_TYPE_FINAL_LIST:
11475 tfinal = XML_SCHEMAS_FINAL_DEFAULT_LIST;
11476 break;
11477 case XML_SCHEMAS_TYPE_FINAL_UNION:
11478 tfinal = XML_SCHEMAS_FINAL_DEFAULT_UNION;
11479 break;
11480 }
11481 tflags = schema->flags;
11482 }
11483 if (tflags & tfinal)
11484 return (1);
11485 else
11486 return (0);
11487
11488}
11489
11490/**
11491 * xmlSchemaGetUnionSimpleTypeMemberTypes:
11492 * @type: the Union Simple Type
11493 *
11494 * Returns a list of member types of @type if existing,
11495 * returns NULL otherwise.
11496 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011497static xmlSchemaTypeLinkPtr
Daniel Veillard01fa6152004-06-29 17:04:39 +000011498xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type)
11499{
11500 while (type != NULL) {
11501 if (type->memberTypes != NULL)
11502 return (type->memberTypes);
11503 else
11504 type = type->baseType;
11505 }
11506 return (NULL);
11507}
11508
11509/**
11510 * xmlSchemaGetListSimpleTypeItemType:
11511 * @type: the simple type definition
11512 *
11513 * Returns the item type definition of the list simple type.
11514 */
11515static xmlSchemaTypePtr
11516xmlSchemaGetListSimpleTypeItemType(xmlSchemaTypePtr type)
11517{
11518 if ((type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) == 0)
11519 return (NULL);
11520 /*
11521 * Note: In libxml2, the built-in types do not reflect
11522 * the datatype hierarchy (yet?) - we have to treat them
11523 * in a special way.
11524 */
11525 if (type->type == XML_SCHEMA_TYPE_BASIC)
11526 return (xmlSchemaGetBuiltInListSimpleTypeItemType(type));
11527 if (type->subtypes->type == XML_SCHEMA_TYPE_LIST)
11528 /* 1 If the <list> alternative is chosen, then the type
11529 * definition ·resolved· to by the ·actual value· of the
11530 * itemType [attribute] of <list>, if present, otherwise
11531 * the type definition corresponding to the <simpleType>
11532 * among the [children] of <list>.
11533 */
11534 return (type->subtypes->subtypes);
11535 else {
11536 /* 2 If the <restriction> option is chosen, then the
11537 * {item type definition} of the {base type definition}.
11538 */
11539 return (xmlSchemaGetListSimpleTypeItemType(type->baseType));
11540 }
11541}
11542
11543/**
11544 * xmlSchemaCheckCOSSTDerivedOK:
11545 * @type: the derived simple type definition
11546 * @baseType: the base type definition
11547 *
11548 * Checks wheter @type can be validly
11549 * derived from @baseType.
11550 *
11551 * Returns 0 on success, an positive error code otherwise.
11552 */
11553static int
11554xmlSchemaCheckCOSSTDerivedOK(xmlSchemaPtr schema,
11555 xmlSchemaTypePtr type,
11556 xmlSchemaTypePtr baseType,
11557 int subset)
11558{
11559 /*
11560 * Schema Component Constraint: Type Derivation OK (Simple)
11561 *
11562 *
11563 * 1 They are the same type definition.
11564 * TODO: The identy check might have to be more complex than this.
11565 */
11566 if (type == baseType)
11567 return (0);
11568 /*
11569 * 2.1 restriction is not in the subset, or in the {final}
11570 * of its own {base type definition};
11571 */
11572 if ((subset & XML_SCHEMAS_TYPE_FINAL_RESTRICTION) ||
11573 (xmlSchemaTypeFinalContains(schema,
11574 type->baseType, XML_SCHEMAS_TYPE_FINAL_RESTRICTION))) {
11575 return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_1);
11576 }
11577 /* 2.2 */
11578 if (type->baseType == baseType) {
11579 /*
11580 * 2.2.1 D's ·base type definition· is B.
11581 */
11582 return (0);
11583 }
11584 /*
11585 * 2.2.2 D's ·base type definition· is not the ·ur-type definition·
11586 * and is validly derived from B given the subset, as defined by this
11587 * constraint.
11588 */
11589 if ((type->baseType != xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE)) &&
11590 (xmlSchemaCheckCOSSTDerivedOK(schema, type->baseType, baseType, subset) == 0)) {
11591 return (0);
11592 }
11593 /*
11594 * 2.2.3 D's {variety} is list or union and B is the ·simple ur-type
11595 * definition·.
11596 */
11597 if (((type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) ||
11598 (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION)) &&
11599 (baseType == xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE))) {
11600 return (0);
11601 }
11602 /*
11603 * 2.2.4 B's {variety} is union and D is validly derived from a type
11604 * definition in B's {member type definitions} given the subset, as
11605 * defined by this constraint.
11606 *
11607 * NOTE: This seems not to involve built-in types, since there is no
11608 * built-in Union Simple Type.
11609 */
11610 if (baseType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
11611 xmlSchemaTypeLinkPtr cur;
11612
11613 cur = baseType->memberTypes;
11614 while (cur != NULL) {
11615 if (xmlSchemaCheckCOSSTDerivedOK(schema, type,
11616 cur->type, subset) == 0)
11617 return (0);
11618 cur = cur->next;
11619 }
11620 }
11621
11622 return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_2);
11623}
11624
11625
11626/**
11627 * xmlSchemaCheckSTPropsCorrect:
11628 * @ctxt: the schema parser context
11629 * @type: the simple type definition
11630 *
11631 * Checks st-props-correct.
11632 *
11633 * Returns 0 if the properties are correct,
11634 * if not, a positive error code and -1 on internal
11635 * errors.
11636 */
11637static int
11638xmlSchemaCheckSTPropsCorrect(xmlSchemaParserCtxtPtr ctxt,
11639 xmlSchemaTypePtr type)
11640{
11641 xmlSchemaTypePtr baseType = type->baseType, anySimpleType,
11642 anyType;
Daniel Veillardc0826a72004-08-10 14:17:33 +000011643 xmlChar *str = NULL;
Daniel Veillard01fa6152004-06-29 17:04:39 +000011644
Daniel Veillardc0826a72004-08-10 14:17:33 +000011645 /* STATE: error funcs converted. */
Daniel Veillard01fa6152004-06-29 17:04:39 +000011646 /*
11647 * Schema Component Constraint: Simple Type Definition Properties Correct
11648 *
11649 * NOTE: This is somehow redundant, since we actually built a simple type
11650 * to have all the needed information; this acts as an self test.
11651 */
11652 anySimpleType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
11653 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
11654 /*
11655 * TODO: 1 The values of the properties of a simple type definition must be as
11656 * described in the property tableau in Datatype definition, modulo the
11657 * impact of Missing Sub-components (§5.3).
11658 */
11659 /* Base type: If the datatype has been ·derived· by ·restriction·
11660 * then the Simple Type Definition component from which it is ·derived·,
11661 * otherwise the Simple Type Definition for anySimpleType (§4.1.6).
11662 */
11663 if (baseType == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011664 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011665 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011666 NULL, type, NULL,
11667 "No base type existent", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011668 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
11669 }
11670 if ((baseType->type != XML_SCHEMA_TYPE_SIMPLE) &&
11671 ((baseType->type != XML_SCHEMA_TYPE_BASIC) ||
11672 (baseType == anyType))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011673 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011674 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011675 NULL, type, NULL,
11676 "The base type %s is not a simple type",
11677 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
11678 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011679 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
11680 }
11681 if ((baseType != anySimpleType) &&
11682 (type->subtypes->type != XML_SCHEMA_TYPE_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011683 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011684 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011685 NULL, type, NULL,
11686 "A type, derived by list or union, must have"
11687 "the simple ur-type definition as base type, not %s",
11688 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
11689 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011690 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
11691 }
11692 /*
11693 * Variety: One of {atomic, list, union}.
11694 */
11695 if (((type->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) &&
11696 ((type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) == 0) &&
11697 ((type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) == 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011698 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011699 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011700 NULL, type, NULL,
11701 "The variety is absent", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011702 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
11703 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000011704 /* TODO: Finish this. Hmm, is this finished? */
Daniel Veillard01fa6152004-06-29 17:04:39 +000011705
11706 /*
11707 * 2 All simple type definitions must be derived ultimately from the ·simple
11708 * ur-type definition (so· circular definitions are disallowed). That is, it
11709 * must be possible to reach a built-in primitive datatype or the ·simple
11710 * ur-type definition· by repeatedly following the {base type definition}.
11711 */
11712 baseType = type->baseType;
11713 while ((baseType != NULL) && (baseType->type != XML_SCHEMA_TYPE_BASIC)) {
11714 if (baseType->contentType == XML_SCHEMA_CONTENT_UNKNOWN)
11715 xmlSchemaTypeFixup(baseType, ctxt, NULL);
11716 if (baseType == anySimpleType)
11717 break;
11718 else if (baseType == type) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011719 xmlSchemaPCustomErr(ctxt,
11720 XML_SCHEMAP_ST_PROPS_CORRECT_2,
11721 NULL, type, NULL,
11722 "The definition is circular", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011723 return (XML_SCHEMAP_ST_PROPS_CORRECT_2);
11724 }
11725 baseType = baseType->baseType;
11726 }
11727 /*
11728 * 3 The {final} of the {base type definition} must not contain restriction.
11729 */
11730 if (xmlSchemaTypeFinalContains(ctxt->schema, baseType,
11731 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011732 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011733 XML_SCHEMAP_ST_PROPS_CORRECT_3,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011734 NULL, type, NULL,
11735 "The 'final' of its base type %s must not contain "
11736 "'restriction'",
11737 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
11738 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011739 return (XML_SCHEMAP_ST_PROPS_CORRECT_3);
11740 }
11741 return (0);
11742}
11743
11744/**
11745 * xmlSchemaCheckDerivationValidSimpleRestriction:
11746 * @ctxt: the schema parser context
11747 * @type: the simple type definition
11748 *
11749 * Checks if the given @type (simpleType) is derived
11750 * validly by restriction.
11751 *
11752 * Returns -1 on internal errors, 0 if the type is validly derived,
11753 * a positive error code otherwise.
11754 */
11755static int
11756xmlSchemaCheckCOSSTRestricts(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011757 xmlSchemaTypePtr type)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011758{
Daniel Veillardc0826a72004-08-10 14:17:33 +000011759 xmlChar *str = NULL;
11760
11761 /* STATE: error funcs converted. */
Daniel Veillard01fa6152004-06-29 17:04:39 +000011762
11763 if (type->type != XML_SCHEMA_TYPE_SIMPLE) {
11764 xmlSchemaPErr(ctxt, type->node,
11765 XML_ERR_INTERNAL_ERROR,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011766 "xmlSchemaCheckDerivationValidSimpleRestriction: The given "
11767 "type '%s' is not a user-derived simpleType.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000011768 type->name, NULL);
11769 return (-1);
11770 }
11771
11772 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) {
11773 xmlSchemaTypePtr primitive;
11774 /*
11775 * 1.1 The {base type definition} must be an atomic simple
11776 * type definition or a built-in primitive datatype.
11777 */
11778 if ((type->baseType->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011779 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011780 XML_SCHEMAP_COS_ST_RESTRICTS_1_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011781 NULL, type, NULL,
11782 "The base type %s is not an atomic simple type",
11783 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
11784 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011785 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_1);
11786 }
11787 /* 1.2 The {final} of the {base type definition} must not contain
11788 * restriction.
11789 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000011790 /* OPTIMIZE TODO : This is already done in xmlSchemaCheckStPropsCorrect */
Daniel Veillard01fa6152004-06-29 17:04:39 +000011791 if (xmlSchemaTypeFinalContains(ctxt->schema, type->baseType,
11792 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011793 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011794 XML_SCHEMAP_COS_ST_RESTRICTS_1_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011795 NULL, type, NULL,
11796 "The final of its base type %s must not contain 'restriction'",
11797 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
11798 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011799 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_2);
11800 }
11801
11802 /*
11803 * 1.3.1 DF must be an allowed constraining facet for the {primitive
11804 * type definition}, as specified in the appropriate subsection of 3.2
11805 * Primitive datatypes.
11806 */
11807 if (type->facets != NULL) {
11808 xmlSchemaFacetPtr facet;
11809 int ok = 1;
11810
11811 primitive = xmlSchemaGetPrimitiveType(type);
11812 if (primitive == NULL) {
11813 xmlSchemaPErr(ctxt, type->node,
11814 XML_ERR_INTERNAL_ERROR,
11815 "xmlSchemaCheckDerivationValidSimpleRestriction: failed "
Daniel Veillardc0826a72004-08-10 14:17:33 +000011816 "to get primitive type of type '%s'.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000011817 type->name, NULL);
11818 return (-1);
11819 }
11820 facet = type->facets;
11821 do {
11822 if (xmlSchemaIsBuiltInTypeFacet(primitive, facet->type) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011823 ok = 0;
11824 xmlSchemaPIllegalFacetAtomicErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011825 XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011826 NULL, type, primitive, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011827 }
11828 facet = facet->next;
11829 } while (facet != NULL);
11830 if (ok == 0)
Daniel Veillardc0826a72004-08-10 14:17:33 +000011831 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011832 }
11833 /*
11834 * TODO: 1.3.2 (facet derivation)
11835 */
11836 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
11837 xmlSchemaTypePtr itemType = NULL;
11838
11839 itemType = xmlSchemaGetListSimpleTypeItemType(type);
11840 if (itemType == NULL) {
11841 xmlSchemaPErr(ctxt, type->node,
11842 XML_ERR_INTERNAL_ERROR,
11843 "Internal error: xmlSchemaCheckDerivationValidSimpleRestriction: "
Daniel Veillardc0826a72004-08-10 14:17:33 +000011844 "failed to evaluate the item type of type '%s'.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000011845 type->name, NULL);
11846 return (-1);
11847 }
11848 /*
11849 * 2.1 The {item type definition} must have a {variety} of atomic or
11850 * union (in which case all the {member type definitions}
11851 * must be atomic).
11852 */
11853 if (((itemType->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) &&
11854 ((itemType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) == 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011855 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011856 XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011857 NULL, type, NULL,
11858 "The item type %s must have a variety of atomic or union",
11859 xmlSchemaFormatItemForReport(&str, NULL, itemType, NULL, 1));
11860 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011861 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
11862 } else if (itemType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
11863 xmlSchemaTypeLinkPtr member;
11864
11865 member = itemType->memberTypes;
11866 while (member != NULL) {
11867 if ((member->type->flags &
11868 XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011869 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011870 XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011871 NULL, type, NULL,
11872 "The item type is a union type, but the "
11873 "member type %s of this item type is not atomic",
11874 xmlSchemaFormatItemForReport(&str, NULL, member->type, NULL, 1));
11875 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011876 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
11877 }
11878 member = member->next;
11879 }
11880 }
11881
11882 if (type->baseType == xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE)) {
11883 xmlSchemaFacetPtr facet;
11884 /*
11885 * This is the case if we have: <simpleType><list ..
11886 */
11887 /*
11888 * 2.3.1
11889 * 2.3.1.1 The {final} of the {item type definition} must not
11890 * contain list.
11891 */
11892 if (xmlSchemaTypeFinalContains(ctxt->schema,
11893 itemType, XML_SCHEMAS_TYPE_FINAL_LIST)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011894 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011895 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011896 NULL, type, NULL,
11897 "The final of its item type %s must not contain 'list'",
11898 xmlSchemaFormatItemForReport(&str, NULL, itemType, NULL, 1));
11899 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011900 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1);
11901 }
11902 /*
11903 * 2.3.1.2 The {facets} must only contain the whiteSpace
11904 * facet component.
11905 */
11906 if (type->facets != NULL) {
11907 facet = type->facets;
11908 do {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011909 if (facet->type != XML_SCHEMA_FACET_WHITESPACE) {
11910 xmlSchemaPIllegalFacetListUnionErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011911 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011912 NULL, type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011913 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2);
11914 }
11915 facet = facet->next;
11916 } while (facet != NULL);
11917 }
11918 /*
11919 * TODO: Datatypes states:
11920 * A ·list· datatype can be ·derived· from an ·atomic· datatype
11921 * whose ·lexical space· allows space (such as string or anyURI)or
11922 * a ·union· datatype any of whose {member type definitions}'s
11923 * ·lexical space· allows space.
11924 */
11925 } else {
11926 /*
11927 * This is the case if we have: <simpleType><restriction ...
11928 */
11929 /*
11930 * 2.3.2
11931 * 2.3.2.1 The {base type definition} must have a {variety} of list.
11932 */
11933 if ((type->baseType->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011934 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011935 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011936 NULL, type, NULL,
11937 "The base type %s must be a list type",
11938 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
11939 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011940 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1);
11941 }
11942 /*
11943 * 2.3.2.2 The {final} of the {base type definition} must not
11944 * contain restriction.
11945 */
11946 if (xmlSchemaTypeFinalContains(ctxt->schema, type->baseType,
11947 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011948 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011949 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011950 NULL, type, NULL,
11951 "The final of the base type %s must not contain 'restriction'",
11952 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
11953 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011954 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2);
11955 }
11956 /*
11957 * 2.3.2.3 The {item type definition} must be validly derived
11958 * from the {base type definition}'s {item type definition} given
11959 * the empty set, as defined in Type Derivation OK (Simple) (§3.14.6).
11960 */
11961 {
11962 xmlSchemaTypePtr baseItemType;
11963
11964 baseItemType = xmlSchemaGetListSimpleTypeItemType(type->baseType);
11965 if (baseItemType == NULL) {
11966 xmlSchemaPErr(ctxt, type->node,
11967 XML_ERR_INTERNAL_ERROR,
11968 "xmlSchemaCheckDerivationValidSimpleRestriction: "
Daniel Veillardc0826a72004-08-10 14:17:33 +000011969 "List simple type '%s': Failed to "
11970 "evaluate the item type of its base type '%s'.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000011971 type->name, type->baseType->name);
11972 return (-1);
11973 }
11974 if ((itemType != baseItemType) &&
11975 (xmlSchemaCheckCOSSTDerivedOK(ctxt->schema, itemType,
11976 baseItemType, 0) != 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011977 xmlChar *strBIT = NULL, *strBT = NULL;
11978 xmlSchemaPCustomErrExt(ctxt,
11979 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3,
11980 NULL, type, NULL,
11981 "The item type %s is not validly derived from the "
11982 "item type %s of the base type %s",
11983 xmlSchemaFormatItemForReport(&str, NULL, itemType, NULL, 1),
11984 xmlSchemaFormatItemForReport(&strBIT, NULL, baseItemType, NULL, 1),
11985 xmlSchemaFormatItemForReport(&strBT, NULL, type->baseType, NULL, 1));
11986
11987 FREE_AND_NULL(str)
11988 FREE_AND_NULL(strBIT)
11989 FREE_AND_NULL(strBT)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011990 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3);
11991 }
11992 }
11993
11994 if (type->facets != NULL) {
11995 xmlSchemaFacetPtr facet;
11996 int ok = 1;
11997 /*
11998 * 2.3.2.4 Only length, minLength, maxLength, whiteSpace, pattern
11999 * and enumeration facet components are allowed among the {facets}.
12000 */
12001 facet = type->facets;
12002 do {
12003 switch (facet->type) {
12004 case XML_SCHEMA_FACET_LENGTH:
12005 case XML_SCHEMA_FACET_MINLENGTH:
12006 case XML_SCHEMA_FACET_MAXLENGTH:
12007 case XML_SCHEMA_FACET_WHITESPACE:
12008 /*
12009 * TODO: 2.5.1.2 List datatypes
12010 * The value of ·whiteSpace· is fixed to the value collapse.
12011 */
12012 case XML_SCHEMA_FACET_PATTERN:
12013 case XML_SCHEMA_FACET_ENUMERATION:
12014 break;
12015 default: {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012016 xmlSchemaPIllegalFacetListUnionErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012017 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012018 NULL, type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012019 /*
12020 * We could return, but it's nicer to report all
12021 * invalid facets.
12022 */
12023 ok = 0;
12024 }
12025 }
12026 facet = facet->next;
12027 } while (facet != NULL);
12028 if (ok == 0)
12029 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4);
12030 /*
12031 * TODO: 2.3.2.5 For each facet in the {facets} (call this DF), if there
12032 * is a facet of the same kind in the {facets} of the {base type
12033 * definition} (call this BF),then the DF's {value} must be a valid
12034 * restriction of BF's {value} as defined in [XML Schemas: Datatypes].
12035 */
12036 }
12037
12038
12039 }
12040 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
12041 /*
12042 * 3.1 The {member type definitions} must all have {variety} of
12043 * atomic or list.
12044 */
12045 xmlSchemaTypeLinkPtr member;
12046
12047 member = type->memberTypes;
12048 while (member != NULL) {
12049 if (((member->type->flags &
12050 XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) &&
12051 ((member->type->flags &
12052 XML_SCHEMAS_TYPE_VARIETY_LIST) == 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012053 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012054 XML_SCHEMAP_COS_ST_RESTRICTS_3_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012055 NULL, type, NULL,
12056 "The member type %s is neither an atomic, nor a list type",
12057 xmlSchemaFormatItemForReport(&str, NULL, member->type, NULL, 1));
12058 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012059 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_1);
12060 }
12061 member = member->next;
12062 }
12063 /*
12064 * 3.3.1 If the {base type definition} is the ·simple ur-type
12065 * definition·
12066 */
12067 if (type->baseType == xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE)) {
12068 /*
12069 * 3.3.1.1 All of the {member type definitions} must have a
12070 * {final} which does not contain union.
12071 */
12072 member = type->memberTypes;
12073 while (member != NULL) {
12074 if (xmlSchemaTypeFinalContains(ctxt->schema, member->type,
12075 XML_SCHEMAS_TYPE_FINAL_UNION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012076 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012077 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012078 NULL, type, NULL,
12079 "The final of member type %s contains 'union'",
12080 xmlSchemaFormatItemForReport(&str, NULL, member->type, NULL, 1));
12081 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012082 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1);
12083 }
12084 member = member->next;
12085 }
12086 /*
12087 * 3.3.1.2 The {facets} must be empty.
12088 */
12089 if (type->facetSet != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012090 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012091 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012092 NULL, type, NULL,
12093 "No facets allowed", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012094 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2);
12095 }
12096 } else {
12097 /*
12098 * 3.3.2.1 The {base type definition} must have a {variety} of union.
12099 */
12100 if ((type->baseType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012101 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012102 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012103 NULL, type, NULL,
12104 "The base type %s is not a union type",
12105 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
12106 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012107 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1);
12108 }
12109 /*
12110 * 3.3.2.2 The {final} of the {base type definition} must not contain restriction.
12111 */
12112 if (xmlSchemaTypeFinalContains(ctxt->schema, type->baseType,
12113 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012114 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012115 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012116 NULL, type, NULL,
12117 "The final of its base type %s must not contain 'restriction'",
12118 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
12119 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012120 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2);
12121 }
12122 /*
12123 * 3.3.2.3 The {member type definitions}, in order, must be validly
12124 * derived from the corresponding type definitions in the {base
12125 * type definition}'s {member type definitions} given the empty set,
12126 * as defined in Type Derivation OK (Simple) (§3.14.6).
12127 */
12128 {
12129 xmlSchemaTypeLinkPtr baseMember;
12130
12131 /*
12132 * OPTIMIZE: if the type is restricting, it has no local defined
12133 * member types and inherits the member types of the base type;
12134 * thus a check for equality can be skipped.
12135 */
12136 /*
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000012137 * Even worse: I cannot see a scenario where a restricting
Daniel Veillard01fa6152004-06-29 17:04:39 +000012138 * union simple type can have other member types as the member
12139 * types of it's base type. This check seems not necessary with
12140 * respect to the derivation process in libxml2.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000012141 * But necessary if constructing types with an API.
Daniel Veillard01fa6152004-06-29 17:04:39 +000012142 */
12143 if (type->memberTypes != NULL) {
12144 member = type->memberTypes;
12145 baseMember = xmlSchemaGetUnionSimpleTypeMemberTypes(type->baseType);
12146 if ((member == NULL) && (baseMember != NULL)) {
12147 xmlSchemaPErr(ctxt, type->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012148 XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012149 "Internal error: "
12150 "xmlSchemaCheckDerivationValidSimpleRestriction "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012151 "(3.3.2.3), union simple type '%s', unequal number "
Daniel Veillard01fa6152004-06-29 17:04:39 +000012152 "of member types in the base type\n",
12153 type->name, NULL);
12154 }
12155 while (member != NULL) {
12156 if (baseMember == NULL) {
12157 xmlSchemaPErr(ctxt, type->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012158 XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012159 "Internal error: "
12160 "xmlSchemaCheckDerivationValidSimpleRestriction "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012161 "(3.3.2.3), union simple type '%s', unequal number "
12162 "of member types in the base type.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000012163 type->name, NULL);
12164 }
12165 if ((member->type != baseMember->type) &&
12166 (xmlSchemaCheckCOSSTDerivedOK(ctxt->schema,
12167 member->type, baseMember->type, 0) != 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012168 xmlChar *strBMT = NULL, *strBT = NULL;
12169
12170 xmlSchemaPCustomErrExt(ctxt,
12171 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3,
12172 NULL, type, NULL,
12173 "The member type %s is not validly derived from its "
12174 "corresponding member type %s of the base type %s",
12175 xmlSchemaFormatItemForReport(&str, NULL, member->type, NULL, 1),
12176 xmlSchemaFormatItemForReport(&strBMT, NULL, baseMember->type, NULL, 1),
12177 xmlSchemaFormatItemForReport(&strBT, NULL, type->baseType, NULL, 1));
12178 FREE_AND_NULL(str)
12179 FREE_AND_NULL(strBMT)
12180 FREE_AND_NULL(strBT)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012181 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3);
12182 }
12183 member = member->next;
12184 baseMember = baseMember->next;
12185 }
12186 }
12187 }
12188 /*
12189 * 3.3.2.4 Only pattern and enumeration facet components are
12190 * allowed among the {facets}.
12191 */
12192 if (type->facets != NULL) {
12193 xmlSchemaFacetPtr facet;
12194 int ok = 1;
12195
12196 facet = type->facets;
12197 do {
12198 if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
12199 (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012200 xmlSchemaPIllegalFacetListUnionErr(ctxt,
12201 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4,
12202 NULL, type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012203 ok = 0;
12204 }
12205 facet = facet->next;
12206 } while (facet != NULL);
12207 if (ok == 0)
12208 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4);
12209
12210 }
12211 /*
12212 * TODO: 3.3.2.5 (facet derivation)
12213 */
12214 }
12215 }
12216
12217 return (0);
12218}
12219
12220/**
12221 * xmlSchemaCheckSRCSimpleType:
12222 * @ctxt: the schema parser context
12223 * @type: the simple type definition
12224 *
12225 * Checks crc-simple-type constraints.
12226 *
12227 * Returns 0 if the constraints are satisfied,
12228 * if not a positive error code and -1 on internal
12229 * errors.
12230 */
12231static int
12232xmlSchemaCheckSRCSimpleType(xmlSchemaParserCtxtPtr ctxt,
12233 xmlSchemaTypePtr type)
12234{
12235 /*
12236 * NOTE: src-simple-type 2-4 are redundant, since the checks
12237 * were are done for the corresponding <restriction>, <list> and <union>
12238 * elements, but W3C wants a <simpleType> error as well, so it gets one.
12239 * Maby this can be skipped in the future, if we get sure it's not needed.
12240 */
12241 if (type->subtypes == NULL) {
12242 xmlSchemaPErr(ctxt, type->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012243 XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012244 "Internal error: xmlSchemaCheckSRCSimpleType, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012245 "no subtype on simple type '%s'.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000012246 type->name, NULL);
12247 return (-1);
12248 }
12249 /*
12250 * src-simple-type.1 The corresponding simple type definition, if any,
12251 * must satisfy the conditions set out in Constraints on Simple Type
12252 * Definition Schema Components (§3.14.6).
12253 */
12254 if ((xmlSchemaCheckSTPropsCorrect(ctxt, type) != 0) ||
12255 (xmlSchemaCheckCOSSTRestricts(ctxt, type) != 0)) {
12256 /*
12257 * TODO: Removed this, since it got annoying to get an
12258 * extra error report, if anything failed until now.
12259 * Enable this if needed.
12260 */
12261 /*
12262 xmlSchemaPErr(ctxt, type->node,
12263 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012264 "Simple type '%s' does not satisfy the constraints "
Daniel Veillard01fa6152004-06-29 17:04:39 +000012265 "on simple type definitions.\n",
12266 type->name, NULL);
12267 */
12268 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_1);
12269 }
12270
12271 if (type->subtypes->type == XML_SCHEMA_TYPE_RESTRICTION) {
12272 /*
12273 * src-simple-type.2 If the <restriction> alternative is chosen,
12274 * either it must have a base [attribute] or a <simpleType> among its
12275 * [children], but not both.
12276 */
William M. Brack2f2a6632004-08-20 23:09:47 +000012277 /*
12278 * XML_SCHEMAP_SRC_SIMPLE_TYPE_2
12279 * NOTE: This was removed, since this will be already handled
12280 * in the parse function for <restriction>.
12281 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000012282 } else if (type->subtypes->type == XML_SCHEMA_TYPE_LIST) {
12283 /* src-simple-type.3 If the <list> alternative is chosen, either it must have
12284 * an itemType [attribute] or a <simpleType> among its [children],
12285 * but not both.
12286 * NOTE: baseType is set to the local simple type definiton,
12287 * if existent, at parse time. This is a hack and not nice.
12288 */
William M. Brack2f2a6632004-08-20 23:09:47 +000012289 /*
12290 * TODO: Remove this, and add the check to the parse function of <list>.
12291 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000012292 if (((type->subtypes->base == NULL) &&
12293 (type->baseType == NULL)) ||
12294 ((type->subtypes->base != NULL) &&
12295 (type->subtypes->baseType != NULL))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012296 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012297 XML_SCHEMAP_SRC_SIMPLE_TYPE_3,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012298 NULL, type, NULL,
12299 "Either the attribute 'itemType' or the <simpleType> child "
12300 "must be present on the <list> child ", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012301 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_3);
12302 }
12303
12304
12305 } else if (type->subtypes->type == XML_SCHEMA_TYPE_UNION) {
12306 xmlSchemaTypeLinkPtr member;
12307 xmlSchemaTypePtr ancestor, anySimpleType;
12308
12309 anySimpleType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
12310
12311 /* src-simple-type.4 Circular union type definition is disallowed. That is, if
12312 * the <union> alternative is chosen, there must not be any entries
12313 * in the memberTypes [attribute] at any depth which resolve to the
12314 * component corresponding to the <simpleType>.
12315 */
12316 member = type->memberTypes;
12317 while (member != NULL) {
12318 ancestor = member->type;
12319 while ((ancestor != NULL) && (ancestor->type != XML_SCHEMA_TYPE_BASIC)) {
12320 if (ancestor->contentType == XML_SCHEMA_CONTENT_UNKNOWN)
12321 xmlSchemaTypeFixup(ancestor, ctxt, NULL);
12322 if (ancestor == anySimpleType)
12323 break;
12324 else if (ancestor == type) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012325 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012326 XML_SCHEMAP_SRC_SIMPLE_TYPE_4,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012327 NULL, type, NULL,
12328 "The definition is circular", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012329 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_4);
12330 } else if (ancestor->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
12331 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000012332 * TODO, FIXME: Although a list simple type must not have a union ST
Daniel Veillard01fa6152004-06-29 17:04:39 +000012333 * type as item type, which in turn has a list ST as member
12334 * type, we will assume this here as well, since this check
12335 * was not yet performed.
12336 */
12337
12338 }
12339 ancestor = ancestor->baseType;
12340 }
12341 member = member->next;
12342 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000012343 }
12344
12345 return (0);
12346}
12347
William M. Brack2f2a6632004-08-20 23:09:47 +000012348#if 0 /* Not yet used code for CT schema validation */
12349static int
12350xmlSchemaCheckCVCSimpleType(xmlSchemaValidCtxtPtr ctxt,
12351 const xmlChar * value,
12352 xmlSchemaTypePtr type,
12353 int fireErrors)
12354{
12355 int ret;
12356 /*
12357 * 3.14.4 Simple Type Definition Validation Rules
12358 * Validation Rule: String Valid
12359 */
12360 /*
12361 * 1 It is schema-valid with respect to that definition as defined
12362 * by Datatype Valid in [XML Schemas: Datatypes].
12363 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012364 ret = xmlSchemaValidateSimpleTypeValue(ctxt, type, value,
12365 fireErrors, 1, 1, 1);
William M. Brack2f2a6632004-08-20 23:09:47 +000012366 return (ret);
12367 /*
12368 * 2.1 If The definition is ENTITY or is validly derived from ENTITY given
12369 * the empty set, as defined in Type Derivation OK (Simple) (§3.14.6), then
12370 * the string must be a ·declared entity name·.
12371 */
12372 /*
12373 * 2.2 If The definition is ENTITIES or is validly derived from ENTITIES
12374 * given the empty set, as defined in Type Derivation OK (Simple) (§3.14.6),
12375 * then every whitespace-delimited substring of the string must be a ·declared
12376 * entity name·.
12377 */
12378 /*
12379 * 2.3 otherwise no further condition applies.
12380 */
12381
12382 return (0);
12383}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012384#endif
12385
William M. Brack2f2a6632004-08-20 23:09:47 +000012386
12387static int
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012388xmlSchemaCreatePCtxtOnVCtxt(xmlSchemaValidCtxtPtr vctxt)
12389{
12390 if (vctxt->pctxt == NULL) {
12391 vctxt->pctxt =xmlSchemaNewParserCtxtUseDict("*", vctxt->schema->dict);
12392 /* vctxt->pctxt = xmlSchemaNewParserCtxt("*"); */
12393 if (vctxt->pctxt == NULL) {
12394 xmlSchemaVErr(vctxt, NULL,
12395 XML_SCHEMAV_INTERNAL,
12396 "Internal error: xmlSchemaCreatePCtxtOnVCtxt, "
12397 "failed to create a temp. parser context.\n",
William M. Brack2f2a6632004-08-20 23:09:47 +000012398 NULL, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012399 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012400 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012401 /* TODO: Pass user data. */
12402 xmlSchemaSetParserErrors(vctxt->pctxt, vctxt->error, vctxt->warning, NULL);
12403 }
12404 return (0);
12405}
12406
12407static int
12408xmlSchemaCreateVCtxtOnPCtxt(xmlSchemaParserCtxtPtr ctxt)
12409{
12410 if (ctxt->vctxt == NULL) {
12411 ctxt->vctxt = xmlSchemaNewValidCtxt(NULL);
12412 if (ctxt->vctxt == NULL) {
12413 xmlSchemaPErr(ctxt, NULL,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012414 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012415 "Internal error: xmlSchemaCreatePCtxtOnVCtxt, "
12416 "failed to create a temp. validation context.\n",
12417 NULL, NULL);
12418 return (-1);
12419 }
12420 /* TODO: Pass user data. */
12421 xmlSchemaSetValidErrors(ctxt->vctxt, ctxt->error, ctxt->warning, NULL);
12422 }
12423 return (0);
12424}
12425
12426/**
12427 * xmlSchemaCheckCOSValidDefault:
12428 * @ctxt: the schema parser context
12429 * @type: the simple type definition
12430 * @value: the default value
12431 * @node: an optional node (the holder of the value)
12432 *
12433 * Checks the "cos-valid-default" constraints.
12434 *
12435 * Returns 0 if the constraints are satisfied,
12436 * if not, a positive error code and -1 on internal
12437 * errors.
12438 */
12439static int
12440xmlSchemaCheckCOSValidDefault(xmlSchemaParserCtxtPtr pctxt,
12441 xmlSchemaValidCtxtPtr vctxt,
12442 xmlSchemaTypePtr type,
12443 const xmlChar *value,
12444 xmlNodePtr node)
12445{
12446 int ret = 0;
12447
12448 /*
12449 * cos-valid-default:
12450 * Schema Component Constraint: Element Default Valid (Immediate)
12451 * For a string to be a valid default with respect to a type
12452 * definition the appropriate case among the following must be true:
12453 */
12454 /*
12455 * NOTE: This has to work without a given node (the holder of the
12456 * value), since it should work on the component, i.e. an underlying
12457 * DOM must not be mandatory.
12458 */
12459 if ((pctxt == NULL) || (vctxt == NULL)) {
12460 xmlSchemaPErr(pctxt, node,
12461 XML_SCHEMAP_INTERNAL,
12462 "Internal error: xmlSchemaCheckCOSValidDefault, "
12463 "bad arguments: the parser and/or validation context is "
12464 "missing.\n",
12465 NULL, NULL);
12466 return (-1);
12467 }
12468 if IS_COMPLEX_TYPE(type) {
William M. Brack2f2a6632004-08-20 23:09:47 +000012469 /*
12470 * Complex type.
12471 *
12472 * 2.1 its {content type} must be a simple type definition or mixed.
12473 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012474 /*
12475 * TODO: Adjust this when the content type will be computed
12476 * correctly.
12477 */
12478 if ((type->contentType != XML_SCHEMA_CONTENT_SIMPLE) &&
12479 (type->contentType != XML_SCHEMA_CONTENT_BASIC) &&
12480 (type->contentType != XML_SCHEMA_CONTENT_MIXED)) {
12481 xmlSchemaPSimpleTypeErr(pctxt,
12482 XML_SCHEMAP_COS_VALID_DEFAULT_2_1,
12483 NULL, NULL, node,
12484 type, NULL, NULL,
12485 "If the type of a constraint value is complex, its content "
12486 "type must be mixed or a simple type",
12487 NULL, NULL);
12488 return(XML_SCHEMAP_COS_VALID_DEFAULT_2_1);
12489 }
12490 if (type->contentType == XML_SCHEMA_CONTENT_MIXED) {
William M. Brack2f2a6632004-08-20 23:09:47 +000012491 /*
12492 * 2.2.2 If the {content type} is mixed, then the {content type}'s
12493 * particle must be ·emptiable· as defined by Particle Emptiable
12494 * (§3.9.6).
12495 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012496
William M. Brack2f2a6632004-08-20 23:09:47 +000012497 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012498 * URGENT TODO: Implement this.
William M. Brack2f2a6632004-08-20 23:09:47 +000012499 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012500 return (0);
William M. Brack2f2a6632004-08-20 23:09:47 +000012501 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012502 }
12503 /*
12504 * 1 If the type definition is a simple type definition, then the string
12505 * must be ·valid· with respect to that definition as defined by String
12506 * Valid (§3.14.4).
12507 *
12508 * AND
12509 *
12510 * 2.2.1 If the {content type} is a simple type definition, then the
12511 * string must be ·valid· with respect to that simple type definition
12512 * as defined by String Valid (§3.14.4).
12513 */
12514 vctxt->node = node;
12515 vctxt->cur = NULL;
12516 ret = xmlSchemaValidateSimpleTypeValue(vctxt, type, value, 1, 1, 1, 0);
12517 /* ret = xmlSchemaCheckCVCSimpleType(vctxt, elemDecl->value, typeDef, 0); */
12518 if (ret < 0) {
12519 xmlSchemaPErr(pctxt, node,
12520 /* NOTNICE: error code: This function will be used during
12521 * schema construction and xsi:type validation.
12522 */
12523 XML_SCHEMAP_INTERNAL,
12524 "Internal error: xmlSchemaCheckCOSValidDefault, "
12525 "while validating a value constaint value.\n",
12526 NULL, NULL);
12527
12528 }
12529 return (ret);
William M. Brack2f2a6632004-08-20 23:09:47 +000012530}
12531
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012532#if 0 /* Not yet used code for CT schema validation */
William M. Brack2f2a6632004-08-20 23:09:47 +000012533/**
12534 * xmlSchemaGetSTContentOfCT:
12535 * @ctxt: the schema parser context
12536 * @type: the complex type definition
12537 *
12538 *
12539 * Returns the corresponding simple type for the content of
12540 * the complex type.
12541 */
12542static xmlSchemaTypePtr
12543xmlSchemaGetSTContentOfCT(xmlSchemaParserCtxtPtr ctxt,
12544 xmlSchemaTypePtr type)
12545{
12546 xmlSchemaTypePtr orig = type, anyType;
12547
12548 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
12549 while ((type != NULL) && (type != anyType) &&
12550 (type->type == XML_SCHEMA_TYPE_COMPLEX)) {
12551 if (type->type == XML_SCHEMA_TYPE_SIMPLE)
12552 return(type);
12553 type = type->baseType;
12554 }
12555 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012556 XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000012557 NULL, orig, NULL,
12558 "Internal error: xmlSchemaGetSTContentTypeOfCT, "
12559 "no simple type for the content of complex type '%s' could be "
12560 "computed", orig->name);
12561 return (NULL);
12562}
12563
12564
William M. Brack2f2a6632004-08-20 23:09:47 +000012565
William M. Brack2f2a6632004-08-20 23:09:47 +000012566
12567/**
12568 * xmlSchemaCheckCOSCTExtends:
12569 * @ctxt: the schema parser context
12570 * @type: the complex type definition
12571 *
12572 * Schema Component Constraint: Derivation Valid (Extension)
12573 *
12574 * Returns 0 if the constraints are satisfied, a positive
12575 * error code if not and -1 if an internal error occured.
12576 */
12577static int
12578xmlSchemaCheckCOSCTExtends(xmlSchemaParserCtxtPtr ctxt,
12579 xmlSchemaTypePtr type)
12580{
12581 xmlSchemaTypePtr base;
12582 /*
12583 * 1 If the {base type definition} is a complex type definition,
12584 * then all of the following must be true:
12585 */
12586 base = type->baseType;
12587 if (base == NULL) {
12588 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012589 XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000012590 NULL, type, NULL,
12591 "Internal error: xmlSchemaCheckCOSCTExtends, "
12592 "the complex type '%s' has no base type", type->name);
12593 return (-1);
12594 }
12595 if (base->type == XML_SCHEMA_TYPE_COMPLEX) {
12596 /*
12597 * 1.1 The {final} of the {base type definition} must not
12598 * contain extension.
12599 */
12600 if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
12601 xmlSchemaPCustomErr(ctxt,
12602 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
12603 NULL, type, NULL,
12604 "The 'final' of the base type definition "
12605 "contains extension", NULL);
12606 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
12607 }
12608 /*
12609 * 1.2 Its {attribute uses} must be a subset of the {attribute uses}
12610 * of the complex type definition itself, that is, for every attribute
12611 * use in the {attribute uses} of the {base type definition}, there
12612 * must be an attribute use in the {attribute uses} of the complex
12613 * type definition itself whose {attribute declaration} has the same
12614 * {name}, {target namespace} and {type definition} as its attribute
12615 * declaration
12616 *
12617 * NOTE: This will be already satisfied by the way the attribute uses
12618 * are extended in xmlSchemaBuildAttributeValidation; thus this check
12619 * is not needed.
12620 */
12621
12622 /*
12623 * 1.3 If it has an {attribute wildcard}, the complex type definition
12624 * must also have one, and the base type definition's {attribute
12625 * wildcard}'s {namespace constraint} must be a subset of the complex
12626 * type definition's {attribute wildcard}'s {namespace constraint},
12627 * as defined by Wildcard Subset (§3.10.6).
12628 *
12629 * This is already checked in xmlSchemaBuildAttributeValidation; thus
12630 * this check is not needed.
12631 */
12632
12633 /*
12634 * 1.4 One of the following must be true:
12635 *
12636 * 1.4.1 The {content type} of the {base type definition} and the
12637 * {content type} of the complex type definition itself must be the same
12638 * simple type definition
12639 */
12640
12641
12642
12643 } else {
12644 /*
12645 * 2 If the {base type definition} is a simple type definition,
12646 * then all of the following must be true:
12647 */
12648 /*
12649 * 2.1 The {content type} must be the same simple type definition.
12650 */
12651 /*
12652 * 2.2 The {final} of the {base type definition} must not contain
12653 * extension
12654 */
12655 }
12656
12657}
12658
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012659static int
12660xmlSchemaCheckSRCCT(xmlSchemaParserCtxtPtr ctxt,
12661 xmlSchemaTypePtr type)
12662{
12663 xmlSchemaTypePtr base, content;
12664 int OK = 0;
12665
12666 /*
12667 * TODO: Adjust the error codes here, as I used
12668 * XML_SCHEMAP_SRC_CT_1 only yet.
12669 */
12670 /*
12671 * Schema Representation Constraint:
12672 * Complex Type Definition Representation OK
12673 */
12674 base = type->baseType;
12675 if (base == NULL) {
12676 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL, NULL, type, NULL,
12677 "Internal error: xmlSchemaCheckSRCCT, '%s', no base type",
12678 type->name);
12679 return (-1);
12680 }
12681
12682 if (type->subtypes != NULL) {
12683 if (type->subtypes->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
12684 if IS_COMPLEX_TYPE(base) {
12685 /*
12686 * 1 If the <complexContent> alternative is chosen, the type definition
12687 * ·resolved· to by the ·actual value· of the base [attribute]
12688 * must be a complex type definition;
12689 */
12690 xmlSchemaPCustomErr(ctxt,
12691 XML_SCHEMAP_SRC_CT_1,
12692 NULL, type, NULL,
12693 "The base type is not a complex type", NULL);
12694 return (XML_SCHEMAP_SRC_CT_1);
12695 }
12696 } else if (type->subtypes->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
12697
12698 if IS_SIMPLE_TYPE(base) {
12699 if (type->flags &
12700 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
12701 /*
12702 * 2.1.3 only if the <extension> alternative is also
12703 * chosen, a simple type definition.
12704 */
12705 /* TODO: Change error code to ..._SRC_CT_2_1_3. */
12706 xmlSchemaPCustomErr(ctxt,
12707 XML_SCHEMAP_SRC_CT_1,
12708 NULL, type, NULL,
12709 "A complex type (simple content) cannot restrict "
12710 "an other simple type",
12711 NULL);
12712 return (XML_SCHEMAP_SRC_CT_1);
12713 }
12714 OK = 1;
12715
12716 } else { /* if IS_SIMPLE_TYPE(base) */
12717 if (base->contentType = XML_SCHEMA_CONTENT_MIXED) {
12718 /*
12719 * 2.1.2 only if the <restriction> alternative is also
12720 * chosen, a complex type definition whose {content type}
12721 * is mixed and a particle emptyable.
12722 */
12723 /*
12724 * FIXME TODO: Check for *empiable particle* is missing.
12725 */
12726 if ((type->flags &
12727 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) == 0) {
12728 xmlSchemaPCustomErr(ctxt,
12729 XML_SCHEMAP_SRC_CT_1,
12730 NULL, type, NULL,
12731 "A complex type (simple content) cannot "
12732 "extend an other complex type which has a "
12733 "content type of: 'mixed' and emptiable particle",
12734 NULL);
12735 return (XML_SCHEMAP_SRC_CT_1);
12736 }
12737 /*
12738 * NOTE: This will be fired as well, if the base type
12739 * is *'anyType'*.
12740 * NOTE: type->subtypes->subtypes will be the
12741 * <restriction> item.
12742 */
12743 if (type->subtypes->subtypes == NULL) {
12744 /* Yes, this is paranoid programming. */
12745 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
12746 NULL, type, NULL,
12747 "Internal error: xmlSchemaCheckSRCCT, "
12748 "'%s', <simpleContent> has no <restriction>",
12749 type->name);
12750 return (-1);
12751 }
12752 /*
12753 * 2.2 If clause 2.1.2 above is satisfied, then there
12754 * must be a <simpleType> among the [children] of
12755 * <restriction>.
12756 */
12757 if (type->subtypes->subtypes->type !=
12758 XML_SCHEMA_TYPE_SIMPLE) {
12759 /* TODO: Change error code to ..._SRC_CT_2_2. */
12760 xmlSchemaPCustomErr(ctxt,
12761 XML_SCHEMAP_SRC_CT_1,
12762 NULL, type, NULL,
12763 "A <simpleType> is expected among the children "
12764 "of <restriction>", NULL);
12765 return (XML_SCHEMAP_SRC_CT_1);
12766 }
12767 OK = 1;
12768 } else { /* if (base->contentType = XML_SCHEMA_CONTENT_MIXED)*/
12769 /*
12770 * 2.1.1 a complex type definition whose {content type} is a
12771 * simple type definition;
12772 */
12773 if (base->contentType == XML_SCHEMA_CONTENT_ELEMENTS) {
12774 xmlSchemaPCustomErr(ctxt,
12775 XML_SCHEMAP_SRC_CT_1,
12776 NULL, type, NULL,
12777 "A complex type (simple content) cannot "
12778 "be derived from the complex type '%s'",
12779 base->name);
12780 return (XML_SCHEMAP_SRC_CT_1);
12781 }
12782 content = base->contentTypeDef;
12783 if (content == NULL) {
12784 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
12785 NULL, type, NULL,
12786 "Internal error: xmlSchemaCheckSRCCT, "
12787 "'%s', base type has no content type",
12788 type->name);
12789 return (-1);
12790 }
12791 if (content->type != XML_SCHEMA_TYPE_SIMPLE) {
12792 xmlSchemaPCustomErr(ctxt,
12793 XML_SCHEMAP_SRC_CT_1,
12794 NULL, type, NULL,
12795 "A complex type (simple content) cannot "
12796 "be derived from the complex type '%s'",
12797 base->name);
12798 return (XML_SCHEMAP_SRC_CT_1);
12799 }
12800 }
12801 }
12802 }
12803 }
12804 /*
12805 * TODO: 3 The corresponding complex type definition component must
12806 * satisfy the conditions set out in Constraints on Complex Type
12807 * Definition Schema Components (§3.4.6);
12808 *
12809 * TODO: 4 If clause 2.2.1 or clause 2.2.2 in the correspondence specification
12810 * above for {attribute wildcard} is satisfied, the intensional
12811 * intersection must be expressible, as defined in Attribute Wildcard
12812 * Intersection (§3.10.6).
12813 */
12814
12815}
William M. Brack2f2a6632004-08-20 23:09:47 +000012816#endif
12817
Daniel Veillard01fa6152004-06-29 17:04:39 +000012818/**
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000012819 * xmlSchemaGroupDefFixup:
12820 * @typeDecl: the schema model group definition
12821 * @ctxt: the schema parser context
12822 *
12823 * Fixes model group definitions.
12824 */
12825static void
12826xmlSchemaGroupDefFixup(xmlSchemaTypePtr group,
12827 xmlSchemaParserCtxtPtr ctxt,
12828 const xmlChar * name ATTRIBUTE_UNUSED)
12829{
12830 group->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
12831 if ((group->ref != NULL) && (group->subtypes == NULL)) {
12832 xmlSchemaTypePtr groupDef;
12833 /*
12834 * Resolve the reference.
12835 */
12836 groupDef = xmlSchemaGetGroup(ctxt->schema, group->ref,
12837 group->refNs);
12838 if (groupDef == NULL) {
12839 xmlSchemaPResCompAttrErr(ctxt,
12840 XML_SCHEMAP_SRC_RESOLVE,
12841 NULL, group, NULL,
12842 "ref", group->ref, group->refNs,
12843 XML_SCHEMA_TYPE_GROUP, NULL);
12844 return;
12845 }
12846 group->subtypes = groupDef;
12847 }
12848}
12849
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012850#if 0 /* Enable when the content type will be computed. */
12851static int
12852xmlSchemaComputeContentType(xmlSchemaParserCtxtPtr ctxt,
12853 xmlSchemaTypePtr type)
12854{
12855 xmlSchemaTypePtr base, res = NULL;
12856
12857 base = type->baseType;
12858 if (base == NULL) {
12859 xmlSchemaPCustomErr(ctxt,
12860 XML_SCHEMAP_INTERNAL,
12861 NULL, type, NULL,
12862 "Internal error: xmlSchemaGetContentType, "
12863 "the complex type '%s' has no base type", type->name);
12864 return (-1);
12865 }
12866 if (IS_ANYTYPE(base) || (type->subtypes->type ==
12867 XML_SCHEMA_TYPE_COMPLEX_CONTENT)) {
12868 xmlSchemaTypePtr start;
12869 /*
12870 * Effective 'mixed'.
12871 */
12872 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
12873 type->contentType = XML_SCHEMA_CONTENT_MIXED;
12874 /*
12875 * Effective content.
12876 */
12877 if (IS_ANYTYPE(base))
12878 start = type;
12879 else
12880 start = type->subtypes;
12881
12882 } else { /* if XML_SCHEMA_TYPE_COMPLEX_CONTENT */
12883 xmlSchemaTypePtr baseContentItem;
12884
12885 /*
12886 * Complex type with simple content.
12887 */
12888 if IS_COMPLEX_TYPE(base) {
12889 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
12890 /*
12891 * Summary: a complex type (simple content) can *restrict*
12892 * a complex type with the following content type:
12893 * 1. 'mixed' and an emptiable particle
12894 * 2. simple type
12895 */
12896 if (base->contentType == XML_SCHEMA_CONTENT_MIXED) {
12897 /*
12898 * 2 if the {content type} of the base type is mixed and a
12899 * particle which is ·emptiable·,
12900 * [...]
12901 * then starting from the simple type definition
12902 * corresponding to the <simpleType> among the [children]
12903 * of <restriction> (**which must be present**)
12904 *
12905 * FIXME TODO: Handle "emptiable particle".
12906 */
12907 res = type->subtypes->subtypes;
12908 if (res == NULL) {
12909 xmlSchemaPCustomErr(ctxt,
12910 XML_SCHEMAP_INTERNAL,
12911 NULL, type, NULL,
12912 "Internal error: xmlSchemaGetContentType, "
12913 "CT '%s' (restricting): <simpleContent> has no "
12914 "<restriction>",
12915 type->name);
12916 return (-1);
12917 }
12918
12919 res->subtypes;
12920 if (res == NULL) {
12921 xmlSchemaPCustomErr(ctxt,
12922 XML_SCHEMAP_INTERNAL,
12923 NULL, type, NULL,
12924 "Internal error: xmlSchemaGetContentType, "
12925 "CT '%s' (restricting): <restriction> has no "
12926 "mandatory <simpleType>",
12927 type->name);
12928 return (-1);
12929 }
12930 } else {
12931 baseContentItem = base->contentTypeDef;
12932 if (baseContentItem == NULL) {
12933 xmlSchemaPCustomErr(ctxt,
12934 XML_SCHEMAP_INTERNAL,
12935 NULL, type, NULL,
12936 "Internal error: xmlSchemaGetContentType, "
12937 "CT '%s' (restricting), the base type has no "
12938 "content type", type->name);
12939 return (-1);
12940 }
12941 if IS_SIMPLE_TYPE(baseContentItem) {
12942 /*
12943 * 1 If the base type is a complex type whose own
12944 * {content type} is a simple type and the <restriction>
12945 * alternative is chosen
12946 */
12947 /* type->subtypes->subtypes will be the restriction item.*/
12948 res = type->subtypes->subtypes;
12949 if (res == NULL) {
12950 xmlSchemaPCustomErr(ctxt,
12951 XML_SCHEMAP_INTERNAL,
12952 NULL, type, NULL,
12953 "Internal error: xmlSchemaGetContentType, "
12954 "CT '%s' (restricting): <simpleType> has no "
12955 "<restriction>", type->name);
12956 return (-1);
12957 }
12958 /*
12959 * 1.1 the simple type definition corresponding to the
12960 * <simpleType> among the [children] of <restriction>if
12961 * there is one;
12962 */
12963 res = res->subtypes;
12964 if (res == NULL) {
12965 /*
12966 * 1.2 otherwise the {content type}
12967 * of the base type .
12968 */
12969 res = baseContentItem;
12970 }
12971 }
12972 }
12973 /*
12974 * SPECIAL TODO: If *restricting* the spec wants us to
12975 * create an *additional* simple type which restricts the
12976 * located simple type; we won't do this yet, and look how
12977 * far we get with it.
12978 */
12979 } else { /* if XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION */
12980 /*
12981 * Summary: a complex type (simple content) can *extend*
12982 * only a complex base with a simple type as content.
12983 */
12984 /*
12985 * 3 If the type definition ·resolved· to by the ·actual
12986 * value· of the base [attribute] is a complex type
12987 * definition (whose own {content type} *must be* a simple
12988 * type definition, see below) and the *<extension>*
12989 * alternative is chosen, then the {content type} of that
12990 * complex type definition;
12991 */
12992 res = base->contentTypeDef;
12993 if (res == NULL) {
12994 xmlSchemaPCustomErr(ctxt,
12995 XML_SCHEMAP_INTERNAL,
12996 NULL, type, NULL,
12997 "Internal error: xmlSchemaGetContentType, "
12998 "CT '%s' (extending), the base type has no content "
12999 "type", type->name);
13000 return (-1);
13001 }
13002 if (! IS_SIMPLE_TYPE(res)) {
13003 xmlSchemaPCustomErr(ctxt,
13004 XML_SCHEMAP_INTERNAL,
13005 NULL, type, NULL,
13006 "Internal error: xmlSchemaGetContentType, "
13007 "CT '%s' (extending), the content type of the "
13008 "base is not a simple type", type->name);
13009 return (-1);
13010 }
13011 }
13012 } else /* if IS_COMPLEX_TYPE(base) */
13013 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
13014 /*
13015 * 4 otherwise (the type definition ·resolved· to by the
13016 * ·actual value· of the base [attribute] is a simple type
13017 * definition and the <extension> alternative is chosen),
13018 * then that simple type definition.
13019 */
13020 res = base;
13021 }
13022 type->contentTypeDef = res;
13023 if (res == NULL) {
13024 xmlSchemaPCustomErr(ctxt,
13025 XML_SCHEMAP_INTERNAL,
13026 NULL, type, NULL,
13027 "Internal error: xmlSchemaGetContentType, "
13028 "'%s', the content type could not be determined",
13029 type->name);
13030 return (-1);
13031 }
13032
13033 }
13034
13035}
13036#endif
13037
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000013038/**
Daniel Veillard4255d502002-04-16 15:50:10 +000013039 * xmlSchemaTypeFixup:
13040 * @typeDecl: the schema type definition
13041 * @ctxt: the schema parser context
13042 *
13043 * Fixes the content model of the type.
13044 */
13045static void
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013046xmlSchemaTypeFixup(xmlSchemaTypePtr item,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013047 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +000013048{
Daniel Veillard01fa6152004-06-29 17:04:39 +000013049 xmlSchemaTypePtr ctxtType;
13050
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013051 if (item == NULL)
Daniel Veillard82bbbd42003-05-11 20:16:09 +000013052 return;
Daniel Veillard4e5d6652004-06-29 21:01:12 +000013053 /*
13054 * Do not allow the following types to be typefixed, prior to
13055 * the corresponding simple/complex types.
13056 */
13057 if (ctxt->ctxtType == NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013058 switch (item->type) {
Daniel Veillard4e5d6652004-06-29 21:01:12 +000013059 case XML_SCHEMA_TYPE_SIMPLE_CONTENT:
13060 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:
13061 case XML_SCHEMA_TYPE_UNION:
13062 case XML_SCHEMA_TYPE_RESTRICTION:
13063 case XML_SCHEMA_TYPE_EXTENSION:
13064 return;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000013065 default:
13066 break;
Daniel Veillard4e5d6652004-06-29 21:01:12 +000013067 }
13068 }
Daniel Veillard4255d502002-04-16 15:50:10 +000013069 if (name == NULL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013070 name = item->name;
13071 if (item->contentType == XML_SCHEMA_CONTENT_UNKNOWN) {
13072 switch (item->type) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013073 case XML_SCHEMA_TYPE_SIMPLE_CONTENT:{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013074 if (item->subtypes != NULL) {
13075 if (item->subtypes->contentType ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013076 XML_SCHEMA_CONTENT_UNKNOWN) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013077 xmlSchemaTypeFixup(item->subtypes, ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013078 NULL);
13079 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013080 item->contentType =
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013081 XML_SCHEMA_CONTENT_SIMPLE;
13082 /* item->subtypes->contentType; */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013083 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013084 break;
13085 }
13086 case XML_SCHEMA_TYPE_RESTRICTION:{
Daniel Veillard01fa6152004-06-29 17:04:39 +000013087 xmlSchemaTypePtr base = NULL;
13088
13089 ctxt->ctxtType->flags |=
13090 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013091 if (item->baseType != NULL)
13092 base = item->baseType;
13093 else if (item->base != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013094 base =
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013095 xmlSchemaGetType(ctxt->schema, item->base,
13096 item->baseNs);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013097 if (base == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013098 xmlSchemaPResCompAttrErr(ctxt,
13099 XML_SCHEMAP_SRC_RESOLVE,
William M. Brack2f2a6632004-08-20 23:09:47 +000013100 NULL, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013101 (xmlNodePtr) xmlSchemaGetPropNode(item->node, "base"),
13102 "base", item->base, item->baseNs,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013103 XML_SCHEMA_TYPE_BASIC, "type definition");
Daniel Veillard01fa6152004-06-29 17:04:39 +000013104 } else if (base->contentType ==
Daniel Veillard3646d642004-06-02 19:19:14 +000013105 XML_SCHEMA_CONTENT_UNKNOWN) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013106 xmlSchemaTypeFixup(base, ctxt, NULL);
13107 }
William M. Brack2f2a6632004-08-20 23:09:47 +000013108 }
13109 ctxt->ctxtType->baseType = base;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013110 if (ctxt->ctxtType->type == XML_SCHEMA_TYPE_COMPLEX) {
13111 /*
13112 * ComplexType restriction.
William M. Brack2f2a6632004-08-20 23:09:47 +000013113 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013114 /*
13115 * Content type.
13116 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013117 if (item->subtypes == NULL)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013118 /* 1.1.1 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013119 item->contentType = XML_SCHEMA_CONTENT_EMPTY;
13120 else if ((item->subtypes->subtypes == NULL) &&
13121 ((item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013122 XML_SCHEMA_TYPE_ALL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013123 || (item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013124 XML_SCHEMA_TYPE_SEQUENCE)))
13125 /* 1.1.2 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013126 item->contentType = XML_SCHEMA_CONTENT_EMPTY;
13127 else if ((item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013128 XML_SCHEMA_TYPE_CHOICE)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013129 && (item->subtypes->subtypes == NULL))
Daniel Veillard01fa6152004-06-29 17:04:39 +000013130 /* 1.1.3 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013131 item->contentType = XML_SCHEMA_CONTENT_EMPTY;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013132 else {
13133 /* 1.2 and 2.X are applied at the other layer */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013134 item->contentType =
Daniel Veillard01fa6152004-06-29 17:04:39 +000013135 XML_SCHEMA_CONTENT_ELEMENTS;
13136 }
13137 } else {
13138 /*
13139 * SimpleType restriction.
13140 */
William M. Brack2f2a6632004-08-20 23:09:47 +000013141 /* TODO: Nothing? */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013142 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013143 break;
13144 }
13145 case XML_SCHEMA_TYPE_EXTENSION:{
Daniel Veillard01fa6152004-06-29 17:04:39 +000013146 xmlSchemaTypePtr base = NULL;
13147 xmlSchemaContentType explicitContentType;
13148
13149 /*
13150 * An extension does exist on a complexType only.
13151 */
13152 ctxt->ctxtType->flags |=
13153 XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013154 if (item->recurse) {
Daniel Veillard3646d642004-06-02 19:19:14 +000013155 /* TODO: The word "recursive" should be changed to "circular" here. */
Daniel Veillardc0826a72004-08-10 14:17:33 +000013156 xmlSchemaPCustomErr(ctxt,
13157 XML_SCHEMAP_UNKNOWN_BASE_TYPE,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013158 NULL, item, item->node,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013159 "This item is circular", NULL);
Daniel Veillard2582a332004-04-18 19:49:46 +000013160 return;
13161 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013162 if (item->base != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013163 base =
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013164 xmlSchemaGetType(ctxt->schema, item->base,
13165 item->baseNs);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013166 if (base == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013167 xmlSchemaPResCompAttrErr(ctxt,
13168 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013169 NULL, item, item->node,
13170 "base", item->base, item->baseNs,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013171 XML_SCHEMA_TYPE_BASIC, "type definition");
Daniel Veillard01fa6152004-06-29 17:04:39 +000013172 } else if (base->contentType ==
13173 XML_SCHEMA_CONTENT_UNKNOWN) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013174 item->recurse = 1;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013175 xmlSchemaTypeFixup(base, ctxt, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013176 item->recurse = 0;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013177 }
13178 /*
13179 * The type definition ·resolved· to by the ·actual
13180 * value· of the base [attribute]
13181 */
13182 ctxt->ctxtType->baseType = base;
13183 /*
13184 * TODO: This one is still needed for computation of
13185 * the content model by xmlSchemaBuildAContentModel.
13186 * Try to get rid of it.
13187 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013188 item->baseType = base;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013189 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013190 if ((item->subtypes != NULL) &&
13191 (item->subtypes->contentType == XML_SCHEMA_CONTENT_UNKNOWN))
13192 xmlSchemaTypeFixup(item->subtypes, ctxt, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013193
13194 explicitContentType = XML_SCHEMA_CONTENT_ELEMENTS;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013195 if (item->subtypes == NULL)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013196 /* 1.1.1 */
13197 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013198 else if ((item->subtypes->subtypes == NULL) &&
13199 ((item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013200 XML_SCHEMA_TYPE_ALL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013201 || (item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013202 XML_SCHEMA_TYPE_SEQUENCE)))
13203 /* 1.1.2 */
13204 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013205 else if ((item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013206 XML_SCHEMA_TYPE_CHOICE)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013207 && (item->subtypes->subtypes == NULL))
Daniel Veillard01fa6152004-06-29 17:04:39 +000013208 /* 1.1.3 */
13209 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
13210 if (base != NULL) {
13211 /* It will be reported later, if the base is missing. */
13212 if (explicitContentType == XML_SCHEMA_CONTENT_EMPTY) {
13213 /* 2.1 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013214 item->contentType = base->contentType;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013215 } else if (base->contentType ==
13216 XML_SCHEMA_CONTENT_EMPTY) {
13217 /* 2.2 imbitable ! */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013218 item->contentType =
Daniel Veillard01fa6152004-06-29 17:04:39 +000013219 XML_SCHEMA_CONTENT_ELEMENTS;
13220 } else {
13221 /* 2.3 imbitable pareil ! */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013222 item->contentType =
Daniel Veillard01fa6152004-06-29 17:04:39 +000013223 XML_SCHEMA_CONTENT_ELEMENTS;
13224 }
13225 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013226 break;
13227 }
13228 case XML_SCHEMA_TYPE_COMPLEX:{
Daniel Veillard4e5d6652004-06-29 21:01:12 +000013229 ctxtType = ctxt->ctxtType;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013230 ctxt->ctxtType = item;
13231 /*
13232 * Start with an empty content-type type.
13233 */
13234 if (item->subtypes == NULL)
13235 item->contentType = XML_SCHEMA_CONTENT_EMPTY;
13236
13237 if ((item->subtypes == NULL) ||
13238 ((item->subtypes->type !=
Daniel Veillard01fa6152004-06-29 17:04:39 +000013239 XML_SCHEMA_TYPE_SIMPLE_CONTENT) &&
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013240 (item->subtypes->type !=
Daniel Veillard01fa6152004-06-29 17:04:39 +000013241 XML_SCHEMA_TYPE_COMPLEX_CONTENT))) {
13242 /*
13243 * This case is understood as shorthand for complex
13244 * content restricting the ur-type definition, and
13245 * the details of the mappings should be modified as
13246 * necessary.
13247 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013248 item->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
13249 item->flags |=
Daniel Veillard01fa6152004-06-29 17:04:39 +000013250 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013251 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013252 * Assume that we inherit the content-type type
13253 * from 'anyType', which is 'mixed' and a particle
13254 * emptiable.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013255 */
13256 item->contentType = item->baseType->contentType;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013257 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013258 /*
13259 * Fixup the sub components.
13260 */
13261 if ((item->subtypes != NULL) &&
13262 (item->subtypes->contentType ==
13263 XML_SCHEMA_CONTENT_UNKNOWN)) {
13264 xmlSchemaTypeFixup(item->subtypes, ctxt, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013265 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013266 if (item->flags & XML_SCHEMAS_TYPE_MIXED) {
13267 item->contentType = XML_SCHEMA_CONTENT_MIXED;
13268 } else if (item->subtypes != NULL) {
13269 /*
13270 * Use the content-type type of the model groups
13271 * defined, if 'mixed' is not set. If 'mixed' is set
13272 * it will expand the content-type by allowing character
13273 * content to appear.
13274 */
13275 item->contentType =
13276 item->subtypes->contentType;
13277 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000013278
13279 /*
13280 * Some optimization for validation:
13281 * If there are no facets beside the "whitespace" facet,
13282 * then a value needs not to checked against against a
13283 * facet, thus no computed value is needed.
13284 * TODO URGENT: This is just a workaround, we need to
13285 * introduce the correct usage of contentType to store the
13286 * facets in!
13287 */
13288 if (item->baseType->flags && XML_SCHEMAS_TYPE_FACETSNEEDVALUE)
13289 item->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
13290 else {
13291 xmlSchemaFacetLinkPtr cur;
13292
13293 for (cur = item->facetSet; cur != NULL;
13294 cur = cur->next) {
13295 if (cur->facet->type != XML_SCHEMA_FACET_WHITESPACE) {
13296 item->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
13297 break;
13298 }
13299 }
13300 }
13301
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013302 xmlSchemaBuildAttributeValidation(ctxt, item);
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +000013303 xmlSchemaCheckDefaults(item, ctxt, item->name);
Daniel Veillard4e5d6652004-06-29 21:01:12 +000013304 ctxt->ctxtType = ctxtType;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013305 break;
13306 }
13307 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013308 if (item->subtypes == NULL) {
13309 item->contentType = XML_SCHEMA_CONTENT_EMPTY;
13310 if (item->flags & XML_SCHEMAS_TYPE_MIXED)
13311 item->contentType =
Daniel Veillard1aefc862004-03-04 11:40:48 +000013312 XML_SCHEMA_CONTENT_MIXED;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013313 } else {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013314 if (item->flags & XML_SCHEMAS_TYPE_MIXED) {
13315 item->contentType =
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013316 XML_SCHEMA_CONTENT_MIXED;
Daniel Veillard3646d642004-06-02 19:19:14 +000013317 } else {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013318 xmlSchemaTypeFixup(item->subtypes, ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013319 NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013320 if (item->subtypes != NULL)
13321 item->contentType =
13322 item->subtypes->contentType;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013323 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013324 /*
13325 * Removed due to implementation of the build of attribute uses.
13326 */
13327 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013328 if (item->attributes == NULL)
13329 item->attributes =
13330 item->subtypes->attributes;
Daniel Veillard3646d642004-06-02 19:19:14 +000013331 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013332 }
13333 break;
13334 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013335 case XML_SCHEMA_TYPE_SIMPLE:
13336 /*
13337 * Simple Type Definition Schema Component
13338 *
13339 */
Daniel Veillard4e5d6652004-06-29 21:01:12 +000013340 ctxtType = ctxt->ctxtType;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013341 item->contentType = XML_SCHEMA_CONTENT_SIMPLE;
13342 if (item->subtypes->contentType ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013343 XML_SCHEMA_CONTENT_UNKNOWN) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013344 ctxt->ctxtType = item;
13345 xmlSchemaTypeFixup(item->subtypes, ctxt, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013346 }
13347 /* Fixup base type */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013348 if ((item->baseType != NULL) &&
13349 (item->baseType->contentType ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013350 XML_SCHEMA_CONTENT_UNKNOWN)) {
13351 /* OPTIMIZE: Actually this one will never by hit, since
13352 * the base type is already type-fixed in <restriction>.
13353 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013354 ctxt->ctxtType = item;
13355 xmlSchemaTypeFixup(item->baseType, ctxt, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013356 }
13357 /* Base type:
13358 * 2 If the <list> or <union> alternative is chosen,
13359 * then the ·simple ur-type definition·.
13360 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013361 if (item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013362 XML_SCHEMA_TYPE_LIST) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013363 item->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
13364 item->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
13365 } else if (item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013366 XML_SCHEMA_TYPE_UNION) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013367 item->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
13368 item->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
13369 } else if (item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013370 XML_SCHEMA_TYPE_RESTRICTION) {
13371 xmlSchemaFacetLinkPtr facet, cur, last = NULL;
13372
13373 /*
13374 * Variety
13375 * If the <restriction> alternative is chosen, then the
13376 * {variety} of the {base type definition}.
13377 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013378 if (item->baseType != NULL) {
13379 if (item->baseType->flags &
Daniel Veillard01fa6152004-06-29 17:04:39 +000013380 XML_SCHEMAS_TYPE_VARIETY_ATOMIC)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013381 item->flags |= XML_SCHEMAS_TYPE_VARIETY_ATOMIC;
13382 else if (item->baseType->flags &
Daniel Veillard01fa6152004-06-29 17:04:39 +000013383 XML_SCHEMAS_TYPE_VARIETY_LIST)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013384 item->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
13385 else if (item->baseType->flags &
Daniel Veillard01fa6152004-06-29 17:04:39 +000013386 XML_SCHEMAS_TYPE_VARIETY_UNION)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013387 item->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013388 /*
13389 * Schema Component Constraint: Simple Type Restriction
13390 * (Facets)
13391 * NOTE: Satisfaction of 1 and 2 arise from the fixup
13392 * applied beforehand.
13393 *
13394 * 3 The {facets} of R are the union of S and the {facets}
13395 * of B, eliminating duplicates. To eliminate duplicates,
13396 * when a facet of the same kind occurs in both S and the
13397 * {facets} of B, the one in the {facets} of B is not
13398 * included, with the exception of enumeration and pattern
13399 * facets, for which multiple occurrences with distinct values
13400 * are allowed.
13401 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013402 if (item->baseType->facetSet != NULL) {
13403 last = item->facetSet;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013404 if (last != NULL)
13405 while (last->next != NULL)
13406 last = last->next;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000013407 cur = item->baseType->facetSet;
13408 for (; cur != NULL; cur = cur->next) {
13409 /*
13410 * Base patterns won't be add here:
13411 * they are ORed in a type and
13412 * ANDed in derived types. This will
13413 * happed at validation level by
13414 * walking the base axis of the type.
13415 */
13416 if (cur->facet->type ==
13417 XML_SCHEMA_FACET_PATTERN)
13418 continue;
13419 facet = NULL;
13420 if ((item->facetSet != NULL) &&
13421 /* REMOVED: a check for
13422 * XML_SCHEMA_FACET_PATTERN was already
13423 * performed above.
13424
13425 * (cur->facet->type !=
13426 * XML_SCHEMA_FACET_PATTERN) &&
Daniel Veillard01fa6152004-06-29 17:04:39 +000013427 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000013428 (cur->facet->type !=
13429 XML_SCHEMA_FACET_ENUMERATION)) {
13430 facet = item->facetSet;
13431 do {
13432 if (cur->facet->type ==
13433 facet->facet->type)
13434 break;
13435 facet = facet->next;
13436 } while (facet != NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013437 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000013438 if (facet == NULL) {
13439 facet = (xmlSchemaFacetLinkPtr)
13440 xmlMalloc(sizeof(xmlSchemaFacetLink));
13441 if (facet == NULL) {
13442 xmlSchemaPErrMemory(ctxt,
13443 "fixing simpleType", NULL);
13444 return;
13445 }
13446 /*
13447 * The facets are not copied but referenced
13448 * via the facet link.
13449 */
13450 facet->facet = cur->facet;
13451 facet->next = NULL;
13452 if (last == NULL)
13453 item->facetSet = facet;
13454 else
13455 last->next = facet;
13456 last = facet;
13457 }
13458 }
13459 }
13460 /*
13461 * Some optimization for validation:
13462 * If there are no facets beside the "whitespace" facet,
13463 * then a value needs not to checked against against a
13464 * facet, thus no computed value is needed.
13465 */
13466 if (item->baseType->flags && XML_SCHEMAS_TYPE_FACETSNEEDVALUE)
13467 item->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
13468 else {
13469 for (cur = item->facetSet; cur != NULL;
13470 cur = cur->next) {
13471 if (cur->facet->type != XML_SCHEMA_FACET_WHITESPACE) {
13472 item->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
13473 break;
13474 }
13475 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013476 }
13477 }
13478 }
13479 /*
13480 * Check constraints.
13481 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013482 xmlSchemaCheckSRCSimpleType(ctxt, item);
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +000013483 xmlSchemaCheckDefaults(item, ctxt, item->name);
Daniel Veillard4e5d6652004-06-29 21:01:12 +000013484 ctxt->ctxtType = ctxtType;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013485 break;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000013486 case XML_SCHEMA_TYPE_SEQUENCE:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013487 case XML_SCHEMA_TYPE_ALL:
13488 case XML_SCHEMA_TYPE_CHOICE:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013489 item->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013490 break;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000013491 case XML_SCHEMA_TYPE_GROUP:
13492 /*
13493 * TODO: Handling was moved to xmlSchemaGroupDefFixup.
13494 */
13495 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013496 case XML_SCHEMA_TYPE_LIST:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013497 xmlSchemaParseListRefFixup(item, ctxt);
13498 item->contentType = XML_SCHEMA_CONTENT_SIMPLE;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013499 break;
13500 case XML_SCHEMA_TYPE_UNION:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013501 xmlSchemaParseUnionRefCheck(item, ctxt);
13502 item->contentType = XML_SCHEMA_CONTENT_SIMPLE;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013503 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013504 case XML_SCHEMA_TYPE_BASIC:
13505 case XML_SCHEMA_TYPE_ANY:
13506 case XML_SCHEMA_TYPE_FACET:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013507 case XML_SCHEMA_TYPE_UR:
13508 case XML_SCHEMA_TYPE_ELEMENT:
13509 case XML_SCHEMA_TYPE_ATTRIBUTE:
13510 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
William M. Brack29aa7722004-05-12 00:27:56 +000013511 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013512 case XML_SCHEMA_TYPE_NOTATION:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013513 case XML_SCHEMA_FACET_MININCLUSIVE:
13514 case XML_SCHEMA_FACET_MINEXCLUSIVE:
13515 case XML_SCHEMA_FACET_MAXINCLUSIVE:
13516 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
13517 case XML_SCHEMA_FACET_TOTALDIGITS:
13518 case XML_SCHEMA_FACET_FRACTIONDIGITS:
13519 case XML_SCHEMA_FACET_PATTERN:
13520 case XML_SCHEMA_FACET_ENUMERATION:
13521 case XML_SCHEMA_FACET_WHITESPACE:
13522 case XML_SCHEMA_FACET_LENGTH:
13523 case XML_SCHEMA_FACET_MAXLENGTH:
13524 case XML_SCHEMA_FACET_MINLENGTH:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013525 item->contentType = XML_SCHEMA_CONTENT_SIMPLE;
13526 if (item->subtypes != NULL)
13527 xmlSchemaTypeFixup(item->subtypes, ctxt, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013528 break;
13529 }
13530 }
Daniel Veillard8651f532002-04-17 09:06:27 +000013531#ifdef DEBUG_TYPE
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013532 if (item->node != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013533 xmlGenericError(xmlGenericErrorContext,
13534 "Type of %s : %s:%d :", name,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013535 item->node->doc->URL,
13536 xmlGetLineNo(item->node));
Daniel Veillarddecd64d2002-04-18 14:41:51 +000013537 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013538 xmlGenericError(xmlGenericErrorContext, "Type of %s :", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +000013539 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013540 switch (item->contentType) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013541 case XML_SCHEMA_CONTENT_SIMPLE:
13542 xmlGenericError(xmlGenericErrorContext, "simple\n");
13543 break;
13544 case XML_SCHEMA_CONTENT_ELEMENTS:
13545 xmlGenericError(xmlGenericErrorContext, "elements\n");
13546 break;
Daniel Veillard8651f532002-04-17 09:06:27 +000013547 case XML_SCHEMA_CONTENT_UNKNOWN:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013548 xmlGenericError(xmlGenericErrorContext, "unknown !!!\n");
13549 break;
Daniel Veillard8651f532002-04-17 09:06:27 +000013550 case XML_SCHEMA_CONTENT_EMPTY:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013551 xmlGenericError(xmlGenericErrorContext, "empty\n");
13552 break;
Daniel Veillard8651f532002-04-17 09:06:27 +000013553 case XML_SCHEMA_CONTENT_MIXED:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013554 xmlGenericError(xmlGenericErrorContext, "mixed\n");
13555 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013556 /* Removed, since not used. */
13557 /*
Daniel Veillard8651f532002-04-17 09:06:27 +000013558 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013559 xmlGenericError(xmlGenericErrorContext, "mixed or elems\n");
13560 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013561 */
Daniel Veillard8651f532002-04-17 09:06:27 +000013562 case XML_SCHEMA_CONTENT_BASIC:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013563 xmlGenericError(xmlGenericErrorContext, "basic\n");
13564 break;
13565 default:
13566 xmlGenericError(xmlGenericErrorContext,
13567 "not registered !!!\n");
13568 break;
Daniel Veillard8651f532002-04-17 09:06:27 +000013569 }
13570#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000013571}
13572
13573/**
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000013574 * xmlSchemaCheckFacet:
13575 * @facet: the facet
13576 * @typeDecl: the schema type definition
13577 * @ctxt: the schema parser context or NULL
13578 * @name: name of the type
13579 *
13580 * Checks the default values types, especially for facets
13581 *
13582 * Returns 0 if okay or -1 in cae of error
13583 */
13584int
13585xmlSchemaCheckFacet(xmlSchemaFacetPtr facet,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013586 xmlSchemaTypePtr typeDecl,
13587 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000013588{
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +000013589 xmlSchemaTypePtr nonNegativeIntegerType = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013590 int ret = 0, reuseValCtxt = 0;
13591
Daniel Veillardce682bc2004-11-05 17:22:25 +000013592 if ((facet == NULL) || (typeDecl == NULL))
13593 return(-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013594 /*
13595 * TODO: will the parser context be given if used from
13596 * the relaxNG module?
13597 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000013598
13599 if (nonNegativeIntegerType == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013600 nonNegativeIntegerType =
Daniel Veillard01fa6152004-06-29 17:04:39 +000013601 xmlSchemaGetBuiltInType(XML_SCHEMAS_NNINTEGER);
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000013602 }
13603 switch (facet->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013604 case XML_SCHEMA_FACET_MININCLUSIVE:
13605 case XML_SCHEMA_FACET_MINEXCLUSIVE:
13606 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Daniel Veillardf4b05d02004-07-05 13:10:37 +000013607 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
13608 case XML_SCHEMA_FACET_ENUMERATION: {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013609 /*
13610 * Okay we need to validate the value
13611 * at that point.
13612 */
13613 xmlSchemaValidCtxtPtr vctxt;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013614 xmlSchemaTypePtr base;
Daniel Veillardf4b05d02004-07-05 13:10:37 +000013615
13616 /* 4.3.5.5 Constraints on enumeration Schema Components
13617 * Schema Component Constraint: enumeration valid restriction
13618 * It is an ·error· if any member of {value} is not in the
13619 * ·value space· of {base type definition}.
13620 *
13621 * minInclusive, maxInclusive, minExclusive, maxExclusive:
13622 * The value ·must· be in the
13623 * ·value space· of the ·base type·.
13624 */
13625 /*
13626 * This function is intended to deliver a compiled value
13627 * on the facet. In XML Schemas the type holding a facet,
13628 * cannot be a built-in type. Thus to ensure that other API
13629 * calls (relaxng) do work, if the given type is a built-in
13630 * type, we will assume that the given built-in type *is
13631 * already* the base type.
13632 */
13633 if (typeDecl->type != XML_SCHEMA_TYPE_BASIC) {
13634 base = typeDecl->baseType;
13635 if (base == NULL) {
13636 xmlSchemaPErr(ctxt, typeDecl->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013637 XML_SCHEMAP_INTERNAL,
Daniel Veillardf4b05d02004-07-05 13:10:37 +000013638 "Internal error: xmlSchemaCheckFacet, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000013639 "the type '%s' has no base type.\n",
Daniel Veillardf4b05d02004-07-05 13:10:37 +000013640 typeDecl->name, NULL);
13641 return (-1);
13642 }
13643 } else
13644 base = typeDecl;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013645 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013646 * This avoids perseverative creation of the
13647 * validation context if a parser context is
13648 * used.
Daniel Veillard01fa6152004-06-29 17:04:39 +000013649 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013650 if (ctxt != NULL) {
13651 reuseValCtxt = 1;
13652 if (ctxt->vctxt == NULL) {
13653 if (xmlSchemaCreateVCtxtOnPCtxt(ctxt) == -1)
13654 return (-1);
13655 }
13656 vctxt = ctxt->vctxt;
13657 } else {
13658 vctxt = xmlSchemaNewValidCtxt(NULL);
13659 if (vctxt == NULL) {
13660 xmlSchemaPErr(ctxt, typeDecl->node,
13661 XML_SCHEMAP_INTERNAL,
13662 "Internal error: xmlSchemaCheckFacet, "
13663 "creating a new validation context.\n",
13664 NULL, NULL);
13665 return (-1);
13666 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013667 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013668
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013669 vctxt->node = facet->node;
13670 vctxt->cur = NULL;
13671 /*
13672 * NOTE: This call does not check the content nodes,
13673 * since they are not available:
13674 * facet->node is just the node holding the facet
13675 * definition, *not* the attribute holding the *value*
13676 * of the facet.
13677 */
13678 ret = xmlSchemaValidateSimpleTypeValue(vctxt, base,
13679 facet->value, 0, 1, 1, 0);
Daniel Veillardf4b05d02004-07-05 13:10:37 +000013680 facet->val = vctxt->value;
13681 vctxt->value = NULL;
13682 if (ret > 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013683 /* error code */
13684 if (ctxt != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013685 xmlSchemaPErrExt(ctxt, facet->node,
13686 XML_SCHEMAP_INVALID_FACET,
13687 NULL, NULL, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013688 "Type definition '%s': The value '%s' of the "
13689 "facet '%s' is not valid.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000013690 name, facet->value,
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000013691 BAD_CAST xmlSchemaFacetTypeToString(facet->type),
Daniel Veillard01fa6152004-06-29 17:04:39 +000013692 NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013693 }
13694 ret = -1;
Daniel Veillardf4b05d02004-07-05 13:10:37 +000013695 } else if (ret < 0) {
13696 xmlSchemaPErrExt(ctxt, facet->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013697 XML_SCHEMAP_INTERNAL,
Daniel Veillardf4b05d02004-07-05 13:10:37 +000013698 NULL, NULL, NULL,
13699 "Internal error: xmlSchemaCheckFacet, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000013700 "failed to validate the value '%s' name of the "
13701 "facet '%s' against the base type '%s'.\n",
Daniel Veillardf4b05d02004-07-05 13:10:37 +000013702 facet->value,
13703 BAD_CAST xmlSchemaFacetTypeToString(facet->type),
13704 base->name, NULL, NULL);
13705 ret = -1;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013706 }
13707 if (reuseValCtxt == 0)
13708 xmlSchemaFreeValidCtxt(vctxt);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013709 break;
13710 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013711 case XML_SCHEMA_FACET_PATTERN:
13712 facet->regexp = xmlRegexpCompile(facet->value);
13713 if (facet->regexp == NULL) {
13714 xmlSchemaPErr(ctxt, typeDecl->node,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013715 XML_SCHEMAP_REGEXP_INVALID,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013716 "Type definition '%s': The value '%s' of the "
13717 "facet 'pattern' is not valid.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000013718 name, facet->value);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013719 ret = -1;
13720 }
13721 break;
13722 case XML_SCHEMA_FACET_TOTALDIGITS:
13723 case XML_SCHEMA_FACET_FRACTIONDIGITS:
13724 case XML_SCHEMA_FACET_LENGTH:
13725 case XML_SCHEMA_FACET_MAXLENGTH:
13726 case XML_SCHEMA_FACET_MINLENGTH:{
13727 int tmp;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000013728
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013729 tmp =
13730 xmlSchemaValidatePredefinedType(nonNegativeIntegerType,
13731 facet->value,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +000013732 &(facet->val));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013733 if (tmp != 0) {
13734 /* error code */
13735 if (ctxt != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013736 xmlSchemaPErrExt(ctxt, facet->node,
13737 XML_SCHEMAP_INVALID_FACET_VALUE,
13738 NULL, NULL, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013739 "Type definition '%s': The value '%s' of the "
13740 "facet '%s' is not valid.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000013741 name, facet->value,
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000013742 BAD_CAST xmlSchemaFacetTypeToString(facet->type),
Daniel Veillard01fa6152004-06-29 17:04:39 +000013743 NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013744 }
13745 ret = -1;
13746 }
13747 break;
13748 }
13749 case XML_SCHEMA_FACET_WHITESPACE:{
13750 if (xmlStrEqual(facet->value, BAD_CAST "preserve")) {
13751 facet->whitespace = XML_SCHEMAS_FACET_PRESERVE;
13752 } else if (xmlStrEqual(facet->value, BAD_CAST "replace")) {
13753 facet->whitespace = XML_SCHEMAS_FACET_REPLACE;
13754 } else if (xmlStrEqual(facet->value, BAD_CAST "collapse")) {
13755 facet->whitespace = XML_SCHEMAS_FACET_COLLAPSE;
13756 } else {
13757 if (ctxt != NULL) {
13758 xmlSchemaPErr(ctxt, facet->node,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013759 XML_SCHEMAP_INVALID_WHITE_SPACE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013760 "Type definition '%s': The value '%s' of the "
13761 "facet 'whiteSpace' is not valid.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000013762 name, facet->value);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013763 }
13764 ret = -1;
13765 }
13766 }
13767 default:
13768 break;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000013769 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013770 return (ret);
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000013771}
13772
13773/**
Daniel Veillard4255d502002-04-16 15:50:10 +000013774 * xmlSchemaCheckDefaults:
13775 * @typeDecl: the schema type definition
13776 * @ctxt: the schema parser context
13777 *
13778 * Checks the default values types, especially for facets
13779 */
13780static void
13781xmlSchemaCheckDefaults(xmlSchemaTypePtr typeDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013782 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +000013783{
Daniel Veillard4255d502002-04-16 15:50:10 +000013784 if (name == NULL)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013785 name = typeDecl->name;
13786 /*
13787 * NOTE: It is intended to use the facets list, instead
13788 * of facetSet.
13789 */
13790 if (typeDecl->facets != NULL) {
13791 xmlSchemaFacetPtr facet = typeDecl->facets;
13792
13793 while (facet != NULL) {
13794 xmlSchemaCheckFacet(facet, typeDecl, ctxt, name);
13795 facet = facet->next;
13796 }
13797 }
Daniel Veillard4255d502002-04-16 15:50:10 +000013798}
13799
13800/**
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000013801 * xmlSchemaGetCircModelGrDefRef:
13802 * @ctxtGr: the searched model group
13803 * @list: the list of model groups to be processed
13804 *
13805 * This one is intended to be used by
13806 * xmlSchemaCheckGroupDefCircular only.
13807 *
13808 * Returns the circular model group definition reference, otherwise NULL.
13809 */
13810static xmlSchemaTypePtr
13811xmlSchemaGetCircModelGrDefRef(xmlSchemaTypePtr ctxtGrDef,
13812 xmlSchemaTypePtr gr)
13813{
13814 xmlSchemaTypePtr circ = NULL;
13815 int marked;
13816 /*
13817 * We will search for an model group reference which
13818 * references the context model group definition.
13819 */
13820 while (gr != NULL) {
13821 if (((gr->type == XML_SCHEMA_TYPE_GROUP) ||
13822 (gr->type == XML_SCHEMA_TYPE_ALL) ||
13823 (gr->type == XML_SCHEMA_TYPE_SEQUENCE) ||
13824 (gr->type == XML_SCHEMA_TYPE_CHOICE)) &&
13825 (gr->subtypes != NULL)) {
13826 marked = 0;
13827 if ((gr->type == XML_SCHEMA_TYPE_GROUP) &&
13828 (gr->ref != NULL)) {
13829 if (gr->subtypes == ctxtGrDef)
13830 return (gr);
13831 else if (gr->subtypes->flags &
13832 XML_SCHEMAS_TYPE_MARKED) {
13833 gr = gr->next;
13834 continue;
13835 } else {
13836 /*
13837 * Mark to avoid infinite recursion on
13838 * circular references not yet examined.
13839 */
13840 gr->subtypes->flags |= XML_SCHEMAS_TYPE_MARKED;
13841 marked = 1;
13842 }
13843 if (gr->subtypes->subtypes != NULL)
13844 circ = xmlSchemaGetCircModelGrDefRef(ctxtGrDef,
13845 gr->subtypes->subtypes);
13846 /*
13847 * Unmark the visited model group definition.
13848 */
13849 if (marked)
13850 gr->subtypes->flags ^= XML_SCHEMAS_TYPE_MARKED;
13851 if (circ != NULL)
13852 return (circ);
13853 } else {
13854 circ = xmlSchemaGetCircModelGrDefRef(ctxtGrDef,
13855 (xmlSchemaTypePtr) gr->subtypes);
13856 if (circ != NULL)
13857 return (circ);
13858 }
13859
13860 }
13861 gr = gr->next;
13862 }
13863 return (NULL);
13864}
13865
13866/**
13867 * xmlSchemaCheckGroupDefCircular:
13868 * attrGr: the model group definition
13869 * @ctxt: the parser context
13870 * @name: the name
13871 *
13872 * Checks for circular references to model group definitions.
13873 */
13874static void
13875xmlSchemaCheckGroupDefCircular(xmlSchemaTypePtr modelGrDef,
13876 xmlSchemaParserCtxtPtr ctxt,
13877 const xmlChar * name ATTRIBUTE_UNUSED)
13878{
13879 /*
13880 * Schema Component Constraint: Model Group Correct
13881 * 2 Circular groups are disallowed. That is, within the {particles}
13882 * of a group there must not be at any depth a particle whose {term}
13883 * is the group itself.
13884 */
13885 /*
13886 * NOTE: "gr->subtypes" holds the referenced group.
13887 */
13888 if ((modelGrDef->type != XML_SCHEMA_TYPE_GROUP) ||
13889 ((modelGrDef->flags & XML_SCHEMAS_TYPE_GLOBAL) == 0) ||
13890 (modelGrDef->subtypes == NULL))
13891 return;
13892 else {
13893 xmlSchemaTypePtr circ;
13894
13895 circ = xmlSchemaGetCircModelGrDefRef(modelGrDef, modelGrDef->subtypes);
13896 if (circ != NULL) {
13897 /*
13898 * TODO: Report the referenced attr group as QName.
13899 */
13900 xmlSchemaPCustomErr(ctxt,
13901 XML_SCHEMAP_MG_PROPS_CORRECT_2,
13902 NULL, NULL, circ->node,
13903 "Circular reference to the model group definition '%s' "
13904 "defined", modelGrDef->name);
13905 /*
13906 * NOTE: We will cut the reference to avoid further
13907 * confusion of the processor.
13908 * TODO: SPEC: Does the spec define how to process here?
13909 */
13910 circ->subtypes = NULL;
13911 }
13912 }
13913}
13914
13915
13916/**
13917 * xmlSchemaGetCircAttrGrRef:
13918 * @ctxtGr: the searched attribute group
13919 * @attr: the current attribute list to be processed
13920 *
13921 * This one is intended to be used by
13922 * xmlSchemaCheckSRCAttributeGroupCircular only.
13923 *
13924 * Returns the circular attribute grou reference, otherwise NULL.
13925 */
13926static xmlSchemaAttributeGroupPtr
13927xmlSchemaGetCircAttrGrRef(xmlSchemaAttributeGroupPtr ctxtGr,
13928 xmlSchemaAttributePtr attr)
13929{
13930 xmlSchemaAttributeGroupPtr circ = NULL, gr;
13931 int marked;
13932 /*
13933 * We will search for an attribute group reference which
13934 * references the context attribute group.
13935 */
13936 while (attr != NULL) {
13937 marked = 0;
13938 if (attr->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
13939 gr = (xmlSchemaAttributeGroupPtr) attr;
13940 if (gr->refItem != NULL) {
13941 if (gr->refItem == ctxtGr)
13942 return (gr);
13943 else if (gr->refItem->flags &
13944 XML_SCHEMAS_ATTRGROUP_MARKED) {
13945 attr = attr->next;
13946 continue;
13947 } else {
13948 /*
13949 * Mark as visited to avoid infinite recursion on
13950 * circular references not yet examined.
13951 */
13952 gr->refItem->flags |= XML_SCHEMAS_ATTRGROUP_MARKED;
13953 marked = 1;
13954 }
13955 }
13956 if (gr->attributes != NULL)
13957 circ = xmlSchemaGetCircAttrGrRef(ctxtGr, gr->attributes);
13958 /*
13959 * Unmark the visited group's attributes.
13960 */
13961 if (marked)
13962 gr->refItem->flags ^= XML_SCHEMAS_ATTRGROUP_MARKED;
13963 if (circ != NULL)
13964 return (circ);
13965 }
13966 attr = attr->next;
13967 }
13968 return (NULL);
13969}
13970
13971/**
13972 * xmlSchemaCheckSRCAttributeGroupCircular:
13973 * attrGr: the attribute group definition
13974 * @ctxt: the parser context
13975 * @name: the name
13976 *
13977 * Checks for circular references of attribute groups.
13978 */
13979static void
13980xmlSchemaCheckAttributeGroupCircular(xmlSchemaAttributeGroupPtr attrGr,
13981 xmlSchemaParserCtxtPtr ctxt,
13982 const xmlChar * name ATTRIBUTE_UNUSED)
13983{
13984 /*
13985 * Schema Representation Constraint:
13986 * Attribute Group Definition Representation OK
13987 * 3 Circular group reference is disallowed outside <redefine>.
13988 * That is, unless this element information item's parent is
13989 * <redefine>, then among the [children], if any, there must
13990 * not be an <attributeGroup> with ref [attribute] which resolves
13991 * to the component corresponding to this <attributeGroup>. Indirect
13992 * circularity is also ruled out. That is, when QName resolution
13993 * (Schema Document) (§3.15.3) is applied to a ·QName· arising from
13994 * any <attributeGroup>s with a ref [attribute] among the [children],
13995 * it must not be the case that a ·QName· is encountered at any depth
13996 * which resolves to the component corresponding to this <attributeGroup>.
13997 */
13998 /*
13999 * Only global components can be referenced.
14000 */
14001 if (((attrGr->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL) == 0) ||
14002 (attrGr->attributes == NULL))
14003 return;
14004 else {
14005 xmlSchemaAttributeGroupPtr circ;
14006
14007 circ = xmlSchemaGetCircAttrGrRef(attrGr, attrGr->attributes);
14008 if (circ != NULL) {
14009 /*
14010 * TODO: Report the referenced attr group as QName.
14011 */
14012 xmlSchemaPCustomErr(ctxt,
14013 XML_SCHEMAP_SRC_ATTRIBUTE_GROUP_3,
14014 NULL, NULL, circ->node,
14015 "Circular reference to the attribute group '%s' "
14016 "defined", attrGr->name);
14017 /*
14018 * NOTE: We will cut the reference to avoid further
14019 * confusion of the processor.
14020 * BADSPEC: The spec should define how to process in this case.
14021 */
14022 circ->attributes = NULL;
14023 circ->refItem = NULL;
14024 }
14025 }
14026}
14027
14028/**
Daniel Veillard13e04c62002-04-23 17:51:29 +000014029 * xmlSchemaAttrGrpFixup:
14030 * @attrgrpDecl: the schema attribute definition
14031 * @ctxt: the schema parser context
14032 * @name: the attribute name
14033 *
14034 * Fixes finish doing the computations on the attributes definitions
14035 */
14036static void
Daniel Veillard3646d642004-06-02 19:19:14 +000014037xmlSchemaAttrGrpFixup(xmlSchemaAttributeGroupPtr attrgrp,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014038 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard13e04c62002-04-23 17:51:29 +000014039{
14040 if (name == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000014041 name = attrgrp->name;
14042 if (attrgrp->attributes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014043 return;
Daniel Veillard3646d642004-06-02 19:19:14 +000014044 if (attrgrp->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014045 xmlSchemaAttributeGroupPtr ref;
Daniel Veillard13e04c62002-04-23 17:51:29 +000014046
Daniel Veillardc0826a72004-08-10 14:17:33 +000014047 ref = xmlSchemaGetAttributeGroup(ctxt->schema, attrgrp->ref,
14048 attrgrp->refNs);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014049 if (ref == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000014050 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014051 XML_SCHEMAP_SRC_RESOLVE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014052 NULL, (xmlSchemaTypePtr) attrgrp, attrgrp->node,
14053 "ref", attrgrp->ref, attrgrp->refNs,
14054 XML_SCHEMA_TYPE_ATTRIBUTEGROUP, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014055 return;
14056 }
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000014057 attrgrp->refItem = ref;
14058 /*
14059 * Check for self reference!
14060 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014061 xmlSchemaAttrGrpFixup(ref, ctxt, NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +000014062 attrgrp->attributes = ref->attributes;
14063 attrgrp->attributeWildcard = ref->attributeWildcard;
14064 }
Daniel Veillard13e04c62002-04-23 17:51:29 +000014065}
14066
14067/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014068 * xmlSchemaAttrCheckValConstr:
14069 * @item: an schema attribute declaration/use
14070 * @ctxt: a schema parser context
14071 * @name: the name of the attribute
14072 *
14073 * Validates the value constraints of an attribute declaration/use.
Daniel Veillard4255d502002-04-16 15:50:10 +000014074 *
14075 * Fixes finish doing the computations on the attributes definitions
14076 */
14077static void
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014078xmlSchemaCheckAttrValConstr(xmlSchemaAttributePtr item,
14079 xmlSchemaParserCtxtPtr ctxt,
14080 const xmlChar * name ATTRIBUTE_UNUSED)
14081{
14082
14083 /*
14084 * a-props-correct
14085 * Schema Component Constraint: Attribute Declaration Properties Correct
14086 *
14087 * 2 if there is a {value constraint}, the canonical lexical
14088 * representation of its value must be ·valid· with respect
14089 * to the {type definition} as defined in String Valid (§3.14.4).
14090 */
14091
14092 if (item->defValue != NULL) {
14093 int ret;
14094 xmlNodePtr node;
14095 xmlSchemaTypePtr type;
14096
14097 if (item->subtypes == NULL) {
14098 xmlSchemaPErr(ctxt, item->node,
14099 XML_SCHEMAP_INTERNAL,
14100 "Internal error: xmlSchemaCheckAttrValConstr, "
14101 "type is missing... skipping validation of "
14102 "value constraint", NULL, NULL);
14103 return;
14104 }
14105
14106 /*
14107 * TODO: Try to avoid creating a new context.
14108 * TODO: This all is not very performant.
14109 */
14110 type = item->subtypes;
14111 /*
14112 * Ensure there's validation context.
14113 */
14114 if (ctxt->vctxt == NULL) {
14115 if (xmlSchemaCreateVCtxtOnPCtxt(ctxt) == -1) {
14116 xmlSchemaPErr(ctxt, item->node,
14117 XML_SCHEMAP_INTERNAL,
14118 "Internal error: xmlSchemaCheckAttrValConstr, "
14119 "creating a new validation context.\n",
14120 NULL, NULL);
14121 return;
14122 }
14123 }
14124
14125 if (item->flags & XML_SCHEMAS_ATTR_FIXED)
14126 node = (xmlNodePtr) xmlHasProp(item->node, BAD_CAST "fixed");
14127 else
14128 node = (xmlNodePtr) xmlHasProp(item->node, BAD_CAST "default");
14129 ctxt->vctxt->node = node;
14130 ctxt->vctxt->cur = NULL;
14131 /*
14132 * NOTE: This call does not check the content nodes,
14133 * since they are not available:
14134 * facet->node is just the node holding the facet
14135 * definition, *not* the attribute holding the *value*
14136 * of the facet.
14137 */
14138 ret = xmlSchemaValidateSimpleTypeValue(ctxt->vctxt, type,
14139 item->defValue, 0, 1, 1, 0);
14140 if (ret == 0) {
14141 /*
14142 * Store the computed value.
14143 */
14144 item->defVal = ctxt->vctxt->value;
14145 ctxt->vctxt->value = NULL;
14146 } else if (ret > 0) {
14147 if (ctxt != NULL) {
14148 xmlSchemaPSimpleTypeErr(ctxt,
14149 XML_SCHEMAP_A_PROPS_CORRECT_2,
14150 NULL, NULL, node,
14151 type, NULL, item->defValue,
14152 NULL, NULL, NULL);
14153 }
14154 } else if (ret < 0) {
14155 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
14156 NULL, NULL, node,
14157 "Internal error: xmlSchemaAttrCheckValConstr, "
14158 "failed to validate the value constraint of the "
14159 "attribute decl/use against the type '%s'",
14160 type->name);
14161 }
14162 }
14163}
14164
14165#if 0 /* Not used yet. */
14166static int
14167xmlSchemaCheckElemPropsCorrect(xmlSchemaParserCtxtPtr ctxt,
14168 xmlSchemaElementPtr edecl)
14169{
14170 /*
14171 * TODO: 1 The values of the properties of an element declaration must be as
14172 * described in the property tableau in The Element Declaration Schema
14173 * Component (§3.3.1), modulo the impact of Missing Sub-components (§5.3).
14174 */
14175 /*
14176 * 2 If there is a {value constraint}, the canonical lexical
14177 * representation of its value must be ·valid· with respect to the {type
14178 * definition} as defined in Element Default Valid (Immediate) (§3.3.6).
14179 *
14180 * NOTE: This is done in xmlSchemaCheckElemValConstr.
14181 */
14182 /*
14183 * 3 If there is a non-·absent· {substitution group affiliation},
14184 * then {scope} must be global.
14185 *
14186 * NOTE: This is done in xmlSchemaParseElement.
14187 * TODO: Move it to this layer here.
14188 */
14189 /*
14190 * TODO: 4 If there is a {substitution group affiliation}, the {type definition}
14191 * of the element declaration must be validly derived from the {type
14192 * definition} of the {substitution group affiliation}, given the value
14193 * of the {substitution group exclusions} of the {substitution group
14194 * affiliation}, as defined in Type Derivation OK (Complex) (§3.4.6)
14195 * (if the {type definition} is complex) or as defined in
14196 * Type Derivation OK (Simple) (§3.14.6) (if the {type definition} is
14197 * simple).
14198 */
14199 /*
14200 * TODO: 5 If the {type definition} or {type definition}'s {content type}
14201 * is or is derived from ID then there must not be a {value constraint}.
14202 * Note: The use of ID as a type definition for elements goes beyond
14203 * XML 1.0, and should be avoided if backwards compatibility is desired
14204 */
14205 /*
14206 * TODO: 6 Circular substitution groups are disallowed. That is, it must not
14207 * be possible to return to an element declaration by repeatedly following
14208 * the {substitution group affiliation} property.
14209 */
14210}
14211#endif
14212
14213/**
14214 * xmlSchemaCheckElemValConstr:
14215 * @item: an schema element declaration/particle
14216 * @ctxt: a schema parser context
14217 * @name: the name of the attribute
14218 *
14219 * Validates the value constraints of an element declaration.
14220 *
14221 * Fixes finish doing the computations on the element declarations.
14222 */
14223static void
14224xmlSchemaCheckElemValConstr(xmlSchemaElementPtr decl,
14225 xmlSchemaParserCtxtPtr ctxt,
14226 const xmlChar * name ATTRIBUTE_UNUSED)
14227{
14228 if (decl->value != NULL) {
14229 int ret;
14230 xmlNodePtr node = NULL;
14231 xmlSchemaTypePtr type;
14232
14233 /*
14234 * 2 If there is a {value constraint}, the canonical lexical
14235 * representation of its value must be ·valid· with respect to the {type
14236 * definition} as defined in Element Default Valid (Immediate) (§3.3.6).
14237 */
14238 if (decl->subtypes == NULL) {
14239 xmlSchemaPErr(ctxt, decl->node,
14240 XML_SCHEMAP_INTERNAL,
14241 "Internal error: xmlSchemaCheckElemValConstr, "
14242 "type is missing... skipping validation of "
14243 "the value constraint", NULL, NULL);
14244 return;
14245 }
14246 /*
14247 * Ensure there's a validation context.
14248 */
14249 if (xmlSchemaCreateVCtxtOnPCtxt(ctxt) == -1)
14250 return;
14251
14252 type = decl->subtypes;
14253
14254 if (decl->node != NULL) {
14255 if (decl->flags & XML_SCHEMAS_ELEM_FIXED)
14256 node = (xmlNodePtr) xmlHasProp(decl->node, BAD_CAST "fixed");
14257 else
14258 node = (xmlNodePtr) xmlHasProp(decl->node, BAD_CAST "default");
14259 }
14260 ctxt->vctxt->node = node;
14261 ctxt->vctxt->cur = NULL;
14262 ret = xmlSchemaCheckCOSValidDefault(ctxt, ctxt->vctxt, type, decl->value,
14263 node);
14264 if (ret == 0) {
14265 /*
14266 * Consume the computed value.
14267 */
14268 decl->defVal = ctxt->vctxt->value;
14269 ctxt->vctxt->value = NULL;
14270 } else if (ret < 0) {
14271 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
14272 NULL, NULL, node,
14273 "Internal error: xmlSchemaElemCheckValConstr, "
14274 "failed to validate the value constraint of the "
14275 "element declaration '%s'",
14276 decl->name);
14277 }
14278 }
14279}
14280
14281/**
14282 * xmlSchemaAttrFixup:
14283 * @item: an schema attribute declaration/use.
14284 * @ctxt: a schema parser context
14285 * @name: the name of the attribute
14286 *
14287 * Fixes finish doing the computations on attribute declarations/uses.
14288 */
14289static void
14290xmlSchemaAttrFixup(xmlSchemaAttributePtr item,
14291 xmlSchemaParserCtxtPtr ctxt,
14292 const xmlChar * name ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +000014293{
Daniel Veillardc0826a72004-08-10 14:17:33 +000014294 /*
14295 * TODO: If including this is done twice (!) for every attribute.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014296 * -> Hmm, check if this is still done.
Daniel Veillardc0826a72004-08-10 14:17:33 +000014297 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000014298 /*
14299 * The simple type definition corresponding to the <simpleType> element
14300 * information item in the [children], if present, otherwise the simple
14301 * type definition ·resolved· to by the ·actual value· of the type
14302 * [attribute], if present, otherwise the ·simple ur-type definition·.
14303 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014304 if (item->flags & XML_SCHEMAS_ATTR_INTERNAL_RESOLVED)
Daniel Veillardc0826a72004-08-10 14:17:33 +000014305 return;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014306 item->flags |= XML_SCHEMAS_ATTR_INTERNAL_RESOLVED;
14307 if (item->subtypes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014308 return;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014309 if (item->typeName != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014310 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000014311
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014312 type = xmlSchemaGetType(ctxt->schema, item->typeName,
14313 item->typeNs);
14314 if ((type == NULL) || (! IS_SIMPLE_TYPE(type))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000014315 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014316 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014317 NULL, (xmlSchemaTypePtr) item, item->node,
14318 "type", item->typeName, item->typeNs,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014319 XML_SCHEMA_TYPE_SIMPLE, NULL);
14320 } else
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014321 item->subtypes = type;
14322
14323 } else if (item->ref != NULL) {
14324 xmlSchemaAttributePtr decl;
Daniel Veillard4255d502002-04-16 15:50:10 +000014325
Daniel Veillardc0826a72004-08-10 14:17:33 +000014326 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014327 * We have an attribute use here; assign the referenced
14328 * attribute declaration.
14329 */
14330 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000014331 * TODO: Evaluate, what errors could occur if the declaration is not
14332 * found. It might be possible that the "typefixup" might crash if
14333 * no ref declaration was found.
14334 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014335 decl = xmlSchemaGetAttribute(ctxt->schema, item->ref, item->refNs);
14336 if (decl == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000014337 xmlSchemaPResCompAttrErr(ctxt,
14338 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014339 NULL, (xmlSchemaTypePtr) item, item->node,
14340 "ref", item->ref, item->refNs,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014341 XML_SCHEMA_TYPE_ATTRIBUTE, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014342 return;
14343 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014344 item->refDecl = decl;
14345 xmlSchemaAttrFixup(decl, ctxt, NULL);
14346
14347 item->subtypes = decl->subtypes;
14348 /*
14349 * Attribute Use Correct
14350 * au-props-correct.2: If the {attribute declaration} has a fixed
14351 * {value constraint}, then if the attribute use itself has a
14352 * {value constraint}, it must also be fixed and its value must match
14353 * that of the {attribute declaration}'s {value constraint}.
14354 */
14355 if ((decl->flags & XML_SCHEMAS_ATTR_FIXED) &&
14356 (item->defValue != NULL)) {
14357 if (((item->flags & XML_SCHEMAS_ATTR_FIXED) == 0) ||
14358 (!xmlStrEqual(item->defValue, decl->defValue))) {
14359 xmlSchemaPCustomErr(ctxt,
14360 XML_SCHEMAP_AU_PROPS_CORRECT_2,
14361 NULL, NULL, item->node,
14362 "The value constraint must be fixed "
14363 "and match the referenced attribute "
14364 "declarations's value constraint '%s'",
14365 decl->defValue);
14366 }
14367 /*
14368 * FUTURE: One should change the values of the attr. use
14369 * if ever validation should be attempted even if the
14370 * schema itself was not fully valid.
14371 */
14372 }
Daniel Veillard3646d642004-06-02 19:19:14 +000014373 } else {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014374 item->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
14375 }
Daniel Veillard4255d502002-04-16 15:50:10 +000014376}
14377
14378/**
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000014379 * xmlSchemaResolveIDCKeyRef:
14380 * @idc: the identity-constraint definition
14381 * @ctxt: the schema parser context
14382 * @name: the attribute name
14383 *
14384 * Resolve keyRef references to key/unique IDCs.
14385 */
14386static void
14387xmlSchemaResolveIDCKeyRef(xmlSchemaIDCPtr idc,
14388 xmlSchemaParserCtxtPtr ctxt,
14389 const xmlChar * name)
14390{
14391 if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF)
14392 return;
14393 if (idc->ref->name != NULL) {
14394 idc->ref->item = (xmlSchemaBasicItemPtr) xmlHashLookup2(
14395 ctxt->schema->idcDef,
14396 idc->ref->name,
14397 idc->ref->targetNamespace);
14398 if (idc->ref->item == NULL) {
14399 /*
14400 * TODO: It is actually not an error to fail to resolve.
14401 */
14402 xmlSchemaPResCompAttrErr(ctxt,
14403 XML_SCHEMAP_SRC_RESOLVE,
14404 NULL, (xmlSchemaTypePtr) idc, idc->node,
14405 "refer", idc->ref->name,
14406 idc->ref->targetNamespace,
14407 XML_SCHEMA_TYPE_IDC_KEYREF, NULL);
14408 return;
14409 }
14410 }
14411}
14412
14413/**
Daniel Veillard4255d502002-04-16 15:50:10 +000014414 * xmlSchemaParse:
14415 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +000014416 *
Daniel Veillard01c13b52002-12-10 15:19:08 +000014417 * parse a schema definition resource and build an internal
Daniel Veillard4255d502002-04-16 15:50:10 +000014418 * XML Shema struture which can be used to validate instances.
14419 * *WARNING* this interface is highly subject to change
14420 *
14421 * Returns the internal XML Schema structure built from the resource or
14422 * NULL in case of error
14423 */
14424xmlSchemaPtr
14425xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt)
14426{
14427 xmlSchemaPtr ret = NULL;
14428 xmlDocPtr doc;
Daniel Veillardbd2904b2003-11-25 15:38:59 +000014429 xmlNodePtr root;
Daniel Veillarddda22c12004-01-24 08:31:30 +000014430 int preserve = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000014431
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014432 /*
14433 * This one is used if the schema to be parsed was specified via
14434 * the API; i.e. not automatically by the validated instance document.
14435 */
14436
Daniel Veillard4255d502002-04-16 15:50:10 +000014437 xmlSchemaInitTypes();
14438
Daniel Veillard6045c902002-10-09 21:13:59 +000014439 if (ctxt == NULL)
Daniel Veillard4255d502002-04-16 15:50:10 +000014440 return (NULL);
14441
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000014442 ctxt->nberrors = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000014443 ctxt->counter = 0;
14444 ctxt->container = NULL;
14445
14446 /*
14447 * First step is to parse the input document into an DOM/Infoset
14448 */
Daniel Veillard6045c902002-10-09 21:13:59 +000014449 if (ctxt->URL != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +000014450 doc = xmlReadFile((const char *) ctxt->URL, NULL,
14451 SCHEMAS_PARSE_OPTIONS);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014452 if (doc == NULL) {
14453 xmlSchemaPErr(ctxt, NULL,
14454 XML_SCHEMAP_FAILED_LOAD,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014455 "xmlSchemaParse: could not load '%s'.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014456 ctxt->URL, NULL);
14457 return (NULL);
14458 }
Daniel Veillard6045c902002-10-09 21:13:59 +000014459 } else if (ctxt->buffer != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +000014460 doc = xmlReadMemory(ctxt->buffer, ctxt->size, NULL, NULL,
14461 SCHEMAS_PARSE_OPTIONS);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014462 if (doc == NULL) {
14463 xmlSchemaPErr(ctxt, NULL,
14464 XML_SCHEMAP_FAILED_PARSE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014465 "xmlSchemaParse: could not parse.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014466 NULL, NULL);
14467 return (NULL);
14468 }
14469 doc->URL = xmlStrdup(BAD_CAST "in_memory_buffer");
Daniel Veillard65765282004-01-08 16:59:30 +000014470 ctxt->URL = xmlDictLookup(ctxt->dict, BAD_CAST "in_memory_buffer", -1);
Daniel Veillard9d751502003-10-29 13:21:47 +000014471 } else if (ctxt->doc != NULL) {
14472 doc = ctxt->doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +000014473 preserve = 1;
Daniel Veillard6045c902002-10-09 21:13:59 +000014474 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014475 xmlSchemaPErr(ctxt, NULL,
14476 XML_SCHEMAP_NOTHING_TO_PARSE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014477 "xmlSchemaParse: could not parse.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014478 NULL, NULL);
14479 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000014480 }
14481
14482 /*
14483 * Then extract the root and Schema parse it
14484 */
14485 root = xmlDocGetRootElement(doc);
14486 if (root == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014487 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
14488 XML_SCHEMAP_NOROOT,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014489 "The schema has no document element.\n", NULL, NULL);
Daniel Veillarddda22c12004-01-24 08:31:30 +000014490 if (!preserve) {
14491 xmlFreeDoc(doc);
14492 }
Daniel Veillard4255d502002-04-16 15:50:10 +000014493 return (NULL);
14494 }
14495
14496 /*
14497 * Remove all the blank text nodes
14498 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +000014499 xmlSchemaCleanupDoc(ctxt, root);
Daniel Veillard4255d502002-04-16 15:50:10 +000014500
14501 /*
14502 * Then do the parsing for good
14503 */
14504 ret = xmlSchemaParseSchema(ctxt, root);
Daniel Veillard1d913862003-11-21 00:28:39 +000014505 if (ret == NULL) {
Daniel Veillarddda22c12004-01-24 08:31:30 +000014506 if (!preserve) {
14507 xmlFreeDoc(doc);
14508 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014509 return (NULL);
Daniel Veillard1d913862003-11-21 00:28:39 +000014510 }
Daniel Veillard4255d502002-04-16 15:50:10 +000014511 ret->doc = doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +000014512 ret->preserve = preserve;
Daniel Veillard4255d502002-04-16 15:50:10 +000014513 ctxt->schema = ret;
Daniel Veillardc0826a72004-08-10 14:17:33 +000014514 ctxt->ctxtType = NULL;
14515 ctxt->parentItem = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000014516 /*
Daniel Veillardf2a12832003-11-24 13:04:35 +000014517 * Then fixup all attributes declarations
14518 */
14519 xmlHashScan(ret->attrDecl, (xmlHashScanner) xmlSchemaAttrFixup, ctxt);
14520
14521 /*
14522 * Then fixup all attributes group declarations
14523 */
14524 xmlHashScan(ret->attrgrpDecl, (xmlHashScanner) xmlSchemaAttrGrpFixup,
14525 ctxt);
14526
14527 /*
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000014528 * Resolve identity-constraint keyRefs.
14529 */
14530 xmlHashScan(ret->idcDef, (xmlHashScanner) xmlSchemaResolveIDCKeyRef, ctxt);
14531
14532 /*
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000014533 * Check attribute groups for circular references.
14534 */
14535 xmlHashScan(ret->attrgrpDecl, (xmlHashScanner)
14536 xmlSchemaCheckAttributeGroupCircular, ctxt);
14537
14538 /*
14539 * Then fixup all model group definitions.
14540 */
14541 xmlHashScan(ret->groupDecl, (xmlHashScanner) xmlSchemaGroupDefFixup, ctxt);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014542
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000014543 /*
Daniel Veillard4255d502002-04-16 15:50:10 +000014544 * Then fixup all types properties
Daniel Veillardc0826a72004-08-10 14:17:33 +000014545 */
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000014546 xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaTypeFixup, ctxt);
Daniel Veillardc0826a72004-08-10 14:17:33 +000014547
14548 /*
14549 * Then fix references of element declaration; apply constraints.
14550 */
14551 xmlHashScanFull(ret->elemDecl,
14552 (xmlHashScannerFull) xmlSchemaRefFixupCallback, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +000014553
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000014554 /*
14555 * Check model groups defnitions for circular references.
14556 */
14557 xmlHashScan(ret->groupDecl, (xmlHashScanner)
14558 xmlSchemaCheckGroupDefCircular, ctxt);
14559
Daniel Veillard4255d502002-04-16 15:50:10 +000014560 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014561 * Then build the content model for all complex types
Daniel Veillard4255d502002-04-16 15:50:10 +000014562 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014563 xmlHashScan(ret->typeDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014564 (xmlHashScanner) xmlSchemaBuildContentModel, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +000014565
14566 /*
14567 * Then check the defaults part of the type like facets values
14568 */
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +000014569 /* OLD: xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaCheckDefaults, ctxt); */
Daniel Veillard4255d502002-04-16 15:50:10 +000014570
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014571 /*
14572 * Validate the value constraint of attribute declarations/uses.
14573 */
14574 xmlHashScan(ret->attrDecl, (xmlHashScanner) xmlSchemaCheckAttrValConstr, ctxt);
14575
14576 /*
14577 * Validate the value constraint of element declarations.
14578 */
14579 xmlHashScan(ret->elemDecl, (xmlHashScanner) xmlSchemaCheckElemValConstr, ctxt);
14580
Daniel Veillardc0826a72004-08-10 14:17:33 +000014581
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000014582 if (ctxt->nberrors != 0) {
14583 xmlSchemaFree(ret);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014584 ret = NULL;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000014585 }
Daniel Veillard4255d502002-04-16 15:50:10 +000014586 return (ret);
14587}
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014588
Daniel Veillard4255d502002-04-16 15:50:10 +000014589/**
Daniel Veillard01c13b52002-12-10 15:19:08 +000014590 * xmlSchemaSetParserErrors:
Daniel Veillard4255d502002-04-16 15:50:10 +000014591 * @ctxt: a schema validation context
Daniel Veillard01c13b52002-12-10 15:19:08 +000014592 * @err: the error callback
14593 * @warn: the warning callback
14594 * @ctx: contextual data for the callbacks
Daniel Veillard4255d502002-04-16 15:50:10 +000014595 *
Daniel Veillard01c13b52002-12-10 15:19:08 +000014596 * Set the callback functions used to handle errors for a validation context
Daniel Veillard4255d502002-04-16 15:50:10 +000014597 */
14598void
14599xmlSchemaSetParserErrors(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014600 xmlSchemaValidityErrorFunc err,
14601 xmlSchemaValidityWarningFunc warn, void *ctx)
14602{
Daniel Veillard4255d502002-04-16 15:50:10 +000014603 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014604 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000014605 ctxt->error = err;
14606 ctxt->warning = warn;
14607 ctxt->userData = ctx;
14608}
14609
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000014610/**
Daniel Veillard259f0df2004-08-18 09:13:18 +000014611 * xmlSchemaGetParserErrors:
14612 * @ctxt: a XMl-Schema parser context
14613 * @err: the error callback result
14614 * @warn: the warning callback result
14615 * @ctx: contextual data for the callbacks result
14616 *
14617 * Get the callback information used to handle errors for a parser context
14618 *
14619 * Returns -1 in case of failure, 0 otherwise
14620 */
14621int
14622xmlSchemaGetParserErrors(xmlSchemaParserCtxtPtr ctxt,
14623 xmlSchemaValidityErrorFunc * err,
14624 xmlSchemaValidityWarningFunc * warn, void **ctx)
14625{
14626 if (ctxt == NULL)
14627 return(-1);
14628 if (err != NULL)
14629 *err = ctxt->error;
14630 if (warn != NULL)
14631 *warn = ctxt->warning;
14632 if (ctx != NULL)
14633 *ctx = ctxt->userData;
14634 return(0);
14635}
14636
14637/**
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000014638 * xmlSchemaFacetTypeToString:
14639 * @type: the facet type
14640 *
14641 * Convert the xmlSchemaTypeType to a char string.
14642 *
14643 * Returns the char string representation of the facet type if the
14644 * type is a facet and an "Internal Error" string otherwise.
14645 */
14646static const char *
14647xmlSchemaFacetTypeToString(xmlSchemaTypeType type)
14648{
14649 switch (type) {
14650 case XML_SCHEMA_FACET_PATTERN:
14651 return ("pattern");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014652 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000014653 return ("maxExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014654 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000014655 return ("maxInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014656 case XML_SCHEMA_FACET_MINEXCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000014657 return ("minExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014658 case XML_SCHEMA_FACET_MININCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000014659 return ("minInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014660 case XML_SCHEMA_FACET_WHITESPACE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000014661 return ("whiteSpace");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014662 case XML_SCHEMA_FACET_ENUMERATION:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000014663 return ("enumeration");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014664 case XML_SCHEMA_FACET_LENGTH:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000014665 return ("length");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014666 case XML_SCHEMA_FACET_MAXLENGTH:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000014667 return ("maxLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014668 case XML_SCHEMA_FACET_MINLENGTH:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000014669 return ("minLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014670 case XML_SCHEMA_FACET_TOTALDIGITS:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000014671 return ("totalDigits");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014672 case XML_SCHEMA_FACET_FRACTIONDIGITS:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000014673 return ("fractionDigits");
14674 default:
14675 break;
14676 }
14677 return ("Internal Error");
14678}
14679
Daniel Veillardc0826a72004-08-10 14:17:33 +000014680
Daniel Veillardc0826a72004-08-10 14:17:33 +000014681
14682static int
14683xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type)
14684{
14685 xmlSchemaTypePtr anc;
14686
14687 /*
14688 * The normalization type can be changed only for types which are derived
14689 * from xsd:string.
14690 */
14691 if (type->type == XML_SCHEMA_TYPE_BASIC) {
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +000014692 if (type->builtInType == XML_SCHEMAS_STRING)
Daniel Veillardc0826a72004-08-10 14:17:33 +000014693 return(XML_SCHEMAS_VAL_WTSP_PRESERVE);
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +000014694 else if (type->builtInType == XML_SCHEMAS_NORMSTRING)
14695 return(XML_SCHEMAS_VAL_WTSP_REPLACE);
Daniel Veillardc0826a72004-08-10 14:17:33 +000014696 else {
14697 /*
14698 * For all ·atomic· datatypes other than string (and types ·derived·
14699 * by ·restriction· from it) the value of whiteSpace is fixed to
14700 * collapse
14701 */
14702 return(XML_SCHEMAS_VAL_WTSP_COLLAPSE);
14703 }
14704 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
14705 /*
14706 * For list types the facet "whiteSpace" is fixed to "collapse".
14707 */
14708 return (XML_SCHEMAS_VAL_WTSP_COLLAPSE);
14709 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
14710 return (-1);
14711 } else if (type->facetSet != NULL) {
14712 xmlSchemaTypePtr anyST;
14713 xmlSchemaFacetLinkPtr lin;
14714
14715 /*
14716 * Atomic types.
14717 */
14718 anyST = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
14719 anc = type->baseType;
14720 do {
14721 /*
14722 * For all ·atomic· datatypes other than string (and types ·derived·
14723 * by ·restriction· from it) the value of whiteSpace is fixed to
14724 * collapse
14725 */
14726 if ((anc->type == XML_SCHEMA_TYPE_BASIC) &&
14727 (anc->builtInType == XML_SCHEMAS_STRING)) {
14728
14729 lin = type->facetSet;
14730 do {
14731 if (lin->facet->type == XML_SCHEMA_FACET_WHITESPACE) {
14732 if (lin->facet->whitespace ==
14733 XML_SCHEMAS_FACET_COLLAPSE) {
14734 return(XML_SCHEMAS_VAL_WTSP_COLLAPSE);
14735 } else if (lin->facet->whitespace ==
14736 XML_SCHEMAS_FACET_REPLACE) {
14737 return(XML_SCHEMAS_VAL_WTSP_REPLACE);
14738 } else
14739 return(XML_SCHEMAS_VAL_WTSP_PRESERVE);
14740 break;
14741 }
14742 lin = lin->next;
14743 } while (lin != NULL);
14744 break;
14745 }
14746 anc = anc->baseType;
14747 } while (anc != anyST);
14748 return (XML_SCHEMAS_VAL_WTSP_COLLAPSE);
14749 }
14750 return (-1);
14751}
14752
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000014753/**
Daniel Veillard377e1a92004-04-16 16:30:05 +000014754 * xmlSchemaValidateFacetsInternal:
14755 * @ctxt: a schema validation context
Daniel Veillardc0826a72004-08-10 14:17:33 +000014756 * @type: the type holding the facets
Daniel Veillard377e1a92004-04-16 16:30:05 +000014757 * @facets: the list of facets to check
14758 * @value: the lexical repr of the value to validate
14759 * @val: the precomputed value
William M. Bracke7091952004-05-11 15:09:58 +000014760 * @fireErrors: if 0, only internal errors will be fired;
14761 * otherwise all errors will be fired.
Daniel Veillard377e1a92004-04-16 16:30:05 +000014762 *
14763 * Check a value against all facet conditions
14764 *
14765 * Returns 0 if the element is schemas valid, a positive error code
14766 * number otherwise and -1 in case of internal or API error.
14767 */
14768static int
14769xmlSchemaValidateFacetsInternal(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014770 xmlSchemaTypePtr type,
14771 const xmlChar * value,
14772 unsigned long length,
14773 int fireErrors)
Daniel Veillard377e1a92004-04-16 16:30:05 +000014774{
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000014775 int ret = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014776 xmlNodePtr node;
Daniel Veillardc0826a72004-08-10 14:17:33 +000014777 xmlSchemaTypePtr biType; /* The build-in type. */
14778 xmlSchemaTypePtr tmpType;
14779 xmlSchemaFacetLinkPtr facetLink;
Daniel Veillardc7e3cc42004-09-28 12:33:52 +000014780 int retFacet;
Daniel Veillardc0826a72004-08-10 14:17:33 +000014781 xmlSchemaFacetPtr facet;
14782 unsigned long len = 0;
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000014783
Daniel Veillardc0826a72004-08-10 14:17:33 +000014784#ifdef DEBUG_UNION_VALIDATION
14785 printf("Facets of type: '%s'\n", (const char *) type->name);
14786 printf(" fireErrors: %d\n", fireErrors);
14787#endif
14788
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014789 node = ctxt->node;
Daniel Veillardc0826a72004-08-10 14:17:33 +000014790 /*
14791 * NOTE: Do not jump away, if the facetSet of the given type is
14792 * empty: until now, "pattern" facets of the *base types* need to
14793 * be checked as well.
14794 */
14795 biType = type->baseType;
14796 while ((biType != NULL) && (biType->type != XML_SCHEMA_TYPE_BASIC))
14797 biType = biType->baseType;
14798 if (biType == NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014799 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014800 "Internal error: xmlSchemaValidateFacetsInternal, "
14801 "the base type axis of the given type '%s' does not resolve to "
14802 "a built-in type.\n",
14803 type->name, NULL);
14804 return (-1);
14805 }
14806
14807 if (type->facetSet != NULL) {
14808 facetLink = type->facetSet;
14809 while (facetLink != NULL) {
14810 facet = facetLink->facet;
14811 /*
14812 * Skip the pattern "whiteSpace": it is used to
14813 * format the character content beforehand.
14814 */
14815 switch (facet->type) {
14816 case XML_SCHEMA_FACET_WHITESPACE:
14817 case XML_SCHEMA_FACET_PATTERN:
14818 case XML_SCHEMA_FACET_ENUMERATION:
14819 break;
14820 case XML_SCHEMA_FACET_LENGTH:
14821 case XML_SCHEMA_FACET_MINLENGTH:
14822 case XML_SCHEMA_FACET_MAXLENGTH:
14823 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
14824 ret = xmlSchemaValidateListSimpleTypeFacet(facet,
14825 value, length, 0);
14826 len = length;
14827 } else
14828 ret = xmlSchemaValidateLengthFacet(biType, facet,
14829 value, ctxt->value, &len);
14830 break;
14831 default:
14832 ret = xmlSchemaValidateFacet(biType, facet, value,
14833 ctxt->value);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014834 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000014835 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014836 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014837 "Internal error: xmlSchemaValidateFacetsInternal, "
14838 "validating facet of type '%s'.\n",
14839 type->name, NULL);
14840 break;
14841 } else if ((ret > 0) && (fireErrors)) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014842 xmlSchemaVFacetErr(ctxt, ret, node, value, len,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014843 type, facet, NULL, NULL, NULL, NULL);
14844 }
14845
14846 facetLink = facetLink->next;
14847 }
14848 if (ret >= 0) {
14849 /*
14850 * Process enumerations.
14851 */
14852 retFacet = 0;
14853 facetLink = type->facetSet;
14854 while (facetLink != NULL) {
14855 if (facetLink->facet->type == XML_SCHEMA_FACET_ENUMERATION) {
14856 retFacet = xmlSchemaValidateFacet(biType, facetLink->facet,
14857 value, ctxt->value);
14858 if (retFacet <= 0)
14859 break;
14860 }
14861 facetLink = facetLink->next;
14862 }
14863 if (retFacet > 0) {
14864 ret = XML_SCHEMAV_CVC_ENUMERATION_VALID;
14865 if (fireErrors)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014866 xmlSchemaVFacetErr(ctxt, ret, node,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014867 value, 0, type, NULL, NULL, NULL, NULL, NULL);
14868 } else if (retFacet < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014869 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014870 "Internal error: xmlSchemaValidateFacetsInternal, "
14871 "validating facet of type '%s'.\n",
14872 BAD_CAST "enumeration", NULL);
14873 ret = -1;
14874 }
14875 }
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000014876 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000014877 if (ret >= 0) {
14878 /*
14879 * Process patters. Pattern facets are ORed at type level
14880 * and ANDed if derived. Walk the base type axis.
14881 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000014882 tmpType = type;
14883 facet = NULL;
14884 do {
14885 retFacet = 0;
14886 for (facetLink = tmpType->facetSet; facetLink != NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014887 facetLink = facetLink->next) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000014888 if (facetLink->facet->type != XML_SCHEMA_FACET_PATTERN)
14889 continue;
14890 retFacet = xmlSchemaValidateFacet(biType, facetLink->facet,
14891 value, ctxt->value);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014892 if (retFacet == 0)
Daniel Veillardc0826a72004-08-10 14:17:33 +000014893 break;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014894 else if (retFacet < 0) {
14895 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
14896 "Internal error: xmlSchemaValidateFacetsInternal, "
14897 "validating 'pattern' facet '%s' of type '%s'.\n",
14898 facetLink->facet->value, tmpType->name);
14899 ret = -1;
14900 break;
14901 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +000014902 /* Save the last non-validating facet. */
14903 facet = facetLink->facet;
14904 }
14905 if (retFacet != 0)
14906 break;
14907 tmpType = tmpType->baseType;
14908 } while ((tmpType != NULL) && (tmpType->type != XML_SCHEMA_TYPE_BASIC));
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014909 if (retFacet > 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000014910 ret = XML_SCHEMAV_CVC_PATTERN_VALID;
14911 if (fireErrors) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014912 xmlSchemaVFacetErr(ctxt, ret, node, value, 0, type, facet,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014913 NULL, NULL, NULL, NULL);
14914 }
14915 }
14916 }
14917
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000014918 return (ret);
14919}
14920
Daniel Veillard4255d502002-04-16 15:50:10 +000014921/************************************************************************
14922 * *
14923 * Simple type validation *
14924 * *
14925 ************************************************************************/
Daniel Veillard377e1a92004-04-16 16:30:05 +000014926
Daniel Veillard4255d502002-04-16 15:50:10 +000014927
14928/************************************************************************
14929 * *
14930 * DOM Validation code *
14931 * *
14932 ************************************************************************/
14933
Daniel Veillard4255d502002-04-16 15:50:10 +000014934static int xmlSchemaValidateAttributes(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014935 xmlNodePtr elem,
Daniel Veillard3646d642004-06-02 19:19:14 +000014936 xmlSchemaTypePtr type);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014937static int xmlSchemaValidateElementByType(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014938 xmlSchemaTypePtr type,
14939 int valSimpleContent);
Daniel Veillard4255d502002-04-16 15:50:10 +000014940
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000014941static void xmlSchemaBeginElement(xmlSchemaValidCtxtPtr vctxt);
14942static void xmlSchemaEndElement(xmlSchemaValidCtxtPtr vctxt);
14943
14944#ifdef ELEM_INFO_ENABLED
14945/**
14946 * xmlSchemaGetFreshElemInfo:
14947 * @vctxt: the schema validation context
14948 *
14949 * Creates/reuses and initializes the element info item for
14950 * the currect tree depth.
14951 *
14952 * Returns the element info item or NULL on API or internal errors.
14953 */
14954static xmlSchemaElemInfoPtr
14955xmlSchemaGetFreshElemInfo(xmlSchemaValidCtxtPtr vctxt)
14956{
14957 xmlSchemaElemInfoPtr info = NULL;
14958
14959 if (vctxt->depth > vctxt->sizeElemInfos) {
14960 xmlSchemaVErr(vctxt, NULL, XML_SCHEMAV_INTERNAL,
14961 "Internal error: xmlSchemaPushDepthInfo, "
14962 "an inconsistent depth encountered.\n",
14963 NULL, NULL);
14964 return (NULL);
14965 }
14966 if (vctxt->elemInfos == NULL) {
14967 vctxt->elemInfos = (xmlSchemaElemInfoPtr *)
14968 xmlMalloc(10 * sizeof(xmlSchemaElemInfoPtr));
14969 if (vctxt->elemInfos == NULL) {
14970 xmlSchemaVErrMemory(vctxt,
14971 "allocating the element info array", NULL);
14972 return (NULL);
14973 }
14974 memset(vctxt->elemInfos, 0, 10 * sizeof(xmlSchemaElemInfoPtr));
14975 vctxt->sizeElemInfos = 10;
14976 } else if (vctxt->sizeElemInfos == vctxt->depth) {
14977 int i = vctxt->sizeElemInfos;
14978
14979 vctxt->sizeElemInfos *= 2;
14980 vctxt->elemInfos = (xmlSchemaElemInfoPtr *)
14981 xmlRealloc(vctxt->elemInfos, vctxt->sizeElemInfos *
14982 sizeof(xmlSchemaElemInfoPtr));
14983 if (vctxt->elemInfos == NULL) {
14984 xmlSchemaVErrMemory(vctxt,
14985 "re-allocating the element info array", NULL);
14986 return (NULL);
14987 }
14988 /*
14989 * We need the new memory to be NULLed.
14990 * TODO: Use memset instead?
14991 */
14992 for (; i < vctxt->sizeElemInfos; i++)
14993 vctxt->elemInfos[i] = NULL;
14994 } else
14995 info = vctxt->elemInfos[vctxt->depth];
14996
14997 if (info == NULL) {
14998 info = (xmlSchemaElemInfoPtr)
14999 xmlMalloc(sizeof(xmlSchemaElemInfo));
15000 if (info == NULL) {
15001 xmlSchemaVErrMemory(vctxt,
15002 "allocating an element info", NULL);
15003 return (NULL);
15004 }
15005 vctxt->elemInfos[vctxt->depth] = info;
15006 }
15007 memset(info, 0, sizeof(xmlSchemaElemInfo));
15008 info->depth = vctxt->depth;
15009
15010 return (info);
15011}
15012#endif /* ELEM_INFO_ENABLED */
15013
Daniel Veillard3646d642004-06-02 19:19:14 +000015014
15015/**
15016 * xmlSchemaFreeAttrStates:
15017 * @state: a list of attribute states
15018 *
15019 * Free the given list of attribute states
15020 *
15021 */
15022static void
15023xmlSchemaFreeAttributeStates(xmlSchemaAttrStatePtr state)
15024{
15025 xmlSchemaAttrStatePtr tmp;
15026 while (state != NULL) {
15027 tmp = state;
15028 state = state->next;
15029 xmlFree(tmp);
15030 }
15031}
15032
Daniel Veillard4255d502002-04-16 15:50:10 +000015033/**
15034 * xmlSchemaRegisterAttributes:
15035 * @ctxt: a schema validation context
15036 * @attrs: a list of attributes
15037 *
15038 * Register the list of attributes as the set to be validated on that element
15039 *
15040 * Returns -1 in case of error, 0 otherwise
15041 */
15042static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015043xmlSchemaRegisterAttributes(xmlSchemaValidCtxtPtr ctxt, xmlAttrPtr attrs)
15044{
Daniel Veillard3646d642004-06-02 19:19:14 +000015045 xmlSchemaAttrStatePtr tmp;
15046
15047 ctxt->attr = NULL;
15048 ctxt->attrTop = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000015049 while (attrs != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015050 if ((attrs->ns != NULL) &&
15051 (xmlStrEqual(attrs->ns->href, xmlSchemaInstanceNs))) {
15052 attrs = attrs->next;
15053 continue;
15054 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000015055 tmp = (xmlSchemaAttrStatePtr)
15056 xmlMalloc(sizeof(xmlSchemaAttrState));
15057 if (tmp == NULL) {
15058 xmlSchemaVErrMemory(ctxt, "registering attributes", NULL);
15059 return (-1);
15060 }
Daniel Veillard3646d642004-06-02 19:19:14 +000015061 tmp->attr = attrs;
15062 tmp->state = XML_SCHEMAS_ATTR_UNKNOWN;
15063 tmp->next = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015064 tmp->decl = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000015065 if (ctxt->attr == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015066 ctxt->attr = tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000015067 else
15068 ctxt->attrTop->next = tmp;
15069 ctxt->attrTop = tmp;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015070 attrs = attrs->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000015071 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015072 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000015073}
15074
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015075#if 0 /* Currently not used */
Daniel Veillard4255d502002-04-16 15:50:10 +000015076/**
Daniel Veillard4255d502002-04-16 15:50:10 +000015077 * xmlSchemaValidateCheckNodeList
15078 * @nodelist: the list of nodes
15079 *
15080 * Check the node list is only made of text nodes and entities pointing
15081 * to text nodes
15082 *
15083 * Returns 1 if true, 0 if false and -1 in case of error
15084 */
15085static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015086xmlSchemaValidateCheckNodeList(xmlNodePtr nodelist)
15087{
Daniel Veillard4255d502002-04-16 15:50:10 +000015088 while (nodelist != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015089 if (nodelist->type == XML_ENTITY_REF_NODE) {
15090 TODO /* implement recursion in the entity content */
15091 }
15092 if ((nodelist->type != XML_TEXT_NODE) &&
15093 (nodelist->type != XML_COMMENT_NODE) &&
15094 (nodelist->type != XML_PI_NODE) &&
William M. Bracke7091952004-05-11 15:09:58 +000015095 (nodelist->type != XML_CDATA_SECTION_NODE)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015096 return (0);
15097 }
15098 nodelist = nodelist->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000015099 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015100 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +000015101}
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015102#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000015103
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015104static void
15105xmlSchemaPostSchemaAssembleFixup(xmlSchemaParserCtxtPtr ctxt)
15106{
15107 int i, nbItems;
15108 xmlSchemaTypePtr item, *items;
15109
15110
15111 /*
15112 * During the Assemble of the schema ctxt->curItems has
15113 * been filled with the relevant new items. Fix those up.
15114 */
15115 nbItems = ctxt->assemble->nbItems;
15116 items = (xmlSchemaTypePtr *) ctxt->assemble->items;
15117
15118 for (i = 0; i < nbItems; i++) {
15119 item = items[i];
15120 switch (item->type) {
15121 case XML_SCHEMA_TYPE_ATTRIBUTE:
15122 xmlSchemaAttrFixup((xmlSchemaAttributePtr) item, ctxt, NULL);
15123 break;
15124 case XML_SCHEMA_TYPE_ELEMENT:
15125 xmlSchemaRefFixupCallback((xmlSchemaElementPtr) item, ctxt,
15126 NULL, NULL, NULL);
15127 break;
15128 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
15129 xmlSchemaAttrGrpFixup((xmlSchemaAttributeGroupPtr) item,
15130 ctxt, NULL);
15131 break;
15132 case XML_SCHEMA_TYPE_GROUP:
15133 xmlSchemaGroupDefFixup(item, ctxt, NULL);
15134 default:
15135 break;
15136 }
15137 }
15138 /*
15139 * Circularity checks.
15140 */
15141 for (i = 0; i < nbItems; i++) {
15142 item = items[i];
15143 switch (item->type) {
15144 case XML_SCHEMA_TYPE_GROUP:
15145 xmlSchemaCheckGroupDefCircular(item, ctxt, NULL);
15146 break;
15147 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
15148 xmlSchemaCheckAttributeGroupCircular(
15149 (xmlSchemaAttributeGroupPtr) item, ctxt, NULL);
15150 break;
15151 default:
15152 break;
15153 }
15154 }
15155 /*
15156 * Fixup for all other item.
15157 * TODO: Hmm, not sure if starting from complex/simple types,
15158 * all subsequent items will be reached.
15159 */
15160 for (i = 0; i < nbItems; i++) {
15161 item = items[i];
15162 switch (item->type) {
15163 case XML_SCHEMA_TYPE_SIMPLE:
15164 case XML_SCHEMA_TYPE_COMPLEX:
15165 xmlSchemaTypeFixup(item, ctxt, NULL);
15166 break;
15167 default:
15168 break;
15169 }
15170 }
15171 /*
15172 * Check facet values. Note that facets are
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +000015173 * hold by simple type components only (and
15174 * by complex types in the current implementation).
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015175 */
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +000015176 /* OLD:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015177 for (i = 0; i < nbItems; i++) {
15178 item = items[i];
15179 switch (item->type) {
15180 case XML_SCHEMA_TYPE_SIMPLE:
15181 case XML_SCHEMA_TYPE_COMPLEX:
15182 xmlSchemaCheckDefaults(item, ctxt, NULL);
15183 break;
15184 default:
15185 break;
15186 }
15187 }
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +000015188 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015189 /*
15190 * Build the content model for complex types.
15191 */
15192 for (i = 0; i < nbItems; i++) {
15193 item = items[i];
15194 switch (item->type) {
15195 case XML_SCHEMA_TYPE_COMPLEX:
15196 xmlSchemaBuildContentModel(item, ctxt, NULL);
15197 break;
15198 default:
15199 break;
15200 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015201 }
15202 /*
15203 * Validate value contraint values.
15204 */
15205 for (i = 0; i < nbItems; i++) {
15206 item = items[i];
15207 switch (item->type) {
15208 case XML_SCHEMA_TYPE_ATTRIBUTE:
15209 xmlSchemaCheckAttrValConstr((xmlSchemaAttributePtr) item, ctxt, NULL);
15210 break;
15211 case XML_SCHEMA_TYPE_ELEMENT:
15212 xmlSchemaCheckElemValConstr((xmlSchemaElementPtr) item, ctxt, NULL);
15213 break;
15214 default:
15215 break;
15216 }
15217 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015218}
15219
15220/**
15221 * xmlSchemaAssembleByLocation:
15222 * @pctxt: a schema parser context
15223 * @vctxt: a schema validation context
15224 * @schema: the existing schema
15225 * @node: the node that fired the assembling
15226 * @nsName: the namespace name of the new schema
15227 * @location: the location of the schema
15228 *
15229 * Expands an existing schema by an additional schema.
15230 *
15231 * Returns 0 if the new schema is correct, a positive error code
15232 * number otherwise and -1 in case of an internal or API error.
15233 */
15234static int
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015235xmlSchemaAssembleByLocation(xmlSchemaValidCtxtPtr vctxt,
15236 xmlSchemaPtr schema,
15237 xmlNodePtr node,
15238 const xmlChar *nsName,
15239 const xmlChar *location)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015240{
15241 const xmlChar *targetNs, *oldtns;
15242 xmlDocPtr doc, olddoc;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015243 int oldflags, ret = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015244 xmlNodePtr docElem;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015245 xmlSchemaParserCtxtPtr pctxt;
15246
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015247 /*
15248 * This should be used:
15249 * 1. on <import>(s)
15250 * 2. if requested by the validated instance
15251 * 3. if requested via the API
15252 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015253 if ((vctxt == NULL) || (schema == NULL))
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015254 return (-1);
15255 /*
15256 * Create a temporary parser context.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015257 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015258 if ((vctxt->pctxt == NULL) &&
15259 (xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1)) {
15260 xmlSchemaVErr(vctxt, node,
15261 XML_SCHEMAV_INTERNAL,
15262 "Internal error: xmlSchemaAssembleByLocation, "
15263 "failed to create a temp. parser context.\n",
15264 NULL, NULL);
15265 return (-1);
15266 }
15267 pctxt = vctxt->pctxt;
15268 /*
15269 * Set the counter to produce unique names for anonymous items.
15270 */
15271 pctxt->counter = schema->counter;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015272 /*
15273 * Acquire the schema document.
15274 */
15275 ret = xmlSchemaAcquireSchemaDoc(pctxt, schema, node,
15276 nsName, location, &doc, &targetNs, 0);
15277 if (ret != 0) {
15278 if (doc != NULL)
15279 xmlFreeDoc(doc);
15280 } else if (doc != NULL) {
15281 docElem = xmlDocGetRootElement(doc);
15282 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015283 * Create new assemble info.
15284 */
15285 if (pctxt->assemble == NULL) {
15286 pctxt->assemble = xmlSchemaNewAssemble();
15287 if (pctxt->assemble == NULL) {
15288 xmlSchemaVErrMemory(vctxt,
15289 "Memory error: xmlSchemaAssembleByLocation, "
15290 "allocating assemble info", NULL);
15291 xmlFreeDoc(doc);
15292 return (-1);
15293 }
15294 }
15295 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015296 * Save and reset the context & schema.
15297 */
15298 oldflags = schema->flags;
15299 oldtns = schema->targetNamespace;
15300 olddoc = schema->doc;
15301
15302 xmlSchemaClearSchemaDefaults(schema);
15303 schema->targetNamespace = targetNs;
15304 /* schema->nbCurItems = 0; */
15305 pctxt->schema = schema;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015306 pctxt->ctxtType = NULL;
15307 pctxt->parentItem = NULL;
15308
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015309 xmlSchemaParseSchemaDefaults(pctxt, schema, docElem);
15310 xmlSchemaParseSchemaTopLevel(pctxt, schema, docElem->children);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015311 xmlSchemaPostSchemaAssembleFixup(pctxt);
15312 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015313 * Set the counter of items.
15314 */
15315 schema->counter = pctxt->counter;
15316 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015317 * Free the list of assembled components.
15318 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015319 pctxt->assemble->nbItems = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015320 /*
15321 * Restore the context & schema.
15322 */
15323 schema->flags = oldflags;
15324 schema->targetNamespace = oldtns;
15325 schema->doc = olddoc;
15326 ret = pctxt->err;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015327 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015328 return (ret);
15329}
15330
15331/**
15332 * xmlSchemaAssembleByXSIAttr:
15333 * @vctxt: a schema validation context
15334 * @xsiAttr: an xsi attribute
15335 * @noNamespace: whether a schema with no target namespace is exptected
15336 *
15337 * Expands an existing schema by an additional schema using
15338 * the xsi:schemaLocation or xsi:noNamespaceSchemaLocation attribute
15339 * of an instance. If xsi:noNamespaceSchemaLocation is used, @noNamespace
15340 * must be set to 1.
15341 *
15342 * Returns 0 if the new schema is correct, a positive error code
15343 * number otherwise and -1 in case of an internal or API error.
15344 */
15345static int
15346xmlSchemaAssembleByXSIAttr(xmlSchemaValidCtxtPtr vctxt,
15347 xmlAttrPtr xsiAttr,
15348 int noNamespace)
15349{
15350 xmlChar *value;
15351 const xmlChar *cur, *end;
15352 const xmlChar *nsname = NULL, *location;
15353 int count = 0;
15354 int ret = 0;
15355
15356 if (xsiAttr == NULL) {
15357 xmlSchemaVCustomErr(vctxt, XML_SCHEMAV_INTERNAL,
15358 NULL, NULL,
15359 "Internal error: xmlSchemaAssembleByXSIAttr, "
15360 "bad arguments", NULL);
15361 return (-1);
15362 }
15363 /*
15364 * Parse the value; we will assume an even number of values
15365 * to be given (this is how Xerces and XSV work).
15366 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015367 value = xmlNodeGetContent((xmlNodePtr) xsiAttr);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015368 cur = value;
15369 do {
15370 if (noNamespace != 1) {
15371 /*
15372 * Get the namespace name.
15373 */
15374 while (IS_BLANK_CH(*cur))
15375 cur++;
15376 end = cur;
15377 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
15378 end++;
15379 if (end == cur)
15380 break;
15381 count++;
15382 nsname = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
15383 cur = end;
15384 }
15385 /*
15386 * Get the URI.
15387 */
15388 while (IS_BLANK_CH(*cur))
15389 cur++;
15390 end = cur;
15391 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
15392 end++;
15393 if (end == cur)
15394 break;
15395 count++;
15396 location = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015397 cur = end;
15398 ret = xmlSchemaAssembleByLocation(vctxt, vctxt->schema,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015399 xsiAttr->parent, nsname, location);
15400 if (ret == -1) {
15401 xmlSchemaVCustomErr(vctxt,
15402 XML_SCHEMAV_INTERNAL,
15403 (xmlNodePtr) xsiAttr, NULL,
15404 "Internal error: xmlSchemaAssembleByXSIAttr, "
15405 "assembling schemata", NULL);
15406 if (value != NULL)
15407 xmlFree(value);
15408 return (-1);
15409 }
15410 } while (*cur != 0);
15411 if (value != NULL)
15412 xmlFree(value);
15413 return (ret);
15414}
15415
15416/**
15417 * xmlSchemaAssembleByXSIElem:
15418 * @vctxt: a schema validation context
15419 * @elem: an element node possibly holding xsi attributes
15420 * @noNamespace: whether a schema with no target namespace is exptected
15421 *
15422 * Assembles an existing schema by an additional schema using
15423 * the xsi:schemaLocation or xsi:noNamespaceSchemaLocation attributes
15424 * of the given @elem.
15425 *
15426 * Returns 0 if the new schema is correct, a positive error code
15427 * number otherwise and -1 in case of an internal or API error.
15428 */
15429static int
15430xmlSchemaAssembleByXSIElem(xmlSchemaValidCtxtPtr vctxt,
15431 xmlNodePtr elem)
15432{
15433 int ret = 0, retNs = 0;
15434 xmlAttrPtr attr;
15435
15436 attr = xmlHasNsProp(elem, BAD_CAST "schemaLocation", xmlSchemaInstanceNs);
15437 if (attr != NULL) {
15438 retNs = xmlSchemaAssembleByXSIAttr(vctxt, attr, 0);
15439 if (retNs == -1)
15440 return (-1);
15441 }
15442 attr = xmlHasNsProp(elem, BAD_CAST "noNamespaceSchemaLocation", xmlSchemaInstanceNs);
15443 if (attr != NULL) {
15444 ret = xmlSchemaAssembleByXSIAttr(vctxt, attr, 1);
15445 if (ret == -1)
15446 return (-1);
15447 }
15448 if (retNs != 0)
15449 return (retNs);
15450 else
15451 return (ret);
15452}
15453
Daniel Veillard4255d502002-04-16 15:50:10 +000015454/**
Daniel Veillard4255d502002-04-16 15:50:10 +000015455 * xmlSchemaValidateCallback:
15456 * @ctxt: a schema validation context
15457 * @name: the name of the element detected (might be NULL)
15458 * @type: the type
15459 *
15460 * A transition has been made in the automata associated to an element
15461 * content model
15462 */
15463static void
15464xmlSchemaValidateCallback(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015465 const xmlChar * name ATTRIBUTE_UNUSED,
15466 xmlSchemaTypePtr type, xmlNodePtr node)
15467{
Daniel Veillard4255d502002-04-16 15:50:10 +000015468 xmlSchemaTypePtr oldtype = ctxt->type;
15469 xmlNodePtr oldnode = ctxt->node;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015470
Daniel Veillard4255d502002-04-16 15:50:10 +000015471#ifdef DEBUG_CONTENT
Daniel Veillard8651f532002-04-17 09:06:27 +000015472 xmlGenericError(xmlGenericErrorContext,
15473 "xmlSchemaValidateCallback: %s, %s, %s\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015474 name, type->name, node->name);
Daniel Veillard4255d502002-04-16 15:50:10 +000015475#endif
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015476 /*
15477 * @type->type will be XML_SCHEMA_TYPE_ANY or XML_SCHEMA_TYPE_ELEMENT.
15478 */
Daniel Veillard4255d502002-04-16 15:50:10 +000015479 ctxt->type = type;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015480 ctxt->node = node;
15481 ctxt->cur = node->children;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015482
15483#ifdef ELEM_INFO_ENABLED
15484 xmlSchemaBeginElement(ctxt);
15485#endif
15486
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015487 /*
15488 * Assemble new schemata using xsi.
15489 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015490 if (ctxt->xsiAssemble) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015491 int ret;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015492
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015493 ret = xmlSchemaAssembleByXSIElem(ctxt, ctxt->node);
15494 if (ret == -1) {
15495 xmlSchemaVCustomErr(ctxt,
15496 XML_SCHEMAV_INTERNAL,
15497 ctxt->node, NULL,
15498 "Internal error: xmlSchemaValidateElement, "
15499 "assembling schema by xsi", NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015500 goto leave;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015501 }
15502 /*
15503 * NOTE: We won't react on schema parser errors here.
15504 * TODO: But a warning would be nice.
15505 */
15506 }
15507 switch (type->type) {
15508 case XML_SCHEMA_TYPE_ELEMENT: {
15509 /*
15510 * NOTE: The build of the content model
15511 * (xmlSchemaBuildAContentModel) ensures that the element
15512 * declaration (and not a reference to it) will be given.
15513 */
15514 if (((xmlSchemaElementPtr) ctxt->type)->ref != NULL) {
15515 /*
15516 * This is paranoid coding ;-)... it should not
15517 * happen here any more.
15518 */
15519 xmlSchemaVCustomErr(ctxt,
15520 XML_SCHEMAV_INTERNAL,
15521 node, NULL,
15522 "Internal error: xmlSchemaValidateCallback, "
15523 "element declaration 'reference' encountered, "
15524 "but an element declaration was expected",
15525 NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015526 goto leave;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015527 }
15528 xmlSchemaValidateElementByDeclaration(ctxt,
15529 (xmlSchemaElementPtr) type);
15530 break;
15531 }
15532 case XML_SCHEMA_TYPE_ANY:
15533 xmlSchemaValidateElementByWildcard(ctxt, type);
15534 break;
15535 default:
15536 break;
15537 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015538leave:
15539
15540#ifdef ELEM_INFO_ENABLED
15541 xmlSchemaEndElement(ctxt);
15542 /*
15543 xmlSchemaDebugDumpIDCTable(stdout,
15544 NULL,
15545 ctxt->node->name,
15546 ctxt->elemInfo->idcTable);
15547 */
15548#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000015549 ctxt->type = oldtype;
15550 ctxt->node = oldnode;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015551}
Daniel Veillard4255d502002-04-16 15:50:10 +000015552
Daniel Veillard01fa6152004-06-29 17:04:39 +000015553/**
15554 * xmlSchemaValidateSimpleTypeValue:
15555 * @ctxt: a schema validation context
15556 * @value: the value to be validated
15557 * @fireErrors: shall errors be reported?
15558 * @applyFacets: shall facets be applied?
Daniel Veillardc0826a72004-08-10 14:17:33 +000015559 * @normalize: shall the value be normalized?
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015560 * @checkNodes: shall the content nodes be checked?
Daniel Veillard01fa6152004-06-29 17:04:39 +000015561 *
15562 * Validates a value by the given type (user derived or built-in).
15563 *
15564 * Returns 0 if the value is valid, a positive error code
15565 * number otherwise and -1 in case of an internal or API error.
Daniel Veillard01fa6152004-06-29 17:04:39 +000015566 */
15567static int
15568xmlSchemaValidateSimpleTypeValue(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015569 xmlSchemaTypePtr type,
15570 const xmlChar *value,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015571 int fireErrors,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015572 int applyFacets,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015573 int normalize,
15574 int checkNodes)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015575{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015576 xmlNodePtr node;
Daniel Veillardc0826a72004-08-10 14:17:33 +000015577 int ret = 0;
15578 xmlChar *normValue = NULL;
15579 int wtsp;
15580
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015581 node = ctxt->node;
15582 /* Save the current whitespace normalization type. */
Daniel Veillardc0826a72004-08-10 14:17:33 +000015583 wtsp = ctxt->valueWS;
15584 /*
15585 * Normalize the value.
15586 */
15587 if (normalize &&
15588 (ctxt->valueWS != XML_SCHEMAS_VAL_WTSP_COLLAPSE)) {
15589 int norm = xmlSchemaGetWhiteSpaceFacetValue(type);
15590
15591 if ((norm != -1) && (norm > ctxt->valueWS)) {
15592 if (norm == XML_SCHEMAS_VAL_WTSP_COLLAPSE)
15593 normValue = xmlSchemaCollapseString(value);
15594 else
15595 normValue = xmlSchemaWhiteSpaceReplace(value);
15596 ctxt->valueWS = norm;
15597 if (normValue != NULL)
15598 value = (const xmlChar *) normValue;
15599 }
15600 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015601 /*
15602 * The nodes of a content must be checked only once,
15603 * this is not working since list types will fire this
15604 * multiple times.
15605 */
15606 if ((checkNodes == 1) && (ctxt->cur != NULL)) {
15607 xmlNodePtr cur = ctxt->cur;
15608
15609 do {
15610 switch (cur->type) {
15611 case XML_TEXT_NODE:
15612 case XML_CDATA_SECTION_NODE:
15613 case XML_PI_NODE:
15614 case XML_COMMENT_NODE:
15615 case XML_XINCLUDE_START:
15616 case XML_XINCLUDE_END:
15617 break;
15618 case XML_ENTITY_REF_NODE:
15619 case XML_ENTITY_NODE:
15620 /* TODO: Scour the entities for illegal nodes. */
15621 TODO break;
15622 case XML_ELEMENT_NODE: {
15623 /* NOTE: Changed to an internal error, since the
15624 * existence of an element node will be already checked in
15625 * xmlSchemaValidateElementBySimpleType and in
15626 * xmlSchemaValidateElementByComplexType.
15627 */
15628 xmlSchemaVCustomErr(ctxt,
15629 XML_SCHEMAV_INTERNAL,
15630 /* XML_SCHEMAS_ERR_INVALIDELEM, */
15631 node, type,
15632 "Element '%s' found in simple type content",
15633 cur->name);
15634 return (XML_SCHEMAV_INTERNAL);
15635 }
15636 case XML_ATTRIBUTE_NODE:
15637 case XML_DOCUMENT_NODE:
15638 case XML_DOCUMENT_TYPE_NODE:
15639 case XML_DOCUMENT_FRAG_NODE:
15640 case XML_NOTATION_NODE:
15641 case XML_HTML_DOCUMENT_NODE:
15642 case XML_DTD_NODE:
15643 case XML_ELEMENT_DECL:
15644 case XML_ATTRIBUTE_DECL:
15645 case XML_ENTITY_DECL:
15646 case XML_NAMESPACE_DECL:
15647#ifdef LIBXML_DOCB_ENABLED
15648 case XML_DOCB_DOCUMENT_NODE:
15649#endif
15650 xmlSchemaVCustomErr(ctxt,
15651 XML_SCHEMAV_INTERNAL,
15652 /* XML_SCHEMAS_ERR_INVALIDELEM, */
15653 node, NULL,
15654 "Node of unexpected type found in simple type content",
15655 NULL);
15656 return (XML_SCHEMAV_INTERNAL);
15657 }
15658 cur = cur->next;
15659 } while (cur != NULL);
15660 }
15661
William M. Brack2f2a6632004-08-20 23:09:47 +000015662 if (type->type == XML_SCHEMA_TYPE_COMPLEX) {
15663 xmlSchemaTypePtr base, anyType;
15664
15665 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
15666
15667 base = type->baseType;
15668 while ((base != NULL) &&
15669 (base->type != XML_SCHEMA_TYPE_SIMPLE) &&
15670 (base->type != XML_SCHEMA_TYPE_BASIC) &&
15671 (base != anyType)) {
15672 base = base->baseType;
15673 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015674 ret = xmlSchemaValidateSimpleTypeValue(ctxt, base, value, 1, 0, 1, 0);
William M. Brack2f2a6632004-08-20 23:09:47 +000015675 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015676 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000015677 "Internal error: xmlSchemaValidateSimpleTypeValue, "
15678 "validating complex type '%s'\n",
15679 type->name, NULL);
15680 } else if ((ret == 0) && (applyFacets) && (type->facetSet != NULL)) {
15681 /*
15682 * Check facets.
15683 */
15684 /*
15685 * This is somehow not nice, since if an error occurs
15686 * the reported type will be the complex type; the spec
15687 * wants a simple type to be created on the complex type
15688 * if it has a simple content. For now we have to live with
15689 * it.
15690 */
15691 ret = xmlSchemaValidateFacetsInternal(ctxt, type,
15692 value, 0, fireErrors);
15693 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015694 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000015695 "Internal error: xmlSchemaValidateSimpleTypeValue, "
15696 "validating facets of complex type '%s'\n",
15697 type->name, NULL);
15698 } else if (ret > 0) {
15699 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
William M. Brack2f2a6632004-08-20 23:09:47 +000015700 if (fireErrors)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015701 xmlSchemaVSimpleTypeErr(ctxt, ret, node, value, type);
William M. Brack2f2a6632004-08-20 23:09:47 +000015702 }
15703 }
15704 } else if (type->type == XML_SCHEMA_TYPE_BASIC) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000015705
15706 if (ctxt->value != NULL) {
15707 xmlSchemaFreeValue(ctxt->value);
15708 ctxt->value = NULL;
15709 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015710 /*
15711 * STREAM-READ-CHILDREN.
15712 */
15713 ret = xmlSchemaValPredefTypeNodeNoNorm(type, value, &(ctxt->value), node);
Daniel Veillardc0826a72004-08-10 14:17:33 +000015714 if (ret > 0) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000015715 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST)
15716 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
15717 else
15718 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
Daniel Veillardc0826a72004-08-10 14:17:33 +000015719 if (fireErrors)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015720 xmlSchemaVSimpleTypeErr(ctxt, ret, node, value, type);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015721 } else if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015722 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015723 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000015724 "validating built-in type '%s'\n", type->name, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015725 }
15726 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) {
15727 /* 1.2.1 if {variety} is ·atomic· then the string must ·match·
15728 * a literal in the ·lexical space· of {base type definition}
15729 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015730 ret = xmlSchemaValidateSimpleTypeValue(ctxt, type->baseType, value, 0, 0, 0, 0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015731 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015732 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015733 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000015734 "validating atomic simple type '%s'\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000015735 type->name, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +000015736 } else if (ret > 0) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000015737 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
Daniel Veillardc0826a72004-08-10 14:17:33 +000015738 if (fireErrors)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015739 xmlSchemaVSimpleTypeErr(ctxt, ret, node, value, type);
Daniel Veillardc0826a72004-08-10 14:17:33 +000015740 } else if ((applyFacets) && (type->facetSet != NULL)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000015741 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000015742 * Check facets.
Daniel Veillard01fa6152004-06-29 17:04:39 +000015743 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000015744 ret = xmlSchemaValidateFacetsInternal(ctxt, type,
15745 value, 0, fireErrors);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015746 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015747 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015748 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000015749 "validating facets of atomic simple type '%s'\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000015750 type->name, NULL);
15751 } else if (ret > 0) {
15752 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
Daniel Veillardc0826a72004-08-10 14:17:33 +000015753 /*
15754 Disabled, since the facet validation already reports errors.
15755 if (fireErrors)
15756 xmlSchemaVSimpleTypeErr(ctxt, ret, ctxt->cur, value, type);
15757 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000015758 }
15759 }
15760 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
15761
15762 xmlSchemaTypePtr tmpType;
15763 const xmlChar *cur, *end;
15764 xmlChar *tmp;
Daniel Veillardc0826a72004-08-10 14:17:33 +000015765 unsigned long len = 0;
Daniel Veillard01fa6152004-06-29 17:04:39 +000015766
15767 /* 1.2.2 if {variety} is ·list· then the string must be a sequence
15768 * of white space separated tokens, each of which ·match·es a literal
15769 * in the ·lexical space· of {item type definition}
15770 */
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +000015771
Kasimier T. Buchcikde938cd2005-01-13 12:25:57 +000015772 if (value == NULL)
15773 value = BAD_CAST "";
Daniel Veillardc0826a72004-08-10 14:17:33 +000015774 tmpType = xmlSchemaGetListSimpleTypeItemType(type);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015775 cur = value;
15776 do {
15777 while (IS_BLANK_CH(*cur))
15778 cur++;
15779 end = cur;
15780 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
15781 end++;
15782 if (end == cur)
15783 break;
15784 tmp = xmlStrndup(cur, end - cur);
15785 len++;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015786 ret = xmlSchemaValidateSimpleTypeValue(ctxt, tmpType, tmp, 0, 1, 0, 0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015787 xmlFree(tmp);
Daniel Veillardc0826a72004-08-10 14:17:33 +000015788 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015789 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015790 "Internal error: xmlSchemaValidateSimpleTypeValue, "
15791 "validating an item of list simple type '%s'\n",
15792 type->name, NULL);
15793 break;
15794 } else if (ret > 0) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000015795 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
Daniel Veillardc0826a72004-08-10 14:17:33 +000015796 if (fireErrors)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015797 xmlSchemaVSimpleTypeErr(ctxt, ret, node, value, type);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015798 break;
Daniel Veillardc0826a72004-08-10 14:17:33 +000015799 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000015800 cur = end;
15801 } while (*cur != 0);
15802 /*
15803 * Check facets.
15804 */
15805 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015806 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015807 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000015808 "validating list simple type '%s'\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000015809 type->name, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +000015810 } else if ((ret == 0) && (applyFacets)) {
15811 ret = xmlSchemaValidateFacetsInternal(ctxt, type,
15812 value, len, fireErrors);
15813 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015814 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015815 "Internal error: xmlSchemaValidateSimpleTypeValue, "
15816 "validating facets of list simple type '%s'\n",
15817 type->name, NULL);
15818 } else if (ret > 0) {
15819 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
Daniel Veillard01fa6152004-06-29 17:04:39 +000015820 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000015821 Disabled, since the facet validation already reports errors.
15822 if (fireErrors)
15823 xmlSchemaVSimpleTypeErr(ctxt, ret, ctxt->cur, value, type);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015824 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000015825 }
15826
Daniel Veillard01fa6152004-06-29 17:04:39 +000015827 }
15828 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
15829 xmlSchemaTypeLinkPtr memberLink;
15830
15831 /*
15832 * TODO: For all datatypes ·derived· by ·union· whiteSpace does
15833 * not apply directly; however, the normalization behavior of ·union·
15834 * types is controlled by the value of whiteSpace on that one of the
15835 * ·memberTypes· against which the ·union· is successfully validated.
15836 *
15837 * This means that the value is normalized by the first validating
15838 * member type, then the facets of the union type are applied. This
15839 * needs changing of the value!
15840 */
15841
15842 /*
15843 * 1.2.3 if {variety} is ·union· then the string must ·match· a
15844 * literal in the ·lexical space· of at least one member of
15845 * {member type definitions}
15846 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000015847#ifdef DEBUG_UNION_VALIDATION
15848 printf("Union ST : '%s'\n", (const char *) type->name);
15849 printf(" fireErrors : %d\n", fireErrors);
15850 printf(" applyFacets: %d\n", applyFacets);
15851#endif
Daniel Veillard01fa6152004-06-29 17:04:39 +000015852 memberLink = xmlSchemaGetUnionSimpleTypeMemberTypes(type);
15853 if (memberLink == NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015854 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015855 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000015856 "union simple type '%s' has no member types\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000015857 type->name, NULL);
15858 ret = -1;
15859 }
15860 if (ret == 0) {
15861 while (memberLink != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015862 ret = xmlSchemaValidateSimpleTypeValue(ctxt, memberLink->type,
15863 value, 0, 1, 1, 0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015864 if ((ret <= 0) || (ret == 0))
15865 break;
15866 memberLink = memberLink->next;
15867 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000015868 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015869 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015870 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000015871 "validating members of union simple type '%s'\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000015872 type->name, NULL);
15873 } else if (ret > 0) {
15874 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
Daniel Veillardc0826a72004-08-10 14:17:33 +000015875 if (fireErrors)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015876 xmlSchemaVSimpleTypeErr(ctxt, ret, node, value, type);
Daniel Veillardc0826a72004-08-10 14:17:33 +000015877 }
15878 }
15879 /*
15880 * Apply facets (pattern, enumeration).
15881 */
15882 if ((ret == 0) && (applyFacets) && (type->facetSet != NULL)) {
15883 int mws;
15884 /*
15885 * The normalization behavior of ·union· types is controlled by
15886 * the value of whiteSpace on that one of the ·memberTypes·
15887 * against which the ·union· is successfully validated.
15888 */
15889 if (normValue != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015890 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015891 "Internal error: xmlSchemaValidateSimpleTypeValue, "
15892 "the value was already normalized for the union simple "
15893 "type '%s'.\n", type->name, NULL);
15894 }
15895 mws = xmlSchemaGetWhiteSpaceFacetValue(memberLink->type);
15896 if (mws > ctxt->valueWS) {
15897 if (mws == XML_SCHEMAS_VAL_WTSP_COLLAPSE)
15898 normValue = xmlSchemaCollapseString(value);
15899 else
15900 normValue = xmlSchemaWhiteSpaceReplace(value);
15901 if (normValue != NULL)
15902 value = (const xmlChar *) normValue;
15903 }
15904
15905 ret = xmlSchemaValidateFacetsInternal(ctxt, type,
15906 value, 0, fireErrors);
15907 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015908 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015909 "Internal error: xmlSchemaValidateSimpleTypeValue, "
15910 "validating facets of union simple type '%s'\n",
15911 type->name, NULL);
15912 } else if (ret > 0) {
15913 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
15914 /*
15915 if (fireErrors)
15916 xmlSchemaVSimpleTypeErr(ctxt, ret, ctxt->cur, value, type);
15917 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000015918 }
15919 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000015920 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000015921 ctxt->valueWS = wtsp;
15922 if (normValue != NULL)
15923 xmlFree(normValue);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015924 return (ret);
15925}
15926
15927/**
15928 * xmlSchemaValidateSimpleTypeElement:
15929 * @ctxt: a schema validation context
15930 * @node: the element node to be validated.
15931 *
15932 * Validate the element against a simple type.
15933 *
15934 * Returns 0 if the element is valid, a positive error code
15935 * number otherwise and -1 in case of an internal or API error.
15936 */
15937static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015938xmlSchemaValidateElementBySimpleType(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015939 xmlSchemaTypePtr type,
15940 int valSimpleContent)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015941{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015942 xmlSchemaTypePtr oldtype;
15943 xmlNodePtr node;
Daniel Veillard01fa6152004-06-29 17:04:39 +000015944 xmlAttrPtr attr;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015945 xmlNodePtr cur;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015946 int ret = 0, retval = 0;
15947
Daniel Veillard01fa6152004-06-29 17:04:39 +000015948 if ((ctxt == NULL) || (type == NULL)) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015949 xmlSchemaVCustomErr(ctxt, XML_SCHEMAV_INTERNAL, NULL, NULL,
15950 "Internal error: xmlSchemaValidateElementBySimpleType, "
15951 "bad arguments", NULL);
15952 return (-1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015953 }
15954
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015955 oldtype = ctxt->type;
15956 node = ctxt->node;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015957 /*
15958 * cvc-type: 3.1.2 The element information item must have no element
15959 * information item [children].
15960 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015961 /*
15962 * STREAM: Child nodes are processed.
15963 */
15964 cur = node->children;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015965 while (cur != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015966 /*
15967 * TODO: Entities, will they produce elements as well?
15968 */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015969 if (cur->type == XML_ELEMENT_NODE) {
15970 xmlSchemaVCustomErr(ctxt,
15971 XML_SCHEMAV_CVC_TYPE_3_1_2,
15972 node, type,
15973 "No element content allowed", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015974 ret = XML_SCHEMAV_CVC_TYPE_3_1_2;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015975 }
15976 cur = cur->next;
Daniel Veillard01fa6152004-06-29 17:04:39 +000015977 }
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015978
Daniel Veillard01fa6152004-06-29 17:04:39 +000015979 /*
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015980 * cvc-type 3.1.1:
15981 *
15982 * The attributes of must be empty, excepting those whose namespace name
15983 * is identical to http://www.w3.org/2001/XMLSchema-instance and whose local
15984 * name is one of type, nil, schemaLocation or noNamespaceSchemaLocation.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015985 */
15986 /*
15987 * STREAM: Attribute nodes are processed.
15988 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000015989 attr = node->properties;
15990 while (attr != NULL) {
15991 if ((attr->ns == NULL) ||
15992 (!xmlStrEqual(attr->ns->href, xmlSchemaInstanceNs)) ||
15993 ((!xmlStrEqual(attr->name, BAD_CAST "type")) &&
15994 (!xmlStrEqual(attr->name, BAD_CAST "nil")) &&
15995 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation")) &&
15996 (!xmlStrEqual
15997 (attr->name, BAD_CAST "noNamespaceSchemaLocation")))) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015998 xmlSchemaVIllegalAttrErr(ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015999 XML_SCHEMAV_CVC_TYPE_3_1_1, attr);
16000 ret = XML_SCHEMAV_CVC_TYPE_3_1_1;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016001 }
16002 attr = attr->next;
16003 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016004 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016005 * This will skip validation if the type is 'anySimpleType' and
16006 * if the value was already validated (e.g. default values).
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016007 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016008 if ((valSimpleContent == 1) &&
16009 ((type->type != XML_SCHEMA_TYPE_BASIC) ||
16010 (type->builtInType != XML_SCHEMAS_ANYSIMPLETYPE))) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016011 xmlChar *value;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016012
16013 value = xmlNodeGetContent(node);
16014 /*
16015 * NOTE: This call will not check the content nodes, since
16016 * this should be checked here already.
16017 */
16018 retval = xmlSchemaValidateSimpleTypeValue(ctxt, type, value,
16019 1, 1, 1, 0);
William M. Brack2f2a6632004-08-20 23:09:47 +000016020 if (value != NULL)
16021 xmlFree(value);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016022 if (retval != 0)
16023 ret = retval;
William M. Brack2f2a6632004-08-20 23:09:47 +000016024 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016025 ctxt->type = oldtype;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016026 return (ret);
16027}
Daniel Veillard4255d502002-04-16 15:50:10 +000016028
16029/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016030 * xmlSchemaValQNameAcquire:
16031 * @value: the lexical represantation of the QName value
16032 * @node: the node to search for the corresponding namespace declaration
16033 * @nsName: the resulting namespace name if found
16034 *
16035 * Checks that a value conforms to the lexical space of the type QName;
16036 * if valid, the corresponding namespace name is searched and retured
16037 * as a copy in @nsName. The local name is returned in @localName as
16038 * a copy.
16039 *
16040 * Returns 0 if valid, 1 if not valid by type, 2 if no corresponding
16041 * namespace declaration was found in scope; -1 in case of an internal or
16042 * API error.
16043 */
16044static int
16045xmlSchemaValQNameAcquire(const xmlChar *value, xmlNodePtr node,
16046 xmlChar **nsName, xmlChar **localName)
16047{
16048 int ret;
16049 xmlChar *local = NULL;
16050
16051 if ((nsName == NULL) || (localName == NULL) || (node == NULL))
16052 return (-1);
16053 *nsName = NULL;
16054 *localName = NULL;
16055 ret = xmlValidateQName(value, 1);
16056 if (ret == 0) {
16057 xmlChar *prefix;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016058 xmlNsPtr ns;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016059
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016060 /*
16061 * NOTE: xmlSplitQName2 will return a duplicated
16062 * string.
16063 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016064 local = xmlSplitQName2(value, &prefix);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016065 if (local == NULL)
16066 local = xmlStrdup(value);
16067 ns = xmlSearchNs(node->doc, node, prefix);
16068 /*
16069 * A namespace need not to be found if the prefix is NULL.
16070 */
16071 if (ns != NULL) {
16072 /*
16073 * TODO: Is it necessary to duplicate the URI here?
16074 */
16075 *nsName = xmlStrdup(ns->href);
16076 } else if (prefix != NULL) {
16077 xmlFree(prefix);
16078 if (local != NULL)
16079 xmlFree(local);
16080 return (2);
16081 }
16082 *localName = local;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016083 if (prefix != NULL)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016084 xmlFree(prefix);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016085 } else
16086 return (1);
16087 return (ret);
16088}
16089
16090/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016091 * xmlSchemaHasElemContent:
16092 * @node: the node
16093 *
16094 * Scours the content of the given node for element
16095 * nodes.
16096 *
16097 * Returns 1 if an element node is found,
16098 * 0 otherwise.
16099 */
16100static int
16101xmlSchemaHasElemContent(xmlNodePtr node)
16102{
16103 if (node == NULL)
16104 return (0);
16105 node = node->children;
16106 while (node != NULL) {
16107 if (node->type == XML_ELEMENT_NODE)
16108 return (1);
16109 node = node->next;
16110 }
16111 return (0);
16112}
16113/**
16114 * xmlSchemaHasElemOrCharContent:
16115 * @node: the node
16116 *
16117 * Scours the content of the given node for element
16118 * and character nodes.
16119 *
16120 * Returns 1 if an element or character node is found,
16121 * 0 otherwise.
16122 */
16123static int
16124xmlSchemaHasElemOrCharContent(xmlNodePtr node)
16125{
16126 if (node == NULL)
16127 return (0);
16128 node = node->children;
16129 while (node != NULL) {
16130 switch (node->type) {
16131 case XML_ELEMENT_NODE:
16132 /*
16133 * TODO: Ask Daniel if these are all character nodes.
16134 */
16135 case XML_TEXT_NODE:
16136 case XML_CDATA_SECTION_NODE:
16137 /*
16138 * TODO: How XML_ENTITY_NODEs evaluated?
16139 */
16140 case XML_ENTITY_REF_NODE:
16141 case XML_ENTITY_NODE:
16142 return (1);
16143 break;
16144 default:
16145 break;
16146 }
16147 node = node->next;
16148 }
16149 return (0);
16150}
16151
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016152/************************************************************************
16153 * *
16154 * Identity-constraints (IDC) *
16155 * *
16156 ************************************************************************/
16157
16158#ifdef IDC_ENABLED
16159
16160/**
16161 * xmlSchemaIDCNewBinding:
16162 * @idcDef: the IDC definition of this binding
16163 *
16164 * Creates a new IDC binding.
16165 *
16166 * Returns the new binding in case of succeeded, NULL on internal errors.
16167 */
16168static xmlSchemaPSVIIDCBindingPtr
16169xmlSchemaIDCNewBinding(xmlSchemaIDCPtr idcDef)
16170{
16171 xmlSchemaPSVIIDCBindingPtr ret;
16172
16173 ret = (xmlSchemaPSVIIDCBindingPtr) xmlMalloc(
16174 sizeof(xmlSchemaPSVIIDCBinding));
16175 if (ret == NULL) {
16176 xmlSchemaVErrMemory(NULL,
16177 "allocating a PSVI IDC binding item", NULL);
16178 return (NULL);
16179 }
16180 memset(ret, 0, sizeof(xmlSchemaPSVIIDCBinding));
16181 ret->definition = idcDef;
16182 return (ret);
16183}
16184
16185/**
16186 * xmlSchemaIDCStoreNodeTableItem:
16187 * @vctxt: the WXS validation context
16188 * @item: the IDC node table item
16189 *
16190 * The validation context is used to store an IDC node table items.
16191 * They are stored to avoid copying them if IDC node-tables are merged
16192 * with corresponding parent IDC node-tables (bubbling).
16193 *
16194 * Returns 0 if succeeded, -1 on internal errors.
16195 */
16196static int
16197xmlSchemaIDCStoreNodeTableItem(xmlSchemaValidCtxtPtr vctxt,
16198 xmlSchemaPSVIIDCNodePtr item)
16199{
16200 /*
16201 * Add to gobal list.
16202 */
16203 if (vctxt->idcNodes == NULL) {
16204 vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
16205 xmlMalloc(20 * sizeof(xmlSchemaPSVIIDCNodePtr));
16206 if (vctxt->idcNodes == NULL) {
16207 xmlSchemaVErrMemory(vctxt,
16208 "allocating the IDC node table item list", NULL);
16209 return (-1);
16210 }
16211 vctxt->sizeIdcNodes = 20;
16212 } else if (vctxt->sizeIdcNodes <= vctxt->nbIdcNodes) {
16213 vctxt->sizeIdcNodes *= 2;
16214 vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
16215 xmlRealloc(vctxt->idcNodes, vctxt->sizeIdcNodes *
16216 sizeof(xmlSchemaPSVIIDCNodePtr));
16217 if (vctxt->idcNodes == NULL) {
16218 xmlSchemaVErrMemory(vctxt,
16219 "re-allocating the IDC node table item list", NULL);
16220 return (-1);
16221 }
16222 }
16223 vctxt->idcNodes[vctxt->nbIdcNodes++] = item;
16224
16225 return (0);
16226}
16227
16228/**
16229 * xmlSchemaIDCStoreKey:
16230 * @vctxt: the WXS validation context
16231 * @item: the IDC key
16232 *
16233 * The validation context is used to store an IDC key.
16234 *
16235 * Returns 0 if succeeded, -1 on internal errors.
16236 */
16237static int
16238xmlSchemaIDCStoreKey(xmlSchemaValidCtxtPtr vctxt,
16239 xmlSchemaPSVIIDCKeyPtr key)
16240{
16241 /*
16242 * Add to gobal list.
16243 */
16244 if (vctxt->idcKeys == NULL) {
16245 vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
16246 xmlMalloc(40 * sizeof(xmlSchemaPSVIIDCKeyPtr));
16247 if (vctxt->idcKeys == NULL) {
16248 xmlSchemaVErrMemory(vctxt,
16249 "allocating the IDC key storage list", NULL);
16250 return (-1);
16251 }
16252 vctxt->sizeIdcKeys = 40;
16253 } else if (vctxt->sizeIdcKeys <= vctxt->nbIdcKeys) {
16254 vctxt->sizeIdcKeys *= 2;
16255 vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
16256 xmlRealloc(vctxt->idcKeys, vctxt->sizeIdcKeys *
16257 sizeof(xmlSchemaPSVIIDCKeyPtr));
16258 if (vctxt->idcKeys == NULL) {
16259 xmlSchemaVErrMemory(vctxt,
16260 "re-allocating the IDC key storage list", NULL);
16261 return (-1);
16262 }
16263 }
16264 vctxt->idcKeys[vctxt->nbIdcKeys++] = key;
16265
16266 return (0);
16267}
16268
16269/**
16270 * xmlSchemaIDCAppendNodeTableItem:
16271 * @bind: the IDC binding
16272 * @ntItem: the node-table item
16273 *
16274 * Appends the IDC node-table item to the binding.
16275 *
16276 * Returns 0 on success and -1 on internal errors.
16277 */
16278static int
16279xmlSchemaIDCAppendNodeTableItem(xmlSchemaPSVIIDCBindingPtr bind,
16280 xmlSchemaPSVIIDCNodePtr ntItem)
16281{
16282 if (bind->nodeTable == NULL) {
16283 bind->sizeNodes = 10;
16284 bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
16285 xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr));
16286 if (bind->nodeTable == NULL) {
16287 xmlSchemaVErrMemory(NULL,
16288 "allocating an array of IDC node-table items", NULL);
16289 return(-1);
16290 }
16291 } else if (bind->sizeNodes <= bind->nbNodes) {
16292 bind->sizeNodes *= 2;
16293 bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
16294 xmlRealloc(bind->nodeTable, bind->sizeNodes *
16295 sizeof(xmlSchemaPSVIIDCNodePtr));
16296 if (bind->nodeTable == NULL) {
16297 xmlSchemaVErrMemory(NULL,
16298 "re-allocating an array of IDC node-table items", NULL);
16299 return(-1);
16300 }
16301 }
16302 bind->nodeTable[bind->nbNodes++] = ntItem;
16303 return(0);
16304}
16305
16306/**
16307 * xmlSchemaIDCAquireBinding:
16308 * @vctxt: the WXS validation context
16309 * @matcher: the IDC matcher
16310 *
16311 * Looks up an PSVI IDC binding, for the IDC definition and
16312 * of the given matcher. If none found, a new one is created
16313 * and added to the IDC table.
16314 *
16315 * Returns an IDC binding or NULL on internal errors.
16316 */
16317static xmlSchemaPSVIIDCBindingPtr
16318xmlSchemaIDCAquireBinding(xmlSchemaValidCtxtPtr vctxt,
16319 xmlSchemaIDCMatcherPtr matcher)
16320{
16321 xmlSchemaElemInfoPtr info;
16322
16323 info = vctxt->elemInfos[matcher->depth];
16324
16325 if (info->idcTable == NULL) {
16326 info->idcTable = xmlSchemaIDCNewBinding(matcher->aidc->def);
16327 if (info->idcTable == NULL)
16328 return (NULL);
16329 return(info->idcTable);
16330 } else {
16331 xmlSchemaPSVIIDCBindingPtr bind = NULL;
16332
16333 bind = info->idcTable;
16334 do {
16335 if (bind->definition == matcher->aidc->def)
16336 return(bind);
16337 if (bind->next == NULL) {
16338 bind->next = xmlSchemaIDCNewBinding(matcher->aidc->def);
16339 if (bind->next == NULL)
16340 return (NULL);
16341 return(bind->next);
16342 }
16343 bind = bind->next;
16344 } while (bind != NULL);
16345 }
16346 return (NULL);
16347}
16348
16349/**
16350 * xmlSchemaIDCFreeKey:
16351 * @key: the IDC key
16352 *
16353 * Frees an IDC key together with its compiled value.
16354 */
16355static void
16356xmlSchemaIDCFreeKey(xmlSchemaPSVIIDCKeyPtr key)
16357{
16358 if (key->compValue != NULL)
16359 xmlSchemaFreeValue(key->compValue);
16360 xmlFree(key);
16361}
16362
16363/**
16364 * xmlSchemaIDCFreeBinding:
16365 *
16366 * Frees an IDC binding. Note that the node table-items
16367 * are not freed.
16368 */
16369xmlSchemaIDCFreeBinding(xmlSchemaPSVIIDCBindingPtr bind)
16370{
16371 if (bind->nodeTable != NULL) {
16372 xmlFree(bind->nodeTable);
16373 }
16374 xmlFree(bind);
16375}
16376
16377/**
16378 * xmlSchemaIDCFreeIDCTable:
16379 * @bind: the first IDC binding in the list
16380 *
16381 * Frees an IDC table, i.e. all the IDC bindings in the list.
16382 */
16383static void
16384xmlSchemaIDCFreeIDCTable(xmlSchemaPSVIIDCBindingPtr bind)
16385{
16386 xmlSchemaPSVIIDCBindingPtr prev;
16387
16388 while (bind != NULL) {
16389 prev = bind;
16390 bind = bind->next;
16391 xmlSchemaIDCFreeBinding(prev);
16392 }
16393}
16394
16395/**
16396 * xmlSchemaIDCFreeMatcherList:
16397 * @matcher: the first IDC matcher in the list
16398 *
16399 * Frees a list of IDC matchers.
16400 */
16401static void
16402xmlSchemaIDCFreeMatcherList(xmlSchemaIDCMatcherPtr matcher)
16403{
16404 xmlSchemaIDCMatcherPtr next;
16405
16406 while (matcher != NULL) {
16407 next = matcher->next;
16408 if (matcher->keySeqs != NULL) {
16409 int i;
16410 for (i = 0; i < matcher->sizeKeySeqs; i++)
16411 if (matcher->keySeqs[i] != NULL)
16412 xmlFree(matcher->keySeqs[i]);
16413 xmlFree(matcher->keySeqs);
16414 }
16415 xmlFree(matcher);
16416 matcher = next;
16417 }
16418}
16419
16420/**
16421 * xmlSchemaAreValuesEqual:
16422 * @ta: the first type
16423 * @a: the first value
16424 * @tb: the second type
16425 * @b: the second value
16426 *
16427 * Compares two values.
16428 *
16429 * Returns 1 if they are equal, 0 if not and -1 on internal errors.
16430 */
16431static int
16432xmlSchemaAreValuesEqual(xmlSchemaTypePtr ta,
16433 xmlSchemaValPtr a,
16434 xmlSchemaTypePtr tb,
16435 xmlSchemaValPtr b)
16436{
16437 int typeEqual = 0;
16438
16439 /* Same user derived/built-in derived/built-in primitive types. */
16440 if (ta == tb)
16441 goto compareValue;
16442
16443 /*
16444 * Comparison with anySimpleTypes is not supported by this implemention.
16445 */
16446 if ((ta->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) ||
16447 (tb->builtInType == XML_SCHEMAS_ANYSIMPLETYPE))
16448 return(0);
16449
16450 /*
16451 * 4.2.1 equal (data-types)
16452 *
16453 * the ·value space·s of all ·primitive· datatypes are disjoint
16454 * (they do not share any values)
16455 */
16456 if ((ta->builtInType != 0) && (tb->builtInType != 0) &&
16457 (ta->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE) &&
16458 (tb->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE))
16459 return(0);
16460
16461 if ((ta->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) ||
16462 (ta->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) ||
16463 (tb->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) ||
16464 (tb->flags & XML_SCHEMAS_TYPE_VARIETY_UNION)) {
16465 TODO
16466 return(0);
16467 }
16468 /*
16469 * (1) if a datatype T' is ·derived· by ·restriction· from an atomic datatype
16470 * T then the ·value space· of T' is a subset of the ·value space· of T.
16471 */
16472 /*
16473 * (2) if datatypes T' and T'' are ·derived· by ·restriction· from a common
16474 * atomic ancestor T then the ·value space·s of T' and T'' may overlap.
16475 */
16476
16477 {
16478 xmlSchemaTypePtr pta = ta, ptb = tb;
16479
16480 /* Note that we will compare the primitives here. */
16481 while ((pta->builtInType == 0) ||
16482 ((pta->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE) == 0))
16483 pta = pta->baseType;
16484 while ((ptb->builtInType == 0) ||
16485 ((ptb->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE) == 0))
16486 ptb = ptb->baseType;
16487 if (pta == ptb)
16488 goto compareValue;
16489 return(0);
16490 }
16491compareValue:
16492 {
16493#ifdef IDC_VALUE_SUPPORT
16494 int ret;
16495 ret = xmlSchemaCompareValuesOpt(a, b,
16496 XML_SCHEMA_VALUECOMP_STRISNORM);
16497 if (ret == 0)
16498 return(1);
16499 else if (ret == -2)
16500 return(-1);
16501 else
16502 return(0);
16503#else
16504 return (1);
16505#endif
16506 }
16507}
16508
16509/**
16510 * xmlSchemaXPathChangeState:
16511 * @vctxt: the WXS validation context
16512 * @sto: the state object
16513 * @newState: the state index to be added to the history
16514 *
16515 * Adds an entry (vctxt->depth and newState) to the history of the
16516 * state object.
16517 *
16518 * Returns 1 if they are equal, 0 if not and -1 on internal errors.
16519 */
16520static int
16521xmlSchemaXPathChangeState(xmlSchemaValidCtxtPtr vctxt,
16522 xmlSchemaIDCStateObjPtr sto,
16523 int newState)
16524
16525{
16526 int *change = NULL;
16527 /*
16528 * Create/grow the array of history items.
16529 */
16530 if (sto->history == NULL) {
16531 sto->history = (int **) xmlMalloc(5 * sizeof(int *));
16532 if (sto->history == NULL) {
16533 xmlSchemaVErrMemory(NULL,
16534 "allocating an array of state change informations", NULL);
16535 xmlFree(sto);
16536 return(-1);
16537 }
16538 memset(sto->history, 0, 5 * sizeof(int *));
16539 sto->sizeHistory = 10;
16540 } else if (sto->sizeHistory > sto->nbHistory) {
16541 /*
16542 * Reuse a history item.
16543 */
16544 change = sto->history[sto->nbHistory];
16545 } else {
16546 int i = sto->sizeHistory;
16547
16548 sto->sizeHistory *= 2;
16549 sto->history = (int **) xmlRealloc(sto->history,
16550 sto->sizeHistory * sizeof(int *));
16551 if (sto->history == NULL) {
16552 xmlSchemaVErrMemory(NULL,
16553 "re-allocating an array of state change informations", NULL);
16554 return(-1);
16555 }
16556 /*
16557 * The new memory needs to be NULLed.
16558 * TODO: Use memset instead?
16559 */
16560 for (; i < sto->sizeHistory; i++)
16561 sto->history[i] = NULL;
16562 }
16563 /*
16564 * Create the history item.
16565 */
16566 if (change == NULL) {
16567 change = (int *) xmlMalloc(2 * sizeof(int));
16568 if (change == NULL) {
16569 xmlSchemaVErrMemory(NULL,
16570 "allocating a state change information", NULL);
16571 return(-1);
16572 }
16573 sto->history[sto->nbHistory] = change;
16574 }
16575 sto->nbHistory++;
16576 /*
16577 * Init the history item.
16578 */
16579 change[0] = vctxt->depth;
16580 change[1] = newState;
16581#ifdef DEBUG_IDC
16582 xmlGenericError(xmlGenericErrorContext, "IDC: push state '%d'\n",
16583 newState);
16584#endif
16585 return(0);
16586}
16587
16588/**
16589 * xmlSchemaIDCAddStateObject:
16590 * @vctxt: the WXS validation context
16591 * @matcher: the IDC matcher
16592 * @sel: the XPath information
16593 * @parent: the parent "selector" state object if any
16594 * @type: "selector" or "field"
16595 *
16596 * Creates/reuses and activates state objects for the given
16597 * XPath information; if the XPath expression consists of unions,
16598 * multiple state objects are created for every unioned expression.
16599 *
16600 * Returns 0 on success and -1 on internal errors.
16601 */
16602static int
16603xmlSchemaIDCAddStateObject(xmlSchemaValidCtxtPtr vctxt,
16604 xmlSchemaIDCMatcherPtr matcher,
16605 xmlSchemaIDCSelectPtr sel,
16606 xmlSchemaIDCStateObjPtr parent,
16607 int type)
16608{
16609 xmlSchemaIDCStateObjPtr sto;
16610 int i = 0, stateId, reversed;
16611
16612 /*
16613 * Create a state object for every location path in the XPath expression.
16614 */
16615 while (1) {
16616#ifdef IDC_XPATH_SUPPORT
16617 stateId = xmlXPathWXSIDCGetLocationPath(sel->xpathComp, i, &reversed);
16618#else
16619 break;
16620#endif
16621 if (stateId < 0)
16622 break;
16623 /*
16624 * Reuse the state objects from the pool.
16625 */
16626 if (vctxt->xpathStatePool != NULL) {
16627 sto = vctxt->xpathStatePool;
16628 vctxt->xpathStatePool = sto->next;
16629 sto->next = NULL;
16630 } else {
16631 /*
16632 * Create a new state object.
16633 */
16634 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 sto->type = type;
16643 sto->parent = parent;
16644 sto->matcher = matcher;
16645 sto->sel = sel;
16646 sto->nbHistory = 0;
16647 /*
16648 * Add to global list.
16649 */
16650 if (vctxt->xpathStates != NULL)
16651 sto->next = vctxt->xpathStates;
16652 vctxt->xpathStates = sto;
16653#if DEBUG_IDC
16654 xmlGenericError(xmlGenericErrorContext, "IDC: STO push '%s'\n",
16655 sto->sel->xpath);
16656#endif
16657 xmlSchemaXPathChangeState(vctxt, sto, stateId);
16658 /*
16659 * Set if the state object should be processed as a push
16660 * down transducer (topDown == 1) or upwards the ancestor axis of
16661 * the tree.
16662 */
16663 if (reversed)
16664 sto->topDown = 1;
16665 i++;
16666 };
16667
16668 return (0);
16669}
16670
16671/**
16672 * xmlSchemaXPathEvaluate:
16673 * @vctxt: the WXS validation context
16674 * @nodeType: the nodeType of the current node
16675 *
16676 * Evaluates all active XPath state objects.
16677 *
16678 * Returns the number of IC "field" state objects which resolved to
16679 * this node, 0 if none resolved and -1 on internal errors.
16680 */
16681static int
16682xmlSchemaXPathEvaluate(xmlSchemaValidCtxtPtr vctxt,
16683 const xmlChar *namespaceName,
16684 const xmlChar *localName,
16685 xmlElementType nodeType)
16686{
16687 xmlSchemaIDCStateObjPtr sto, head = NULL, first;
16688 int retState, *change;
16689 int res, resolved = 0;
16690
16691 if (vctxt->xpathStates == NULL)
16692 return (0);
16693#if DEBUG_IDC
16694 {
16695 xmlChar *str = NULL;
16696 xmlGenericError(xmlGenericErrorContext,
16697 "IDC: EVAL on %s, depth %d, type %d\n",
16698 xmlSchemaFormatNsUriLocal(&str, namespaceName,
16699 localName), vctxt->depth, nodeType);
16700 FREE_AND_NULL(str)
16701 }
16702#endif
16703 /*
16704 * Process all active XPath state objects.
16705 */
16706 first = vctxt->xpathStates;
16707 sto = first;
16708 while (sto != head) {
16709 /*
16710 * Evaluate:
16711 * 1. all bottom-up state objs.
16712 * 2. top-down state objs. which are not marked as
16713 * matching or blocking.
16714 * Note: sto->history[0][0] will hold the depth of creation.
16715 */
16716 if (sto->topDown == 0) {
16717 /*
16718 * Always start from the beginning with bottom-up
16719 * evaluation.
16720 */
16721 change = sto->history[0];
16722 } else {
16723 change = sto->history[sto->nbHistory -1];
16724 if (change[1] < 0)
16725 goto next_sto;
16726 }
16727 /*
16728 * change[0] holds the depth of change.
16729 * change[1] holds the state index or the "match" or "blocked"
16730 * indicator.
16731 */
16732 retState = -1;
16733#if DEBUG_IDC
16734 if (sto->type == XPATH_STATE_OBJ_IDC_SELECTOR)
16735 xmlGenericError(xmlGenericErrorContext, "IDC: ['%s'] selector '%s'\n",
16736 sto->matcher->aidc->def->name, sto->sel->xpath);
16737 else
16738 xmlGenericError(xmlGenericErrorContext, "IDC: ['%s'] field '%s'\n",
16739 sto->matcher->aidc->def->name, sto->sel->xpath);
16740#endif
16741 if (sto->topDown == 0) {
16742 /*
16743 * The XPath will be evaluated using the
16744 * ancestor-or-self axis.
16745 */
16746#ifdef IDC_XPATH_SUPPORT
16747 res = xmlXPathWXSIDCEvalOneNode(sto->sel->xpathComp,
16748 change[1], &retState, nodeType,
16749 localName, namespaceName);
16750#else
16751 res = 0;
16752#endif
16753 if (res == 1) {
16754 int i;
16755
16756 if (nodeType == XML_ELEMENT_NODE)
16757 i = vctxt->depth -1;
16758 else
16759 i = vctxt->depth;
16760 while ((res == 1) && (i >= 0)) {
16761 /*
16762 * If we get a partial match, evaluate the
16763 * ancestor axis.
16764 */
16765#ifdef IDC_XPATH_SUPPORT
16766 res = xmlXPathWXSIDCEvalOneNode(sto->sel->xpathComp,
16767 retState, &retState, XML_ELEMENT_NODE,
16768 vctxt->elemInfos[i]->localName,
16769 vctxt->elemInfos[i]->namespaceName);
16770#endif
16771 i--;
16772 }
16773 }
16774 if (res == -1) {
16775 xmlSchemaVErr(vctxt, vctxt->node,
16776 XML_SCHEMAV_INTERNAL,
16777 "Internal error: xmlSchemaXPathEvaluate, "
16778 "failed to evaluate a node.\n",
16779 NULL, NULL);
16780 return (-1);
16781 } else if (res != 2) {
16782 /*
16783 * We will record matches only.
16784 */
16785#if DEBUG_IDC
16786 xmlGenericError(xmlGenericErrorContext, "IDC: "
16787 "no match\n");
16788#endif
16789 goto next_sto;
16790 }
16791 } else {
16792 /*
16793 * Push-down.
16794 */
16795#ifdef IDC_XPATH_SUPPORT
16796 res = xmlXPathWXSIDCEvalOneNode(sto->sel->xpathComp,
16797 change[1], &retState, nodeType,
16798 localName, namespaceName);
16799#else
16800 res = 0;
16801#endif
16802 if (res == -1) {
16803 xmlSchemaVErr(vctxt, vctxt->node,
16804 XML_SCHEMAV_INTERNAL,
16805 "Internal error: xmlSchemaXPathEvaluate, "
16806 "failed to evaluate a node.\n",
16807 NULL, NULL);
16808 return (-1);
16809 } else if (res == 0) {
16810 /*
16811 * No Match.
16812 */
16813#if DEBUG_IDC
16814 xmlGenericError(xmlGenericErrorContext,
16815 "IDC: no match, blocked\n");
16816#endif
16817 if (xmlSchemaXPathChangeState(vctxt, sto, -3) == -1)
16818 return (-1);
16819 } else if (res == 1) {
16820 /*
16821 * Partial match.
16822 */
16823#if DEBUG_IDC
16824 xmlGenericError(xmlGenericErrorContext,
16825 "IDC: partial match\n");
16826#endif
16827 if (xmlSchemaXPathChangeState(vctxt, sto, retState) == -1)
16828 return (-1);
16829 }
16830 }
16831 if (res != 2)
16832 goto next_sto;
16833 /*
16834 * Full match.
16835 */
16836#if DEBUG_IDC
16837 xmlGenericError(xmlGenericErrorContext, "IDC: "
16838 "final match\n");
16839#endif
16840 /*
16841 * Register a state-change.
16842 */
16843 if (xmlSchemaXPathChangeState(vctxt, sto, -2) == -1)
16844 return (-1);
16845 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
16846 xmlSchemaIDCSelectPtr sel;
16847 /*
16848 * Activate state objects for the IDC fields of
16849 * the IDC selector.
16850 */
16851#if DEBUG_IDC
16852 xmlGenericError(xmlGenericErrorContext, "IDC: "
16853 "activating field states\n");
16854#endif
16855 sel = sto->matcher->aidc->def->fields;
16856 while (sel != NULL) {
16857 if (xmlSchemaIDCAddStateObject(vctxt, sto->matcher,
16858 sel, sto, XPATH_STATE_OBJ_TYPE_IDC_FIELD) == -1)
16859 return (-1);
16860 sel = sel->next;
16861 }
16862 } else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
16863 /*
16864 * An IDC key node was found.
16865 */
16866#if DEBUG_IDC
16867 xmlGenericError(xmlGenericErrorContext,
16868 "IDC: key found\n");
16869#endif
16870 /*
16871 * Notify that the character value of this node is
16872 * needed.
16873 */
16874 if (resolved == 0)
16875 vctxt->elemInfo->flags |= XML_SCHEMA_ELEM_INFO_VALUE_NEEDED;
16876 resolved++;
16877 }
16878next_sto:
16879 if (sto->next == NULL) {
16880 /*
16881 * Evaluate field state objects created on this node.
16882 */
16883 head = first;
16884 sto = vctxt->xpathStates;
16885 } else
16886 sto = sto->next;
16887 }
16888 return (resolved);
16889}
16890
16891/**
16892 * xmlSchemaXPathProcessChanges:
16893 * @vctxt: the WXS validation context
16894 * @type: the simple/complex type of the current node if any at all
16895 *
16896 * Processes and pops the history items of the IDC state objects.
16897 * IDC key-sequences are validated/created on IDC bindings.
16898 *
16899 * Returns 0 on success and -1 on internal errors.
16900 */
16901static int
16902xmlSchemaXPathProcessChanges(xmlSchemaValidCtxtPtr vctxt,
16903 xmlSchemaTypePtr type)
16904{
16905 xmlSchemaIDCStateObjPtr sto, nextsto;
16906 int res, *change;
16907 xmlSchemaPSVIIDCKeyPtr key = NULL;
16908
16909 if (vctxt->xpathStates == NULL)
16910 return (0);
16911 sto = vctxt->xpathStates;
16912
16913#if DEBUG_IDC
16914 {
16915 xmlChar *str = NULL;
16916 xmlGenericError(xmlGenericErrorContext,
16917 "IDC: BACK on %s, depth %d\n",
16918 xmlSchemaFormatNsUriLocal(&str, vctxt->elemInfo->namespaceName,
16919 vctxt->elemInfo->localName), vctxt->depth);
16920 FREE_AND_NULL(str)
16921 }
16922#endif
16923
16924 /*
16925 * Evaluate the state objects.
16926 */
16927 while (sto != NULL) {
16928 /*
16929 * If (nbHistory == 1) then there are no history left
16930 * (only the initial one), so deregister the state object.
16931 */
16932 if (sto->nbHistory == 1)
16933 goto deregister_check;
16934
16935 change = sto->history[sto->nbHistory -1];
16936
16937 /*
16938 * Ony history at the current depth are of interest.
16939 */
16940 if (change[0] != vctxt->depth) {
16941 sto = sto->next;
16942 continue;
16943 }
16944
16945 if (change[1] == -2) {
16946 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
16947 if (! IS_SIMPLE_TYPE(type)) {
16948 /*
16949 * Not qualified if the field resolves to a node of non
16950 * simple type.
16951 */
16952 xmlSchemaVCustomErr(vctxt,
16953 XML_SCHEMAV_CVC_IDC,
16954 vctxt->node,
16955 (xmlSchemaTypePtr) sto->matcher->aidc->def,
16956 "The field '%s' does evaluate to a node of "
16957 "non-simple type", sto->sel->xpath);
16958
16959 sto->nbHistory--;
16960 sto = sto->next;
16961 continue;
16962 }
16963 if (vctxt->value == NULL) {
16964 /*
16965 * Failed to provide the normalized value; maby
16966 * the value was invalid.
16967 */
16968 xmlSchemaVErr(vctxt, NULL,
16969 XML_SCHEMAV_INTERNAL,
16970 "Internal error: xmlSchemaIDCEvaluateMatches, "
16971 "normalized node value not available.\n",
16972 NULL, NULL);
16973 sto->nbHistory--;
16974 sto = sto->next;
16975 continue;
16976 } else {
16977 xmlSchemaIDCMatcherPtr matcher = sto->matcher;
16978 xmlSchemaPSVIIDCKeyPtr *keySeq;
16979 int pos, sizeNeeded, index;
16980
16981 /*
16982 * The key will be anchored on the matcher's list of
16983 * key-sequences. The position in this list is determined
16984 * by the target node's depth relative to the matcher's
16985 * depth of creation (i.e. the depth of the scope element).
16986 * Note that sto->parent will be the selector state object,
16987 * which resolved to a target node. Since this match was
16988 * recorded in the last change entry, we can obtain the
16989 * depth of the target node from there.
16990 */
16991 pos = sto->parent->history[sto->parent->nbHistory -1][0] -
16992 matcher->depth;
16993 sizeNeeded = pos;
16994 index = sto->sel->index;
16995
16996 /*
16997 * Create/grow the array of key-sequences.
16998 */
16999 if (matcher->keySeqs == NULL) {
17000 if (pos > 9)
17001 matcher->sizeKeySeqs = pos * 2;
17002 else
17003 matcher->sizeKeySeqs = 10;
17004 matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
17005 xmlMalloc(matcher->sizeKeySeqs *
17006 sizeof(xmlSchemaPSVIIDCKeyPtr *));
17007 if (matcher->keySeqs == NULL) {
17008 xmlSchemaVErrMemory(NULL,
17009 "allocating an array of key-sequences",
17010 NULL);
17011 return(-1);
17012 }
17013 memset(matcher->keySeqs, 0,
17014 matcher->sizeKeySeqs *
17015 sizeof(xmlSchemaPSVIIDCKeyPtr *));
17016 } else if (pos >= matcher->sizeKeySeqs) {
17017 int i = matcher->sizeKeySeqs;
17018
17019 matcher->sizeKeySeqs *= 2;
17020 matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
17021 xmlRealloc(matcher->keySeqs,
17022 matcher->sizeKeySeqs *
17023 sizeof(xmlSchemaPSVIIDCKeyPtr *));
17024 if (matcher->keySeqs == NULL) {
17025 xmlSchemaVErrMemory(NULL,
17026 "reallocating an array of key-sequences",
17027 NULL);
17028 return (-1);
17029 }
17030 /*
17031 * The array needs to be NULLed.
17032 * TODO: Use memset?
17033 */
17034 for (; i < matcher->sizeKeySeqs; i++)
17035 matcher->keySeqs[i] = NULL;
17036 }
17037
17038 /*
17039 * Get/create the key-sequence.
17040 */
17041 keySeq = matcher->keySeqs[pos];
17042 if (keySeq == NULL) {
17043 goto create_sequence;
17044 } else {
17045 if (keySeq[index] != NULL) {
17046 /*
17047 * cvc-identity-constraint:
17048 * 3 For each node in the ·target node set· all
17049 * of the {fields}, with that node as the context
17050 * node, evaluate to either an empty node-set or
17051 * a node-set with exactly one member, which must
17052 * have a simple type.
17053 *
17054 * The key was already set; report an error.
17055 */
17056 xmlSchemaVCustomErr(vctxt,
17057 XML_SCHEMAV_CVC_IDC,
17058 vctxt->node, (xmlSchemaTypePtr) matcher->aidc->def,
17059 "The field '%s' evaluates to a node-set "
17060 "with more than one member", sto->sel->xpath);
17061 return (1);
17062 } else {
17063 goto create_key;
17064 }
17065 }
17066
17067create_sequence:
17068 /*
17069 * Create a key-sequence.
17070 */
17071 keySeq = (xmlSchemaPSVIIDCKeyPtr *) xmlMalloc(
17072 matcher->aidc->def->nbFields *
17073 sizeof(xmlSchemaPSVIIDCKeyPtr));
17074 if (keySeq == NULL) {
17075 xmlSchemaVErrMemory(NULL,
17076 "allocating an IDC key-sequence", NULL);
17077 return(-1);
17078 }
17079 memset(keySeq, 0, matcher->aidc->def->nbFields *
17080 sizeof(xmlSchemaPSVIIDCKeyPtr));
17081 matcher->keySeqs[pos] = keySeq;
17082create_key:
17083 /*
17084 * Created a key once per node only.
17085 */
17086 if (key == NULL) {
17087 key = (xmlSchemaPSVIIDCKeyPtr) xmlMalloc(
17088 sizeof(xmlSchemaPSVIIDCKey));
17089 if (key == NULL) {
17090 xmlSchemaVErrMemory(NULL,
17091 "allocating a IDC key", NULL);
17092 xmlFree(keySeq);
17093 matcher->keySeqs[pos] = NULL;
17094 return(-1);
17095 }
17096 /*
17097 * Consume the compiled value.
17098 */
17099 key->type = type;
17100 key->compValue = vctxt->value;
17101 vctxt->value = NULL;
17102 /*
17103 * Store the key in a global list.
17104 */
17105 if (xmlSchemaIDCStoreKey(vctxt, key) == -1) {
17106 xmlSchemaIDCFreeKey(key);
17107 return (-1);
17108 }
17109 }
17110 keySeq[index] = key;
17111 }
17112 } else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
17113
17114 xmlSchemaPSVIIDCKeyPtr **keySeq = NULL;
17115 xmlSchemaPSVIIDCBindingPtr bind;
17116 xmlSchemaPSVIIDCNodePtr ntItem;
17117 xmlSchemaIDCMatcherPtr matcher;
17118 xmlSchemaIDCPtr idc;
17119 int pos, i, j, nbKeys;
17120 /*
17121 * Here we have the following scenario:
17122 * An IDC 'selector' state object resolved to a target node,
17123 * during the time this target node was in the
17124 * ancestor-or-self axis, the 'field' state object(s) looked
17125 * out for matching nodes to create a key-sequence for this
17126 * target node. Now we are back to this target node and need
17127 * to put the key-sequence, together with the target node
17128 * itself, into the node-table of the corresponding IDC
17129 * binding.
17130 */
17131 matcher = sto->matcher;
17132 idc = matcher->aidc->def;
17133 nbKeys = idc->nbFields;
17134 pos = vctxt->depth - matcher->depth;
17135 /*
17136 * Check if the matcher has any key-sequences at all, plus
17137 * if it has a key-sequence for the current target node.
17138 */
17139 if ((matcher->keySeqs == NULL) ||
17140 (matcher->sizeKeySeqs <= pos)) {
17141 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
17142 goto selector_key_error;
17143 else
17144 goto selector_leave;
17145 }
17146
17147 keySeq = &(matcher->keySeqs[pos]);
17148 if (*keySeq == NULL) {
17149 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
17150 goto selector_key_error;
17151 else
17152 goto selector_leave;
17153 }
17154
17155 for (i = 0; i < nbKeys; i++) {
17156 if (*keySeq[i] == NULL) {
17157 /*
17158 * Not qualified, if not all fields did resolve.
17159 */
17160 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY) {
17161 /*
17162 * All fields of a "key" IDC must resolve.
17163 */
17164 goto selector_key_error;
17165 }
17166 goto selector_leave;
17167 }
17168 }
17169 /*
17170 * All fields did resolve.
17171 */
17172
17173 /*
17174 * 4.1 If the {identity-constraint category} is unique(/key),
17175 * then no two members of the ·qualified node set· have
17176 * ·key-sequences· whose members are pairwise equal, as
17177 * defined by Equal in [XML Schemas: Datatypes].
17178 *
17179 * Get the IDC binding from the matcher and check for
17180 * duplicate key-sequences.
17181 */
17182 bind = xmlSchemaIDCAquireBinding(vctxt, matcher);
17183 if ((idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) &&
17184 (bind->nbNodes != 0)) {
17185 xmlSchemaPSVIIDCKeyPtr key, bkey, *bkeySeq;
17186
17187 i = 0;
17188 /*
17189 * Compare the key-sequences, key by key.
17190 */
17191 do {
17192 bkeySeq = bind->nodeTable[i]->keys;
17193 for (j = 0; j < nbKeys; j++) {
17194 key = *keySeq[j];
17195 bkey = bkeySeq[j];
17196 res = xmlSchemaAreValuesEqual(key->type,
17197 key->compValue, bkey->type, bkey->compValue);
17198 if (res == -1) {
17199 return (-1);
17200 } else if (res == 0)
17201 break;
17202 }
17203 if (res == 1) {
17204 /*
17205 * Duplicate found.
17206 */
17207 break;
17208 }
17209 i++;
17210 } while (i < bind->nbNodes);
17211 if (i != bind->nbNodes) {
17212 /*
17213 * TODO: Try to report the key-sequence.
17214 */
17215 xmlSchemaVCustomErr(vctxt,
17216 XML_SCHEMAV_CVC_IDC,
17217 vctxt->node,
17218 (xmlSchemaTypePtr) idc,
17219 "Duplicate key-sequence found", NULL);
17220
17221 goto selector_leave;
17222 }
17223 }
17224 /*
17225 * Add a node-table item to the IDC binding.
17226 */
17227 ntItem = (xmlSchemaPSVIIDCNodePtr) xmlMalloc(
17228 sizeof(xmlSchemaPSVIIDCNode));
17229 if (ntItem == NULL) {
17230 xmlSchemaVErrMemory(NULL,
17231 "allocating an IDC node-table item", NULL);
17232 xmlFree(*keySeq);
17233 *keySeq = NULL;
17234 return(-1);
17235 }
17236 memset(ntItem, 0, sizeof(xmlSchemaPSVIIDCNode));
17237
17238 /*
17239 * Store the node-table item on global list.
17240 */
17241 if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) {
17242 if (xmlSchemaIDCStoreNodeTableItem(vctxt, ntItem) == -1) {
17243 xmlFree(ntItem);
17244 xmlFree(*keySeq);
17245 *keySeq = NULL;
17246 return (-1);
17247 }
17248 }
17249 /*
17250 * Init the node-table item. Consume the key-sequence.
17251 */
17252 ntItem->node = vctxt->node;
17253 ntItem->keys = *keySeq;
17254 *keySeq = NULL;
17255 if (xmlSchemaIDCAppendNodeTableItem(bind, ntItem) == -1) {
17256 if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
17257 /*
17258 * Free the item, since keyref items won't be
17259 * put on a global list.
17260 */
17261 xmlFree(ntItem->keys);
17262 xmlFree(ntItem);
17263 }
17264 return (-1);
17265 }
17266
17267 goto selector_leave;
17268selector_key_error:
17269 /*
17270 * 4.2.1 (KEY) The ·target node set· and the
17271 * ·qualified node set· are equal, that is, every
17272 * member of the ·target node set· is also a member
17273 * of the ·qualified node set· and vice versa.
17274 */
17275 xmlSchemaVCustomErr(vctxt,
17276 XML_SCHEMAV_CVC_IDC,
17277 vctxt->node,
17278 (xmlSchemaTypePtr) idc,
17279 "All 'key' fields must evaluate to a node",
17280 NULL);
17281selector_leave:
17282 /*
17283 * Free the key-sequence if not added to the IDC table.
17284 */
17285 if (*keySeq != NULL) {
17286 xmlFree(*keySeq);
17287 *keySeq = NULL;
17288 }
17289 } /* if selector */
17290 } /* if matched */
17291
17292 sto->nbHistory--;
17293
17294deregister_check:
17295 /*
17296 * Deregister state objects if they reach the depth of creation.
17297 * Note that this has to be checked before and after processing
17298 * any history if the state object resolved to partially/fully
17299 * to a node on which it was created as well, since this scenario
17300 * created two entries in the list of history for the same node.
17301 */
17302 if ((sto->nbHistory == 1) && (sto->history[0][0] == vctxt->depth)) {
17303#if DEBUG_IDC
17304 xmlGenericError(xmlGenericErrorContext, "IDC: STO pop '%s'\n",
17305 sto->sel->xpath);
17306#endif
17307 if (vctxt->xpathStates != sto) {
17308 xmlSchemaVErr(vctxt, vctxt->node,
17309 XML_SCHEMAV_INTERNAL,
17310 "Internal error: xmlSchemaXPathProcessChanges, "
17311 "The state object to be removed is not the first "
17312 "in the list.\n",
17313 NULL, NULL);
17314 }
17315 sto->nbHistory = 0;
17316 nextsto = sto->next;
17317 /*
17318 * Unlink from the list of active XPath state objects.
17319 */
17320 vctxt->xpathStates = sto->next;
17321 sto->next = vctxt->xpathStatePool;
17322 /*
17323 * Link it to the pool of reusable state objects.
17324 */
17325 vctxt->xpathStatePool = sto;
17326 sto = nextsto;
17327 } else
17328 sto = sto->next;
17329 } /* while (sto != NULL) */
17330 return (0);
17331}
17332
17333/**
17334 * xmlSchemaIDCRegisterMatchers:
17335 * @vctxt: the WXS validation context
17336 * @elemDecl: the element declaration
17337 *
17338 * Creates helper objects to evaluate IDC selectors/fields
17339 * successively.
17340 *
17341 * Returns 0 if OK and -1 on internal errors.
17342 */
17343static int
17344xmlSchemaIDCRegisterMatchers(xmlSchemaValidCtxtPtr vctxt,
17345 xmlSchemaElementPtr elemDecl)
17346{
17347 xmlSchemaIDCMatcherPtr matcher, last = NULL;
17348 xmlSchemaIDCPtr idc, refIdc;
17349 xmlSchemaIDCAugPtr aidc;
17350
17351 idc = (xmlSchemaIDCPtr) elemDecl->idcs;
17352 if (idc == NULL)
17353 return (0);
17354
17355#if DEBUG_IDC
17356 {
17357 xmlChar *str = NULL;
17358 xmlGenericError(xmlGenericErrorContext,
17359 "IDC: MATCHERS on %s, depth %d\n",
17360 xmlSchemaFormatNsUriLocal(&str, vctxt->elemInfo->namespaceName,
17361 vctxt->elemInfo->localName), vctxt->depth);
17362 FREE_AND_NULL(str)
17363 }
17364#endif
17365 if (vctxt->elemInfo->idcMatchers != NULL) {
17366 xmlSchemaVErr(vctxt, vctxt->node,
17367 XML_SCHEMAV_INTERNAL,
17368 "Internal error: xmlSchemaIDCRegisterMatchers: "
17369 "The chain of IDC matchers is expected to be empty.\n",
17370 NULL, NULL);
17371 return (-1);
17372 }
17373 do {
17374 if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
17375 /*
17376 * Since IDCs bubbles are expensive we need to know the
17377 * depth at which the bubbles should stop; this will be
17378 * the depth of the top-most keyref IDC. If no keyref
17379 * references a key/unique IDC, the bubbleDepth will
17380 * be -1, indicating that no bubbles are needed.
17381 */
17382 refIdc = (xmlSchemaIDCPtr) idc->ref->item;
17383 if (refIdc != NULL) {
17384 /*
17385 * Lookup the augmented IDC.
17386 */
17387 aidc = vctxt->aidcs;
17388 while (aidc != NULL) {
17389 if (aidc->def == refIdc)
17390 break;
17391 aidc = aidc->next;
17392 }
17393 if (aidc == NULL) {
17394 xmlSchemaVErr(vctxt, vctxt->node,
17395 XML_SCHEMAV_INTERNAL,
17396 "Internal error: xmlSchemaIDCRegisterMatchers: "
17397 "Could not find an augmented IDC item for an IDC "
17398 "definition.\n",
17399 NULL, NULL);
17400 return (-1);
17401 }
17402 if ((aidc->bubbleDepth == -1) ||
17403 (vctxt->depth < aidc->bubbleDepth))
17404 aidc->bubbleDepth = vctxt->depth;
17405 }
17406 }
17407 /*
17408 * Lookup the augmented IDC item for the IDC definition.
17409 */
17410 aidc = vctxt->aidcs;
17411 while (aidc != NULL) {
17412 if (aidc->def == idc)
17413 break;
17414 aidc = aidc->next;
17415 }
17416 if (aidc == NULL) {
17417 xmlSchemaVErr(vctxt, vctxt->node,
17418 XML_SCHEMAV_INTERNAL,
17419 "Internal error: xmlSchemaIDCRegisterMatchers: "
17420 "Could not find an augmented IDC item for an IDC definition.\n",
17421 NULL, NULL);
17422 return (-1);
17423 }
17424 /*
17425 * Create an IDC matcher for every IDC definition.
17426 */
17427 matcher = (xmlSchemaIDCMatcherPtr)
17428 xmlMalloc(sizeof(xmlSchemaIDCMatcher));
17429 if (matcher == NULL) {
17430 xmlSchemaVErrMemory(vctxt,
17431 "allocating an IDC matcher", NULL);
17432 return (-1);
17433 }
17434 memset(matcher, 0, sizeof(xmlSchemaIDCMatcher));
17435 if (last == NULL)
17436 vctxt->elemInfo->idcMatchers = matcher;
17437 else
17438 last->next = matcher;
17439 last = matcher;
17440
17441 matcher->type = IDC_MATCHER;
17442 matcher->depth = vctxt->depth;
17443 matcher->aidc = aidc;
17444#if DEBUG_IDC
17445 xmlGenericError(xmlGenericErrorContext, "IDC: register matcher\n");
17446#endif
17447 /*
17448 * Init the automaton state object.
17449 */
17450 if (xmlSchemaIDCAddStateObject(vctxt, matcher,
17451 idc->selector, NULL, XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) == -1)
17452 return (-1);
17453
17454 idc = idc->next;
17455 } while (idc != NULL);
17456 return (0);
17457}
17458
17459/**
17460 * xmlSchemaBubbleIDCNodeTables:
17461 * @depth: the current tree depth
17462 *
17463 * Merges IDC bindings of an element at @depth into the corresponding IDC
17464 * bindings of its parent element. If a duplicate note-table entry is found,
17465 * both, the parent node-table entry and child entry are discarded from the
17466 * node-table of the parent.
17467 *
17468 * Returns 0 if OK and -1 on internal errors.
17469 */
17470static int
17471xmlSchemaBubbleIDCNodeTables(xmlSchemaValidCtxtPtr vctxt)
17472{
17473 xmlSchemaPSVIIDCBindingPtr bind; /* IDC bindings of the current node. */
17474 xmlSchemaPSVIIDCBindingPtr *parTable, parBind, lastParBind; /* parent IDC bindings. */
17475 xmlSchemaPSVIIDCNodePtr node, parNode; /* node-table entries. */
17476 xmlSchemaPSVIIDCKeyPtr key, parKey; /* keys of in a key-sequence. */
17477 xmlSchemaIDCAugPtr aidc;
17478 int i, j, k, ret, oldNum, newDupls = 0;
17479 int duplTop;
17480
17481 /*
17482 * The node table has the following sections:
17483 *
17484 * O --> old node-table entries (first)
17485 * O
17486 * + --> new node-table entries
17487 * +
17488 * % --> new duplicate node-table entries
17489 * %
17490 * # --> old duplicate node-table entries
17491 * # (last)
17492 *
17493 */
17494 bind = vctxt->elemInfo->idcTable;
17495 if (bind == NULL) {
17496 /* Fine, no table, no bubbles. */
17497 return (0);
17498 }
17499
17500 parTable = &(vctxt->elemInfos[vctxt->depth -1]->idcTable);
17501 /*
17502 * Walk all bindings; create new or add to existing bindings.
17503 * Remove duplicate key-sequences.
17504 */
17505start_binding:
17506 while (bind != NULL) {
17507 /*
17508 * Skip keyref IDCs.
17509 */
17510 if (bind->definition->type == XML_SCHEMA_TYPE_IDC_KEYREF)
17511 continue;
17512 /*
17513 * Check if the key/unique IDC table needs to be bubbled.
17514 */
17515 aidc = vctxt->aidcs;
17516 do {
17517 if (aidc->def == bind->definition) {
17518 if (aidc->bubbleDepth == vctxt->depth) {
17519 bind = bind->next;
17520 goto start_binding;
17521 }
17522 break;
17523 }
17524 aidc = aidc->next;
17525 } while (aidc != NULL);
17526 if (parTable != NULL)
17527 parBind = *parTable;
17528 while (parBind != NULL) {
17529 /*
17530 * Search a matching parent binding for the
17531 * IDC definition.
17532 */
17533 if (parBind->definition == bind->definition) {
17534
17535 /*
17536 * Compare every node-table entry of the child node,
17537 * i.e. the key-sequence within, ...
17538 */
17539 oldNum = parBind->nbNodes; /* Skip newly added items. */
17540 duplTop = oldNum + parBind->nbDupls;
17541
17542 for (i = 0; i < bind->nbNodes; i++) {
17543 node = bind->nodeTable[i];
17544 if (node == NULL)
17545 continue;
17546 /*
17547 * ...with every key-sequence of the parent node, already
17548 * evaluated to be a duplicate key-sequence.
17549 */
17550 if (parBind->nbDupls != 0) {
17551 j = bind->nbNodes + newDupls;
17552 while (j < duplTop) {
17553 parNode = parBind->nodeTable[j];
17554 for (k = 0; k < bind->definition->nbFields; k++) {
17555 key = node->keys[k];
17556 parKey = parNode->keys[k];
17557 ret = xmlSchemaAreValuesEqual(key->type,
17558 key->compValue,
17559 parKey->type, parKey->compValue);
17560 if (ret == -1) {
17561 /* TODO: Internal error */
17562 return(-1);
17563 } else if (ret == 0)
17564 break;
17565
17566 }
17567 if (ret == 1)
17568 /* Duplicate found. */
17569 break;
17570 j++;
17571 }
17572 if (j != duplTop) {
17573 /* Duplicate found. */
17574 continue;
17575 }
17576 }
17577 /*
17578 * ... and with every key-sequence of the parent node.
17579 */
17580 j = 0;
17581 while (j < oldNum) {
17582 parNode = parBind->nodeTable[j];
17583 /*
17584 * Compare key by key.
17585 */
17586 for (k = 0; k < parBind->definition->nbFields; k++) {
17587 key = node->keys[k];
17588 parKey = parNode->keys[k];
17589
17590 ret = xmlSchemaAreValuesEqual(key->type,
17591 key->compValue,
17592 parKey->type, parKey->compValue);
17593 if (ret == -1) {
17594 /* TODO: Internal error */
17595 } else if (ret == 0)
17596 break;
17597
17598 }
17599 if (ret == 1)
17600 /*
17601 * The key-sequences are equal.
17602 */
17603 break;
17604 j++;
17605 }
17606 if (j != oldNum) {
17607 /*
17608 * Handle duplicates.
17609 */
17610 newDupls++;
17611 oldNum--;
17612 parBind->nbNodes--;
17613 /*
17614 * Move last old item to pos of duplicate.
17615 */
17616 parBind->nodeTable[j] =
17617 parBind->nodeTable[oldNum];
17618
17619 if (parBind->nbNodes != oldNum) {
17620 /*
17621 * If new items exist, move last new item to
17622 * last of old items.
17623 */
17624 parBind->nodeTable[oldNum] =
17625 parBind->nodeTable[parBind->nbNodes];
17626 }
17627 /*
17628 * Move duplicate to last pos of new/old items.
17629 */
17630 parBind->nodeTable[parBind->nbNodes] = parNode;
17631
17632 } else {
17633 /*
17634 * Add the node-table entry (node and key-sequence) of
17635 * the child node to the node table of the parent node.
17636 */
17637 if (parBind->nodeTable == NULL) {
17638 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
17639 xmlMalloc(1 * sizeof(xmlSchemaPSVIIDCNodePtr));
17640 if (parBind->nodeTable == NULL) {
17641 xmlSchemaVErrMemory(NULL,
17642 "allocating IDC list of node-table items", NULL);
17643 return(-1);
17644 }
17645 parBind->sizeNodes = 1;
17646 } else if (duplTop >= parBind->sizeNodes) {
17647 parBind->sizeNodes++;
17648 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
17649 xmlRealloc(parBind->nodeTable, parBind->sizeNodes *
17650 sizeof(xmlSchemaPSVIIDCNodePtr));
17651 if (parBind->nodeTable == NULL) {
17652 xmlSchemaVErrMemory(NULL,
17653 "re-allocating IDC list of node-table items", NULL);
17654 return(-1);
17655 }
17656 }
17657
17658 /*
17659 * Move first old duplicate to last position
17660 * of old duplicates +1.
17661 */
17662 if (parBind->nbDupls != 0) {
17663 parBind->nodeTable[duplTop] =
17664 parBind->nodeTable[parBind->nbNodes + newDupls];
17665 }
17666 /*
17667 * Move first new duplicate to last position of
17668 * new duplicates +1.
17669 */
17670 if (newDupls != 0) {
17671 parBind->nodeTable[parBind->nbNodes + newDupls] =
17672 parBind->nodeTable[parBind->nbNodes];
17673 }
17674 /*
17675 * Append the new node-table entry to the 'new node-table
17676 * entries' section.
17677 */
17678 parBind->nodeTable[parBind->nbNodes] = node;
17679 parBind->nbNodes++;
17680 duplTop++;
17681 }
17682 }
17683 parBind->nbDupls += newDupls;
17684 break;
17685 }
17686 if (parBind->next == NULL)
17687 lastParBind = parBind;
17688 parBind = parBind->next;
17689 }
17690 if (parBind == NULL) {
17691 /*
17692 * No binding for the IDC was found: create a new one and
17693 * copy all node-tables.
17694 */
17695 parBind = xmlSchemaIDCNewBinding(bind->definition);
17696 if (parBind == NULL)
17697 return(-1);
17698
17699 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
17700 xmlMalloc(bind->nbNodes * sizeof(xmlSchemaPSVIIDCNodePtr));
17701 if (parBind->nodeTable == NULL) {
17702 xmlSchemaVErrMemory(NULL,
17703 "allocating an array of IDC node-table items", NULL);
17704 xmlSchemaIDCFreeBinding(parBind);
17705 return(-1);
17706 }
17707 parBind->sizeNodes = bind->nbNodes;
17708 memcpy(parBind->nodeTable, bind->nodeTable,
17709 bind->nbNodes * sizeof(xmlSchemaPSVIIDCNodePtr));
17710 /*
17711 for (i = 1; i < bind->nbNodes; i++)
17712 parBind->nodeTable[i] = bind->nodeTable[i];
17713 */
17714 if (*parTable == NULL)
17715 *parTable = parBind;
17716 else
17717 lastParBind->next = parBind;
17718 }
17719 bind = bind->next;
17720 }
17721 return (0);
17722}
17723
17724/**
17725 * xmlSchemaCheckCVCIDCKeyRef:
17726 * @vctxt: the WXS validation context
17727 * @elemDecl: the element declaration
17728 *
17729 * Check the cvc-idc-keyref constraints.
17730 */
17731static int
17732xmlSchemaCheckCVCIDCKeyRef(xmlSchemaValidCtxtPtr vctxt)
17733{
17734 xmlSchemaPSVIIDCBindingPtr refbind, bind;
17735
17736 refbind = vctxt->elemInfo->idcTable;
17737 /*
17738 * Find a keyref.
17739 */
17740 while (refbind != NULL) {
17741 if (refbind->definition->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
17742 int i, j, k, res;
17743 xmlSchemaPSVIIDCKeyPtr *refKeys, *keys;
17744 xmlSchemaPSVIIDCKeyPtr refKey, key;
17745
17746 /*
17747 * Find the referred key/unique.
17748 */
17749 bind = vctxt->elemInfo->idcTable;
17750 do {
17751 if ((xmlSchemaIDCPtr) refbind->definition->ref->item ==
17752 bind->definition)
17753 break;
17754 bind = bind->next;
17755 } while (bind != NULL);
17756
17757 /*
17758 * Search for a matching key-sequences.
17759 */
17760 for (i = 0; i < refbind->nbNodes; i++) {
17761 res = 0;
17762 if (bind != NULL) {
17763 refKeys = refbind->nodeTable[i]->keys;
17764 for (j = 0; j < bind->nbNodes; j++) {
17765 keys = bind->nodeTable[j]->keys;
17766 for (k = 0; k < bind->definition->nbFields; k++) {
17767 refKey = refKeys[k];
17768 key = keys[k];
17769 res = xmlSchemaAreValuesEqual(key->type, key->compValue,
17770 refKey->type, refKey->compValue);
17771 if (res == 0)
17772 break;
17773 else if (res == -1) {
17774 return (-1);
17775 }
17776 }
17777 if (res == 1) {
17778 /*
17779 * Match found.
17780 */
17781 break;
17782 }
17783 }
17784 }
17785 if (res == 0) {
17786 /* TODO: Report the key-sequence. */
17787 xmlSchemaVCustomErr(vctxt,
17788 XML_SCHEMAV_CVC_IDC,
17789 refbind->nodeTable[i]->node,
17790 (xmlSchemaTypePtr) refbind->definition,
17791 "No matching key-sequence found", NULL);
17792 }
17793 }
17794 }
17795 refbind = refbind->next;
17796 }
17797 return (0);
17798}
17799#endif /* IDC_ENABLED */
17800
17801#ifdef ELEM_INFO_ENABLED
17802/**
17803 * xmlSchemaBeginElement:
17804 * @vctxt: the WXS validation context
17805 *
17806 * Just a temporary workaround to simulate streaming validation
17807 * a bit.
17808 */
17809static void
17810xmlSchemaBeginElement(xmlSchemaValidCtxtPtr vctxt)
17811{
17812 vctxt->depth++;
17813 vctxt->elemInfo = xmlSchemaGetFreshElemInfo(vctxt);
17814 vctxt->elemInfo->node = vctxt->node;
17815 vctxt->elemInfo->localName = vctxt->node->name;
17816 if (vctxt->node->ns != NULL)
17817 vctxt->elemInfo->namespaceName = vctxt->node->ns->href;
17818 else
17819 vctxt->elemInfo->namespaceName = NULL;
17820}
17821
17822/**
17823 * xmlSchemaEndElement:
17824 * @vctxt: the WXS validation context
17825 *
17826 * Just a temporary workaround to simulate streaming validation
17827 * a bit.
17828 */
17829static void
17830xmlSchemaEndElement(xmlSchemaValidCtxtPtr vctxt)
17831{
17832 if (vctxt->depth < 0) {
17833 /* TODO: raise error? */
17834 vctxt->depth--;
17835 return;
17836 }
17837#ifdef IDC_ENABLED
17838 /*
17839 * Evaluate the history of changes of active state objects.
17840 */
17841 xmlSchemaXPathProcessChanges(vctxt, vctxt->elemInfo->typeDef);
17842
17843 if (vctxt->elemInfo->value != NULL) {
17844 xmlSchemaFreeValue(vctxt->elemInfo->value);
17845 vctxt->elemInfo->value = NULL;
17846 }
17847 /*
17848 * TODO: 6 The element information item must be ·valid· with respect to each of
17849 * the {identity-constraint definitions} as per Identity-constraint
17850 * Satisfied (§3.11.4).
17851 */
17852 /*
17853 * Validate IDC keyrefs.
17854 */
17855 xmlSchemaCheckCVCIDCKeyRef(vctxt);
17856#endif
17857
17858 /*
17859 * Merge/free the IDC table.
17860 */
17861 if (vctxt->elemInfo->idcTable != NULL) {
17862#ifdef DEBUG_IDC
17863 xmlSchemaDebugDumpIDCTable(stdout,
17864 vctxt->elemInfo->namespaceName,
17865 vctxt->elemInfo->localName,
17866 vctxt->elemInfo->idcTable);
17867#endif
17868#ifdef IDC_ENABLED
17869 if (vctxt->depth > 0) {
17870 /*
17871 * Merge the IDC node table with the table of the parent node.
17872 */
17873 xmlSchemaBubbleIDCNodeTables(vctxt);
17874 }
17875 /*
17876 * TODO: Don't free the PSVI IDC tables if they are
17877 * requested for the PSVI.
17878 */
17879 xmlSchemaIDCFreeIDCTable(vctxt->elemInfo->idcTable);
17880#endif
17881 vctxt->elemInfo->idcTable = NULL;
17882 }
17883
17884 /*
17885 * Cleanup IDC matchers.
17886 */
17887#ifdef IDC_ENABLED
17888 if (vctxt->elemInfo->idcMatchers != NULL) {
17889 xmlSchemaIDCFreeMatcherList(vctxt->elemInfo->idcMatchers);
17890 vctxt->elemInfo->idcMatchers = NULL;
17891 }
17892#endif
17893
17894 /*
17895 * Skip further processing if we are on the validation root.
17896 */
17897 if (vctxt->depth == 0) {
17898 vctxt->depth--;
17899 return;
17900 }
17901
17902 /*
17903 * Reset the bubbleDepth if needed.
17904 */
17905#ifdef IDC_ENABLED
17906 if (vctxt->aidcs != NULL) {
17907 xmlSchemaIDCAugPtr aidc = vctxt->aidcs;
17908 do {
17909 if (aidc->bubbleDepth == vctxt->depth) {
17910 /*
17911 * A bubbleDepth of a key/unique IDC matches the current
17912 * depth, this means that we are leaving the scope of the
17913 * top-most keyref IDC.
17914 */
17915 aidc->bubbleDepth = -1;
17916 }
17917 aidc = aidc->next;
17918 } while (aidc != NULL);
17919 }
17920#endif
17921 vctxt->depth--;
17922 vctxt->elemInfo = vctxt->elemInfos[vctxt->depth];
17923 vctxt->node = vctxt->elemInfo->node;
17924}
17925
17926#endif /* ELEM_INFO_ENABLED */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017927
17928/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017929 * xmlSchemaValidateElementByDeclaration:
Daniel Veillard4255d502002-04-16 15:50:10 +000017930 * @ctxt: a schema validation context
17931 * @node: the top node.
17932 *
17933 * Validate the content of an element type.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017934 * Validation Rule: Element Locally Valid (Element)
Daniel Veillard4255d502002-04-16 15:50:10 +000017935 *
17936 * Returns 0 if the element is schemas valid, a positive error code
17937 * number otherwise and -1 in case of internal or API error.
17938 */
17939static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017940xmlSchemaValidateElementByDeclaration(xmlSchemaValidCtxtPtr ctxt,
17941 xmlSchemaElementPtr elemDecl)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017942{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017943 xmlNodePtr elem;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017944 int ret = 0;
17945 xmlSchemaTypePtr actualType = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017946 xmlAttrPtr attr;
17947 xmlChar *attrValue;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017948 int nilled = 0, elemHasContent = -1;
Daniel Veillard3646d642004-06-02 19:19:14 +000017949
17950 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017951 * This one is called by xmlSchemaValidateElementByWildcardInternal,
17952 * xmlSchemaValidateElementByAnyType and xmlSchemaValidateElement.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017953 * Note that @elemDecl will be the declaration and never the
17954 * reference to a declaration.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017955 */
Daniel Veillard3646d642004-06-02 19:19:14 +000017956
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017957 if (ctxt == NULL) {
17958 xmlSchemaVErr(ctxt, NULL, XML_SCHEMAV_INTERNAL,
17959 "Internal error: xmlSchemaValidateElementByDeclaration, "
17960 "bad arguments.\n",
17961 NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017962 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000017963 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017964
17965 elem = ctxt->node;
17966
17967 /*
17968 * cvc-elt (3.3.4) : 1
17969 */
17970 if (elemDecl == NULL) {
17971 xmlSchemaVCustomErr(ctxt,
17972 XML_SCHEMAV_CVC_ELT_1,
17973 elem, NULL,
17974 "No matching declaration available", NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017975 /*
17976 * Evaluate IDCs even if an error occured.
17977 */
17978#ifdef IDC_ENABLED
17979 if (xmlSchemaXPathEvaluate(ctxt, ctxt->elemInfo->namespaceName,
17980 ctxt->elemInfo->localName, XML_ELEMENT_NODE) == -1)
17981 return (-1);
17982#endif
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017983 return (ctxt->err);
17984 }
17985 /*
17986 * cvc-elt (3.3.4) : 2
17987 */
17988 if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT) {
17989 xmlSchemaVCustomErr(ctxt,
17990 XML_SCHEMAV_CVC_ELT_2,
17991 elem, NULL,
17992 "The element declaration is abstract", NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000017993 /*
17994 * Evaluate IDCs even if an error occured.
17995 */
17996#ifdef IDC_ENABLED
17997 if (xmlSchemaXPathEvaluate(ctxt, ctxt->elemInfo->namespaceName,
17998 ctxt->elemInfo->localName, XML_ELEMENT_NODE) == -1)
17999 return (-1);
18000#endif
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018001 return (ctxt->err);
18002 }
18003
18004 /*
18005 * cvc-elt (3.3.4) : 3
18006 * Handle 'xsi:nil'.
18007 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018008
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018009 attr = xmlHasNsProp(elem, BAD_CAST "nil", xmlSchemaInstanceNs);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018010 if (attr != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018011 attrValue = xmlNodeGetContent((xmlNodePtr) attr);
18012 ctxt->node = (xmlNodePtr) attr;
18013 ctxt->cur = attr->children;
18014 ret = xmlSchemaValidateSimpleTypeValue(ctxt,
18015 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
18016 BAD_CAST attrValue, 1, 1, 1, 1);
18017 ctxt->node = elem;
18018 ctxt->type = (xmlSchemaTypePtr) elemDecl;
18019 if (ret < 0) {
18020 xmlSchemaVCustomErr(ctxt,
18021 XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018022 (xmlNodePtr) attr, (xmlSchemaTypePtr) elemDecl,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018023 "Internal error: xmlSchemaValidateElementByDeclaration, "
18024 "validating the attribute 'xsi:nil'", NULL);
18025 if (attrValue != NULL)
18026 xmlFree(attrValue);
18027 return (-1);
18028 }
18029 if ((elemDecl->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018030 /*
18031 * cvc-elt (3.3.4) : 3.1
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018032 */
18033 xmlSchemaVCustomErr(ctxt,
18034 XML_SCHEMAV_CVC_ELT_3_1,
18035 elem, NULL,
18036 "The element is not 'nillable'", NULL);
18037 } else {
18038 if (xmlStrEqual(BAD_CAST attrValue, BAD_CAST "true") ||
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018039 xmlStrEqual(BAD_CAST attrValue, BAD_CAST "1")) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018040 ret = 0;
18041 /*
18042 * cvc-elt (3.3.4) : 3.2.1
18043 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018044 elemHasContent = xmlSchemaHasElemOrCharContent(elem);
18045 if (elemHasContent == 1) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018046 xmlSchemaVCustomErr(ctxt,
18047 XML_SCHEMAV_CVC_ELT_3_2_1,
18048 /* XML_SCHEMAS_ERR_NOTEMPTY, */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018049 elem, (xmlSchemaTypePtr) elemDecl,
18050 "The 'nilled' element must have no character or "
18051 "element content", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018052 ret = XML_SCHEMAV_CVC_ELT_3_2_1;
18053 }
18054 /*
18055 * cvc-elt (3.3.4) : 3.2.2
18056 */
18057 if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) &&
18058 (elemDecl->value != NULL)) {
18059 xmlSchemaVCustomErr(ctxt, XML_SCHEMAV_CVC_ELT_3_2_2,
18060 /* XML_SCHEMAS_ERR_HAVEDEFAULT, */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018061 elem, (xmlSchemaTypePtr) elemDecl,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018062 "There is a fixed value constraint defined for "
18063 "the 'nilled' element", NULL);
18064 ret = XML_SCHEMAV_CVC_ELT_3_2_2;
18065 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018066 if (ret == 0)
18067 nilled = 1;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018068 }
18069 }
18070 if (attrValue != NULL)
18071 xmlFree(attrValue);
18072 }
18073
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018074
18075 actualType = elemDecl->subtypes;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018076 /*
18077 * cvc-elt (3.3.4) : 4
18078 * Handle 'xsi:type'.
18079 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018080
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018081 attr = xmlHasNsProp(elem, BAD_CAST "type", xmlSchemaInstanceNs);
18082 if (attr != NULL) {
18083 xmlChar *nsName = NULL, *local = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018084
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018085 /*
18086 * TODO: We should report a *warning* that the type was overriden
18087 * by the instance.
18088 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018089
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018090 /*
18091 * cvc-elt (3.3.4) : 4.1
18092 */
18093 attrValue = xmlNodeGetContent((xmlNodePtr) attr);
18094 ret = xmlSchemaValQNameAcquire(attrValue, attr->parent,
18095 &nsName, &local);
18096 if (ret < 0) {
18097 xmlSchemaVCustomErr(ctxt,
18098 XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018099 (xmlNodePtr) attr, (xmlSchemaTypePtr) elemDecl,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018100 "Internal error: xmlSchemaValidateElementByDeclaration, "
18101 "validating the attribute 'xsi:type'", NULL);;
18102 FREE_AND_NULL(attrValue)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018103 FREE_AND_NULL(nsName)
18104 FREE_AND_NULL(local)
18105 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018106 } else if (ret == 1) {
18107 xmlSchemaVSimpleTypeErr(ctxt,
18108 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1,
18109 (xmlNodePtr) attr, attrValue,
18110 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME));
18111 } else if (ret == 2) {
18112 xmlSchemaVCustomErr(ctxt,
18113 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1,
18114 (xmlNodePtr) attr,
18115 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
18116 "The QName value '%s' has no "
18117 "corresponding namespace declaration in scope",
18118 attrValue);
18119 } else {
18120 /*
18121 * cvc-elt (3.3.4) : 4.2
18122 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018123 actualType = xmlSchemaGetType(ctxt->schema, local, nsName);
18124 if (actualType == NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018125 xmlChar *strA = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018126
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018127 xmlSchemaVCustomErr(ctxt,
18128 XML_SCHEMAV_CVC_ELT_4_2,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018129 (xmlNodePtr) attr,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018130 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
18131 "The value %s does not resolve to a type "
18132 "definition",
18133 xmlSchemaFormatNsUriLocal(&strA, nsName, local));
18134 FREE_AND_NULL(strA);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018135 } else {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018136 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018137 * URGENT TODO: cvc-elt (3.3.4) : 4.3 (Type Derivation OK)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018138 */
18139 }
18140 }
18141 FREE_AND_NULL(attrValue)
18142 FREE_AND_NULL(nsName)
18143 FREE_AND_NULL(local)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018144 }
18145 /* TODO: Change the handling of missing types according to
18146 * the spec.
18147 */
18148 if (actualType == NULL) {
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000018149 xmlSchemaVCustomErr(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018150 XML_SCHEMAV_CVC_TYPE_1,
18151 elem, (xmlSchemaTypePtr) elemDecl,
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000018152 "The type definition is absent", NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018153 /*
18154 * Evaluate IDCs even if an error occured.
18155 */
18156#ifdef IDC_ENABLED
18157 if (xmlSchemaXPathEvaluate(ctxt, ctxt->elemInfo->namespaceName,
18158 ctxt->elemInfo->localName, XML_ELEMENT_NODE) == -1)
18159 return (-1);
18160#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018161 return (XML_SCHEMAV_CVC_TYPE_1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018162 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018163
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018164 /*
18165 * TODO: Since this should be already checked by the content model automaton,
18166 * and we want to get rid of the XML_SCHEMAS_ERR... types, the error code
18167 * has been changed to XML_SCHEMAV_INTERNAL.
18168 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018169 /*
Daniel Veillard4255d502002-04-16 15:50:10 +000018170 if (child == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000018171 if (decl->minOccurs > 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018172 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018173 XML_SCHEMAS_ERR_MISSING,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018174 "Element %s: missing child %s\n",
18175 node->name, decl->name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018176 }
18177 return (ctxt->err);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018178 }
18179 */
Daniel Veillard4255d502002-04-16 15:50:10 +000018180 /*
18181 * Verify the element matches
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018182 * TODO, FIXME: Can this still happen here? Isn't this already checked
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018183 * by the content model automaton?
Daniel Veillardc0826a72004-08-10 14:17:33 +000018184 if (!xmlStrEqual(child->name, decl->name)) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018185 xmlSchemaVErr3(ctxt, node, XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018186 XML_SCHEMAS_ERR_WRONGELEM,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018187 "Element %s: missing child %s found %s\n",
18188 node->name, decl->name, child->name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018189 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000018190 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018191 */
18192 if (elemHasContent == -1)
18193 elemHasContent = xmlSchemaHasElemOrCharContent(elem);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018194
18195 /*
18196 * IDC: Register identity-constraint XPath matchers.
18197 */
18198#ifdef IDC_ENABLED
18199 if (elemDecl->idcs != NULL)
18200 xmlSchemaIDCRegisterMatchers(ctxt, elemDecl);
18201 /*
18202 * Evaluate IDCs.
18203 */
18204 if (xmlSchemaXPathEvaluate(ctxt, ctxt->elemInfo->namespaceName,
18205 ctxt->elemInfo->localName, XML_ELEMENT_NODE) == -1)
18206 return (-1);
18207#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018208 /*
18209 * cvc-elt (3.3.4) : 5
18210 * The appropriate case among the following must be true:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018211 */
Daniel Veillard4255d502002-04-16 15:50:10 +000018212 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018213 * cvc-elt (3.3.4) : 5.1
18214 * If the declaration has a {value constraint},
18215 * the item has neither element nor character [children] and
18216 * clause 3.2 has not applied, then all of the following must be true:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018217 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018218 if ((elemHasContent == 0) && (nilled == 0) && (elemDecl->value != NULL)) {
18219 /*
18220 * cvc-elt (3.3.4) : 5.1.1
18221 * If the ·actual type definition· is a ·local type definition·
18222 * then the canonical lexical representation of the {value constraint}
18223 * value must be a valid default for the ·actual type definition· as
18224 * defined in Element Default Valid (Immediate) (§3.3.6).
18225 */
18226 /*
18227 * NOTE: 'local' above means types aquired by xsi:type.
18228 */
18229 ret = 0;
18230 if (actualType != elemDecl->subtypes) {
18231 xmlSchemaCreatePCtxtOnVCtxt(ctxt);
18232 ret = xmlSchemaCheckCOSValidDefault(ctxt->pctxt, ctxt, actualType,
18233 elemDecl->value, NULL);
18234 if (ret < 0) {
18235 xmlSchemaVCustomErr(ctxt,
18236 XML_SCHEMAV_INTERNAL,
18237 elem, actualType,
18238 "Internal error: xmlSchemaValidateElementByDeclaration, "
18239 "validating a default value", NULL);
18240 return (-1);
18241 }
18242 }
18243 /*
18244 * cvc-elt (3.3.4) : 5.1.2
18245 * The element information item with the canonical lexical
18246 * representation of the {value constraint} value used as its
18247 * ·normalized value· must be ·valid· with respect to the
18248 * ·actual type definition· as defined by Element Locally Valid (Type)
18249 * (§3.3.4).
18250 */
18251 /*
18252 * Disable validation of the simple content, since it was already
18253 * done above.
18254 */
18255 if (ret == 0) {
18256 if (actualType != elemDecl->subtypes)
18257 ret = xmlSchemaValidateElementByType(ctxt, actualType, 0);
18258 else
18259 ret = xmlSchemaValidateElementByType(ctxt, actualType, 0);
18260 ctxt->node = elem;
18261 if (ret < 0) {
18262 xmlSchemaVCustomErr(ctxt,
18263 XML_SCHEMAV_INTERNAL,
18264 elem, actualType,
18265 "Internal error: xmlSchemaValidateElementByDeclaration, "
18266 "validating against the type", NULL);
18267 return (-1);
18268 }
18269 /*
18270 * PSVI: Create a text node on the instance element.
18271 */
18272 if (ctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) {
18273 xmlNodePtr textChild;
18274
18275 textChild = xmlNewText(elemDecl->value);
18276 if (textChild == NULL) {
18277 xmlSchemaVCustomErr(ctxt,
18278 XML_SCHEMAV_INTERNAL,
18279 elem, actualType,
18280 "Internal error: xmlSchemaValidateElementByDeclaration, "
18281 "could not create a default text node for the instance",
18282 NULL);
18283 } else
18284 xmlAddChild(elem, textChild);
18285 }
18286 }
18287
18288 } else {
18289 /*
18290 * 5.2.1 The element information item must be ·valid· with respect
18291 * to the ·actual type definition· as defined by Element Locally
18292 * Valid (Type) (§3.3.4).
18293 */
18294 ret = xmlSchemaValidateElementByType(ctxt, actualType, 1);
18295 ctxt->node = elem;
18296 if (ret < 0) {
18297 xmlSchemaVCustomErr(ctxt,
18298 XML_SCHEMAV_INTERNAL,
18299 elem, actualType,
18300 "Internal error: xmlSchemaValidateElementByDeclaration, "
18301 "validating a default value", NULL);
18302 return (-1);
18303 }
18304 /*
18305 * 5.2.2 If there is a fixed {value constraint} and clause 3.2 has
18306 * not applied, all of the following must be true:
18307 */
18308
18309 if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) && (nilled == 0)) {
18310 /*
18311 * 5.2.2.1 The element information item must have no element
18312 * information item [children].
18313 *
18314 * TODO REDUNDANT: If the actual type exists, the above call to
18315 * xmlSchemaValidateElementByType will already check for element
18316 * nodes.
18317 */
18318 if (xmlSchemaHasElemContent(elem)) {
18319 xmlSchemaVCustomErr(ctxt,
18320 XML_SCHEMAV_CVC_ELT_5_2_2_1,
18321 elem, (xmlSchemaTypePtr) elemDecl,
18322 "Elements in the content are not allowed if it is "
18323 "constrained by a fixed value", NULL);
18324 } else {
18325 /*
18326 * 5.2.2.2 The appropriate case among the following must
18327 * be true:
18328 */
18329
18330 if (actualType->contentType == XML_SCHEMA_CONTENT_MIXED) {
18331 xmlChar *value;
18332 /*
18333 * 5.2.2.2.1 If the {content type} of the ·actual type
18334 * definition· is mixed, then the *initial value* of the
18335 * item must match the canonical lexical representation
18336 * of the {value constraint} value.
18337 *
18338 * ... the *initial value* of an element information
18339 * item is the string composed of, in order, the
18340 * [character code] of each character information item in
18341 * the [children] of that element information item.
18342 */
18343 value = xmlNodeListGetString(elem->doc, elem->children, 1);
18344 if (! xmlStrEqual(BAD_CAST value, elemDecl->value)) {
18345 /*
18346 * TODO: Report invalid & expected values as well.
18347 * TODO: Implement the cononical stuff.
18348 */
18349 xmlSchemaVCustomErr(ctxt,
18350 XML_SCHEMAV_CVC_ELT_5_2_2_2_1,
18351 elem, (xmlSchemaTypePtr) elemDecl,
18352 "The value does not match the cononical "
18353 "lexical representation of the fixed constraint",
18354 NULL);
18355 }
18356 if (value != NULL)
18357 xmlFree(value);
18358 } else if ((actualType->contentType ==
18359 XML_SCHEMA_CONTENT_SIMPLE) ||
18360 (actualType->contentType == XML_SCHEMA_CONTENT_BASIC)) {
18361 xmlChar *value;
18362
18363 /*
18364 * 5.2.2.2.2 If the {content type} of the ·actual type
18365 * definition· is a simple type definition, then the
18366 * *actual value* of the item must match the canonical
18367 * lexical representation of the {value constraint} value.
18368 */
18369 /*
18370 * TODO: *actual value* is the normalized value, impl. this.
18371 * TODO: Report invalid & expected values as well.
18372 * TODO: Implement the cononical stuff.
18373 *
18374 */
18375 value = xmlNodeListGetString(elem->doc, elem->children, 1);
18376 if (! xmlStrEqual(BAD_CAST value, elemDecl->value)) {
18377 xmlSchemaVCustomErr(ctxt,
18378 XML_SCHEMAV_CVC_ELT_5_2_2_2_2,
18379 elem, (xmlSchemaTypePtr) elemDecl,
18380 "The normalized value does not match the cononical "
18381 "lexical representation of the fixed constraint",
18382 NULL);
18383 }
18384 if (value != NULL)
18385 xmlFree(value);
18386
18387 }
18388 /*
18389 * TODO: What if the content type is not 'mixed' or simple?
18390 */
18391
18392 }
18393
18394 }
18395 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018396 /*
18397 * TODO: 7 If the element information item is the ·validation root·, it must be
18398 * ·valid· per Validation Root Valid (ID/IDREF) (§3.3.4).
18399 */
18400
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018401 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000018402}
18403
Daniel Veillard4255d502002-04-16 15:50:10 +000018404/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018405 * xmlSchemaValidateElementByWildcardInternal:
Daniel Veillardc0826a72004-08-10 14:17:33 +000018406 * @ctxt: a schema validation context
18407 * @node: the top node.
18408 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018409 * Represents the recursive portion of xmlSchemaValidateElementByWildcard.
18410 * Not intended to be used by other functions.
Daniel Veillardc0826a72004-08-10 14:17:33 +000018411 *
18412 * Returns 0 if the element is valid, a positive error code
18413 * number otherwise and -1 in case of an internal error.
18414 */
18415static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018416xmlSchemaValidateElementByWildcardInternal(xmlSchemaValidCtxtPtr ctxt,
18417 xmlSchemaWildcardPtr wild,
18418 xmlNodePtr node)
Daniel Veillardc0826a72004-08-10 14:17:33 +000018419{
18420 const xmlChar *uri;
18421 int ret = 0;
18422 xmlNodePtr child;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018423
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018424 if (ctxt->xsiAssemble) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018425 ret = xmlSchemaAssembleByXSIElem(ctxt, ctxt->node);
18426 if (ret == -1) {
18427 xmlSchemaVCustomErr(ctxt,
18428 XML_SCHEMAV_INTERNAL,
18429 ctxt->node, NULL,
18430 "Internal error: xmlSchemaValidateElement, "
18431 "assembling schema by xsi", NULL);
18432 return (-1);
18433 }
18434 /*
18435 * NOTE: We won't react on schema parser errors here.
18436 * TODO: But a warning would be nice.
18437 */
18438 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000018439 if (wild->processContents != XML_SCHEMAS_ANY_SKIP) {
18440 xmlSchemaElementPtr decl = NULL;
18441
18442 if (node->ns != NULL)
18443 decl = xmlHashLookup3(ctxt->schema->elemDecl,
18444 node->name, node->ns->href, NULL);
18445 else
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018446 decl = xmlHashLookup3(ctxt->schema->elemDecl, node->name,
18447 NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +000018448 if (decl != NULL) {
18449 ctxt->node = node;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018450 ret = xmlSchemaValidateElementByDeclaration(ctxt, decl);
Daniel Veillardc0826a72004-08-10 14:17:33 +000018451 if (ret < 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018452 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000018453 "Internal error: xmlSchemaValidateAnyInternal, "
18454 "validating an element in the context of a wildcard.",
18455 NULL, NULL);
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +000018456 }
18457 return (ret);
Daniel Veillardc0826a72004-08-10 14:17:33 +000018458 } else if (wild->processContents == XML_SCHEMAS_ANY_STRICT) {
18459 /* TODO: Change to proper error code. */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018460 xmlSchemaVWildcardErr(ctxt, XML_SCHEMAV_CVC_ELT_1,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018461 node, wild, "No matching global declaration available");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018462 /*
18463 * Evaluate IDCs even if a validation error occured.
18464 */
18465#ifdef IDC_ENABLED
18466 if (xmlSchemaXPathEvaluate(ctxt, ctxt->elemInfo->namespaceName,
18467 ctxt->elemInfo->localName, XML_ELEMENT_NODE) == -1)
18468 return(-1);
18469#endif
Daniel Veillardc0826a72004-08-10 14:17:33 +000018470 return (ctxt->err);
18471 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018472 /*
18473 * Evaluate IDCs; we need to know if an IDC field resolves to
18474 * such a node. This node has no type definition and will
18475 * definitely result in an IDC validation error if an IDC field
18476 * resolves.
18477 */
18478#ifdef IDC_ENABLED
18479 if (xmlSchemaXPathEvaluate(ctxt, ctxt->elemInfo->namespaceName,
18480 ctxt->elemInfo->localName, XML_ELEMENT_NODE) == -1)
18481 return(-1);
18482#endif
Daniel Veillardc0826a72004-08-10 14:17:33 +000018483 }
18484 if (node->children != NULL) {
18485 child = node->children;
18486 do {
18487 if (child->type == XML_ELEMENT_NODE) {
18488 if (child->ns != NULL)
18489 uri = child->ns->href;
18490 else
18491 uri = NULL;
18492 if (xmlSchemaMatchesWildcardNs(wild, uri) == 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018493 /* TODO: error code. */
18494 xmlSchemaVWildcardErr(ctxt, XML_SCHEMAV_ELEMENT_CONTENT,
Daniel Veillardc0826a72004-08-10 14:17:33 +000018495 child, wild,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018496 "The namespace of the element is not allowed");
Daniel Veillardc0826a72004-08-10 14:17:33 +000018497 return (ctxt->err);
18498 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018499#ifdef ELEM_INFO_ENABLED
18500 ctxt->node = child;
18501 xmlSchemaBeginElement(ctxt);
18502#endif
18503 /*
18504 * Recurse over the children.
18505 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018506 ret = xmlSchemaValidateElementByWildcardInternal(ctxt,
18507 wild, child);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018508#ifdef ELEM_INFO_ENABLED
18509 xmlSchemaEndElement(ctxt);
18510#endif
Daniel Veillardc0826a72004-08-10 14:17:33 +000018511 if (ret != 0)
18512 return (ret);
18513 }
18514 child = child->next;
18515 } while (child != NULL);
18516 }
18517 return (0);
18518}
18519
18520/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018521 * xmlSchemaValidateElementContByWildcard:
Daniel Veillardc0826a72004-08-10 14:17:33 +000018522 * @ctxt: a schema validation context
18523 *
18524 * Returns 0 if the element is valid, a positive error code
18525 * number otherwise and -1 in case of an internal or API error.
18526 */
18527static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018528xmlSchemaValidateElementByWildcard(xmlSchemaValidCtxtPtr ctxt,
18529 xmlSchemaTypePtr type)
Daniel Veillardc0826a72004-08-10 14:17:33 +000018530{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018531 if ((type == NULL) || (type->type != XML_SCHEMA_TYPE_ANY) ||
18532 (ctxt->node == NULL)) {
18533 xmlSchemaVCustomErr(ctxt,
18534 XML_SCHEMAV_INTERNAL, ctxt->node, NULL,
18535 "Internal error: xmlSchemaValidateElementByWildcard, "
18536 "bad arguments", NULL);
18537 return (-1);
18538 }
18539 return(xmlSchemaValidateElementByWildcardInternal(ctxt,
18540 type->attributeWildcard, ctxt->node));
Daniel Veillardc0826a72004-08-10 14:17:33 +000018541}
18542
18543/**
William M. Brack2f2a6632004-08-20 23:09:47 +000018544 * xmlSchemaValidateAnyTypeContent:
18545 * @ctxt: a schema validation context
18546 * @node: the current element
18547 *
18548 * This one validates the content of an element of the type
18549 * 'anyType'. The process contents of the wildcard of 'anyType' is "lax",
18550 * thus elements in the subtree will be validated, if a corresponding
18551 * declaration in the schema exists.
18552 *
18553 * Returns 0 if the element and its subtree is valid, a positive error code
18554 * otherwise and -1 in case of an internal or API error.
18555 */
18556static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018557xmlSchemaValidateElementByAnyType(xmlSchemaValidCtxtPtr ctxt,
18558 xmlSchemaTypePtr type)
William M. Brack2f2a6632004-08-20 23:09:47 +000018559{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018560 xmlSchemaTypePtr oldtype;
18561 xmlNodePtr top, cur;
18562 xmlSchemaElementPtr decl;
William M. Brack2f2a6632004-08-20 23:09:47 +000018563 int skipContent, ret;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018564
18565 if ((type == NULL) || (ctxt->node == NULL))
18566 return (-1);
18567
18568 if (ctxt->node->children == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +000018569 return (0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018570
18571 oldtype = ctxt->type;
18572 top = ctxt->node;
18573 /*
18574 * STREAM: Child nodes are processed.
18575 */
18576 cur = ctxt->node->children;
18577 while (cur != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +000018578 skipContent = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018579 if (cur->type == XML_ELEMENT_NODE) {
William M. Brack2f2a6632004-08-20 23:09:47 +000018580 /*
18581 * The process contents of the wildcard is "lax", thus
18582 * we need to validate the element if a declaration
18583 * exists.
18584 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018585 if (cur->ns != NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +000018586 decl = xmlHashLookup3(ctxt->schema->elemDecl,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018587 cur->name, cur->ns->href, NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +000018588 else
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018589 decl = xmlHashLookup3(ctxt->schema->elemDecl, cur->name, NULL, NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +000018590 if (decl != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018591 ctxt->node = cur;
18592 ret = xmlSchemaValidateElementByDeclaration(ctxt, decl);
18593 ctxt->node = top;
William M. Brack2f2a6632004-08-20 23:09:47 +000018594 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018595 xmlSchemaVErr(ctxt, cur, XML_SCHEMAV_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000018596 "Internal error: xmlSchemaValidateAnyTypeContent, "
18597 "validating an element in the context of a wildcard.",
18598 NULL, NULL);
18599 return (ret);
18600 } else if (ret > 0)
18601 return (ret);
18602 skipContent = 1;
18603 }
18604 }
18605 /*
18606 * Browse the full subtree, deep first.
18607 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018608 if ((skipContent == 0) && (cur->children != NULL)) {
William M. Brack2f2a6632004-08-20 23:09:47 +000018609 /* deep first */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018610 cur = cur->children;
18611 } else if ((cur != top) && (cur->next != NULL)) {
William M. Brack2f2a6632004-08-20 23:09:47 +000018612 /* then siblings */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018613 cur = cur->next;
18614 } else if (cur != top) {
William M. Brack2f2a6632004-08-20 23:09:47 +000018615 /* go up to parents->next if needed */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018616 while (cur != top) {
18617 if (cur->parent != NULL)
18618 cur = cur->parent;
18619 if ((cur != top) && (cur->next != NULL)) {
18620 cur = cur->next;
William M. Brack2f2a6632004-08-20 23:09:47 +000018621 break;
18622 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018623 if (cur->parent == NULL) {
18624 cur = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +000018625 break;
18626 }
18627 }
18628 /* exit condition */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018629 if (cur == top)
18630 cur = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +000018631 } else
18632 break;
18633 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018634 ctxt->type = oldtype;
William M. Brack2f2a6632004-08-20 23:09:47 +000018635 return (0);
18636}
18637
18638/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018639 * xmlSchemaValidateElementByComplexType:
Daniel Veillard4255d502002-04-16 15:50:10 +000018640 * @ctxt: a schema validation context
18641 * @node: the top node.
18642 *
18643 * Validate the content of an element expected to be a complex type type
18644 * xmlschema-1.html#cvc-complex-type
18645 * Validation Rule: Element Locally Valid (Complex Type)
18646 *
18647 * Returns 0 if the element is schemas valid, a positive error code
Daniel Veillard01fa6152004-06-29 17:04:39 +000018648 * number otherwise and -1 in case of internal or API error.
18649 * Note on reported errors: Although it might be nice to report
18650 * the name of the simple/complex type, used to validate the content
18651 * of a node, it is quite unnecessary: for global defined types
18652 * the local name of the element is equal to the NCName of the type,
18653 * for local defined types it makes no sense to output the internal
18654 * computed name of the type. TODO: Instead, one should attach the
18655 * struct of the type involved to the error handler - this allows
18656 * the report of any additional information by the user.
Daniel Veillard4255d502002-04-16 15:50:10 +000018657 */
18658static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018659xmlSchemaValidateElementByComplexType(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018660 xmlSchemaTypePtr type,
18661 int valSimpleContent)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018662{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018663 xmlSchemaTypePtr oldtype;
18664 xmlNodePtr elem, child;
Daniel Veillard01fa6152004-06-29 17:04:39 +000018665 int ret = 0;
William M. Brack2f2a6632004-08-20 23:09:47 +000018666 const xmlChar *nsUri;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018667 xmlSchemaAttrStatePtr attrs = NULL, attrTop = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000018668
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018669 if ((ctxt == NULL) || (type->type != XML_SCHEMA_TYPE_COMPLEX))
18670 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000018671
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018672 oldtype = ctxt->type;
18673 ctxt->type = type;
18674 elem = ctxt->node;
18675
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018676 /*
18677 * Verify the attributes
18678 */
18679 /*
18680 * TODO: This "attrTop" thing is not needed any more.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018681 */
18682 /* NOTE: removed, since a check for abstract is
18683 * done in the cvc-type constraint.
18684 *
18685 *
18686 * if (type->flags & XML_SCHEMAS_TYPE_ABSTRACT) {
18687 * xmlSchemaVComplexTypeErr(ctxt,
18688 * XML_SCHEMAV_CVC_COMPLEX_TYPE_1,
18689 * elem, type,
18690 * "The type definition is abstract");
18691 * return (XML_SCHEMAV_CVC_COMPLEX_TYPE_1);
18692 *}
18693 */
18694
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018695 attrs = ctxt->attr;
18696 attrTop = ctxt->attrTop;
18697 /*
18698 * STREAM: Attribute nodes are processed.
18699 */
18700 xmlSchemaRegisterAttributes(ctxt, elem->properties);
18701 xmlSchemaValidateAttributes(ctxt, elem, type);
18702 if (ctxt->attr != NULL)
18703 xmlSchemaFreeAttributeStates(ctxt->attr);
18704 ctxt->attr = attrs;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018705 ctxt->attrTop = attrTop;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018706
18707 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018708 * TODO: This one creates a regexp even if no content
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018709 * model was defined. Somehow ->contModel is always not NULL
18710 * for complex types, even if they are empty.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018711 * TODO: Check if the obove still occurs.
18712 */
Daniel Veillard4255d502002-04-16 15:50:10 +000018713 switch (type->contentType) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000018714 case XML_SCHEMA_CONTENT_EMPTY: {
18715 /*
18716 * 1 If the {content type} is empty, then the element information
18717 * item has no character or element information item [children].
Daniel Veillard3646d642004-06-02 19:19:14 +000018718 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000018719 /*
18720 * TODO: Is the entity stuff correct?
18721 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018722 if (xmlSchemaHasElemOrCharContent(elem) == 1) {
William M. Brack2f2a6632004-08-20 23:09:47 +000018723 xmlSchemaVComplexTypeErr(ctxt,
18724 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018725 elem, type,
William M. Brack2f2a6632004-08-20 23:09:47 +000018726 "Character or element content is not allowed, "
18727 "because the content type is empty");
Daniel Veillard01fa6152004-06-29 17:04:39 +000018728 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018729 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +000018730 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018731 case XML_SCHEMA_CONTENT_MIXED:
18732 if ((type->subtypes == NULL) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018733 (type->baseType->builtInType == XML_SCHEMAS_ANYTYPE)) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018734 /*
18735 * The type has 'anyType' as its base and no content model
18736 * is defined -> use 'anyType' as the type to validate
18737 * against.
18738 */
18739 ret = xmlSchemaValidateElementByAnyType(ctxt, type->baseType);
18740 /* TODO: Handle -1. */
18741 break;
18742 }
18743 /* No break on purpose. */
Daniel Veillard01fa6152004-06-29 17:04:39 +000018744 case XML_SCHEMA_CONTENT_ELEMENTS:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018745 {
18746 xmlRegExecCtxtPtr oldregexp = NULL;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000018747 xmlChar *values[10];
18748 int terminal, nbval = 10, nbneg;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018749
18750 /*
18751 * Content model check initialization.
18752 */
18753 if (type->contModel != NULL) {
18754 oldregexp = ctxt->regexp;
18755 ctxt->regexp = xmlRegNewExecCtxt(type->contModel,
18756 (xmlRegExecCallbacks)
18757 xmlSchemaValidateCallback, ctxt);
18758#ifdef DEBUG_AUTOMATA
18759 xmlGenericError(xmlGenericErrorContext, "====> %s\n", elem->name);
18760#endif
18761 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018762 /*
18763 * STREAM: Children are processed.
18764 */
18765 child = elem->children;
Daniel Veillard01fa6152004-06-29 17:04:39 +000018766 while (child != NULL) {
18767 if (child->type == XML_ELEMENT_NODE) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000018768 if (child->ns != NULL)
18769 nsUri = child->ns->href;
18770 else
18771 nsUri = NULL;
18772 ret = xmlRegExecPushString2(ctxt->regexp,
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000018773 child->name, nsUri, child);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018774 /*
18775 * URGENT TODO: Could we anchor an error report
18776 * here to notify of invalid elements?
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000018777 * TODO: Perhaps it would be better to report
18778 * only the first erroneous element and then break.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018779 */
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000018780#ifdef DEBUG_AUTOMATA
Daniel Veillard01fa6152004-06-29 17:04:39 +000018781 if (ret < 0)
18782 xmlGenericError(xmlGenericErrorContext,
18783 " --> %s Error\n", child->name);
William M. Bracke7091952004-05-11 15:09:58 +000018784 else
18785 xmlGenericError(xmlGenericErrorContext,
Daniel Veillard01fa6152004-06-29 17:04:39 +000018786 " --> %s\n", child->name);
18787#endif
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000018788 if (ret < 0) {
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000018789 xmlRegExecErrInfo(ctxt->regexp, NULL, &nbval, &nbneg,
18790 &values[0], &terminal);
18791 xmlSchemaVComplexTypeElemErr(ctxt,
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000018792 XML_SCHEMAV_ELEMENT_CONTENT,
18793 child, NULL/* type */,
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000018794 "This element is not expected",
18795 nbval, nbneg, values);
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000018796 ret = 1;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000018797 /*
18798 * Note that this will skip further validation of the
18799 * content.
18800 */
18801 break;
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000018802 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000018803 } else if ((type->contentType == XML_SCHEMA_CONTENT_ELEMENTS) &&
18804 /*
18805 * TODO: Ask Daniel if this are all character nodes.
18806 */
18807 (((child->type == XML_TEXT_NODE) && (!IS_BLANK_NODE(child))) ||
18808 (child->type == XML_ENTITY_NODE) ||
18809 (child->type == XML_ENTITY_REF_NODE) ||
18810 (child->type == XML_CDATA_SECTION_NODE))) {
18811 /*
18812 * 2.3 If the {content type} is element-only, then the
18813 * element information item has no character information
18814 * item [children] other than those whose [character
18815 * code] is defined as a white space in [XML 1.0 (Second
18816 * Edition)].
18817 */
William M. Brack2f2a6632004-08-20 23:09:47 +000018818 xmlSchemaVComplexTypeErr(ctxt,
18819 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_3,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018820 elem, type,
William M. Brack2f2a6632004-08-20 23:09:47 +000018821 "Character content is not allowed, "
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000018822 "because the content type is element-only");
18823 ret = 1;
Daniel Veillard01fa6152004-06-29 17:04:39 +000018824 break;
18825 }
18826 child = child->next;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018827 }
18828 /*
18829 * Content model check finalization.
18830 */
18831 if (type->contModel != NULL) {
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000018832 if (ret == 0) {
18833 xmlRegExecNextValues(ctxt->regexp, &nbval, &nbneg,
18834 &values[0], &terminal);
18835 if (nbval + nbneg != 0) {
18836 /*
18837 * If a next value still exists, I does not have to
18838 * mean that there's an element missing, since it
18839 * might be an optional element. So double check it.
18840 */
18841 ret = xmlRegExecPushString(ctxt->regexp,
18842 NULL, NULL);
18843 if (ret <= 0) {
18844 ret = 1;
18845 xmlSchemaVComplexTypeElemErr(ctxt,
18846 XML_SCHEMAV_ELEMENT_CONTENT,
18847 elem, type, "Missing child element(s)",
18848 nbval, nbneg, values);
18849 } else
18850 ret = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018851#ifdef DEBUG_AUTOMATA
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000018852 xmlGenericError(xmlGenericErrorContext,
18853 "====> %s : %d\n", elem->name, ret);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018854#endif
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000018855 }
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000018856#ifdef DEBUG_CONTENT
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000018857 if (ret == 0)
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000018858 xmlGenericError(xmlGenericErrorContext,
18859 "Element %s content check succeeded\n",
18860 elem->name);
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000018861#endif
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018862 }
18863 xmlRegFreeExecCtxt(ctxt->regexp);
18864 ctxt->regexp = oldregexp;
18865 }
18866 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000018867 break;
18868 case XML_SCHEMA_CONTENT_SIMPLE:
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018869 case XML_SCHEMA_CONTENT_BASIC:
18870 /*
18871 * If the simple content was already validated
18872 * (e.g. a default value), the content need not
18873 * to be validated again.
18874 */
18875 if (valSimpleContent == 1) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000018876 xmlChar *value = NULL;
18877 /*
18878 * We hit a complexType with a simpleContent resolving
18879 * to a user derived or built-in simple type.
William M. Brack2f2a6632004-08-20 23:09:47 +000018880 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000018881 /*
18882 * 2.2 If the {content type} is a simple type definition,
18883 * then the element information item has no element
18884 * information item [children], and the ·normalized value·
18885 * of the element information item is ·valid· with respect
18886 * to that simple type definition as defined by String
18887 * Valid (§3.14.4).
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018888 */
18889 /*
18890 * STREAM: Children are processed.
18891 */
18892 child = elem->children;
Daniel Veillard01fa6152004-06-29 17:04:39 +000018893 while (child != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018894 /*
18895 * TODO: Could the entity stuff produce elements
18896 * as well?
18897 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000018898 if (child->type == XML_ELEMENT_NODE) {
William M. Brack2f2a6632004-08-20 23:09:47 +000018899 xmlSchemaVComplexTypeErr(ctxt,
18900 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018901 elem, type,
William M. Brack2f2a6632004-08-20 23:09:47 +000018902 "Element content is not allowed, because "
18903 "the content type is a simple type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000018904 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
18905 break;
18906 }
18907 child = child->next;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018908 }
18909 ctxt->node = elem;
18910 ctxt->cur = elem->children;
Daniel Veillard01fa6152004-06-29 17:04:39 +000018911 if (ret == 0) {
18912 /*
18913 * Validate the character content against a simple type.
Daniel Veillard3646d642004-06-02 19:19:14 +000018914 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018915 /*
18916 * STREAM: Children are processed.
18917 */
18918 if (elem->children == NULL)
Daniel Veillard01fa6152004-06-29 17:04:39 +000018919 value = NULL;
18920 else
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018921 value = xmlNodeGetContent(elem);
18922 /*
18923 * URGENT TODO: Should facets for the simple type validation be
18924 * disabled, if the derivation of facets for complex types
18925 * is implemented?
18926 */
18927 /*
18928 * NOTE: This call won't check the correct types of the
18929 * content nodes, since this should be done here.
18930 */
18931 ret = xmlSchemaValidateSimpleTypeValue(ctxt, type, value, 1, 1, 1, 0);
William M. Brack2f2a6632004-08-20 23:09:47 +000018932 if (ret > 0) {
18933 /*
18934 * NOTE: Although an error will be reported by
18935 * xmlSchemaValidateSimpleTypeValue, the spec wants
18936 * a specific complex type error to be reported
18937 * additionally.
18938 */
18939 xmlSchemaVComplexTypeErr(ctxt,
18940 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018941 elem, type,
William M. Brack2f2a6632004-08-20 23:09:47 +000018942 "The character content is not valid");
Daniel Veillard01fa6152004-06-29 17:04:39 +000018943 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
18944 } else if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018945 xmlSchemaVErr(ctxt, elem, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000018946 "Internal error: xmlSchemaValidateComplexType, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000018947 "Element '%s': Error while validating character "
18948 "content against complex type '%s'.\n",
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018949 elem->name, type->name);
18950 if (value != NULL)
18951 xmlFree(value);
18952 ctxt->type = oldtype;
Daniel Veillard01fa6152004-06-29 17:04:39 +000018953 return (-1);
18954 }
William M. Brack2f2a6632004-08-20 23:09:47 +000018955 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000018956 if (ret == 0) {
18957 /*
18958 * Apply facets of the complexType. Be sure to pass the
18959 * built-in type to xmlSchemaValidateFacetsInternal.
18960 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018961 /* URGENT TODO: I don't know yet if the facets of the simple type
Daniel Veillard01fa6152004-06-29 17:04:39 +000018962 * are used, or if the facets, defined by this complex type,
18963 * are to be used only. This here applies both facet sets.
18964 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000018965
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018966 ret = xmlSchemaValidateFacetsInternal(ctxt,
18967 type, value, 0, 1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000018968 if (ret > 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +000018969 xmlSchemaVComplexTypeErr(ctxt,
18970 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018971 elem, type,
William M. Brack2f2a6632004-08-20 23:09:47 +000018972 "The character content is not valid");
Daniel Veillard01fa6152004-06-29 17:04:39 +000018973 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
18974 } else if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018975 xmlSchemaVErr(ctxt, elem, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000018976 "Internal error: xmlSchemaValidateComplexType, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000018977 "Element '%s': Error while validating character "
18978 "content against complex type '%s'; failed to "
Daniel Veillard01fa6152004-06-29 17:04:39 +000018979 "apply facets.\n",
18980 type->name, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018981 if (value != NULL)
18982 xmlFree(value);
18983 ctxt->type = oldtype;
18984 return (-1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000018985 }
18986 }
18987 if (value != NULL)
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000018988 xmlFree(value);
18989
Daniel Veillard01fa6152004-06-29 17:04:39 +000018990 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018991 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018992 default:
18993 TODO xmlGenericError(xmlGenericErrorContext,
18994 "unimplemented content type %d\n",
18995 type->contentType);
Daniel Veillard4255d502002-04-16 15:50:10 +000018996 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018997 ctxt->type = oldtype;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018998 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000018999}
19000
19001/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019002 * xmlSchemaValidateElementByType:
Daniel Veillard4255d502002-04-16 15:50:10 +000019003 * @ctxt: a schema validation context
19004 * @elem: an element
19005 * @type: the list of type declarations
19006 *
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019007 * Validation Rule: Element Locally Valid (Type).
Daniel Veillard4255d502002-04-16 15:50:10 +000019008 *
19009 * Returns 0 if the element is schemas valid, a positive error code
19010 * number otherwise and -1 in case of internal or API error.
19011 */
19012static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019013xmlSchemaValidateElementByType(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019014 xmlSchemaTypePtr type,
19015 int valSimpleContent)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019016{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019017 int ret;
Daniel Veillard4255d502002-04-16 15:50:10 +000019018
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019019
19020 if ((ctxt == NULL) || (type == NULL)) {
19021 xmlSchemaVCustomErr(ctxt, XML_SCHEMAV_INTERNAL, NULL, NULL,
19022 "Internal error: xmlSchemaValidateElementByType, "
19023 "bad arguments", NULL);
19024 return (-1);
19025 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019026 /*
19027 * This one is called by "xmlSchemaValidateElementByDeclaration".
19028 * It will forward to the proper validation
19029 * procedures for the given type.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019030 */
19031 if (type == NULL) {
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000019032 xmlSchemaVCustomErr(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019033 XML_SCHEMAV_CVC_TYPE_1,
19034 ctxt->node, NULL,
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000019035 "The type definition is absent", NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019036 return (XML_SCHEMAV_CVC_TYPE_1);
19037 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019038
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019039 if (type->flags & XML_SCHEMAS_TYPE_ABSTRACT) {
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000019040 xmlSchemaVCustomErr(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019041 XML_SCHEMAV_CVC_TYPE_2,
19042 ctxt->node, type,
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000019043 "The type definition is abstract", NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019044 return (XML_SCHEMAV_CVC_TYPE_2);
19045 }
19046
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019047#ifdef ELEM_INFO_ENABLED
19048 ctxt->elemInfo->typeDef = type;
19049#endif
19050
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019051 switch (type->type) {
19052 case XML_SCHEMA_TYPE_COMPLEX:
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019053 ret = xmlSchemaValidateElementByComplexType(ctxt, type,
19054 valSimpleContent);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019055 break;
19056 case XML_SCHEMA_TYPE_SIMPLE:
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019057 ret = xmlSchemaValidateElementBySimpleType(ctxt, type,
19058 valSimpleContent);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019059 break;
19060 case XML_SCHEMA_TYPE_BASIC:
19061 if (type->builtInType == XML_SCHEMAS_ANYTYPE)
19062 ret = xmlSchemaValidateElementByAnyType(ctxt, type);
19063 else
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019064 ret = xmlSchemaValidateElementBySimpleType(ctxt, type,
19065 valSimpleContent);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019066 break;
19067 default:
19068 ret = -1;
19069 break;
19070 }
19071 if (ret == -1)
19072 return (-1);
19073 else
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019074 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000019075}
19076
19077
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019078static int
19079xmlSchemaCheckAttrLocallyValid(xmlSchemaValidCtxtPtr ctxt,
19080 xmlSchemaAttributePtr decl,
19081 xmlSchemaAttrStatePtr state,
19082 xmlAttrPtr attr)
19083{
19084 xmlChar *value;
19085 const xmlChar *defValue;
19086 xmlSchemaValPtr defVal;
19087 int fixed;
19088 int ret;
19089
19090 if (decl->subtypes == NULL) {
19091 state->state = XML_SCHEMAS_ATTR_TYPE_NOT_RESOLVED;
19092 return (XML_SCHEMAS_ATTR_TYPE_NOT_RESOLVED);
19093 }
19094 value = xmlNodeListGetString(attr->doc, attr->children, 1);
19095 ctxt->node = (xmlNodePtr) attr;
19096 ctxt->cur = attr->children;
19097 /*
19098 * NOTE: This call also checks the content nodes for correct type.
19099 */
19100 ret = xmlSchemaValidateSimpleTypeValue(ctxt, decl->subtypes,
19101 value, 1, 1, 1, 1);
19102
19103 /*
19104 * Handle 'fixed' attributes.
19105 */
19106 if (ret > 0) {
19107 state->state = XML_SCHEMAS_ATTR_INVALID_VALUE;
19108 /*
19109 * NOTE: Fixed value constraints will be not
19110 * applied if the value was invalid, because:
19111 * 1. The validation process does not return a precomputed
19112 * value.
19113 * 2. An invalid value implies a violation of a fixed
19114 * value constraint.
19115 */
19116 } else if (ret == 0) {
19117 state->state = XML_SCHEMAS_ATTR_CHECKED;
19118 if (xmlSchemaGetEffectiveValueConstraint(decl,
19119 &fixed, &defValue, &defVal) && (fixed == 1)) {
19120 /*
19121 * cvc-au : Attribute Locally Valid (Use)
19122 * For an attribute information item to be·valid·
19123 * with respect to an attribute use its ·normalized
19124 * value· must match the canonical lexical representation
19125 * of the attribute use's {value constraint} value, if it
19126 * is present and fixed.
19127 */
19128 /*
19129 * NOTE: the validation context holds in ctxt->value the
19130 * precomputed value of the attribute; well for some types,
19131 * fallback to string comparison if no computed value
19132 * exists.
19133 */
19134 if (((ctxt->value != NULL) &&
19135 (xmlSchemaCompareValues(ctxt->value, defVal) != 0)) ||
19136 ((ctxt->value == NULL) &&
19137 (! xmlStrEqual(defValue, BAD_CAST value)))) {
19138 state->state =
19139 XML_SCHEMAS_ATTR_INVALID_FIXED_VALUE;
19140 }
19141 }
19142 }
19143 if (value != NULL) {
19144 xmlFree(value);
19145 }
19146 return (ret);
19147}
19148
Daniel Veillard4255d502002-04-16 15:50:10 +000019149/**
19150 * xmlSchemaValidateAttributes:
19151 * @ctxt: a schema validation context
19152 * @elem: an element
Daniel Veillard3646d642004-06-02 19:19:14 +000019153 * @type: the complexType holding the attribute uses
Daniel Veillard4255d502002-04-16 15:50:10 +000019154 *
19155 * Validate the attributes of an element.
19156 *
Daniel Veillardc0826a72004-08-10 14:17:33 +000019157 * 1. Existent, invalid attributes are reported in the form
19158 * "prefix:localName".
19159 * Reason: readability - it is easier to find the actual XML
19160 * representation of the attributes QName.
19161 * 2. Missing attributes are reported in the form
19162 * {"URI", "localName"}.
19163 * This is necessary, since the the prefix need not to be declared
19164 * at all, and thus is not computable.
19165 *
Daniel Veillard4255d502002-04-16 15:50:10 +000019166 * Returns 0 if the element is schemas valid, a positive error code
19167 * number otherwise and -1 in case of internal or API error.
19168 */
19169static int
Daniel Veillard3646d642004-06-02 19:19:14 +000019170xmlSchemaValidateAttributes(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem, xmlSchemaTypePtr type)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019171{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019172 const xmlChar *nsURI;
Daniel Veillard3646d642004-06-02 19:19:14 +000019173 int ret;
19174 xmlAttrPtr attr; /* An attribute on the element. */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019175 const xmlChar *defValue;
19176 xmlSchemaValPtr defVal;
19177 int fixed;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019178 xmlSchemaAttributeLinkPtr attrUse = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000019179 xmlSchemaAttributePtr attrDecl;
Daniel Veillardc85d0fe2004-04-16 16:46:51 +000019180 int found;
William M. Brack803812b2004-06-03 02:11:24 +000019181 xmlSchemaAttrStatePtr curState, reqAttrStates = NULL, reqAttrStatesTop = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019182 xmlSchemaAttrStatePtr defAttrStates = NULL, defAttrStatesTop = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019183 xmlNodePtr oldnode;
Daniel Veillard3646d642004-06-02 19:19:14 +000019184#ifdef DEBUG_ATTR_VALIDATION
19185 int redundant = 0;
19186#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000019187
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019188
Daniel Veillardc0826a72004-08-10 14:17:33 +000019189 /*
19190 * Allow all attributes if the type is anyType.
19191 */
19192 if (type == xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE))
19193 return (0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019194
19195 oldnode = ctxt->node;
19196 if (type != NULL)
19197 attrUse = type->attributeUses;
Daniel Veillard3646d642004-06-02 19:19:14 +000019198 while (attrUse != NULL) {
Daniel Veillardc85d0fe2004-04-16 16:46:51 +000019199 found = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000019200 attrDecl = attrUse->attr;
19201#ifdef DEBUG_ATTR_VALIDATION
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019202 printf("attr use - name: %s\n", xmlSchemaGetAttrName(attrDecl));
Daniel Veillard3646d642004-06-02 19:19:14 +000019203 printf("attr use - use: %d\n", attrDecl->occurs);
19204#endif
19205 for (curState = ctxt->attr; curState != NULL; curState = curState->next) {
19206
19207 if (curState->decl == attrUse->attr) {
19208#ifdef DEBUG_ATTR_VALIDATION
19209 redundant = 1;
19210#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019211 }
Daniel Veillard3646d642004-06-02 19:19:14 +000019212 attr = curState->attr;
19213#ifdef DEBUG_ATTR_VALIDATION
19214 printf("attr - name: %s\n", attr->name);
19215 if (attr->ns != NULL)
19216 printf("attr - ns: %s\n", attr->ns->href);
19217 else
19218 printf("attr - ns: none\n");
19219#endif
19220 /* TODO: Can this ever happen? */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019221 if (attr == NULL)
19222 continue;
Daniel Veillard3646d642004-06-02 19:19:14 +000019223 if (attrDecl->ref != NULL) {
19224 if (!xmlStrEqual(attr->name, attrDecl->ref))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019225 continue;
19226 if (attr->ns != NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +000019227 if ((attrDecl->refNs == NULL) ||
19228 (!xmlStrEqual(attr->ns->href, attrDecl->refNs)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019229 continue;
Daniel Veillard3646d642004-06-02 19:19:14 +000019230 } else if (attrDecl->refNs != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019231 continue;
19232 }
19233 } else {
Daniel Veillard3646d642004-06-02 19:19:14 +000019234 if (!xmlStrEqual(attr->name, attrDecl->name))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019235 continue;
19236 /*
Daniel Veillardbe9c6322003-11-22 20:37:51 +000019237 * handle the namespaces checks here
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019238 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +000019239 if (attr->ns == NULL) {
19240 /*
William M. Bracke7091952004-05-11 15:09:58 +000019241 * accept an unqualified attribute only if the target
19242 * namespace of the declaration is absent.
Daniel Veillardbe9c6322003-11-22 20:37:51 +000019243 */
Daniel Veillard3646d642004-06-02 19:19:14 +000019244 if (attrDecl->targetNamespace != NULL)
William M. Bracke7091952004-05-11 15:09:58 +000019245 /*
19246 * This check was removed, since the target namespace
19247 * was evaluated during parsing and already took
19248 * "attributeFormDefault" into account.
19249 */
19250 /* ((attributes->flags & XML_SCHEMAS_ATTR_NSDEFAULT) == 0)) */
Daniel Veillardbe9c6322003-11-22 20:37:51 +000019251 continue;
19252 } else {
Daniel Veillard3646d642004-06-02 19:19:14 +000019253 if (attrDecl->targetNamespace == NULL)
Daniel Veillardbe9c6322003-11-22 20:37:51 +000019254 continue;
Daniel Veillard3646d642004-06-02 19:19:14 +000019255 if (!xmlStrEqual(attrDecl->targetNamespace,
Daniel Veillardbe9c6322003-11-22 20:37:51 +000019256 attr->ns->href))
19257 continue;
19258 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019259 }
Daniel Veillard3646d642004-06-02 19:19:14 +000019260#ifdef DEBUG_ATTR_VALIDATION
19261 printf("found\n");
19262#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019263 found = 1;
Daniel Veillard3646d642004-06-02 19:19:14 +000019264 curState->decl = attrDecl;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019265 ret = xmlSchemaCheckAttrLocallyValid(ctxt, attrDecl, curState, attr);
Daniel Veillard3646d642004-06-02 19:19:14 +000019266 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019267 if (!found) {
19268 if (attrDecl->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED) {
19269 xmlSchemaAttrStatePtr tmp;
19270
Daniel Veillard3646d642004-06-02 19:19:14 +000019271#ifdef DEBUG_ATTR_VALIDATION
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019272 printf("required attr not found\n");
Daniel Veillard3646d642004-06-02 19:19:14 +000019273#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019274 /*
19275 * Add a new dummy attribute state.
19276 */
19277 tmp = (xmlSchemaAttrStatePtr) xmlMalloc(sizeof(xmlSchemaAttrState));
19278 if (tmp == NULL) {
19279 xmlSchemaVErrMemory(ctxt, "registering required attributes", NULL);
19280 ctxt->node = oldnode;
19281 return (-1);
19282 }
19283 tmp->attr = NULL;
19284 tmp->state = XML_SCHEMAS_ATTR_MISSING;
19285 tmp->decl = attrDecl;
19286 tmp->next = NULL;
19287
19288 if (reqAttrStates == NULL) {
19289 reqAttrStates = tmp;
19290 reqAttrStatesTop = tmp;
19291 } else {
19292 reqAttrStatesTop->next = tmp;
19293 reqAttrStatesTop = tmp;
19294 }
19295 } else if ((attrDecl->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
19296 (xmlSchemaGetEffectiveValueConstraint(attrDecl,
19297 &fixed, &defValue, &defVal))) {
19298 xmlSchemaAttrStatePtr tmp;
19299 /*
19300 * Handle non existent default/fixed attributes.
19301 */
19302 tmp = (xmlSchemaAttrStatePtr)
19303 xmlMalloc(sizeof(xmlSchemaAttrState));
19304 if (tmp == NULL) {
19305 xmlSchemaVErrMemory(ctxt,
19306 "registering schema specified attributes", NULL);
19307 ctxt->node = oldnode;
19308 return (-1);
19309 }
19310 tmp->attr = NULL;
19311 tmp->state = XML_SCHEMAS_ATTR_DEFAULT;
19312 tmp->decl = attrDecl;
19313 tmp->value = defValue;
19314 tmp->next = NULL;
19315
19316 if (defAttrStates == NULL) {
19317 defAttrStates = tmp;
19318 defAttrStates = tmp;
19319 } else {
19320 defAttrStates->next = tmp;
19321 defAttrStatesTop = tmp;
19322 }
19323 }
Daniel Veillard3646d642004-06-02 19:19:14 +000019324 }
19325 attrUse = attrUse->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000019326 }
Daniel Veillard3646d642004-06-02 19:19:14 +000019327 /*
19328 * Add required attributes to the attribute states of the context.
19329 */
19330 if (reqAttrStates != NULL) {
19331 if (ctxt->attr == NULL) {
19332 ctxt->attr = reqAttrStates;
19333 } else {
19334 ctxt->attrTop->next = reqAttrStates;
19335 }
19336 ctxt->attrTop = reqAttrStatesTop;
Daniel Veillardc0826a72004-08-10 14:17:33 +000019337 }
Daniel Veillard3646d642004-06-02 19:19:14 +000019338 /*
19339 * Process wildcards.
19340 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019341
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019342 if ((type != NULL) && (type->attributeWildcard != NULL)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000019343#ifdef DEBUG_ATTR_VALIDATION
19344 xmlSchemaWildcardNsPtr ns;
19345 printf("matching wildcard: [%d] of complexType: %s\n", type->attributeWildcard, type->name);
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000019346 if (type->attributeWildcard->processContents ==
19347 XML_SCHEMAS_ANY_LAX)
19348 printf("processContents: lax\n");
19349 else if (type->attributeWildcard->processContents ==
19350 XML_SCHEMAS_ANY_STRICT)
19351 printf("processContents: strict\n");
19352 else
19353 printf("processContents: skip\n");
Daniel Veillard3646d642004-06-02 19:19:14 +000019354 if (type->attributeWildcard->any)
19355 printf("type: any\n");
19356 else if (type->attributeWildcard->negNsSet != NULL) {
19357 printf("type: negated\n");
19358 if (type->attributeWildcard->negNsSet->value == NULL)
19359 printf("ns: (absent)\n");
19360 else
19361 printf("ns: %s\n", type->attributeWildcard->negNsSet->value);
19362 } else if (type->attributeWildcard->nsSet != NULL) {
19363 printf("type: set\n");
19364 ns = type->attributeWildcard->nsSet;
19365 while (ns != NULL) {
19366 if (ns->value == NULL)
19367 printf("ns: (absent)\n");
19368 else
19369 printf("ns: %s\n", ns->value);
19370 ns = ns->next;
19371 }
19372 } else
19373 printf("empty\n");
19374
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000019375
19376#endif
Daniel Veillard3646d642004-06-02 19:19:14 +000019377 curState = ctxt->attr;
19378 while (curState != NULL) {
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000019379 if (curState->state == XML_SCHEMAS_ATTR_UNKNOWN) {
19380 if (curState->attr->ns != NULL)
19381 nsURI = curState->attr->ns->href;
19382 else
19383 nsURI = NULL;
19384 if (xmlSchemaMatchesWildcardNs(type->attributeWildcard,
19385 nsURI)) {
19386 /*
19387 * Handle processContents.
19388 */
19389 if ((type->attributeWildcard->processContents ==
19390 XML_SCHEMAS_ANY_LAX) ||
19391 (type->attributeWildcard->processContents ==
19392 XML_SCHEMAS_ANY_STRICT)) {
19393
19394 attr = curState->attr;
19395 attrDecl = xmlSchemaGetAttribute(ctxt->schema,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019396 attr->name, nsURI);
19397 curState->decl = attrDecl;
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000019398 if (attrDecl != NULL) {
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000019399 curState->decl = attrDecl;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019400 ret = xmlSchemaCheckAttrLocallyValid(ctxt, attrDecl, curState, attr);
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000019401 } else if (type->attributeWildcard->processContents ==
19402 XML_SCHEMAS_ANY_LAX) {
19403 curState->state = XML_SCHEMAS_ATTR_CHECKED;
19404 }
19405 } else
Daniel Veillard3646d642004-06-02 19:19:14 +000019406 curState->state = XML_SCHEMAS_ATTR_CHECKED;
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000019407 }
19408 }
Daniel Veillard3646d642004-06-02 19:19:14 +000019409 curState = curState->next;
19410 }
19411 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019412
Daniel Veillardc0826a72004-08-10 14:17:33 +000019413 /*
19414 * Report missing and illegal attributes.
19415 */
19416 if (ctxt->attr != NULL) {
19417 curState = ctxt->attr;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019418 while ((curState != NULL) && (curState != ctxt->attrTop->next)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000019419 if (curState->state != XML_SCHEMAS_ATTR_CHECKED) {
19420 attr = curState->attr;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019421 if (curState->decl != NULL) {
19422 if (curState->decl->ref != NULL)
19423 attrDecl = curState->decl->refDecl;
19424 else
19425 attrDecl = curState->decl;
19426 } else
19427 attrDecl = NULL;
19428 if (curState->state == XML_SCHEMAS_ATTR_MISSING) {
19429 xmlSchemaVMissingAttrErr(ctxt, elem, attrDecl);
19430 } else if (curState->state ==
19431 XML_SCHEMAS_ATTR_TYPE_NOT_RESOLVED) {
19432 xmlSchemaVCustomErr(ctxt,
19433 XML_SCHEMAV_CVC_ATTRIBUTE_2,
19434 (xmlNodePtr) attr,
19435 (xmlSchemaTypePtr) attrDecl,
19436 "The type definition is absent",
19437 NULL);
19438 } else if (curState->state ==
19439 XML_SCHEMAS_ATTR_INVALID_FIXED_VALUE) {
19440 xmlSchemaVCustomErr(ctxt,
19441 XML_SCHEMAV_CVC_AU,
19442 (xmlNodePtr) attr, (xmlSchemaTypePtr) attrDecl,
19443 "The value does not match the fixed value "
19444 "constraint", NULL);
19445 } else if (curState->state == XML_SCHEMAS_ATTR_UNKNOWN) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000019446 /* TODO: "prohibited" won't ever be touched here!.
19447 (curState->state == XML_SCHEMAS_ATTR_PROHIBITED))
19448 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019449 /*
19450 * TODO: One might report different error messages
19451 * for the following errors.
19452 */
19453 if ((type == NULL) || (type->attributeWildcard == NULL)) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000019454 xmlSchemaVIllegalAttrErr(ctxt,
19455 XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_1, attr);
19456 } else {
19457 xmlSchemaVIllegalAttrErr(ctxt,
19458 XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_2, attr);
19459 }
19460 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000019461 }
19462 curState = curState->next;
19463 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019464 }
19465
19466 /*
19467 * Add missing default/fixed attributes.
19468 */
19469 if (ctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) {
19470 curState = defAttrStates;
19471 while (curState != NULL) {
19472 attrDecl = curState->decl;
19473 if (attrDecl->ref != NULL)
19474 attrDecl = attrDecl->refDecl;
19475 /*
19476 * PSVI: Add a new attribute node to the current element.
19477 */
19478 if (attrDecl->targetNamespace == NULL) {
19479 xmlNewProp(elem, attrDecl->name, curState->value);
19480 } else {
19481 xmlNsPtr ns;
19482
19483 ns = xmlSearchNsByHref(elem->doc, elem,
19484 attrDecl->targetNamespace);
19485 if (ns == NULL) {
19486 xmlChar prefix[12];
19487 int counter = 1;
19488
19489 attr = curState->attr;
19490 /*
19491 * Create a namespace declaration on the validation
19492 * root node if no namespace declaration is in scope.
19493 */
19494 snprintf((char *) prefix, sizeof(prefix), "p");
19495 /*
19496 * This is somehow not performant, since the ancestor
19497 * axis beyond @elem will be searched as well.
19498 */
19499 ns = xmlSearchNs(elem->doc, elem, BAD_CAST prefix);
19500 while (ns != NULL) {
19501 if (counter > 1000) {
19502 xmlSchemaVErr(ctxt, (xmlNodePtr) attr,
19503 XML_SCHEMAV_INTERNAL,
19504 "Internal error: xmlSchemaValidateAttributes, "
19505 "could not compute a ns prefix for "
19506 "default/fixed attribute '%s'.\n",
19507 attrDecl->name, NULL);
19508
19509 break;
19510 }
19511 snprintf((char *) prefix,
19512 sizeof(prefix), "p%d", counter++);
19513 ns = xmlSearchNs(elem->doc, elem,
19514 BAD_CAST prefix);
19515 }
19516 if (ns == NULL) {
19517 ns = xmlNewNs(ctxt->validationRoot,
19518 attrDecl->targetNamespace, BAD_CAST prefix);
19519 xmlNewNsProp(elem, ns, attrDecl->name,
19520 curState->value);
19521 }
19522 } else {
19523 xmlNewNsProp(elem, ns, attrDecl->name,
19524 curState->value);
19525 }
19526 }
19527 curState = curState->next;
19528 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000019529 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019530 if (defAttrStates != NULL)
19531 xmlSchemaFreeAttributeStates(defAttrStates);
19532
Daniel Veillard3646d642004-06-02 19:19:14 +000019533#ifdef DEBUG_ATTR_VALIDATION
19534 if (redundant)
19535 xmlGenericError(xmlGenericErrorContext,
19536 "xmlSchemaValidateAttributes: redundant call by type: %s\n",
19537 type->name);
19538#endif
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019539 ctxt->node = oldnode;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019540 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000019541}
19542
19543/**
19544 * xmlSchemaValidateElement:
19545 * @ctxt: a schema validation context
19546 * @elem: an element
19547 *
19548 * Validate an element in a tree
19549 *
19550 * Returns 0 if the element is schemas valid, a positive error code
19551 * number otherwise and -1 in case of internal or API error.
19552 */
19553static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019554xmlSchemaValidateElement(xmlSchemaValidCtxtPtr ctxt)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019555{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019556 xmlSchemaElementPtr elemDecl;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019557 int ret = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000019558
Daniel Veillardc0826a72004-08-10 14:17:33 +000019559 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019560 * This one is called by xmlSchemaValidateDocument and
19561 * xmlSchemaValidateOneElement.
19562 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019563 if (ctxt->schema == NULL) {
19564 /*
19565 * No schema was specified at time of creation of the validation
19566 * context. Use xsi:schemaLocation and xsi:noNamespaceSchemaLocation
19567 * of the instance to build a schema.
19568 */
19569 if (ctxt->pctxt == NULL)
19570 ctxt->pctxt = xmlSchemaNewParserCtxt("*");
19571 if (ctxt->pctxt == NULL)
19572 return (-1);
19573 ctxt->schema = xmlSchemaNewSchema(ctxt->pctxt);
19574 if (ctxt->schema == NULL)
19575 return (-1);
19576 /* TODO: assign user data. */
19577 ctxt->pctxt->error = ctxt->error;
19578 ctxt->pctxt->warning = ctxt->warning;
19579 ctxt->xsiAssemble = 1;
19580 } else
19581 ctxt->xsiAssemble = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019582 /*
19583 * Assemble new schemata using xsi.
Daniel Veillardc0826a72004-08-10 14:17:33 +000019584 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019585 if (ctxt->xsiAssemble) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019586 ret = xmlSchemaAssembleByXSIElem(ctxt, ctxt->node);
19587 if (ret == -1) {
19588 xmlSchemaVCustomErr(ctxt,
19589 XML_SCHEMAV_INTERNAL,
19590 ctxt->node, NULL,
19591 "Internal error: xmlSchemaValidateElement, "
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019592 "assembling schema by xsi", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019593 }
19594 /*
19595 * NOTE: We won't react on schema parser errors here.
19596 * TODO: But a warning would be nice.
19597 */
19598 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019599 if (ret != -1) {
19600 if (ctxt->node->ns != NULL)
19601 elemDecl = xmlSchemaGetElem(ctxt->schema, ctxt->node->name,
19602 ctxt->node->ns->href);
19603 else
19604 elemDecl = xmlSchemaGetElem(ctxt->schema, ctxt->node->name, NULL);
19605
19606 if (elemDecl == NULL) {
19607 xmlSchemaVCustomErr(ctxt,
19608 XML_SCHEMAV_CVC_ELT_1,
19609 ctxt->node, NULL,
19610 "No matching global declaration available", NULL);
19611 ret = XML_SCHEMAV_CVC_ELT_1;
19612 } else {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019613#ifdef ELEM_INFO_ENABLED
19614 ctxt->depth = -1;
19615 xmlSchemaBeginElement(ctxt);
19616#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019617 ret = xmlSchemaValidateElementByDeclaration(ctxt, elemDecl);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019618#ifdef ELEM_INFO_ENABLED
19619 xmlSchemaEndElement(ctxt);
19620#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019621 if (ret < 0) {
19622 xmlSchemaVCustomErr(ctxt,
19623 XML_SCHEMAV_INTERNAL, ctxt->node, NULL,
19624 "Internal error: xmlSchemaValidateElement, "
19625 "calling validation by declaration", NULL);
19626 }
19627 }
19628 }
19629 /* ctxt->xsiAssemble = 0; */
19630 if (ctxt->xsiAssemble) {
19631 if (ctxt->schema != NULL) {
19632 xmlSchemaFree(ctxt->schema);
19633 ctxt->schema = NULL;
19634 }
Daniel Veillard4255d502002-04-16 15:50:10 +000019635 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019636 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000019637}
19638
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019639
Daniel Veillard4255d502002-04-16 15:50:10 +000019640/**
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000019641 * xmlSchemaValidateOneElement:
19642 * @ctxt: a schema validation context
19643 * @elem: an element node
19644 *
19645 * Validate a branch of a tree, starting with the given @elem.
19646 *
19647 * Returns 0 if the element and its subtree is valid, a positive error
19648 * code number otherwise and -1 in case of an internal or API error.
19649 */
19650int
19651xmlSchemaValidateOneElement(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem)
19652{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019653 if ((ctxt == NULL) || (elem == NULL) || (elem->type != XML_ELEMENT_NODE))
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000019654 return (-1);
19655
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019656 if (ctxt->schema == NULL) {
19657 xmlSchemaVErr(ctxt, NULL,
19658 XML_SCHEMAV_INTERNAL,
19659 "API error: xmlSchemaValidateOneElement, "
19660 "no schema specified.\n", NULL, NULL);
19661 return (-1);
19662 }
19663
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000019664 ctxt->doc = elem->doc;
19665 ctxt->err = 0;
19666 ctxt->nberrors = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019667 ctxt->node = elem;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019668 ctxt->validationRoot = elem;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019669 return (xmlSchemaValidateElement(ctxt));
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000019670}
19671
19672/**
Daniel Veillard4255d502002-04-16 15:50:10 +000019673 * xmlSchemaValidateDocument:
19674 * @ctxt: a schema validation context
19675 * @doc: a parsed document tree
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019676 * @xsiAssemble: should schemata be added if requested by the instance?
Daniel Veillard4255d502002-04-16 15:50:10 +000019677 *
19678 * Validate a document tree in memory.
19679 *
19680 * Returns 0 if the document is schemas valid, a positive error code
19681 * number otherwise and -1 in case of internal or API error.
19682 */
19683static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019684xmlSchemaValidateDocument(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
19685{
Daniel Veillard4255d502002-04-16 15:50:10 +000019686 xmlNodePtr root;
Daniel Veillard01fa6152004-06-29 17:04:39 +000019687
Daniel Veillard4255d502002-04-16 15:50:10 +000019688 root = xmlDocGetRootElement(doc);
19689 if (root == NULL) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000019690 xmlSchemaVCustomErr(ctxt,
19691 XML_SCHEMAV_DOCUMENT_ELEMENT_MISSING,
19692 (xmlNodePtr) doc, NULL,
19693 "The document has no document element", NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019694 return (ctxt->err);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019695 }
Daniel Veillard4255d502002-04-16 15:50:10 +000019696 /*
19697 * Okay, start the recursive validation
19698 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019699 ctxt->node = root;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019700 ctxt->validationRoot = root;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019701 xmlSchemaValidateElement(ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +000019702
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019703 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000019704}
19705
19706/************************************************************************
19707 * *
19708 * SAX Validation code *
19709 * *
19710 ************************************************************************/
19711
19712/************************************************************************
19713 * *
19714 * Validation interfaces *
19715 * *
19716 ************************************************************************/
19717
19718/**
19719 * xmlSchemaNewValidCtxt:
19720 * @schema: a precompiled XML Schemas
19721 *
19722 * Create an XML Schemas validation context based on the given schema
19723 *
19724 * Returns the validation context or NULL in case of error
19725 */
19726xmlSchemaValidCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019727xmlSchemaNewValidCtxt(xmlSchemaPtr schema)
19728{
Daniel Veillard4255d502002-04-16 15:50:10 +000019729 xmlSchemaValidCtxtPtr ret;
19730
19731 ret = (xmlSchemaValidCtxtPtr) xmlMalloc(sizeof(xmlSchemaValidCtxt));
19732 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019733 xmlSchemaVErrMemory(NULL, "allocating validation context", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000019734 return (NULL);
19735 }
19736 memset(ret, 0, sizeof(xmlSchemaValidCtxt));
Daniel Veillardc0826a72004-08-10 14:17:33 +000019737 ret->schema = schema;
Daniel Veillard3646d642004-06-02 19:19:14 +000019738 ret->attrTop = NULL;
19739 ret->attr = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000019740 return (ret);
19741}
19742
19743/**
19744 * xmlSchemaFreeValidCtxt:
19745 * @ctxt: the schema validation context
19746 *
19747 * Free the resources associated to the schema validation context
19748 */
19749void
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019750xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt)
19751{
Daniel Veillard4255d502002-04-16 15:50:10 +000019752 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019753 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000019754 if (ctxt->attr != NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000019755 xmlSchemaFreeAttributeStates(ctxt->attr);
Daniel Veillard88c58912002-04-23 07:12:20 +000019756 if (ctxt->value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019757 xmlSchemaFreeValue(ctxt->value);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019758 if (ctxt->pctxt != NULL) {
19759 xmlSchemaFreeParserCtxt(ctxt->pctxt);
19760 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019761
19762#ifdef IDC_ENABLED
19763 if (ctxt->idcNodes != NULL) {
19764 int i;
19765 xmlSchemaPSVIIDCNodePtr item;
19766
19767 for (i = 0; i < ctxt->nbIdcNodes; i++) {
19768 item = ctxt->idcNodes[i];
19769 xmlFree(item->keys);
19770 xmlFree(item);
19771 }
19772 xmlFree(ctxt->idcNodes);
19773 }
19774
19775 if (ctxt->idcKeys != NULL) {
19776 int i;
19777 for (i = 0; i < ctxt->nbIdcKeys; i++)
19778 xmlSchemaIDCFreeKey(ctxt->idcKeys[i]);
19779 xmlFree(ctxt->idcKeys);
19780 }
19781
19782 if (ctxt->xpathStates != NULL)
19783 xmlSchemaFreeIDCStateObjList(ctxt->xpathStates);
19784 if (ctxt->xpathStatePool != NULL)
19785 xmlSchemaFreeIDCStateObjList(ctxt->xpathStatePool);
19786
19787 /*
19788 * Augmented IDC information.
19789 */
19790 if (ctxt->aidcs != NULL) {
19791 xmlSchemaIDCAugPtr cur = ctxt->aidcs, next;
19792 do {
19793 next = cur->next;
19794 xmlFree(cur);
19795 cur = next;
19796 } while (cur != NULL);
19797 }
19798#endif /* IDC_ENABLED */
19799#ifdef ELEM_INFO_ENABLED
19800 if (ctxt->elemInfos != NULL) {
19801 int i;
19802 xmlSchemaElemInfoPtr info;
19803
19804 for (i = 0; i < ctxt->sizeElemInfos; i++) {
19805 info = ctxt->elemInfos[i];
19806 if (info == NULL)
19807 continue;
19808 if (info->value != NULL)
19809 xmlSchemaFreeValue(info->value);
19810#ifdef IDC_ENABLED
19811 if (info->idcMatchers != NULL)
19812 xmlSchemaIDCFreeMatcherList(info->idcMatchers);
19813#endif
19814 /*
19815 * TODO: Free the IDC table if still existent.
19816 */
19817
19818 /*
19819 xmlFree(info->localName);
19820 if (info->namespaceName != NULL)
19821 xmlFree(info->namespaceName);
19822 */
19823 xmlFree(info);
19824 }
19825 xmlFree(ctxt->elemInfos);
19826 }
19827#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000019828 xmlFree(ctxt);
19829}
19830
19831/**
19832 * xmlSchemaSetValidErrors:
19833 * @ctxt: a schema validation context
19834 * @err: the error function
19835 * @warn: the warning function
Daniel Veillarda9b66d02002-12-11 14:23:49 +000019836 * @ctx: the functions context
Daniel Veillard4255d502002-04-16 15:50:10 +000019837 *
William M. Brack2f2a6632004-08-20 23:09:47 +000019838 * Set the error and warning callback informations
Daniel Veillard4255d502002-04-16 15:50:10 +000019839 */
19840void
19841xmlSchemaSetValidErrors(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019842 xmlSchemaValidityErrorFunc err,
19843 xmlSchemaValidityWarningFunc warn, void *ctx)
19844{
Daniel Veillard4255d502002-04-16 15:50:10 +000019845 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019846 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000019847 ctxt->error = err;
19848 ctxt->warning = warn;
19849 ctxt->userData = ctx;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019850 if (ctxt->pctxt != NULL)
19851 xmlSchemaSetParserErrors(ctxt->pctxt, err, warn, ctx);
Daniel Veillard4255d502002-04-16 15:50:10 +000019852}
19853
19854/**
Daniel Veillard259f0df2004-08-18 09:13:18 +000019855 * xmlSchemaGetValidErrors:
19856 * @ctxt: a XML-Schema validation context
19857 * @err: the error function result
19858 * @warn: the warning function result
19859 * @ctx: the functions context result
19860 *
19861 * Get the error and warning callback informations
19862 *
19863 * Returns -1 in case of error and 0 otherwise
19864 */
19865int
19866xmlSchemaGetValidErrors(xmlSchemaValidCtxtPtr ctxt,
19867 xmlSchemaValidityErrorFunc * err,
19868 xmlSchemaValidityWarningFunc * warn, void **ctx)
19869{
19870 if (ctxt == NULL)
19871 return (-1);
19872 if (err != NULL)
19873 *err = ctxt->error;
19874 if (warn != NULL)
19875 *warn = ctxt->warning;
19876 if (ctx != NULL)
19877 *ctx = ctxt->userData;
19878 return (0);
19879}
19880
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019881
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019882/**
Daniel Veillard6927b102004-10-27 17:29:04 +000019883 * xmlSchemaSetValidOptions:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019884 * @ctxt: a schema validation context
19885 * @options: a combination of xmlSchemaValidOption
19886 *
19887 * Sets the options to be used during the validation.
19888 *
19889 * Returns 0 in case of success, -1 in case of an
19890 * API error.
19891 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019892int
19893xmlSchemaSetValidOptions(xmlSchemaValidCtxtPtr ctxt,
19894 int options)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019895
19896{
19897 int i;
19898
19899 if (ctxt == NULL)
19900 return (-1);
19901 /*
19902 * WARNING: Change the start value if adding to the
19903 * xmlSchemaValidOption.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019904 * TODO: Is there an other, more easy to maintain,
19905 * way?
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019906 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019907 for (i = 1; i < (int) sizeof(int) * 8; i++) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019908 if (options & 1<<i) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019909 xmlSchemaVErr(ctxt, NULL,
19910 XML_SCHEMAV_INTERNAL,
19911 "Internal error: xmlSchemaSetValidOptions, "
19912 "invalid option argument.\n", NULL, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019913 return (-1);
19914 }
19915 }
19916 ctxt->options = options;
19917 return (0);
19918}
19919
19920/**
Daniel Veillard6927b102004-10-27 17:29:04 +000019921 * xmlSchemaValidCtxtGetOptions:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019922 * @ctxt: a schema validation context
19923 *
William M. Brack21e4ef22005-01-02 09:53:13 +000019924 * Get the validation context options.
19925 *
19926 * Returns the option combination or -1 on error.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019927 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019928int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019929xmlSchemaValidCtxtGetOptions(xmlSchemaValidCtxtPtr ctxt)
19930
19931{
19932 if (ctxt == NULL)
19933 return (-1);
19934 else
19935 return (ctxt->options);
19936}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019937
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019938
Daniel Veillard259f0df2004-08-18 09:13:18 +000019939/**
Daniel Veillard4255d502002-04-16 15:50:10 +000019940 * xmlSchemaValidateDoc:
19941 * @ctxt: a schema validation context
19942 * @doc: a parsed document tree
19943 *
19944 * Validate a document tree in memory.
19945 *
19946 * Returns 0 if the document is schemas valid, a positive error code
19947 * number otherwise and -1 in case of internal or API error.
19948 */
19949int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019950xmlSchemaValidateDoc(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
19951{
Daniel Veillard4255d502002-04-16 15:50:10 +000019952 int ret;
19953
19954 if ((ctxt == NULL) || (doc == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019955 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000019956
19957 ctxt->doc = doc;
William M. Brack2f2a6632004-08-20 23:09:47 +000019958 ctxt->err = 0;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019959 ctxt->nberrors = 0;
19960
19961 /*
19962 if (ctxt->schema == NULL) {
19963 xmlSchemaVErr(ctxt, NULL,
19964 XML_SCHEMAV_INTERNAL,
19965 "API error: xmlSchemaValidateDoc, "
19966 "no schema specified and assembling of schemata "
19967 "using xsi:schemaLocation and xsi:noNamespaceSchemaLocation "
19968 "is not enabled.\n", NULL, NULL);
19969 return (-1);
19970 }
19971 */
Daniel Veillard4255d502002-04-16 15:50:10 +000019972 ret = xmlSchemaValidateDocument(ctxt, doc);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019973 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000019974}
19975
19976/**
19977 * xmlSchemaValidateStream:
19978 * @ctxt: a schema validation context
19979 * @input: the input to use for reading the data
19980 * @enc: an optional encoding information
19981 * @sax: a SAX handler for the resulting events
19982 * @user_data: the context to provide to the SAX handler.
19983 *
19984 * Validate a document tree in memory.
19985 *
19986 * Returns 0 if the document is schemas valid, a positive error code
19987 * number otherwise and -1 in case of internal or API error.
19988 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019989int
Daniel Veillard4255d502002-04-16 15:50:10 +000019990xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019991 xmlParserInputBufferPtr input, xmlCharEncoding enc,
19992 xmlSAXHandlerPtr sax, void *user_data)
19993{
Daniel Veillard4255d502002-04-16 15:50:10 +000019994 if ((ctxt == NULL) || (input == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019995 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000019996 ctxt->input = input;
19997 ctxt->enc = enc;
19998 ctxt->sax = sax;
19999 ctxt->user_data = user_data;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020000 TODO return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000020001}
20002
20003#endif /* LIBXML_SCHEMAS_ENABLED */