blob: c0d4904e6bd5df2ec96eab8ddfbc10635b11691c [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. Buchcik87250a92005-01-28 15:59:53 +00002539#ifdef IDC_ENABLED
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00002540static void
2541xmlSchemaFreeIDCStateObjList(xmlSchemaIDCStateObjPtr sto)
2542{
2543 xmlSchemaIDCStateObjPtr next;
2544 while (sto != NULL) {
2545 next = sto->next;
2546 if (sto->history != NULL) {
2547 int i;
2548 for (i = 0; i < sto->sizeHistory; i++) {
2549 if (sto->history[i] != NULL)
2550 xmlFree(sto->history[i]);
2551 else
2552 break;
2553 }
2554 xmlFree(sto->history);
2555 }
2556 xmlFree(sto);
2557 sto = next;
2558 }
2559}
2560
2561/**
2562 * xmlSchemaFreeIDC:
2563 * @idc: a identity-constraint definition
2564 *
2565 * Deallocates an identity-constraint definition.
2566 */
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00002567static void
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00002568xmlSchemaFreeIDC(xmlSchemaIDCPtr idc)
2569{
2570 xmlSchemaIDCSelectPtr cur, prev;
2571
2572 if (idc == NULL)
2573 return;
2574 if (idc->annot != NULL)
2575 xmlSchemaFreeAnnot(idc->annot);
2576 if (idc->ref != NULL)
2577 xmlFree(idc->ref);
2578 /* Selector */
2579 if (idc->selector != NULL) {
2580 if (idc->selector->xpathComp != NULL)
2581 xmlXPathFreeCompExpr(idc->selector->xpathComp);
2582 xmlFree(idc->selector);
2583 }
2584 /* Fields */
2585 if (idc->fields != NULL) {
2586 cur = idc->fields;
2587 do {
2588 prev = cur;
2589 cur = cur->next;
2590 if (prev->xpathComp != NULL)
2591 xmlXPathFreeCompExpr(prev->xpathComp);
2592 xmlFree(prev);
2593 } while (cur != NULL);
2594 }
2595 xmlFree(idc);
2596}
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00002597#endif /* IDC_ENABLED */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00002598
Daniel Veillard4255d502002-04-16 15:50:10 +00002599/**
Daniel Veillardb0f397e2003-12-23 23:30:53 +00002600 * xmlSchemaFreeTypeList:
2601 * @type: a schema type structure
2602 *
2603 * Deallocate a Schema Type structure.
2604 */
2605static void
2606xmlSchemaFreeTypeList(xmlSchemaTypePtr type)
2607{
2608 xmlSchemaTypePtr next;
2609
2610 while (type != NULL) {
2611 next = type->redef;
2612 xmlSchemaFreeType(type);
2613 type = next;
2614 }
2615}
2616
2617/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002618 * xmlSchemaFree:
2619 * @schema: a schema structure
2620 *
2621 * Deallocate a Schema structure.
2622 */
2623void
2624xmlSchemaFree(xmlSchemaPtr schema)
2625{
2626 if (schema == NULL)
2627 return;
2628
Daniel Veillard4255d502002-04-16 15:50:10 +00002629 if (schema->notaDecl != NULL)
2630 xmlHashFree(schema->notaDecl,
2631 (xmlHashDeallocator) xmlSchemaFreeNotation);
2632 if (schema->attrDecl != NULL)
2633 xmlHashFree(schema->attrDecl,
2634 (xmlHashDeallocator) xmlSchemaFreeAttribute);
2635 if (schema->attrgrpDecl != NULL)
2636 xmlHashFree(schema->attrgrpDecl,
2637 (xmlHashDeallocator) xmlSchemaFreeAttributeGroup);
2638 if (schema->elemDecl != NULL)
2639 xmlHashFree(schema->elemDecl,
2640 (xmlHashDeallocator) xmlSchemaFreeElement);
2641 if (schema->typeDecl != NULL)
2642 xmlHashFree(schema->typeDecl,
Daniel Veillardb0f397e2003-12-23 23:30:53 +00002643 (xmlHashDeallocator) xmlSchemaFreeTypeList);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00002644 if (schema->groupDecl != NULL)
2645 xmlHashFree(schema->groupDecl,
2646 (xmlHashDeallocator) xmlSchemaFreeType);
Daniel Veillard1d913862003-11-21 00:28:39 +00002647 if (schema->schemasImports != NULL)
2648 xmlHashFree(schema->schemasImports,
2649 (xmlHashDeallocator) xmlSchemaFreeImport);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00002650 if (schema->includes != NULL) {
2651 xmlSchemaFreeIncludeList((xmlSchemaIncludePtr) schema->includes);
2652 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002653 if (schema->annot != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002654 xmlSchemaFreeAnnot(schema->annot);
Daniel Veillarddda22c12004-01-24 08:31:30 +00002655 if (schema->doc != NULL && !schema->preserve)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002656 xmlFreeDoc(schema->doc);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002657 xmlDictFree(schema->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00002658 xmlFree(schema);
2659}
2660
2661/************************************************************************
2662 * *
Daniel Veillard4255d502002-04-16 15:50:10 +00002663 * Debug functions *
2664 * *
2665 ************************************************************************/
2666
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00002667#ifdef LIBXML_OUTPUT_ENABLED
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002668
Daniel Veillard4255d502002-04-16 15:50:10 +00002669/**
2670 * xmlSchemaElementDump:
2671 * @elem: an element
2672 * @output: the file output
2673 *
2674 * Dump the element
2675 */
2676static void
2677xmlSchemaElementDump(xmlSchemaElementPtr elem, FILE * output,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002678 const xmlChar * name ATTRIBUTE_UNUSED,
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002679 const xmlChar * namespace ATTRIBUTE_UNUSED,
2680 const xmlChar * context ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +00002681{
2682 if (elem == NULL)
2683 return;
2684
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002685 if (elem->flags & XML_SCHEMAS_ELEM_REF) {
2686 fprintf(output, "Particle: %s", name);
2687 fprintf(output, ", term element: %s", elem->ref);
2688 if (elem->refNs != NULL)
2689 fprintf(output, " ns %s", elem->refNs);
2690 } else {
2691 fprintf(output, "Element");
2692 if (elem->flags & XML_SCHEMAS_ELEM_GLOBAL)
2693 fprintf(output, " (global)");
2694 fprintf(output, ": %s ", elem->name);
2695 if (namespace != NULL)
2696 fprintf(output, "ns %s", namespace);
2697 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002698 fprintf(output, "\n");
2699 if ((elem->minOccurs != 1) || (elem->maxOccurs != 1)) {
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002700 fprintf(output, " min %d ", elem->minOccurs);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002701 if (elem->maxOccurs >= UNBOUNDED)
2702 fprintf(output, "max: unbounded\n");
2703 else if (elem->maxOccurs != 1)
2704 fprintf(output, "max: %d\n", elem->maxOccurs);
2705 else
2706 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00002707 }
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002708 /*
2709 * Misc other properties.
2710 */
2711 if ((elem->flags & XML_SCHEMAS_ELEM_NILLABLE) ||
2712 (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT) ||
2713 (elem->flags & XML_SCHEMAS_ELEM_FIXED) ||
2714 (elem->flags & XML_SCHEMAS_ELEM_DEFAULT) ||
2715 (elem->id != NULL)) {
2716 fprintf(output, " props: ");
2717 if (elem->flags & XML_SCHEMAS_ELEM_FIXED)
2718 fprintf(output, "[fixed] ");
2719 if (elem->flags & XML_SCHEMAS_ELEM_DEFAULT)
2720 fprintf(output, "[default] ");
2721 if (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT)
2722 fprintf(output, "[abstract] ");
2723 if (elem->flags & XML_SCHEMAS_ELEM_NILLABLE)
2724 fprintf(output, "[nillable] ");
2725 if (elem->id != NULL)
2726 fprintf(output, "[id: '%s'] ", elem->id);
2727 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00002728 }
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002729 /*
2730 * Default/fixed value.
2731 */
Daniel Veillard4255d502002-04-16 15:50:10 +00002732 if (elem->value != NULL)
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002733 fprintf(output, " value: '%s'\n", elem->value);
2734 /*
2735 * Type.
2736 */
2737 if (elem->namedType != NULL) {
2738 fprintf(output, " type: %s ", elem->namedType);
2739 if (elem->namedTypeNs != NULL)
2740 fprintf(output, "ns %s\n", elem->namedTypeNs);
2741 else
2742 fprintf(output, "\n");
2743 }
2744 /*
2745 * Substitution group.
2746 */
2747 if (elem->substGroup != NULL) {
2748 fprintf(output, " substitutionGroup: %s ", elem->substGroup);
2749 if (elem->substGroupNs != NULL)
2750 fprintf(output, "ns %s\n", elem->substGroupNs);
2751 else
2752 fprintf(output, "\n");
2753 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002754}
2755
2756/**
2757 * xmlSchemaAnnotDump:
2758 * @output: the file output
2759 * @annot: a annotation
2760 *
2761 * Dump the annotation
2762 */
2763static void
2764xmlSchemaAnnotDump(FILE * output, xmlSchemaAnnotPtr annot)
2765{
2766 xmlChar *content;
2767
2768 if (annot == NULL)
2769 return;
2770
2771 content = xmlNodeGetContent(annot->content);
2772 if (content != NULL) {
2773 fprintf(output, " Annot: %s\n", content);
2774 xmlFree(content);
2775 } else
2776 fprintf(output, " Annot: empty\n");
2777}
2778
2779/**
2780 * xmlSchemaTypeDump:
2781 * @output: the file output
2782 * @type: a type structure
2783 *
2784 * Dump a SchemaType structure
2785 */
2786static void
2787xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output)
2788{
2789 if (type == NULL) {
2790 fprintf(output, "Type: NULL\n");
2791 return;
2792 }
2793 fprintf(output, "Type: ");
2794 if (type->name != NULL)
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002795 fprintf(output, "%s ", type->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00002796 else
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002797 fprintf(output, "no name ");
2798 if (type->targetNamespace != NULL)
2799 fprintf(output, "ns %s ", type->targetNamespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00002800 switch (type->type) {
2801 case XML_SCHEMA_TYPE_BASIC:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002802 fprintf(output, "[basic] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002803 break;
2804 case XML_SCHEMA_TYPE_SIMPLE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002805 fprintf(output, "[simple] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002806 break;
2807 case XML_SCHEMA_TYPE_COMPLEX:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002808 fprintf(output, "[complex] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002809 break;
2810 case XML_SCHEMA_TYPE_SEQUENCE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002811 fprintf(output, "[sequence] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002812 break;
2813 case XML_SCHEMA_TYPE_CHOICE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002814 fprintf(output, "[choice] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002815 break;
2816 case XML_SCHEMA_TYPE_ALL:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002817 fprintf(output, "[all] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002818 break;
2819 case XML_SCHEMA_TYPE_UR:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002820 fprintf(output, "[ur] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002821 break;
2822 case XML_SCHEMA_TYPE_RESTRICTION:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002823 fprintf(output, "[restriction] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002824 break;
2825 case XML_SCHEMA_TYPE_EXTENSION:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002826 fprintf(output, "[extension] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002827 break;
2828 default:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002829 fprintf(output, "[unknown type %d] ", type->type);
Daniel Veillard4255d502002-04-16 15:50:10 +00002830 break;
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002831 }
2832 fprintf(output, "content: ");
Daniel Veillard4255d502002-04-16 15:50:10 +00002833 switch (type->contentType) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002834 case XML_SCHEMA_CONTENT_UNKNOWN:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002835 fprintf(output, "[unknown] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002836 break;
2837 case XML_SCHEMA_CONTENT_EMPTY:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002838 fprintf(output, "[empty] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002839 break;
2840 case XML_SCHEMA_CONTENT_ELEMENTS:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002841 fprintf(output, "[element] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002842 break;
2843 case XML_SCHEMA_CONTENT_MIXED:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002844 fprintf(output, "[mixed] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002845 break;
2846 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00002847 /* not used. */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002848 break;
2849 case XML_SCHEMA_CONTENT_BASIC:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002850 fprintf(output, "[basic] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002851 break;
2852 case XML_SCHEMA_CONTENT_SIMPLE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002853 fprintf(output, "[simple] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002854 break;
2855 case XML_SCHEMA_CONTENT_ANY:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002856 fprintf(output, "[any] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002857 break;
Daniel Veillard4255d502002-04-16 15:50:10 +00002858 }
2859 fprintf(output, "\n");
2860 if ((type->minOccurs != 1) || (type->maxOccurs != 1)) {
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002861 fprintf(output, " min: %d ", type->minOccurs);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002862 if (type->maxOccurs >= UNBOUNDED)
2863 fprintf(output, "max: unbounded\n");
2864 else if (type->maxOccurs != 1)
2865 fprintf(output, "max: %d\n", type->maxOccurs);
2866 else
2867 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00002868 }
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00002869 if (type->base != NULL) {
2870 fprintf(output, " base type: %s", type->base);
2871 if (type->baseNs != NULL)
2872 fprintf(output, " ns %s\n", type->baseNs);
2873 else
2874 fprintf(output, "\n");
2875 }
Daniel Veillard4255d502002-04-16 15:50:10 +00002876 if (type->annot != NULL)
2877 xmlSchemaAnnotDump(output, type->annot);
2878 if (type->subtypes != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002879 xmlSchemaTypePtr sub = type->subtypes;
Daniel Veillard4255d502002-04-16 15:50:10 +00002880
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002881 fprintf(output, " subtypes: ");
2882 while (sub != NULL) {
2883 fprintf(output, "%s ", sub->name);
2884 sub = sub->next;
2885 }
2886 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00002887 }
2888
2889}
2890
2891/**
2892 * xmlSchemaDump:
2893 * @output: the file output
2894 * @schema: a schema structure
2895 *
2896 * Dump a Schema structure.
2897 */
2898void
2899xmlSchemaDump(FILE * output, xmlSchemaPtr schema)
2900{
Daniel Veillardce682bc2004-11-05 17:22:25 +00002901 if (output == NULL)
2902 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00002903 if (schema == NULL) {
2904 fprintf(output, "Schemas: NULL\n");
2905 return;
2906 }
2907 fprintf(output, "Schemas: ");
2908 if (schema->name != NULL)
2909 fprintf(output, "%s, ", schema->name);
2910 else
2911 fprintf(output, "no name, ");
2912 if (schema->targetNamespace != NULL)
Daniel Veillard580ced82003-03-21 21:22:48 +00002913 fprintf(output, "%s", (const char *) schema->targetNamespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00002914 else
2915 fprintf(output, "no target namespace");
2916 fprintf(output, "\n");
2917 if (schema->annot != NULL)
2918 xmlSchemaAnnotDump(output, schema->annot);
2919
2920 xmlHashScan(schema->typeDecl, (xmlHashScanner) xmlSchemaTypeDump,
2921 output);
2922 xmlHashScanFull(schema->elemDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002923 (xmlHashScannerFull) xmlSchemaElementDump, output);
Daniel Veillard4255d502002-04-16 15:50:10 +00002924}
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00002925
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00002926#ifdef IDC_ENABLED
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00002927/**
2928 * xmlSchemaDebugDumpIDCTable:
2929 * @vctxt: the WXS validation context
2930 *
2931 * Displays the current IDC table for debug purposes.
2932 */
2933static void
2934xmlSchemaDebugDumpIDCTable(FILE * output,
2935 const xmlChar *namespaceName,
2936 const xmlChar *localName,
2937 xmlSchemaPSVIIDCBindingPtr bind)
2938{
2939 xmlChar *str = NULL, *value;
2940 xmlSchemaPSVIIDCNodePtr tab;
2941 xmlSchemaPSVIIDCKeyPtr key;
2942 int i, j, res;
2943
2944 fprintf(output, "IDC: TABLES on %s\n",
2945 xmlSchemaFormatNsUriLocal(&str, namespaceName, localName));
2946 FREE_AND_NULL(str)
2947
2948 if (bind == NULL)
2949 return;
2950 do {
2951 fprintf(output, "IDC: BINDING %s\n",
2952 xmlSchemaFormatNsUriLocal(&str, bind->definition->targetNamespace,
2953 bind->definition->name));
2954 FREE_AND_NULL(str)
2955 for (i = 0; i < bind->nbNodes; i++) {
2956 tab = bind->nodeTable[i];
2957 fprintf(output, " ( ");
2958 for (j = 0; j < bind->definition->nbFields; j++) {
2959 key = tab->keys[j];
2960 if ((key != NULL) && (key->compValue != NULL)) {
2961#ifdef IDC_VALUE_SUPPORT
2962 res = xmlSchemaGetCanonValue(key->compValue, &value);
2963#else
2964 value = xmlStrdup(BAD_CAST "dummy-value");
2965 res = 0;
2966#endif
2967 if (res == 0)
2968 fprintf(output, "\"%s\" ", value);
2969 else
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00002970 fprintf(output, "CANON-VALUE-FAILED ");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00002971 if (value != NULL) {
2972 xmlFree(value);
2973 value = NULL;
2974 }
2975 } else if (key != NULL)
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00002976 fprintf(output, "(no val), ");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00002977 else
2978 fprintf(output, "(key missing), ");
2979 }
2980 fprintf(output, ")\n");
2981 }
2982 bind = bind->next;
2983 } while (bind != NULL);
2984}
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00002985#endif /* IDC_ENABLED */
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00002986#endif /* LIBXML_OUTPUT_ENABLED */
Daniel Veillard4255d502002-04-16 15:50:10 +00002987
2988/************************************************************************
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002989 * *
2990 * Utilities *
2991 * *
2992 ************************************************************************/
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002993
Daniel Veillardc0826a72004-08-10 14:17:33 +00002994/**
2995 * xmlSchemaGetPropNode:
2996 * @node: the element node
2997 * @name: the name of the attribute
2998 *
2999 * Seeks an attribute with a name of @name in
3000 * no namespace.
3001 *
3002 * Returns the attribute or NULL if not present.
3003 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00003004static xmlAttrPtr
Daniel Veillardc0826a72004-08-10 14:17:33 +00003005xmlSchemaGetPropNode(xmlNodePtr node, const char *name)
Daniel Veillard01fa6152004-06-29 17:04:39 +00003006{
3007 xmlAttrPtr prop;
3008
Daniel Veillardc0826a72004-08-10 14:17:33 +00003009 if ((node == NULL) || (name == NULL))
3010 return(NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00003011 prop = node->properties;
3012 while (prop != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00003013 if ((prop->ns == NULL) && xmlStrEqual(prop->name, BAD_CAST name))
3014 return(prop);
3015 prop = prop->next;
3016 }
3017 return (NULL);
3018}
3019
3020/**
3021 * xmlSchemaGetPropNodeNs:
3022 * @node: the element node
3023 * @uri: the uri
3024 * @name: the name of the attribute
3025 *
3026 * Seeks an attribute with a local name of @name and
3027 * a namespace URI of @uri.
3028 *
3029 * Returns the attribute or NULL if not present.
3030 */
3031static xmlAttrPtr
3032xmlSchemaGetPropNodeNs(xmlNodePtr node, const char *uri, const char *name)
3033{
3034 xmlAttrPtr prop;
3035
3036 if ((node == NULL) || (name == NULL))
3037 return(NULL);
3038 prop = node->properties;
3039 while (prop != NULL) {
3040 if ((prop->ns != NULL) &&
3041 xmlStrEqual(prop->name, BAD_CAST name) &&
3042 xmlStrEqual(prop->ns->href, BAD_CAST uri))
Daniel Veillard01fa6152004-06-29 17:04:39 +00003043 return(prop);
3044 prop = prop->next;
3045 }
3046 return (NULL);
3047}
3048
3049static const xmlChar *
3050xmlSchemaGetNodeContent(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
3051{
3052 xmlChar *val;
3053 const xmlChar *ret;
3054
3055 val = xmlNodeGetContent(node);
3056 if (val == NULL)
3057 return(NULL);
3058 ret = xmlDictLookup(ctxt->dict, val, -1);
3059 xmlFree(val);
3060 return(ret);
3061}
3062
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003063/**
3064 * xmlSchemaGetProp:
3065 * @ctxt: the parser context
3066 * @node: the node
3067 * @name: the property name
3068 *
3069 * Read a attribute value and internalize the string
3070 *
3071 * Returns the string or NULL if not present.
3072 */
3073static const xmlChar *
3074xmlSchemaGetProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
3075 const char *name)
3076{
3077 xmlChar *val;
3078 const xmlChar *ret;
3079
3080 val = xmlGetProp(node, BAD_CAST name);
3081 if (val == NULL)
3082 return(NULL);
3083 ret = xmlDictLookup(ctxt->dict, val, -1);
3084 xmlFree(val);
3085 return(ret);
3086}
3087
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003088/************************************************************************
Daniel Veillard4255d502002-04-16 15:50:10 +00003089 * *
3090 * Parsing functions *
3091 * *
3092 ************************************************************************/
3093
3094/**
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003095 * xmlSchemaGetElem:
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003096 * @schema: the schema context
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003097 * @name: the element name
3098 * @ns: the element namespace
3099 *
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003100 * Lookup a global element declaration in the schema.
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003101 *
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003102 * Returns the element declaration or NULL if not found.
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003103 */
3104static xmlSchemaElementPtr
3105xmlSchemaGetElem(xmlSchemaPtr schema, const xmlChar * name,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003106 const xmlChar * namespace)
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003107{
3108 xmlSchemaElementPtr ret;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003109
3110 if ((name == NULL) || (schema == NULL))
3111 return (NULL);
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003112
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003113 ret = xmlHashLookup2(schema->elemDecl, name, namespace);
Daniel Veillardf2a12832003-11-24 13:04:35 +00003114 if ((ret != NULL) &&
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003115 (ret->flags & XML_SCHEMAS_ELEM_GLOBAL)) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003116 return (ret);
Daniel Veillard3646d642004-06-02 19:19:14 +00003117 } else
3118 ret = NULL;
William M. Bracke7091952004-05-11 15:09:58 +00003119 /*
3120 * This one was removed, since top level element declarations have
3121 * the target namespace specified in targetNamespace of the <schema>
3122 * information element, even if elementFormDefault is "unqualified".
3123 */
3124
3125 /* else if ((schema->flags & XML_SCHEMAS_QUALIF_ELEM) == 0) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003126 if (xmlStrEqual(namespace, schema->targetNamespace))
3127 ret = xmlHashLookup2(schema->elemDecl, name, NULL);
3128 else
3129 ret = xmlHashLookup2(schema->elemDecl, name, namespace);
Daniel Veillardf2a12832003-11-24 13:04:35 +00003130 if ((ret != NULL) &&
3131 ((level == 0) || (ret->flags & XML_SCHEMAS_ELEM_TOPLEVEL))) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003132 return (ret);
Daniel Veillardf2a12832003-11-24 13:04:35 +00003133 }
William M. Bracke7091952004-05-11 15:09:58 +00003134 */
Daniel Veillard3646d642004-06-02 19:19:14 +00003135
William M. Brack2f2a6632004-08-20 23:09:47 +00003136 /*
3137 * Removed since imported components will be hold by the main schema only.
3138 *
Daniel Veillard3646d642004-06-02 19:19:14 +00003139 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00003140 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00003141 else
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003142 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00003143 if (import != NULL) {
Daniel Veillardf2a12832003-11-24 13:04:35 +00003144 ret = xmlSchemaGetElem(import->schema, name, namespace, level + 1);
Daniel Veillard3646d642004-06-02 19:19:14 +00003145 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ELEM_GLOBAL)) {
3146 return (ret);
3147 } else
3148 ret = NULL;
3149 }
William M. Brack2f2a6632004-08-20 23:09:47 +00003150 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003151#ifdef DEBUG
3152 if (ret == NULL) {
3153 if (namespace == NULL)
3154 fprintf(stderr, "Unable to lookup type %s", name);
3155 else
3156 fprintf(stderr, "Unable to lookup type %s:%s", name,
3157 namespace);
3158 }
3159#endif
3160 return (ret);
3161}
3162
3163/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003164 * xmlSchemaGetType:
3165 * @schema: the schemas context
3166 * @name: the type name
3167 * @ns: the type namespace
3168 *
3169 * Lookup a type in the schemas or the predefined types
3170 *
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003171 * Returns the group definition or NULL if not found.
Daniel Veillard4255d502002-04-16 15:50:10 +00003172 */
3173static xmlSchemaTypePtr
3174xmlSchemaGetType(xmlSchemaPtr schema, const xmlChar * name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003175 const xmlChar * namespace)
3176{
Daniel Veillard4255d502002-04-16 15:50:10 +00003177 xmlSchemaTypePtr ret;
3178
3179 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003180 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003181 if (schema != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003182 ret = xmlHashLookup2(schema->typeDecl, name, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00003183 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003184 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003185 }
3186 ret = xmlSchemaGetPredefinedType(name, namespace);
Daniel Veillard1d913862003-11-21 00:28:39 +00003187 if (ret != NULL)
3188 return (ret);
William M. Brack2f2a6632004-08-20 23:09:47 +00003189 /*
3190 * Removed, since the imported components will be grafted on the
3191 * main schema only.
Daniel Veillard3646d642004-06-02 19:19:14 +00003192 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00003193 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00003194 else
Daniel Veillard1d913862003-11-21 00:28:39 +00003195 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00003196 if (import != NULL) {
Daniel Veillard1d913862003-11-21 00:28:39 +00003197 ret = xmlSchemaGetType(import->schema, name, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00003198 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL)) {
3199 return (ret);
3200 } else
3201 ret = NULL;
3202 }
William M. Brack2f2a6632004-08-20 23:09:47 +00003203 */
Daniel Veillard4255d502002-04-16 15:50:10 +00003204#ifdef DEBUG
3205 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003206 if (namespace == NULL)
3207 fprintf(stderr, "Unable to lookup type %s", name);
3208 else
3209 fprintf(stderr, "Unable to lookup type %s:%s", name,
3210 namespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00003211 }
3212#endif
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003213 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003214}
3215
Daniel Veillard3646d642004-06-02 19:19:14 +00003216/**
3217 * xmlSchemaGetAttribute:
3218 * @schema: the context of the schema
3219 * @name: the name of the attribute
3220 * @ns: the target namespace of the attribute
3221 *
3222 * Lookup a an attribute in the schema or imported schemas
3223 *
3224 * Returns the attribute declaration or NULL if not found.
3225 */
3226static xmlSchemaAttributePtr
3227xmlSchemaGetAttribute(xmlSchemaPtr schema, const xmlChar * name,
3228 const xmlChar * namespace)
3229{
3230 xmlSchemaAttributePtr ret;
Daniel Veillard3646d642004-06-02 19:19:14 +00003231
3232 if ((name == NULL) || (schema == NULL))
3233 return (NULL);
3234
3235
3236 ret = xmlHashLookup2(schema->attrDecl, name, namespace);
3237 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTR_GLOBAL))
3238 return (ret);
3239 else
3240 ret = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00003241 /*
3242 * Removed, since imported components will be hold by the main schema only.
3243 *
Daniel Veillard3646d642004-06-02 19:19:14 +00003244 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00003245 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00003246 else
3247 import = xmlHashLookup(schema->schemasImports, namespace);
3248 if (import != NULL) {
3249 ret = xmlSchemaGetAttribute(import->schema, name, namespace);
3250 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTR_GLOBAL)) {
3251 return (ret);
3252 } else
3253 ret = NULL;
3254 }
William M. Brack2f2a6632004-08-20 23:09:47 +00003255 */
Daniel Veillard3646d642004-06-02 19:19:14 +00003256#ifdef DEBUG
3257 if (ret == NULL) {
3258 if (namespace == NULL)
3259 fprintf(stderr, "Unable to lookup attribute %s", name);
3260 else
3261 fprintf(stderr, "Unable to lookup attribute %s:%s", name,
3262 namespace);
3263 }
3264#endif
3265 return (ret);
3266}
3267
3268/**
3269 * xmlSchemaGetAttributeGroup:
3270 * @schema: the context of the schema
3271 * @name: the name of the attribute group
3272 * @ns: the target namespace of the attribute group
3273 *
3274 * Lookup a an attribute group in the schema or imported schemas
3275 *
3276 * Returns the attribute group definition or NULL if not found.
3277 */
3278static xmlSchemaAttributeGroupPtr
3279xmlSchemaGetAttributeGroup(xmlSchemaPtr schema, const xmlChar * name,
3280 const xmlChar * namespace)
3281{
3282 xmlSchemaAttributeGroupPtr ret;
Daniel Veillard3646d642004-06-02 19:19:14 +00003283
3284 if ((name == NULL) || (schema == NULL))
3285 return (NULL);
3286
3287
3288 ret = xmlHashLookup2(schema->attrgrpDecl, name, namespace);
3289 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL))
3290 return (ret);
3291 else
3292 ret = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00003293 /*
3294 * Removed since imported components will be hold by the main schema only.
3295 *
Daniel Veillard3646d642004-06-02 19:19:14 +00003296 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00003297 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00003298 else
3299 import = xmlHashLookup(schema->schemasImports, namespace);
3300 if (import != NULL) {
3301 ret = xmlSchemaGetAttributeGroup(import->schema, name, namespace);
3302 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL))
3303 return (ret);
3304 else
3305 ret = NULL;
3306 }
William M. Brack2f2a6632004-08-20 23:09:47 +00003307 */
Daniel Veillard3646d642004-06-02 19:19:14 +00003308#ifdef DEBUG
3309 if (ret == NULL) {
3310 if (namespace == NULL)
3311 fprintf(stderr, "Unable to lookup attribute group %s", name);
3312 else
3313 fprintf(stderr, "Unable to lookup attribute group %s:%s", name,
3314 namespace);
3315 }
3316#endif
3317 return (ret);
3318}
3319
3320/**
3321 * xmlSchemaGetGroup:
3322 * @schema: the context of the schema
3323 * @name: the name of the group
3324 * @ns: the target namespace of the group
3325 *
3326 * Lookup a group in the schema or imported schemas
3327 *
3328 * Returns the group definition or NULL if not found.
3329 */
3330static xmlSchemaTypePtr
3331xmlSchemaGetGroup(xmlSchemaPtr schema, const xmlChar * name,
3332 const xmlChar * namespace)
3333{
3334 xmlSchemaTypePtr ret;
Daniel Veillard3646d642004-06-02 19:19:14 +00003335
3336 if ((name == NULL) || (schema == NULL))
3337 return (NULL);
3338
3339
3340 ret = xmlHashLookup2(schema->groupDecl, name, namespace);
3341 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL))
3342 return (ret);
3343 else
3344 ret = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00003345 /*
3346 * Removed since imported components will be hold by the main schema only.
3347 *
Daniel Veillard3646d642004-06-02 19:19:14 +00003348 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00003349 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00003350 else
3351 import = xmlHashLookup(schema->schemasImports, namespace);
3352 if (import != NULL) {
3353 ret = xmlSchemaGetGroup(import->schema, name, namespace);
3354 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL))
3355 return (ret);
3356 else
3357 ret = NULL;
3358 }
William M. Brack2f2a6632004-08-20 23:09:47 +00003359 */
Daniel Veillard3646d642004-06-02 19:19:14 +00003360#ifdef DEBUG
3361 if (ret == NULL) {
3362 if (namespace == NULL)
3363 fprintf(stderr, "Unable to lookup group %s", name);
3364 else
3365 fprintf(stderr, "Unable to lookup group %s:%s", name,
3366 namespace);
3367 }
3368#endif
3369 return (ret);
3370}
3371
Daniel Veillard4255d502002-04-16 15:50:10 +00003372/************************************************************************
3373 * *
3374 * Parsing functions *
3375 * *
3376 ************************************************************************/
3377
3378#define IS_BLANK_NODE(n) \
3379 (((n)->type == XML_TEXT_NODE) && (xmlSchemaIsBlank((n)->content)))
3380
3381/**
3382 * xmlSchemaIsBlank:
3383 * @str: a string
3384 *
3385 * Check if a string is ignorable
3386 *
3387 * Returns 1 if the string is NULL or made of blanks chars, 0 otherwise
3388 */
3389static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003390xmlSchemaIsBlank(xmlChar * str)
3391{
Daniel Veillard4255d502002-04-16 15:50:10 +00003392 if (str == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003393 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003394 while (*str != 0) {
William M. Brack76e95df2003-10-18 16:20:14 +00003395 if (!(IS_BLANK_CH(*str)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003396 return (0);
3397 str++;
Daniel Veillard4255d502002-04-16 15:50:10 +00003398 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003399 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003400}
3401
3402/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003403 * xmlSchemaAddAssembledItem:
3404 * @ctxt: a schema parser context
3405 * @schema: the schema being built
3406 * @item: the item
3407 *
3408 * Add a item to the schema's list of current items.
3409 * This is used if the schema was already constructed and
3410 * new schemata need to be added to it.
3411 * *WARNING* this interface is highly subject to change.
3412 *
3413 * Returns 0 if suceeds and -1 if an internal error occurs.
3414 */
3415static int
3416xmlSchemaAddAssembledItem(xmlSchemaParserCtxtPtr ctxt,
3417 xmlSchemaTypePtr item)
3418{
3419 static int growSize = 100;
3420 xmlSchemaAssemblePtr ass;
3421
3422 ass = ctxt->assemble;
3423 if (ass->sizeItems < 0) {
3424 /* If disabled. */
3425 return (0);
3426 }
3427 if (ass->sizeItems <= 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00003428 ass->items = (void **) xmlMalloc(growSize * sizeof(xmlSchemaTypePtr));
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003429 if (ass->items == NULL) {
3430 xmlSchemaPErrMemory(ctxt,
3431 "allocating new item buffer", NULL);
3432 return (-1);
3433 }
3434 ass->sizeItems = growSize;
3435 } else if (ass->sizeItems <= ass->nbItems) {
3436 ass->sizeItems *= 2;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00003437 ass->items = (void **) xmlRealloc(ass->items,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003438 ass->sizeItems * sizeof(xmlSchemaTypePtr));
3439 if (ass->items == NULL) {
3440 xmlSchemaPErrMemory(ctxt,
3441 "growing item buffer", NULL);
3442 ass->sizeItems = 0;
3443 return (-1);
3444 }
3445 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00003446 /* ass->items[ass->nbItems++] = (void *) item; */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003447 ((xmlSchemaTypePtr *) ass->items)[ass->nbItems++] = (void *) item;
3448 return (0);
3449}
3450
3451/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003452 * xmlSchemaAddNotation:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003453 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00003454 * @schema: the schema being built
3455 * @name: the item name
3456 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00003457 * Add an XML schema annotation declaration
Daniel Veillard4255d502002-04-16 15:50:10 +00003458 * *WARNING* this interface is highly subject to change
3459 *
3460 * Returns the new struture or NULL in case of error
3461 */
3462static xmlSchemaNotationPtr
3463xmlSchemaAddNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003464 const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +00003465{
3466 xmlSchemaNotationPtr ret = NULL;
3467 int val;
3468
3469 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
3470 return (NULL);
3471
3472 if (schema->notaDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00003473 schema->notaDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00003474 if (schema->notaDecl == NULL)
3475 return (NULL);
3476
3477 ret = (xmlSchemaNotationPtr) xmlMalloc(sizeof(xmlSchemaNotation));
3478 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003479 xmlSchemaPErrMemory(ctxt, "add annotation", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003480 return (NULL);
3481 }
3482 memset(ret, 0, sizeof(xmlSchemaNotation));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003483 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003484 val = xmlHashAddEntry2(schema->notaDecl, name, schema->targetNamespace,
3485 ret);
3486 if (val != 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00003487 /*
3488 * TODO: This should never happen, since a unique name will be computed.
3489 * If it fails, then an other internal error must have occured.
3490 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003491 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
3492 XML_SCHEMAP_REDEFINED_NOTATION,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003493 "Annotation declaration '%s' is already declared.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003494 name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003495 xmlFree(ret);
3496 return (NULL);
3497 }
3498 return (ret);
3499}
3500
3501
3502/**
3503 * xmlSchemaAddAttribute:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003504 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00003505 * @schema: the schema being built
3506 * @name: the item name
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003507 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00003508 *
3509 * Add an XML schema Attrribute declaration
3510 * *WARNING* this interface is highly subject to change
3511 *
3512 * Returns the new struture or NULL in case of error
3513 */
3514static xmlSchemaAttributePtr
3515xmlSchemaAddAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00003516 const xmlChar * name, const xmlChar * namespace,
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003517 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00003518{
3519 xmlSchemaAttributePtr ret = NULL;
3520 int val;
3521
3522 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
3523 return (NULL);
3524
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003525#ifdef DEBUG
3526 fprintf(stderr, "Adding attribute %s\n", name);
3527 if (namespace != NULL)
3528 fprintf(stderr, " target namespace %s\n", namespace);
3529#endif
3530
Daniel Veillard4255d502002-04-16 15:50:10 +00003531 if (schema->attrDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00003532 schema->attrDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00003533 if (schema->attrDecl == NULL)
3534 return (NULL);
3535
3536 ret = (xmlSchemaAttributePtr) xmlMalloc(sizeof(xmlSchemaAttribute));
3537 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003538 xmlSchemaPErrMemory(ctxt, "allocating attribute", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003539 return (NULL);
3540 }
3541 memset(ret, 0, sizeof(xmlSchemaAttribute));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003542 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00003543 ret->targetNamespace = namespace;
Daniel Veillard4255d502002-04-16 15:50:10 +00003544 val = xmlHashAddEntry3(schema->attrDecl, name,
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00003545 namespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003546 if (val != 0) {
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003547 if (topLevel) {
3548 xmlSchemaPCustomErr(ctxt,
3549 XML_SCHEMAP_REDEFINED_ATTR,
3550 NULL, NULL, node,
3551 "A global attribute declaration with the name '%s' does "
3552 "already exist", name);
3553 xmlFree(ret);
3554 return (NULL);
3555 } else {
3556 char buf[20];
3557 xmlChar *str;
3558 /*
3559 * Using the ctxt->container for xmlHashAddEntry3 is ambigious
3560 * in the scenario:
3561 * 1. multiple top-level complex types have different target
3562 * namespaces but have the SAME NAME; this can happen if
3563 * schemata are imported
3564 * 2. those complex types contain attributes with an equal name
3565 * 3. those attributes are in no namespace
3566 * We will compute a new context string.
3567 */
3568 snprintf(buf, 19, "%d", ctxt->counter++ + 1);
3569 str = xmlStrdup(BAD_CAST ctxt->container);
3570 str = xmlStrcat(str, BAD_CAST buf);
3571 val = xmlHashAddEntry3(schema->attrDecl, name,
3572 namespace, xmlDictLookup(ctxt->dict, str, -1), ret);
3573 FREE_AND_NULL(str)
3574 if (val != 0) {
3575 xmlSchemaPCustomErr(ctxt,
3576 XML_SCHEMAP_INTERNAL,
3577 NULL, NULL, node,
3578 "Internal error: xmlSchemaAddElement, "
3579 "a dublicate element declaration with the name '%s' "
3580 "could not be added to the hash.", name);
3581 xmlFree(ret);
3582 return (NULL);
3583 }
3584
3585 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003586 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003587 if (ctxt->assemble != NULL)
3588 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003589 return (ret);
3590}
3591
3592/**
3593 * xmlSchemaAddAttributeGroup:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003594 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00003595 * @schema: the schema being built
3596 * @name: the item name
3597 *
3598 * Add an XML schema Attrribute Group declaration
3599 *
3600 * Returns the new struture or NULL in case of error
3601 */
3602static xmlSchemaAttributeGroupPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003603xmlSchemaAddAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00003604 xmlSchemaPtr schema, const xmlChar * name,
3605 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00003606{
3607 xmlSchemaAttributeGroupPtr ret = NULL;
3608 int val;
3609
3610 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
3611 return (NULL);
3612
3613 if (schema->attrgrpDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00003614 schema->attrgrpDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00003615 if (schema->attrgrpDecl == NULL)
3616 return (NULL);
3617
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003618 ret =
3619 (xmlSchemaAttributeGroupPtr)
3620 xmlMalloc(sizeof(xmlSchemaAttributeGroup));
Daniel Veillard4255d502002-04-16 15:50:10 +00003621 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003622 xmlSchemaPErrMemory(ctxt, "allocating attribute group", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003623 return (NULL);
3624 }
3625 memset(ret, 0, sizeof(xmlSchemaAttributeGroup));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003626 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003627 val = xmlHashAddEntry3(schema->attrgrpDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003628 schema->targetNamespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003629 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00003630 xmlSchemaPCustomErr(ctxt,
3631 XML_SCHEMAP_REDEFINED_ATTRGROUP,
3632 NULL, NULL, node,
3633 "A global attribute group definition with the name '%s' does already exist", name);
Daniel Veillard4255d502002-04-16 15:50:10 +00003634 xmlFree(ret);
3635 return (NULL);
3636 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003637 if (ctxt->assemble != NULL)
3638 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003639 return (ret);
3640}
3641
3642/**
3643 * xmlSchemaAddElement:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003644 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00003645 * @schema: the schema being built
3646 * @name: the type name
3647 * @namespace: the type namespace
3648 *
3649 * Add an XML schema Element declaration
3650 * *WARNING* this interface is highly subject to change
3651 *
3652 * Returns the new struture or NULL in case of error
3653 */
3654static xmlSchemaElementPtr
3655xmlSchemaAddElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00003656 const xmlChar * name, const xmlChar * namespace,
3657 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00003658{
3659 xmlSchemaElementPtr ret = NULL;
3660 int val;
3661
3662 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
3663 return (NULL);
3664
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003665#ifdef DEBUG
3666 fprintf(stderr, "Adding element %s\n", name);
3667 if (namespace != NULL)
3668 fprintf(stderr, " target namespace %s\n", namespace);
3669#endif
3670
Daniel Veillard4255d502002-04-16 15:50:10 +00003671 if (schema->elemDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00003672 schema->elemDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00003673 if (schema->elemDecl == NULL)
3674 return (NULL);
3675
3676 ret = (xmlSchemaElementPtr) xmlMalloc(sizeof(xmlSchemaElement));
3677 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003678 xmlSchemaPErrMemory(ctxt, "allocating element", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003679 return (NULL);
3680 }
3681 memset(ret, 0, sizeof(xmlSchemaElement));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003682 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003683 val = xmlHashAddEntry3(schema->elemDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003684 namespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003685 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00003686 if (topLevel) {
3687 xmlSchemaPCustomErr(ctxt,
3688 XML_SCHEMAP_REDEFINED_ELEMENT,
3689 NULL, NULL, node,
3690 "A global element declaration with the name '%s' does "
3691 "already exist", name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003692 xmlFree(ret);
3693 return (NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +00003694 } else {
3695 char buf[30];
3696
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00003697 snprintf(buf, 29, "#eCont%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00003698 val = xmlHashAddEntry3(schema->elemDecl, name, (xmlChar *) buf,
3699 namespace, ret);
3700 if (val != 0) {
3701 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00003702 XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +00003703 NULL, NULL, node,
3704 "Internal error: xmlSchemaAddElement, "
3705 "a dublicate element declaration with the name '%s' "
3706 "could not be added to the hash.", name);
3707 xmlFree(ret);
3708 return (NULL);
3709 }
3710 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00003711
Daniel Veillard4255d502002-04-16 15:50:10 +00003712 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003713 if (ctxt->assemble != NULL)
3714 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003715 return (ret);
3716}
3717
3718/**
3719 * xmlSchemaAddType:
Daniel Veillard01fa6152004-06-29 17:04:39 +00003720 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00003721 * @schema: the schema being built
3722 * @name: the item name
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003723 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00003724 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00003725 * Add an XML schema item
Daniel Veillard4255d502002-04-16 15:50:10 +00003726 * *WARNING* this interface is highly subject to change
3727 *
3728 * Returns the new struture or NULL in case of error
3729 */
3730static xmlSchemaTypePtr
3731xmlSchemaAddType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00003732 const xmlChar * name, const xmlChar * namespace,
3733 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00003734{
3735 xmlSchemaTypePtr ret = NULL;
3736 int val;
3737
3738 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
3739 return (NULL);
3740
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003741#ifdef DEBUG
3742 fprintf(stderr, "Adding type %s\n", name);
3743 if (namespace != NULL)
3744 fprintf(stderr, " target namespace %s\n", namespace);
3745#endif
3746
Daniel Veillard4255d502002-04-16 15:50:10 +00003747 if (schema->typeDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00003748 schema->typeDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00003749 if (schema->typeDecl == NULL)
3750 return (NULL);
3751
3752 ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
3753 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003754 xmlSchemaPErrMemory(ctxt, "allocating type", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003755 return (NULL);
3756 }
3757 memset(ret, 0, sizeof(xmlSchemaType));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003758 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00003759 ret->redef = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003760 val = xmlHashAddEntry2(schema->typeDecl, name, namespace, ret);
William M. Brack2f2a6632004-08-20 23:09:47 +00003761 if (val != 0) {
3762 if (ctxt->includes == 0) {
3763 xmlSchemaPCustomErr(ctxt,
3764 XML_SCHEMAP_REDEFINED_TYPE,
3765 NULL, NULL, node,
3766 "A global type definition with the name '%s' does already exist", name);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00003767 xmlFree(ret);
3768 return (NULL);
3769 } else {
3770 xmlSchemaTypePtr prev;
3771
3772 prev = xmlHashLookup2(schema->typeDecl, name, namespace);
3773 if (prev == NULL) {
3774 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
Daniel Veillardc0826a72004-08-10 14:17:33 +00003775 XML_ERR_INTERNAL_ERROR,
3776 "Internal error: xmlSchemaAddType, on type "
3777 "'%s'.\n",
3778 name, NULL);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00003779 xmlFree(ret);
3780 return (NULL);
3781 }
3782 ret->redef = prev->redef;
3783 prev->redef = ret;
3784 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003785 }
3786 ret->minOccurs = 1;
3787 ret->maxOccurs = 1;
Daniel Veillard3646d642004-06-02 19:19:14 +00003788 ret->attributeUses = NULL;
3789 ret->attributeWildcard = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003790 if (ctxt->assemble != NULL)
3791 xmlSchemaAddAssembledItem(ctxt,ret);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003792 return (ret);
3793}
3794
3795/**
3796 * xmlSchemaAddGroup:
3797 * @ctxt: a schema validation context
3798 * @schema: the schema being built
3799 * @name: the group name
3800 *
3801 * Add an XML schema Group definition
3802 *
3803 * Returns the new struture or NULL in case of error
3804 */
3805static xmlSchemaTypePtr
3806xmlSchemaAddGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00003807 const xmlChar *name, const xmlChar *namespaceName,
3808 xmlNodePtr node)
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003809{
3810 xmlSchemaTypePtr ret = NULL;
3811 int val;
3812
3813 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
3814 return (NULL);
3815
3816 if (schema->groupDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00003817 schema->groupDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003818 if (schema->groupDecl == NULL)
3819 return (NULL);
3820
3821 ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
3822 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003823 xmlSchemaPErrMemory(ctxt, "adding group", NULL);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003824 return (NULL);
3825 }
3826 memset(ret, 0, sizeof(xmlSchemaType));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003827 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003828 val =
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00003829 xmlHashAddEntry2(schema->groupDecl, name, namespaceName,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003830 ret);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003831 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00003832 xmlSchemaPCustomErr(ctxt,
3833 XML_SCHEMAP_REDEFINED_GROUP,
3834 NULL, NULL, node,
3835 "A global model group definition with the name '%s' does already exist", name);
Daniel Veillard4255d502002-04-16 15:50:10 +00003836 xmlFree(ret);
3837 return (NULL);
3838 }
3839 ret->minOccurs = 1;
3840 ret->maxOccurs = 1;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003841 if (ctxt->assemble != NULL)
3842 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003843 return (ret);
3844}
3845
Daniel Veillard3646d642004-06-02 19:19:14 +00003846/**
3847 * xmlSchemaNewWildcardNs:
3848 * @ctxt: a schema validation context
3849 *
3850 * Creates a new wildcard namespace constraint.
3851 *
3852 * Returns the new struture or NULL in case of error
3853 */
3854static xmlSchemaWildcardNsPtr
3855xmlSchemaNewWildcardNsConstraint(xmlSchemaParserCtxtPtr ctxt)
3856{
3857 xmlSchemaWildcardNsPtr ret;
3858
3859 ret = (xmlSchemaWildcardNsPtr)
3860 xmlMalloc(sizeof(xmlSchemaWildcardNs));
3861 if (ret == NULL) {
3862 xmlSchemaPErrMemory(ctxt, "creating wildcard namespace constraint", NULL);
3863 return (NULL);
3864 }
3865 ret->value = NULL;
3866 ret->next = NULL;
3867 return (ret);
3868}
3869
3870/**
3871 * xmlSchemaAddWildcard:
3872 * @ctxt: a schema validation context
Daniel Veillardc0826a72004-08-10 14:17:33 +00003873 * Adds a wildcard. It corresponds to a
3874 * xsd:anyAttribute and is used as storage for namespace
3875 * constraints on a xsd:any.
Daniel Veillard3646d642004-06-02 19:19:14 +00003876 *
3877 * Returns the new struture or NULL in case of error
3878 */
3879static xmlSchemaWildcardPtr
3880xmlSchemaAddWildcard(xmlSchemaParserCtxtPtr ctxt)
3881{
3882 xmlSchemaWildcardPtr ret = NULL;
3883
3884 if (ctxt == NULL)
3885 return (NULL);
3886
3887 ret = (xmlSchemaWildcardPtr) xmlMalloc(sizeof(xmlSchemaWildcard));
3888 if (ret == NULL) {
3889 xmlSchemaPErrMemory(ctxt, "adding wildcard", NULL);
3890 return (NULL);
3891 }
3892 memset(ret, 0, sizeof(xmlSchemaWildcard));
3893 ret->minOccurs = 1;
3894 ret->maxOccurs = 1;
3895
3896 return (ret);
3897}
3898
Daniel Veillard4255d502002-04-16 15:50:10 +00003899/************************************************************************
3900 * *
3901 * Utilities for parsing *
3902 * *
3903 ************************************************************************/
3904
3905/**
3906 * xmlGetQNameProp:
3907 * @ctxt: a schema validation context
3908 * @node: a subtree containing XML Schema informations
3909 * @name: the attribute name
3910 * @namespace: the result namespace if any
3911 *
3912 * Extract a QName Attribute value
3913 *
3914 * Returns the NCName or NULL if not found, and also update @namespace
3915 * with the namespace URI
3916 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003917static const xmlChar *
Daniel Veillard4255d502002-04-16 15:50:10 +00003918xmlGetQNameProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003919 const char *name, const xmlChar ** namespace)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003920{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003921 const xmlChar *val;
Daniel Veillard4255d502002-04-16 15:50:10 +00003922 xmlNsPtr ns;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003923 const xmlChar *ret, *prefix;
3924 int len;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00003925 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00003926
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003927 *namespace = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00003928 attr = xmlSchemaGetPropNode(node, name);
3929 if (attr == NULL)
3930 return (NULL);
3931 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00003932
Daniel Veillard4255d502002-04-16 15:50:10 +00003933 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003934 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003935
Daniel Veillardba0153a2004-04-01 10:42:31 +00003936 if (!strchr((char *) val, ':')) {
Daniel Veillardebcdebd2004-03-05 00:15:50 +00003937 ns = xmlSearchNs(node->doc, node, 0);
3938 if (ns) {
3939 *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
3940 return (val);
3941 }
3942 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003943 ret = xmlSplitQName3(val, &len);
3944 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003945 return (val);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003946 }
3947 ret = xmlDictLookup(ctxt->dict, ret, -1);
3948 prefix = xmlDictLookup(ctxt->dict, val, len);
Daniel Veillard4255d502002-04-16 15:50:10 +00003949
3950 ns = xmlSearchNs(node->doc, node, prefix);
3951 if (ns == NULL) {
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00003952 xmlSchemaPSimpleTypeErr(ctxt, XML_SCHEMAP_PREFIX_UNDEFINED,
3953 NULL, NULL, (xmlNodePtr) attr,
3954 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), NULL, val,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003955 "The QName value '%s' has no corresponding namespace "
3956 "declaration in scope", val, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00003957 } else {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00003958 *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003959 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003960 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00003961}
3962
3963/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00003964 * xmlSchemaPValAttrNodeQNameValue:
3965 * @ctxt: a schema parser context
3966 * @schema: the schema context
3967 * @ownerDes: the designation of the parent element
3968 * @ownerItem: the parent as a schema object
3969 * @value: the QName value
3970 * @local: the resulting local part if found, the attribute value otherwise
3971 * @uri: the resulting namespace URI if found
3972 *
3973 * Extracts the local name and the URI of a QName value and validates it.
3974 * This one is intended to be used on attribute values that
3975 * should resolve to schema components.
3976 *
3977 * Returns 0, in case the QName is valid, a positive error code
3978 * if not valid and -1 if an internal error occurs.
3979 */
3980static int
3981xmlSchemaPValAttrNodeQNameValue(xmlSchemaParserCtxtPtr ctxt,
3982 xmlSchemaPtr schema,
3983 xmlChar **ownerDes,
3984 xmlSchemaTypePtr ownerItem,
3985 xmlAttrPtr attr,
3986 const xmlChar *value,
3987 const xmlChar **uri,
3988 const xmlChar **prefix,
3989 const xmlChar **local)
3990{
3991 const xmlChar *pref;
3992 xmlNsPtr ns;
3993 int len, ret;
3994
3995 *uri = NULL;
3996 *local = NULL;
3997 if (prefix != 0)
3998 *prefix = NULL;
3999 ret = xmlValidateQName(value, 1);
4000 if (ret > 0) {
4001 xmlSchemaPSimpleTypeErr(ctxt,
4002 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
4003 ownerDes, ownerItem, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00004004 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
4005 "QName", value,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004006 NULL, NULL, NULL);
4007 *local = value;
4008 return (ctxt->err);
4009 } else if (ret < 0)
4010 return (-1);
4011
4012 if (!strchr((char *) value, ':')) {
4013 ns = xmlSearchNs(attr->doc, attr->parent, 0);
4014 if (ns)
4015 *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
4016 else if (schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) {
4017 /*
4018 * This one takes care of included schemas with no
4019 * target namespace.
4020 */
4021 *uri = schema->targetNamespace;
4022 }
4023 *local = value;
4024 return (0);
4025 }
4026 /*
4027 * At this point xmlSplitQName3 has to return a local name.
4028 */
4029 *local = xmlSplitQName3(value, &len);
4030 *local = xmlDictLookup(ctxt->dict, *local, -1);
4031 pref = xmlDictLookup(ctxt->dict, value, len);
4032 if (prefix != 0)
4033 *prefix = pref;
4034 ns = xmlSearchNs(attr->doc, attr->parent, pref);
4035 if (ns == NULL) {
4036 xmlSchemaPSimpleTypeErr(ctxt,
4037 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
4038 ownerDes, ownerItem, (xmlNodePtr) attr,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004039 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), "QName", value,
4040 "The QName value '%s' has no corresponding namespace "
4041 "declaration in scope", value, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004042 return (ctxt->err);
4043 } else {
4044 *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
4045 }
4046 return (0);
4047}
4048
4049/**
4050 * xmlSchemaPValAttrNodeQName:
4051 * @ctxt: a schema parser context
4052 * @schema: the schema context
4053 * @ownerDes: the designation of the owner element
4054 * @ownerItem: the owner as a schema object
4055 * @attr: the attribute node
4056 * @local: the resulting local part if found, the attribute value otherwise
4057 * @uri: the resulting namespace URI if found
4058 *
4059 * Extracts and validates the QName of an attribute value.
4060 * This one is intended to be used on attribute values that
4061 * should resolve to schema components.
4062 *
4063 * Returns 0, in case the QName is valid, a positive error code
4064 * if not valid and -1 if an internal error occurs.
4065 */
4066static int
4067xmlSchemaPValAttrNodeQName(xmlSchemaParserCtxtPtr ctxt,
4068 xmlSchemaPtr schema,
4069 xmlChar **ownerDes,
4070 xmlSchemaTypePtr ownerItem,
4071 xmlAttrPtr attr,
4072 const xmlChar **uri,
4073 const xmlChar **prefix,
4074 const xmlChar **local)
4075{
4076 const xmlChar *value;
4077
4078 value = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
4079 return (xmlSchemaPValAttrNodeQNameValue(ctxt, schema,
4080 ownerDes, ownerItem, attr, value, uri, prefix, local));
4081}
4082
4083/**
4084 * xmlSchemaPValAttrQName:
4085 * @ctxt: a schema parser context
4086 * @schema: the schema context
4087 * @ownerDes: the designation of the parent element
4088 * @ownerItem: the owner as a schema object
4089 * @ownerElem: the parent node of the attribute
4090 * @name: the name of the attribute
4091 * @local: the resulting local part if found, the attribute value otherwise
4092 * @uri: the resulting namespace URI if found
4093 *
4094 * Extracts and validates the QName of an attribute value.
4095 *
4096 * Returns 0, in case the QName is valid, a positive error code
4097 * if not valid and -1 if an internal error occurs.
4098 */
4099static int
4100xmlSchemaPValAttrQName(xmlSchemaParserCtxtPtr ctxt,
4101 xmlSchemaPtr schema,
4102 xmlChar **ownerDes,
4103 xmlSchemaTypePtr ownerItem,
4104 xmlNodePtr ownerElem,
4105 const char *name,
4106 const xmlChar **uri,
4107 const xmlChar **prefix,
4108 const xmlChar **local)
4109{
4110 xmlAttrPtr attr;
4111
4112 attr = xmlSchemaGetPropNode(ownerElem, name);
4113 if (attr == NULL) {
4114 *local = NULL;
4115 *uri = NULL;
4116 return (0);
4117 }
4118 return (xmlSchemaPValAttrNodeQName(ctxt, schema,
4119 ownerDes, ownerItem, attr, uri, prefix, local));
4120}
4121
4122/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004123 * xmlGetMaxOccurs:
4124 * @ctxt: a schema validation context
4125 * @node: a subtree containing XML Schema informations
4126 *
4127 * Get the maxOccurs property
4128 *
4129 * Returns the default if not found, or the value
4130 */
4131static int
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004132xmlGetMaxOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
4133 int min, int max, int def, const char *expected)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004134{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004135 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00004136 int ret = 0;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004137 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00004138
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004139 attr = xmlSchemaGetPropNode(node, "maxOccurs");
4140 if (attr == NULL)
4141 return (def);
4142 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Daniel Veillard4255d502002-04-16 15:50:10 +00004143
4144 if (xmlStrEqual(val, (const xmlChar *) "unbounded")) {
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004145 if (max != UNBOUNDED) {
4146 xmlSchemaPSimpleTypeErr(ctxt,
4147 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
4148 /* XML_SCHEMAP_INVALID_MINOCCURS, */
4149 NULL, NULL, (xmlNodePtr) attr, NULL, expected,
4150 val, NULL, NULL, NULL);
4151 return (def);
4152 } else
4153 return (UNBOUNDED); /* encoding it with -1 might be another option */
Daniel Veillard4255d502002-04-16 15:50:10 +00004154 }
4155
4156 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00004157 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004158 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004159 if (*cur == 0) {
4160 xmlSchemaPSimpleTypeErr(ctxt,
4161 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
4162 /* XML_SCHEMAP_INVALID_MINOCCURS, */
4163 NULL, NULL, (xmlNodePtr) attr, NULL, expected,
4164 val, NULL, NULL, NULL);
4165 return (def);
4166 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004167 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004168 ret = ret * 10 + (*cur - '0');
4169 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00004170 }
William M. Brack76e95df2003-10-18 16:20:14 +00004171 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004172 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004173 /*
4174 * TODO: Restrict the maximal value to Integer.
4175 */
4176 if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
4177 xmlSchemaPSimpleTypeErr(ctxt,
4178 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
4179 /* XML_SCHEMAP_INVALID_MINOCCURS, */
4180 NULL, NULL, (xmlNodePtr) attr, NULL, expected,
4181 val, NULL, NULL, NULL);
4182 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00004183 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004184 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004185}
4186
4187/**
4188 * xmlGetMinOccurs:
4189 * @ctxt: a schema validation context
4190 * @node: a subtree containing XML Schema informations
4191 *
4192 * Get the minOccurs property
4193 *
4194 * Returns the default if not found, or the value
4195 */
4196static int
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004197xmlGetMinOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
4198 int min, int max, int def, const char *expected)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004199{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004200 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00004201 int ret = 0;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004202 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00004203
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004204 attr = xmlSchemaGetPropNode(node, "minOccurs");
4205 if (attr == NULL)
4206 return (def);
4207 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Daniel Veillard4255d502002-04-16 15:50:10 +00004208 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00004209 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004210 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004211 if (*cur == 0) {
4212 xmlSchemaPSimpleTypeErr(ctxt,
4213 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
4214 /* XML_SCHEMAP_INVALID_MINOCCURS, */
4215 NULL, NULL, (xmlNodePtr) attr, NULL, expected,
4216 val, NULL, NULL, NULL);
4217 return (def);
4218 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004219 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004220 ret = ret * 10 + (*cur - '0');
4221 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00004222 }
William M. Brack76e95df2003-10-18 16:20:14 +00004223 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004224 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004225 /*
4226 * TODO: Restrict the maximal value to Integer.
4227 */
4228 if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
4229 xmlSchemaPSimpleTypeErr(ctxt,
4230 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
4231 /* XML_SCHEMAP_INVALID_MINOCCURS, */
4232 NULL, NULL, (xmlNodePtr) attr, NULL, expected,
4233 val, NULL, NULL, NULL);
4234 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00004235 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004236 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004237}
4238
4239/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00004240 * xmlSchemaPGetBoolNodeValue:
4241 * @ctxt: a schema validation context
4242 * @ownerDes: owner designation
4243 * @ownerItem: the owner as a schema item
4244 * @node: the node holding the value
4245 *
4246 * Converts a boolean string value into 1 or 0.
4247 *
4248 * Returns 0 or 1.
4249 */
4250static int
4251xmlSchemaPGetBoolNodeValue(xmlSchemaParserCtxtPtr ctxt,
4252 xmlChar **ownerDes,
4253 xmlSchemaTypePtr ownerItem,
4254 xmlNodePtr node)
4255{
4256 xmlChar *value = NULL;
4257 int res = 0;
4258
4259 value = xmlNodeGetContent(node);
4260 /*
4261 * 3.2.2.1 Lexical representation
4262 * An instance of a datatype that is defined as ·boolean·
4263 * can have the following legal literals {true, false, 1, 0}.
4264 */
4265 if (xmlStrEqual(BAD_CAST value, BAD_CAST "true"))
4266 res = 1;
4267 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "false"))
4268 res = 0;
4269 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "1"))
4270 res = 1;
4271 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "0"))
4272 res = 0;
4273 else {
4274 xmlSchemaPSimpleTypeErr(ctxt,
4275 XML_SCHEMAP_INVALID_BOOLEAN,
4276 ownerDes, ownerItem, node,
4277 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
4278 "(1 | 0 | true | false)", BAD_CAST value,
4279 NULL, NULL, NULL);
4280 }
4281 if (value != NULL)
4282 xmlFree(value);
4283 return (res);
4284}
4285
4286/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004287 * xmlGetBooleanProp:
4288 * @ctxt: a schema validation context
4289 * @node: a subtree containing XML Schema informations
4290 * @name: the attribute name
4291 * @def: the default value
4292 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00004293 * Evaluate if a boolean property is set
Daniel Veillard4255d502002-04-16 15:50:10 +00004294 *
4295 * Returns the default if not found, 0 if found to be false,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004296 * 1 if found to be true
Daniel Veillard4255d502002-04-16 15:50:10 +00004297 */
4298static int
Daniel Veillardc0826a72004-08-10 14:17:33 +00004299xmlGetBooleanProp(xmlSchemaParserCtxtPtr ctxt,
4300 xmlChar **ownerDes,
4301 xmlSchemaTypePtr ownerItem,
4302 xmlNodePtr node,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004303 const char *name, int def)
4304{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004305 const xmlChar *val;
Daniel Veillard4255d502002-04-16 15:50:10 +00004306
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004307 val = xmlSchemaGetProp(ctxt, node, name);
Daniel Veillard4255d502002-04-16 15:50:10 +00004308 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004309 return (def);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004310 /*
4311 * 3.2.2.1 Lexical representation
4312 * An instance of a datatype that is defined as ·boolean·
4313 * can have the following legal literals {true, false, 1, 0}.
4314 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004315 if (xmlStrEqual(val, BAD_CAST "true"))
4316 def = 1;
4317 else if (xmlStrEqual(val, BAD_CAST "false"))
4318 def = 0;
Daniel Veillardc0826a72004-08-10 14:17:33 +00004319 else if (xmlStrEqual(val, BAD_CAST "1"))
4320 def = 1;
4321 else if (xmlStrEqual(val, BAD_CAST "0"))
4322 def = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00004323 else {
Daniel Veillardc0826a72004-08-10 14:17:33 +00004324 xmlSchemaPSimpleTypeErr(ctxt,
4325 XML_SCHEMAP_INVALID_BOOLEAN,
William M. Brack2f2a6632004-08-20 23:09:47 +00004326 ownerDes, ownerItem, node,
4327 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
4328 "(1 | 0 | true | false)", val, NULL, NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004329 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004330 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00004331}
4332
4333/************************************************************************
4334 * *
4335 * Shema extraction from an Infoset *
4336 * *
4337 ************************************************************************/
4338static xmlSchemaTypePtr xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr
4339 ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00004340 xmlNodePtr node,
4341 int topLevel);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004342static xmlSchemaTypePtr xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr
4343 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00004344 xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00004345 xmlNodePtr node,
4346 int topLevel);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004347static xmlSchemaTypePtr xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr
4348 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00004349 xmlSchemaPtr schema,
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00004350 xmlNodePtr node);
Daniel Veillard4255d502002-04-16 15:50:10 +00004351static xmlSchemaTypePtr xmlSchemaParseSequence(xmlSchemaParserCtxtPtr ctxt,
4352 xmlSchemaPtr schema,
4353 xmlNodePtr node);
4354static xmlSchemaTypePtr xmlSchemaParseAll(xmlSchemaParserCtxtPtr ctxt,
4355 xmlSchemaPtr schema,
4356 xmlNodePtr node);
4357static xmlSchemaAttributePtr xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr
4358 ctxt,
4359 xmlSchemaPtr schema,
William M. Bracke7091952004-05-11 15:09:58 +00004360 xmlNodePtr node,
4361 int topLevel);
Daniel Veillard4255d502002-04-16 15:50:10 +00004362static xmlSchemaAttributeGroupPtr
4363xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +00004364 xmlSchemaPtr schema, xmlNodePtr node,
4365 int topLevel);
Daniel Veillard4255d502002-04-16 15:50:10 +00004366static xmlSchemaTypePtr xmlSchemaParseChoice(xmlSchemaParserCtxtPtr ctxt,
4367 xmlSchemaPtr schema,
4368 xmlNodePtr node);
4369static xmlSchemaTypePtr xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt,
4370 xmlSchemaPtr schema,
4371 xmlNodePtr node);
Daniel Veillard3646d642004-06-02 19:19:14 +00004372static xmlSchemaWildcardPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004373xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
4374 xmlSchemaPtr schema, xmlNodePtr node);
Daniel Veillard4255d502002-04-16 15:50:10 +00004375
4376/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004377 * xmlSchemaPValAttrNodeValue:
Daniel Veillard01fa6152004-06-29 17:04:39 +00004378 *
4379 * @ctxt: a schema parser context
Daniel Veillardc0826a72004-08-10 14:17:33 +00004380 * @ownerDes: the designation of the parent element
4381 * @ownerItem: the schema object owner if existent
4382 * @attr: the schema attribute node being validated
4383 * @value: the value
4384 * @type: the built-in type to be validated against
Daniel Veillard01fa6152004-06-29 17:04:39 +00004385 *
4386 * Validates a value against the given built-in type.
4387 * This one is intended to be used internally for validation
4388 * of schema attribute values during parsing of the schema.
4389 *
4390 * Returns 0 if the value is valid, a positive error code
4391 * number otherwise and -1 in case of an internal or API error.
4392 */
4393static int
Daniel Veillardc0826a72004-08-10 14:17:33 +00004394xmlSchemaPValAttrNodeValue(xmlSchemaParserCtxtPtr ctxt,
4395 xmlChar **ownerDes,
4396 xmlSchemaTypePtr ownerItem,
4397 xmlAttrPtr attr,
4398 const xmlChar *value,
4399 xmlSchemaTypePtr type)
Daniel Veillard01fa6152004-06-29 17:04:39 +00004400{
Daniel Veillard01fa6152004-06-29 17:04:39 +00004401
Daniel Veillardc0826a72004-08-10 14:17:33 +00004402 int ret = 0;
4403
4404 /*
4405 * NOTE: Should we move this to xmlschematypes.c? Hmm, but this
4406 * one is really meant to be used internally, so better not.
4407 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00004408 if ((ctxt == NULL) || (type == NULL) || (attr == NULL))
Daniel Veillardc0826a72004-08-10 14:17:33 +00004409 return (-1);
4410 if (type->type != XML_SCHEMA_TYPE_BASIC) {
4411 xmlSchemaPErr(ctxt, (xmlNodePtr) attr,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00004412 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00004413 "Internal error: xmlSchemaPValAttrNodeValue, the given "
Daniel Veillardc0826a72004-08-10 14:17:33 +00004414 "type '%s' is not a built-in type.\n",
4415 type->name, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00004416 return (-1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004417 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00004418 switch (type->builtInType) {
4419 case XML_SCHEMAS_NCNAME:
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00004420 case XML_SCHEMAS_QNAME:
4421 case XML_SCHEMAS_ANYURI:
4422 case XML_SCHEMAS_TOKEN:
4423 case XML_SCHEMAS_LANGUAGE:
4424 ret = xmlSchemaValPredefTypeNode(type, value, NULL, (xmlNodePtr) attr);
4425 break;
4426
4427 /*
4428 case XML_SCHEMAS_NCNAME:
Daniel Veillard01fa6152004-06-29 17:04:39 +00004429 ret = xmlValidateNCName(value, 1);
4430 break;
4431 case XML_SCHEMAS_QNAME:
Daniel Veillardc0826a72004-08-10 14:17:33 +00004432 xmlSchemaPErr(ctxt, (xmlNodePtr) attr,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00004433 XML_SCHEMAP_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004434 "Internal error: xmlSchemaPvalueAttrNode, use "
4435 "the function xmlSchemaExtractSchemaQNamePropvalueidated "
4436 "for extracting QName valueues instead.\n",
4437 NULL, NULL);
4438 return (-1);
4439 case XML_SCHEMAS_ANYURI:
4440 if (value != NULL) {
4441 xmlURIPtr uri = xmlParseURI((const char *) value);
4442 if (uri == NULL)
4443 ret = 1;
4444 else
4445 xmlFreeURI(uri);
Daniel Veillard01fa6152004-06-29 17:04:39 +00004446 }
4447 break;
Daniel Veillardc0826a72004-08-10 14:17:33 +00004448 case XML_SCHEMAS_TOKEN: {
4449 const xmlChar *cur = value;
4450
4451 if (IS_BLANK_CH(*cur)) {
4452 ret = 1;
4453 } else while (*cur != 0) {
4454 if ((*cur == 0xd) || (*cur == 0xa) || (*cur == 0x9)) {
4455 ret = 1;
4456 break;
4457 } else if (*cur == ' ') {
4458 cur++;
4459 if ((*cur == 0) || (*cur == ' ')) {
4460 ret = 1;
4461 break;
4462 }
4463 } else {
4464 cur++;
4465 }
4466 }
4467 }
4468 break;
4469 case XML_SCHEMAS_LANGUAGE:
4470 if (xmlCheckLanguageID(value) != 1)
4471 ret = 1;
4472 break;
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00004473 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00004474 default: {
4475 xmlSchemaPErr(ctxt, (xmlNodePtr) attr,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00004476 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00004477 "Internal error: xmlSchemaPValAttrNodeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +00004478 "valueidation using the type '%s' is not implemented "
4479 "yet.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +00004480 type->name, NULL);
4481 return (-1);
4482 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00004483 }
4484 /*
4485 * TODO: Should we use the S4S error codes instead?
4486 */
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00004487 if (ret < 0) {
4488 xmlSchemaPErr(ctxt, (xmlNodePtr) attr,
4489 XML_SCHEMAP_INTERNAL,
4490 "Internal error: xmlSchemaPValAttrNodeValue, "
4491 "failed to validate a schema attribute value.\n",
4492 NULL, NULL);
4493 return (-1);
4494 } else if (ret > 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00004495 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
4496 xmlSchemaPSimpleTypeErr(ctxt,
4497 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2,
4498 ownerDes, ownerItem, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00004499 type, NULL, value,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004500 NULL, NULL, NULL);
4501 return(XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2);
4502 } else {
4503 xmlSchemaPSimpleTypeErr(ctxt,
4504 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1,
4505 ownerDes, ownerItem, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00004506 type, NULL, value,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004507 NULL, NULL, NULL);
4508 return(XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1);
4509 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00004510 }
4511 return (ret);
4512}
4513
4514/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00004515 * xmlSchemaPValAttrNode:
4516 *
4517 * @ctxt: a schema parser context
4518 * @ownerDes: the designation of the parent element
4519 * @ownerItem: the schema object owner if existent
4520 * @attr: the schema attribute node being validated
4521 * @type: the built-in type to be validated against
4522 * @value: the resulting value if any
4523 *
4524 * Extracts and validates a value against the given built-in type.
4525 * This one is intended to be used internally for validation
4526 * of schema attribute values during parsing of the schema.
4527 *
4528 * Returns 0 if the value is valid, a positive error code
4529 * number otherwise and -1 in case of an internal or API error.
4530 */
4531static int
4532xmlSchemaPValAttrNode(xmlSchemaParserCtxtPtr ctxt,
4533 xmlChar **ownerDes,
4534 xmlSchemaTypePtr ownerItem,
4535 xmlAttrPtr attr,
4536 xmlSchemaTypePtr type,
4537 const xmlChar **value)
4538{
4539 const xmlChar *val;
4540
4541 if ((ctxt == NULL) || (type == NULL) || (attr == NULL))
4542 return (-1);
4543
4544 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
4545 if (value != NULL)
4546 *value = val;
4547
4548 return (xmlSchemaPValAttrNodeValue(ctxt, ownerDes, ownerItem, attr,
4549 val, type));
4550}
4551
4552/**
4553 * xmlSchemaPValAttr:
4554 *
4555 * @ctxt: a schema parser context
4556 * @node: the element node of the attribute
4557 * @ownerDes: the designation of the parent element
4558 * @ownerItem: the schema object owner if existent
4559 * @ownerElem: the owner element node
4560 * @name: the name of the schema attribute node
4561 * @type: the built-in type to be validated against
4562 * @value: the resulting value if any
4563 *
4564 * Extracts and validates a value against the given built-in type.
4565 * This one is intended to be used internally for validation
4566 * of schema attribute values during parsing of the schema.
4567 *
4568 * Returns 0 if the value is valid, a positive error code
4569 * number otherwise and -1 in case of an internal or API error.
4570 */
4571static int
4572xmlSchemaPValAttr(xmlSchemaParserCtxtPtr ctxt,
4573 xmlChar **ownerDes,
4574 xmlSchemaTypePtr ownerItem,
4575 xmlNodePtr ownerElem,
4576 const char *name,
4577 xmlSchemaTypePtr type,
4578 const xmlChar **value)
4579{
4580 xmlAttrPtr attr;
4581
4582 if ((ctxt == NULL) || (type == NULL)) {
4583 if (value != NULL)
4584 *value = NULL;
4585 return (-1);
4586 }
4587 if (type->type != XML_SCHEMA_TYPE_BASIC) {
4588 if (value != NULL)
4589 *value = NULL;
4590 xmlSchemaPErr(ctxt, ownerElem,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00004591 XML_SCHEMAP_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004592 "Internal error: xmlSchemaPValAttr, the given "
4593 "type '%s' is not a built-in type.\n",
4594 type->name, NULL);
4595 return (-1);
4596 }
4597 attr = xmlSchemaGetPropNode(ownerElem, name);
4598 if (attr == NULL) {
4599 if (value != NULL)
4600 *value = NULL;
4601 return (0);
4602 }
4603 return (xmlSchemaPValAttrNode(ctxt, ownerDes, ownerItem, attr,
4604 type, value));
4605}
4606/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004607 * xmlSchemaParseAttrDecls:
4608 * @ctxt: a schema validation context
4609 * @schema: the schema being built
4610 * @node: a subtree containing XML Schema informations
4611 * @type: the hosting type
4612 *
4613 * parse a XML schema attrDecls declaration corresponding to
4614 * <!ENTITY % attrDecls
4615 * '((%attribute;| %attributeGroup;)*,(%anyAttribute;)?)'>
4616 */
4617static xmlNodePtr
4618xmlSchemaParseAttrDecls(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
4619 xmlNodePtr child, xmlSchemaTypePtr type)
4620{
4621 xmlSchemaAttributePtr lastattr, attr;
4622
4623 lastattr = NULL;
4624 while ((IS_SCHEMA(child, "attribute")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004625 (IS_SCHEMA(child, "attributeGroup"))) {
4626 attr = NULL;
4627 if (IS_SCHEMA(child, "attribute")) {
William M. Bracke7091952004-05-11 15:09:58 +00004628 attr = xmlSchemaParseAttribute(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004629 } else if (IS_SCHEMA(child, "attributeGroup")) {
4630 attr = (xmlSchemaAttributePtr)
Daniel Veillard3646d642004-06-02 19:19:14 +00004631 xmlSchemaParseAttributeGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004632 }
4633 if (attr != NULL) {
4634 if (lastattr == NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +00004635 if (type->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP)
4636 ((xmlSchemaAttributeGroupPtr) type)->attributes = attr;
4637 else
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004638 type->attributes = attr;
4639 lastattr = attr;
4640 } else {
4641 lastattr->next = attr;
4642 lastattr = attr;
4643 }
4644 }
4645 child = child->next;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004646 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004647 return (child);
Daniel Veillard4255d502002-04-16 15:50:10 +00004648}
4649
4650/**
4651 * xmlSchemaParseAnnotation:
4652 * @ctxt: a schema validation context
4653 * @schema: the schema being built
4654 * @node: a subtree containing XML Schema informations
4655 *
4656 * parse a XML schema Attrribute declaration
4657 * *WARNING* this interface is highly subject to change
4658 *
William M. Bracke7091952004-05-11 15:09:58 +00004659 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00004660 * 1 in case of success.
4661 */
4662static xmlSchemaAnnotPtr
4663xmlSchemaParseAnnotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
4664 xmlNodePtr node)
4665{
4666 xmlSchemaAnnotPtr ret;
Daniel Veillardc0826a72004-08-10 14:17:33 +00004667 xmlNodePtr child = NULL;
4668 xmlAttrPtr attr;
4669 int barked = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00004670
Daniel Veillardc0826a72004-08-10 14:17:33 +00004671 /*
4672 * INFO: S4S completed.
4673 */
4674 /*
4675 * id = ID
4676 * {any attributes with non-schema namespace . . .}>
4677 * Content: (appinfo | documentation)*
4678 */
Daniel Veillard4255d502002-04-16 15:50:10 +00004679 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
4680 return (NULL);
4681 ret = xmlSchemaNewAnnot(ctxt, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00004682 attr = node->properties;
4683 while (attr != NULL) {
4684 if (((attr->ns == NULL) &&
4685 (!xmlStrEqual(attr->name, BAD_CAST "id"))) ||
4686 ((attr->ns != NULL) &&
4687 xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
4688
4689 xmlSchemaPIllegalAttrErr(ctxt,
4690 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4691 NULL, NULL, attr);
4692 }
4693 attr = attr->next;
4694 }
4695 /* TODO: Check id. */
4696
4697 /*
4698 * And now for the children...
4699 */
4700 child = node->children;
4701 while (child != NULL) {
4702 if (IS_SCHEMA(child, "appinfo")) {
4703 /* TODO: make available the content of "appinfo". */
4704 /*
4705 * source = anyURI
4706 * {any attributes with non-schema namespace . . .}>
4707 * Content: ({any})*
4708 */
4709 attr = child->properties;
4710 while (attr != NULL) {
4711 if (((attr->ns == NULL) &&
4712 (!xmlStrEqual(attr->name, BAD_CAST "source"))) ||
4713 ((attr->ns != NULL) &&
4714 xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004715
Daniel Veillardc0826a72004-08-10 14:17:33 +00004716 xmlSchemaPIllegalAttrErr(ctxt,
4717 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4718 NULL, NULL, attr);
4719 }
4720 attr = attr->next;
4721 }
4722 xmlSchemaPValAttr(ctxt, NULL, NULL, child, "source",
4723 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), NULL);
4724 child = child->next;
4725 } else if (IS_SCHEMA(child, "documentation")) {
4726 /* TODO: make available the content of "documentation". */
4727 /*
4728 * source = anyURI
4729 * {any attributes with non-schema namespace . . .}>
4730 * Content: ({any})*
4731 */
4732 attr = child->properties;
4733 while (attr != NULL) {
4734 if (attr->ns == NULL) {
4735 if (!xmlStrEqual(attr->name, BAD_CAST "source")) {
4736 xmlSchemaPIllegalAttrErr(ctxt,
4737 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4738 NULL, NULL, attr);
4739 }
4740 } else {
4741 if (xmlStrEqual(attr->ns->href, xmlSchemaNs) ||
4742 (xmlStrEqual(attr->name, BAD_CAST "lang") &&
4743 (!xmlStrEqual(attr->ns->href, XML_XML_NAMESPACE)))) {
4744
4745 xmlSchemaPIllegalAttrErr(ctxt,
4746 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
4747 NULL, NULL, attr);
4748 }
4749 }
4750 attr = attr->next;
4751 }
4752 /*
4753 * Attribute "xml:lang".
4754 */
4755 attr = xmlSchemaGetPropNodeNs(child, (const char *) XML_XML_NAMESPACE, "lang");
4756 if (attr != NULL)
4757 xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
4758 xmlSchemaGetBuiltInType(XML_SCHEMAS_LANGUAGE), NULL);
4759 child = child->next;
4760 } else {
4761 if (!barked)
4762 xmlSchemaPContentErr(ctxt,
4763 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
4764 NULL, NULL, node, child, NULL, "(appinfo | documentation)*");
4765 barked = 1;
4766 child = child->next;
4767 }
4768 }
4769
Daniel Veillard4255d502002-04-16 15:50:10 +00004770 return (ret);
4771}
4772
4773/**
4774 * xmlSchemaParseFacet:
4775 * @ctxt: a schema validation context
4776 * @schema: the schema being built
4777 * @node: a subtree containing XML Schema informations
4778 *
4779 * parse a XML schema Facet declaration
4780 * *WARNING* this interface is highly subject to change
4781 *
4782 * Returns the new type structure or NULL in case of error
4783 */
4784static xmlSchemaFacetPtr
4785xmlSchemaParseFacet(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004786 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00004787{
4788 xmlSchemaFacetPtr facet;
4789 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004790 const xmlChar *value;
Daniel Veillard4255d502002-04-16 15:50:10 +00004791
4792 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
4793 return (NULL);
4794
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00004795 facet = xmlSchemaNewFacet();
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004796 if (facet == NULL) {
4797 xmlSchemaPErrMemory(ctxt, "allocating facet", node);
4798 return (NULL);
4799 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004800 facet->node = node;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004801 value = xmlSchemaGetProp(ctxt, node, "value");
Daniel Veillard4255d502002-04-16 15:50:10 +00004802 if (value == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004803 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_FACET_NO_VALUE,
4804 "Facet %s has no value\n", node->name, NULL);
4805 xmlSchemaFreeFacet(facet);
Daniel Veillard4255d502002-04-16 15:50:10 +00004806 return (NULL);
4807 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004808 if (IS_SCHEMA(node, "minInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004809 facet->type = XML_SCHEMA_FACET_MININCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004810 } else if (IS_SCHEMA(node, "minExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004811 facet->type = XML_SCHEMA_FACET_MINEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004812 } else if (IS_SCHEMA(node, "maxInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004813 facet->type = XML_SCHEMA_FACET_MAXINCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004814 } else if (IS_SCHEMA(node, "maxExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004815 facet->type = XML_SCHEMA_FACET_MAXEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004816 } else if (IS_SCHEMA(node, "totalDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004817 facet->type = XML_SCHEMA_FACET_TOTALDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004818 } else if (IS_SCHEMA(node, "fractionDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004819 facet->type = XML_SCHEMA_FACET_FRACTIONDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004820 } else if (IS_SCHEMA(node, "pattern")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004821 facet->type = XML_SCHEMA_FACET_PATTERN;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004822 } else if (IS_SCHEMA(node, "enumeration")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004823 facet->type = XML_SCHEMA_FACET_ENUMERATION;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004824 } else if (IS_SCHEMA(node, "whiteSpace")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004825 facet->type = XML_SCHEMA_FACET_WHITESPACE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004826 } else if (IS_SCHEMA(node, "length")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004827 facet->type = XML_SCHEMA_FACET_LENGTH;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004828 } else if (IS_SCHEMA(node, "maxLength")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00004829 facet->type = XML_SCHEMA_FACET_MAXLENGTH;
4830 } else if (IS_SCHEMA(node, "minLength")) {
4831 facet->type = XML_SCHEMA_FACET_MINLENGTH;
4832 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004833 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_TYPE,
4834 "Unknown facet type %s\n", node->name, NULL);
4835 xmlSchemaFreeFacet(facet);
4836 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004837 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004838 facet->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00004839 facet->value = value;
Daniel Veillard01fa6152004-06-29 17:04:39 +00004840 if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
4841 (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
4842 const xmlChar *fixed;
4843
4844 fixed = xmlSchemaGetProp(ctxt, node, "fixed");
4845 if (fixed != NULL) {
4846 if (xmlStrEqual(fixed, BAD_CAST "true"))
4847 facet->fixed = 1;
4848 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004849 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004850 child = node->children;
4851
4852 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004853 facet->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
4854 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00004855 }
4856 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004857 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_CHILD,
4858 "Facet %s has unexpected child content\n",
4859 node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004860 }
4861 return (facet);
4862}
4863
4864/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00004865 * xmlSchemaParseWildcardNs:
4866 * @ctxt: a schema parser context
4867 * @wildc: the wildcard, already created
4868 * @node: a subtree containing XML Schema informations
4869 *
4870 * Parses the attribute "processContents" and "namespace"
4871 * of a xsd:anyAttribute and xsd:any.
4872 * *WARNING* this interface is highly subject to change
4873 *
4874 * Returns 0 if everything goes fine, a positive error code
4875 * if something is not valid and -1 if an internal error occurs.
4876 */
4877static int
4878xmlSchemaParseWildcardNs(xmlSchemaParserCtxtPtr ctxt,
4879 xmlSchemaPtr schema,
4880 xmlSchemaWildcardPtr wildc,
4881 xmlNodePtr node)
4882{
4883 const xmlChar *pc, *ns, *dictnsItem;
4884 int ret = 0;
4885 xmlChar *nsItem;
4886 xmlSchemaWildcardNsPtr tmp, lastNs = NULL;
4887 xmlAttrPtr attr;
4888
4889 pc = xmlSchemaGetProp(ctxt, node, "processContents");
4890 if ((pc == NULL)
4891 || (xmlStrEqual(pc, (const xmlChar *) "strict"))) {
4892 wildc->processContents = XML_SCHEMAS_ANY_STRICT;
4893 } else if (xmlStrEqual(pc, (const xmlChar *) "skip")) {
4894 wildc->processContents = XML_SCHEMAS_ANY_SKIP;
4895 } else if (xmlStrEqual(pc, (const xmlChar *) "lax")) {
4896 wildc->processContents = XML_SCHEMAS_ANY_LAX;
4897 } else {
4898 xmlSchemaPSimpleTypeErr(ctxt,
4899 XML_SCHEMAP_UNKNOWN_PROCESSCONTENT_CHILD,
4900 NULL, NULL, node,
William M. Brack2f2a6632004-08-20 23:09:47 +00004901 NULL, "(strict | skip | lax)", pc,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004902 NULL, NULL, NULL);
4903 wildc->processContents = XML_SCHEMAS_ANY_STRICT;
4904 ret = XML_SCHEMAP_UNKNOWN_PROCESSCONTENT_CHILD;
4905 }
4906 /*
4907 * Build the namespace constraints.
4908 */
4909 attr = xmlSchemaGetPropNode(node, "namespace");
4910 ns = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
4911 if ((ns == NULL) || (xmlStrEqual(ns, BAD_CAST "##any")))
4912 wildc->any = 1;
4913 else if (xmlStrEqual(ns, BAD_CAST "##other")) {
4914 wildc->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
4915 if (wildc->negNsSet == NULL) {
4916 return (-1);
4917 }
4918 wildc->negNsSet->value = schema->targetNamespace;
4919 } else {
4920 const xmlChar *end, *cur;
4921
4922 cur = ns;
4923 do {
4924 while (IS_BLANK_CH(*cur))
4925 cur++;
4926 end = cur;
4927 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
4928 end++;
4929 if (end == cur)
4930 break;
4931 nsItem = xmlStrndup(cur, end - cur);
4932 if ((xmlStrEqual(nsItem, BAD_CAST "##other")) ||
4933 (xmlStrEqual(nsItem, BAD_CAST "##any"))) {
4934 xmlSchemaPSimpleTypeErr(ctxt,
4935 XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER,
4936 NULL, NULL, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00004937 NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004938 "((##any | ##other) | List of (anyURI | "
4939 "(##targetNamespace | ##local)))",
4940 nsItem, NULL, NULL, NULL);
4941 ret = XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER;
4942 } else {
4943 if (xmlStrEqual(nsItem, BAD_CAST "##targetNamespace")) {
4944 dictnsItem = schema->targetNamespace;
4945 } else if (xmlStrEqual(nsItem, BAD_CAST "##local")) {
4946 dictnsItem = NULL;
4947 } else {
4948 /*
4949 * Validate the item (anyURI).
4950 */
4951 xmlSchemaPValAttrNodeValue(ctxt, NULL, NULL, attr,
4952 nsItem, xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI));
4953 dictnsItem = xmlDictLookup(ctxt->dict, nsItem, -1);
4954 }
4955 /*
4956 * Avoid dublicate namespaces.
4957 */
4958 tmp = wildc->nsSet;
4959 while (tmp != NULL) {
4960 if (dictnsItem == tmp->value)
4961 break;
4962 tmp = tmp->next;
4963 }
4964 if (tmp == NULL) {
4965 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
4966 if (tmp == NULL) {
4967 xmlFree(nsItem);
4968 return (-1);
4969 }
4970 tmp->value = dictnsItem;
4971 tmp->next = NULL;
4972 if (wildc->nsSet == NULL)
4973 wildc->nsSet = tmp;
4974 else
4975 lastNs->next = tmp;
4976 lastNs = tmp;
4977 }
4978
4979 }
4980 xmlFree(nsItem);
4981 cur = end;
4982 } while (*cur != 0);
4983 }
4984 return (ret);
4985}
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00004986
4987static int
4988xmlSchemaPCheckParticleCorrect_2(xmlSchemaParserCtxtPtr ctxt,
4989 xmlSchemaTypePtr item,
4990 xmlNodePtr node,
4991 int minOccurs,
4992 int maxOccurs) {
4993
4994 if (maxOccurs != UNBOUNDED) {
4995 /*
4996 * TODO: Maby we should better not create the particle,
4997 * if min/max is invalid, since it could confuse the build of the
4998 * content model.
4999 */
5000 /*
5001 * 3.9.6 Schema Component Constraint: Particle Correct
5002 *
5003 */
5004 if (maxOccurs < 1) {
5005 /*
5006 * 2.2 {max occurs} must be greater than or equal to 1.
5007 */
5008 xmlSchemaPCustomAttrErr(ctxt,
5009 XML_SCHEMAP_P_PROPS_CORRECT_2_2,
5010 NULL, item, xmlSchemaGetPropNode(node, "maxOccurs"),
5011 "The value must be greater than or equal to 1");
5012 return (XML_SCHEMAP_P_PROPS_CORRECT_2_2);
5013 } else if (minOccurs > maxOccurs) {
5014 /*
5015 * 2.1 {min occurs} must not be greater than {max occurs}.
5016 */
5017 xmlSchemaPCustomAttrErr(ctxt,
5018 XML_SCHEMAP_P_PROPS_CORRECT_2_1,
5019 NULL, item, xmlSchemaGetPropNode(node, "minOccurs"),
5020 "The value must not be greater than the value of 'maxOccurs'");
5021 return (XML_SCHEMAP_P_PROPS_CORRECT_2_1);
5022 }
5023 }
5024 return (0);
5025}
5026
Daniel Veillardc0826a72004-08-10 14:17:33 +00005027/**
Daniel Veillard4255d502002-04-16 15:50:10 +00005028 * xmlSchemaParseAny:
5029 * @ctxt: a schema validation context
5030 * @schema: the schema being built
5031 * @node: a subtree containing XML Schema informations
5032 *
5033 * parse a XML schema Any declaration
5034 * *WARNING* this interface is highly subject to change
5035 *
5036 * Returns the new type structure or NULL in case of error
5037 */
5038static xmlSchemaTypePtr
5039xmlSchemaParseAny(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5040 xmlNodePtr node)
5041{
5042 xmlSchemaTypePtr type;
5043 xmlNodePtr child = NULL;
5044 xmlChar name[30];
Daniel Veillardc0826a72004-08-10 14:17:33 +00005045 xmlSchemaWildcardPtr wildc;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005046 int minOccurs, maxOccurs;
Daniel Veillard4255d502002-04-16 15:50:10 +00005047
5048 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5049 return (NULL);
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005050 maxOccurs = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
5051 "(nonNegativeInteger | unbounded)");
5052 minOccurs = xmlGetMinOccurs(ctxt, node, 0, -1, 1,
5053 "nonNegativeInteger");
5054 if ((minOccurs == 0) && (maxOccurs == 0))
5055 return (NULL);
5056
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00005057 snprintf((char *) name, 30, "#any%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00005058 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00005059 if (type == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005060 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005061 type->node = node;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005062 type->type = XML_SCHEMA_TYPE_ANY;
5063
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00005064 /*
5065 * TODO: Use a particle component here.
5066 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00005067 wildc = xmlSchemaAddWildcard(ctxt);
5068 /*
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005069 * Check min/max sanity.
5070 */
5071 type->maxOccurs = maxOccurs;
5072 type->minOccurs = minOccurs;
5073 xmlSchemaPCheckParticleCorrect_2(ctxt, type,
5074 node, type->minOccurs, type->maxOccurs);
5075 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00005076 * This is not nice, since it is won't be used as a attribute wildcard,
5077 * but better than adding a field to the structure.
5078 */
5079 type->attributeWildcard = wildc;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005080 xmlSchemaParseWildcardNs(ctxt, schema, wildc, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005081 child = node->children;
Daniel Veillard4255d502002-04-16 15:50:10 +00005082 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005083 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5084 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005085 }
5086 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005087 xmlSchemaPErr2(ctxt, node, child,
5088 XML_SCHEMAP_UNKNOWN_SEQUENCE_CHILD,
5089 "Sequence %s has unexpected content\n", type->name,
5090 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005091 }
5092
5093 return (type);
5094}
5095
5096/**
5097 * xmlSchemaParseNotation:
5098 * @ctxt: a schema validation context
5099 * @schema: the schema being built
5100 * @node: a subtree containing XML Schema informations
5101 *
5102 * parse a XML schema Notation declaration
5103 *
5104 * Returns the new structure or NULL in case of error
5105 */
5106static xmlSchemaNotationPtr
5107xmlSchemaParseNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005108 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00005109{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005110 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00005111 xmlSchemaNotationPtr ret;
5112 xmlNodePtr child = NULL;
5113
5114 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5115 return (NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005116 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00005117 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005118 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_NOTATION_NO_NAME,
5119 "Notation has no name\n", NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005120 return (NULL);
5121 }
5122 ret = xmlSchemaAddNotation(ctxt, schema, name);
5123 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005124 return (NULL);
5125 }
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00005126 ret->targetNamespace = schema->targetNamespace;
Daniel Veillard4255d502002-04-16 15:50:10 +00005127 child = node->children;
5128 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005129 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5130 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005131 }
5132 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005133 xmlSchemaPErr2(ctxt, node, child,
5134 XML_SCHEMAP_UNKNOWN_NOTATION_CHILD,
5135 "notation %s has unexpected content\n", name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005136 }
5137
5138 return (ret);
5139}
5140
5141/**
5142 * xmlSchemaParseAnyAttribute:
5143 * @ctxt: a schema validation context
5144 * @schema: the schema being built
5145 * @node: a subtree containing XML Schema informations
5146 *
5147 * parse a XML schema AnyAttrribute declaration
5148 * *WARNING* this interface is highly subject to change
5149 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005150 * Returns a wildcard or NULL.
Daniel Veillard4255d502002-04-16 15:50:10 +00005151 */
Daniel Veillard3646d642004-06-02 19:19:14 +00005152static xmlSchemaWildcardPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005153xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
5154 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00005155{
Daniel Veillard3646d642004-06-02 19:19:14 +00005156 xmlSchemaWildcardPtr ret;
Daniel Veillard4255d502002-04-16 15:50:10 +00005157 xmlNodePtr child = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005158 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005159
5160 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5161 return (NULL);
5162
Daniel Veillard3646d642004-06-02 19:19:14 +00005163 ret = xmlSchemaAddWildcard(ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +00005164 if (ret == NULL) {
5165 return (NULL);
5166 }
William M. Bracke7091952004-05-11 15:09:58 +00005167 ret->type = XML_SCHEMA_TYPE_ANY_ATTRIBUTE;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005168 /*
5169 * Check for illegal attributes.
5170 */
5171 attr = node->properties;
5172 while (attr != NULL) {
5173 if (attr->ns == NULL) {
5174 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
5175 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
5176 (!xmlStrEqual(attr->name, BAD_CAST "processContents"))) {
5177 xmlSchemaPIllegalAttrErr(ctxt,
5178 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5179 NULL, NULL, attr);
5180 }
5181 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5182 xmlSchemaPIllegalAttrErr(ctxt,
5183 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5184 NULL, NULL, attr);
5185 }
5186 attr = attr->next;
5187 }
5188 /* ret->id = xmlSchemaGetProp(ctxt, node, "id"); */
5189 /*
5190 * Parse the namespace list.
5191 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00005192 if (xmlSchemaParseWildcardNs(ctxt, schema, ret, node) != 0) {
5193 xmlSchemaFreeWildcard(ret);
5194 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005195 }
5196 /*
5197 * And now for the children...
5198 */
Daniel Veillard4255d502002-04-16 15:50:10 +00005199 child = node->children;
5200 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005201 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5202 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005203 }
5204 if (child != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00005205 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005206 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
5207 NULL, NULL, node, child,
5208 NULL, "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00005209 }
5210
5211 return (ret);
5212}
5213
5214
5215/**
5216 * xmlSchemaParseAttribute:
5217 * @ctxt: a schema validation context
5218 * @schema: the schema being built
5219 * @node: a subtree containing XML Schema informations
5220 *
5221 * parse a XML schema Attrribute declaration
5222 * *WARNING* this interface is highly subject to change
5223 *
William M. Bracke7091952004-05-11 15:09:58 +00005224 * Returns the attribute declaration.
Daniel Veillard4255d502002-04-16 15:50:10 +00005225 */
5226static xmlSchemaAttributePtr
5227xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Bracke7091952004-05-11 15:09:58 +00005228 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00005229{
Daniel Veillardc0826a72004-08-10 14:17:33 +00005230 const xmlChar *name, *attrValue;
5231 xmlChar *repName = NULL; /* The reported designation. */
Daniel Veillard4255d502002-04-16 15:50:10 +00005232 xmlSchemaAttributePtr ret;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005233 xmlNodePtr child = NULL;
5234 xmlAttrPtr attr, nameAttr;
5235 int isRef = 0;
William M. Bracke7091952004-05-11 15:09:58 +00005236
5237 /*
5238 * Note that the w3c spec assumes the schema to be validated with schema
5239 * for schemas beforehand.
5240 *
5241 * 3.2.3 Constraints on XML Representations of Attribute Declarations
William M. Bracke7091952004-05-11 15:09:58 +00005242 */
Daniel Veillard4255d502002-04-16 15:50:10 +00005243
5244 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5245 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005246 attr = xmlSchemaGetPropNode(node, "ref");
5247 nameAttr = xmlSchemaGetPropNode(node, "name");
5248
5249 if ((attr == NULL) && (nameAttr == NULL)) {
5250 /*
5251 * 3.2.3 : 3.1
5252 * One of ref or name must be present, but not both
5253 */
5254 xmlSchemaPMissingAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_1,
5255 (xmlChar **) &xmlSchemaElemDesAttrDecl, NULL, node, NULL,
5256 "One of the attributes 'ref' or 'name' must be present");
5257 return (NULL);
5258 }
5259 if ((topLevel) || (attr == NULL)) {
5260 if (nameAttr == NULL) {
5261 xmlSchemaPMissingAttrErr(ctxt, XML_SCHEMAP_S4S_ATTR_MISSING,
5262 (xmlChar **) &xmlSchemaElemDesAttrDecl, NULL, node,
5263 "name", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00005264 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005265 }
5266 } else
5267 isRef = 1;
5268
5269 if (isRef) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005270 char buf[50];
Daniel Veillardc0826a72004-08-10 14:17:33 +00005271 const xmlChar *refNs = NULL, *ref = NULL, *refPrefix = NULL;
5272
5273 /*
5274 * Parse as attribute reference.
5275 */
5276 if (xmlSchemaPValAttrNodeQName(ctxt, schema,
5277 (xmlChar **) &xmlSchemaElemDesAttrRef, NULL, attr, &refNs,
5278 &refPrefix, &ref) != 0) {
5279 return (NULL);
5280 }
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00005281 snprintf(buf, 49, "#aRef%d", ctxt->counter++ + 1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005282 name = (const xmlChar *) buf;
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00005283 ret = xmlSchemaAddAttribute(ctxt, schema, name, NULL, node, 0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005284 if (ret == NULL) {
5285 if (repName != NULL)
5286 xmlFree(repName);
5287 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00005288 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005289 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
5290 ret->node = node;
5291 ret->refNs = refNs;
5292 ret->refPrefix = refPrefix;
5293 ret->ref = ref;
5294 /*
5295 xmlSchemaFormatTypeRep(&repName, (xmlSchemaTypePtr) ret, NULL, NULL);
5296 */
5297 if (nameAttr != NULL)
5298 xmlSchemaPMutualExclAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_1,
5299 &repName, (xmlSchemaTypePtr) ret, nameAttr,
5300 "ref", "name");
5301 /*
5302 * Check for illegal attributes.
5303 */
5304 attr = node->properties;
5305 while (attr != NULL) {
5306 if (attr->ns == NULL) {
5307 if (xmlStrEqual(attr->name, BAD_CAST "type") ||
5308 xmlStrEqual(attr->name, BAD_CAST "form")) {
5309 /*
5310 * 3.2.3 : 3.2
5311 * If ref is present, then all of <simpleType>,
5312 * form and type must be absent.
5313 */
5314 xmlSchemaPIllegalAttrErr(ctxt,
5315 XML_SCHEMAP_SRC_ATTRIBUTE_3_2, &repName,
5316 (xmlSchemaTypePtr) ret, attr);
5317 } else if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
5318 (!xmlStrEqual(attr->name, BAD_CAST "use")) &&
5319 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
5320 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
5321 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
5322 (!xmlStrEqual(attr->name, BAD_CAST "default"))) {
5323 xmlSchemaPIllegalAttrErr(ctxt,
5324 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5325 &repName, (xmlSchemaTypePtr) ret, attr);
5326 }
5327 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5328 xmlSchemaPIllegalAttrErr(ctxt,
5329 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5330 &repName, (xmlSchemaTypePtr) ret, attr);
5331 }
5332 attr = attr->next;
5333 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005334 } else {
William M. Bracke7091952004-05-11 15:09:58 +00005335 const xmlChar *ns = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005336
5337 /*
5338 * Parse as attribute declaration.
5339 */
5340 if (xmlSchemaPValAttrNode(ctxt,
5341 (xmlChar **) &xmlSchemaElemDesAttrDecl, NULL, nameAttr,
5342 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
5343 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00005344 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005345 /*
5346 xmlSchemaFormatTypeRep(&repName, NULL, xmlSchemaElemDesAttrDecl, name);
5347 */
5348 /*
5349 * 3.2.6 Schema Component Constraint: xmlns Not Allowed
5350 */
5351 if (xmlStrEqual(name, BAD_CAST "xmlns")) {
5352 xmlSchemaPSimpleTypeErr(ctxt,
5353 XML_SCHEMAP_NO_XMLNS,
5354 &repName, NULL, (xmlNodePtr) nameAttr,
William M. Brack2f2a6632004-08-20 23:09:47 +00005355 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), "NCName", NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005356 "The value must not match 'xmlns'",
5357 NULL, NULL);
5358 if (repName != NULL)
5359 xmlFree(repName);
5360 return (NULL);
5361 }
5362 /*
5363 * Evaluate the target namespace
5364 */
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005365 if (topLevel) {
5366 ns = schema->targetNamespace;
5367 } else {
5368 attr = xmlSchemaGetPropNode(node, "form");
5369 if (attr != NULL) {
5370 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5371 if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
5372 ns = schema->targetNamespace;
5373 } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) {
5374 xmlSchemaPSimpleTypeErr(ctxt,
5375 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5376 &repName, NULL, (xmlNodePtr) attr,
5377 NULL, "(qualified | unqualified)",
5378 attrValue, NULL, NULL, NULL);
5379 }
5380 } else if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
5381 ns = schema->targetNamespace;
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00005382 }
5383 ret = xmlSchemaAddAttribute(ctxt, schema, name, ns, node, topLevel);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005384 if (ret == NULL) {
5385 if (repName != NULL)
5386 xmlFree(repName);
Daniel Veillard3646d642004-06-02 19:19:14 +00005387 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00005388 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005389 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00005390 ret->node = node;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005391 if (topLevel)
5392 ret->flags |= XML_SCHEMAS_ATTR_GLOBAL;
5393 /*
5394 * 3.2.6 Schema Component Constraint: xsi: Not Allowed
5395 */
5396 if (xmlStrEqual(ret->targetNamespace, xmlSchemaInstanceNs)) {
5397 xmlSchemaPCustomErr(ctxt,
5398 XML_SCHEMAP_NO_XSI,
5399 &repName, (xmlSchemaTypePtr) ret, node,
5400 "The target namespace must not match '%s'",
5401 xmlSchemaInstanceNs);
5402 }
5403 /*
5404 * Check for illegal attributes.
5405 */
5406 attr = node->properties;
5407 while (attr != NULL) {
5408 if (attr->ns == NULL) {
5409 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
5410 (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
5411 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
5412 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
5413 (!xmlStrEqual(attr->name, BAD_CAST "type"))) {
5414 if ((topLevel) ||
5415 ((!xmlStrEqual(attr->name, BAD_CAST "form")) &&
5416 (!xmlStrEqual(attr->name, BAD_CAST "use")))) {
5417 xmlSchemaPIllegalAttrErr(ctxt,
5418 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5419 &repName, (xmlSchemaTypePtr) ret, attr);
5420 }
5421 }
5422 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5423 xmlSchemaPIllegalAttrErr(ctxt, XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5424 &repName, (xmlSchemaTypePtr) ret, attr);
5425 }
5426 attr = attr->next;
5427 }
5428 xmlSchemaPValAttrQName(ctxt, schema, &repName, (xmlSchemaTypePtr) ret,
5429 node, "type", &ret->typeNs, NULL, &ret->typeName);
William M. Bracke7091952004-05-11 15:09:58 +00005430 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005431 /* TODO: Check ID. */
5432 ret->id = xmlSchemaGetProp(ctxt, node, "id");
William M. Bracke7091952004-05-11 15:09:58 +00005433 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00005434 * Attribute "fixed".
William M. Bracke7091952004-05-11 15:09:58 +00005435 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00005436 ret->defValue = xmlSchemaGetProp(ctxt, node, "fixed");
5437 if (ret->defValue != NULL)
5438 ret->flags |= XML_SCHEMAS_ATTR_FIXED;
5439 /*
5440 * Attribute "default".
5441 */
5442 attr = xmlSchemaGetPropNode(node, "default");
5443 if (attr != NULL) {
5444 /*
5445 * 3.2.3 : 1
5446 * default and fixed must not both be present.
5447 */
5448 if (ret->flags & XML_SCHEMAS_ATTR_FIXED) {
5449 xmlSchemaPMutualExclAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_1,
5450 &repName, (xmlSchemaTypePtr) ret, attr, "default", "fixed");
5451 } else
5452 ret->defValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5453 }
5454 if (topLevel == 0) {
5455 /*
5456 * Attribute "use".
5457 */
5458 attr = xmlSchemaGetPropNode(node, "use");
5459 if (attr != NULL) {
5460 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5461 if (xmlStrEqual(attrValue, BAD_CAST "optional"))
5462 ret->occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
5463 else if (xmlStrEqual(attrValue, BAD_CAST "prohibited"))
5464 ret->occurs = XML_SCHEMAS_ATTR_USE_PROHIBITED;
5465 else if (xmlStrEqual(attrValue, BAD_CAST "required"))
5466 ret->occurs = XML_SCHEMAS_ATTR_USE_REQUIRED;
5467 else
5468 xmlSchemaPSimpleTypeErr(ctxt,
5469 XML_SCHEMAP_INVALID_ATTR_USE,
5470 &repName, (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00005471 NULL, "(optional | prohibited | required)",
Daniel Veillardc0826a72004-08-10 14:17:33 +00005472 attrValue, NULL, NULL, NULL);
5473 } else
5474 ret->occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
5475 /*
5476 * 3.2.3 : 2
5477 * If default and use are both present, use must have
5478 * the actual value optional.
5479 */
5480 if ((ret->occurs != XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
5481 (ret->defValue != NULL) &&
5482 ((ret->flags & XML_SCHEMAS_ATTR_FIXED) == 0)) {
5483 xmlSchemaPSimpleTypeErr(ctxt,
5484 XML_SCHEMAP_SRC_ATTRIBUTE_2,
5485 &repName, (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00005486 NULL, "(optional | prohibited | required)", NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005487 "The value must be 'optional' if the attribute "
5488 "'default' is present as well", NULL, NULL);
5489 }
5490 }
5491 /*
5492 * And now for the children...
5493 */
Daniel Veillard4255d502002-04-16 15:50:10 +00005494 child = node->children;
5495 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005496 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5497 child = child->next;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005498 }
5499 if (isRef) {
5500 if (child != NULL) {
5501 if (IS_SCHEMA(child, "simpleType"))
5502 /*
5503 * 3.2.3 : 3.2
5504 * If ref is present, then all of <simpleType>,
5505 * form and type must be absent.
5506 */
5507 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_2,
5508 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
5509 "(annotation?)");
5510 else
5511 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
5512 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
5513 "(annotation?)");
5514 }
5515 } else {
5516 if (IS_SCHEMA(child, "simpleType")) {
5517 if (ret->typeName != NULL) {
5518 /*
5519 * 3.2.3 : 4
5520 * type and <simpleType> must not both be present.
5521 */
5522 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_4,
5523 &repName, (xmlSchemaTypePtr) ret, node, child,
5524 "The attribute 'type' and the <simpleType> child "
5525 "are mutually exclusive", NULL);
5526 } else
5527 ret->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
5528 child = child->next;
5529 }
5530 if (child != NULL)
5531 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
5532 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
5533 "(annotation?, simpleType?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00005534 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005535 /*
5536 * Cleanup.
5537 */
5538 if (repName != NULL)
5539 xmlFree(repName);
Daniel Veillard4255d502002-04-16 15:50:10 +00005540 return (ret);
5541}
5542
5543/**
5544 * xmlSchemaParseAttributeGroup:
5545 * @ctxt: a schema validation context
5546 * @schema: the schema being built
5547 * @node: a subtree containing XML Schema informations
5548 *
5549 * parse a XML schema Attribute Group declaration
5550 * *WARNING* this interface is highly subject to change
5551 *
5552 * Returns the attribute group or NULL in case of error.
5553 */
5554static xmlSchemaAttributeGroupPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005555xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +00005556 xmlSchemaPtr schema, xmlNodePtr node,
5557 int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00005558{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005559 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00005560 xmlSchemaAttributeGroupPtr ret;
Daniel Veillard4255d502002-04-16 15:50:10 +00005561 xmlNodePtr child = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005562 const xmlChar *oldcontainer;
5563 xmlAttrPtr attr, nameAttr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005564
5565 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5566 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005567
5568 nameAttr = xmlSchemaGetPropNode(node, "name");
5569 attr = xmlSchemaGetPropNode(node, "ref");
5570 if ((topLevel) || (attr == NULL)) {
5571 /*
5572 * Parse as an attribute group definition.
5573 * Note that those are allowed at top level only.
5574 */
5575 if (nameAttr == NULL) {
5576 xmlSchemaPMissingAttrErr(ctxt,
5577 XML_SCHEMAP_S4S_ATTR_MISSING,
5578 NULL, NULL, node, "name", NULL);
5579 return (NULL);
5580 }
5581 name = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) nameAttr);
5582 /*
5583 * The name is crucial, exit if invalid.
5584 */
5585 if (xmlSchemaPValAttrNode(ctxt,
5586 NULL, NULL, nameAttr,
5587 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
5588 return (NULL);
5589 }
5590 ret = xmlSchemaAddAttributeGroup(ctxt, schema, name, node);
5591 if (ret == NULL)
5592 return (NULL);
5593 ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
5594 ret->flags |= XML_SCHEMAS_ATTRGROUP_GLOBAL;
5595 ret->node = node;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00005596 ret->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005597 } else {
5598 char buf[50];
5599 const xmlChar *refNs = NULL, *ref = NULL, *refPrefix;
5600
5601 /*
5602 * Parse as an attribute group definition reference.
5603 */
5604 if (attr == NULL) {
5605 xmlSchemaPMissingAttrErr(ctxt,
5606 XML_SCHEMAP_S4S_ATTR_MISSING,
5607 NULL, NULL, node, "ref", NULL);
5608 }
5609 xmlSchemaPValAttrNodeQName(ctxt, schema,
5610 NULL, NULL, attr, &refNs, &refPrefix, &ref);
5611
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00005612 snprintf(buf, 49, "#agRef%d", ctxt->counter++ + 1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005613 name = (const xmlChar *) buf;
5614 if (name == NULL) {
5615 xmlSchemaPErrMemory(ctxt, "creating internal name for an "
5616 "attribute group definition reference", node);
5617 return (NULL);
5618 }
5619 ret = xmlSchemaAddAttributeGroup(ctxt, schema, name, node);
5620 if (ret == NULL)
5621 return (NULL);
5622 ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
5623 ret->ref = ref;
5624 ret->refNs = refNs;
5625 /* TODO: Is @refPrefix currently used? */
5626 ret->refPrefix = refPrefix;
5627 ret->node = node;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00005628 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005629 /*
5630 * Check for illegal attributes.
5631 */
5632 attr = node->properties;
5633 while (attr != NULL) {
5634 if (attr->ns == NULL) {
5635 if ((((topLevel == 0) && (!xmlStrEqual(attr->name, BAD_CAST "ref"))) ||
5636 (topLevel && (!xmlStrEqual(attr->name, BAD_CAST "name")))) &&
5637 (!xmlStrEqual(attr->name, BAD_CAST "id")))
5638 {
5639 xmlSchemaPIllegalAttrErr(ctxt,
5640 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5641 NULL, NULL, attr);
5642 }
5643 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5644 xmlSchemaPIllegalAttrErr(ctxt,
5645 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5646 NULL, NULL, attr);
5647 }
5648 attr = attr->next;
5649 }
5650 /* TODO: Validate "id" ? */
5651 /*
5652 * And now for the children...
5653 */
Daniel Veillard4255d502002-04-16 15:50:10 +00005654 oldcontainer = ctxt->container;
Daniel Veillard4255d502002-04-16 15:50:10 +00005655 ctxt->container = name;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005656 child = node->children;
Daniel Veillard4255d502002-04-16 15:50:10 +00005657 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005658 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
5659 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00005660 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005661 if (topLevel) {
5662 child = xmlSchemaParseAttrDecls(ctxt, schema, child, (xmlSchemaTypePtr) ret);
5663 if (IS_SCHEMA(child, "anyAttribute")) {
5664 ret->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
5665 child = child->next;
5666 }
5667 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005668 if (child != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005669 xmlSchemaPContentErr(ctxt,
5670 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
5671 NULL, NULL, node, child, NULL,
5672 "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00005673 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005674 ctxt->container = oldcontainer;
5675 return (ret);
5676}
5677
5678/**
William M. Brack2f2a6632004-08-20 23:09:47 +00005679 * xmlSchemaPValAttrFormDefault:
5680 * @value: the value
5681 * @flags: the flags to be modified
5682 * @flagQualified: the specific flag for "qualified"
5683 *
5684 * Returns 0 if the value is valid, 1 otherwise.
5685 */
5686static int
5687xmlSchemaPValAttrFormDefault(const xmlChar *value,
5688 int *flags,
5689 int flagQualified)
5690{
5691 if (xmlStrEqual(value, BAD_CAST "qualified")) {
5692 if ((*flags & flagQualified) == 0)
5693 *flags |= flagQualified;
5694 } else if (!xmlStrEqual(value, BAD_CAST "unqualified"))
5695 return (1);
5696
5697 return (0);
5698}
5699
5700/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00005701 * xmlSchemaPValAttrBlockFinal:
5702 * @value: the value
5703 * @flags: the flags to be modified
5704 * @flagAll: the specific flag for "#all"
5705 * @flagExtension: the specific flag for "extension"
5706 * @flagRestriction: the specific flag for "restriction"
5707 * @flagSubstitution: the specific flag for "substitution"
5708 * @flagList: the specific flag for "list"
5709 * @flagUnion: the specific flag for "union"
5710 *
5711 * Validates the value of the attribute "final" and "block". The value
5712 * is converted into the specified flag values and returned in @flags.
5713 *
5714 * Returns 0 if the value is valid, 1 otherwise.
5715 */
5716
5717static int
5718xmlSchemaPValAttrBlockFinal(const xmlChar *value,
5719 int *flags,
5720 int flagAll,
5721 int flagExtension,
5722 int flagRestriction,
5723 int flagSubstitution,
5724 int flagList,
5725 int flagUnion)
5726{
5727 int ret = 0;
5728
5729 /*
5730 * TODO: This does not check for dublicate entries.
5731 */
William M. Brack2f2a6632004-08-20 23:09:47 +00005732 if (value == NULL)
5733 return (1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005734 if (xmlStrEqual(value, BAD_CAST "#all")) {
5735 if (flagAll != -1)
5736 *flags |= flagAll;
5737 else {
5738 if (flagExtension != -1)
5739 *flags |= flagExtension;
5740 if (flagRestriction != -1)
5741 *flags |= flagRestriction;
5742 if (flagSubstitution != -1)
5743 *flags |= flagSubstitution;
5744 if (flagList != -1)
5745 *flags |= flagList;
5746 if (flagUnion != -1)
5747 *flags |= flagUnion;
5748 }
5749 } else {
5750 const xmlChar *end, *cur = value;
5751 xmlChar *item;
5752
5753 do {
5754 while (IS_BLANK_CH(*cur))
5755 cur++;
5756 end = cur;
5757 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
5758 end++;
5759 if (end == cur)
5760 break;
5761 item = xmlStrndup(cur, end - cur);
5762 if (xmlStrEqual(item, BAD_CAST "extension")) {
5763 if (flagExtension != -1) {
5764 if ((*flags & flagExtension) == 0)
5765 *flags |= flagExtension;
5766 } else
5767 ret = 1;
5768 } else if (xmlStrEqual(item, BAD_CAST "restriction")) {
5769 if (flagRestriction != -1) {
5770 if ((*flags & flagRestriction) == 0)
5771 *flags |= flagRestriction;
5772 } else
5773 ret = 1;
5774 } else if (xmlStrEqual(item, BAD_CAST "substitution")) {
5775 if (flagSubstitution != -1) {
5776 if ((*flags & flagSubstitution) == 0)
5777 *flags |= flagSubstitution;
5778 } else
5779 ret = 1;
5780 } else if (xmlStrEqual(item, BAD_CAST "list")) {
5781 if (flagList != -1) {
5782 if ((*flags & flagList) == 0)
5783 *flags |= flagList;
5784 } else
5785 ret = 1;
5786 } else if (xmlStrEqual(item, BAD_CAST "union")) {
5787 if (flagUnion != -1) {
5788 if ((*flags & flagUnion) == 0)
5789 *flags |= flagUnion;
5790 } else
5791 ret = 1;
5792 } else
5793 ret = 1;
5794 if (item != NULL)
5795 xmlFree(item);
5796 cur = end;
5797 } while ((ret == 0) && (*cur != 0));
5798 }
5799
5800 return (ret);
5801}
5802
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00005803#ifdef IDC_ENABLED
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00005804static int
5805xmlSchemaCheckCSelectorXPath(xmlSchemaParserCtxtPtr ctxt,
5806 xmlSchemaPtr schema,
5807 xmlSchemaIDCPtr idc,
5808 xmlSchemaIDCSelectPtr selector,
5809 xmlNodePtr parNode,
5810 xmlAttrPtr attr,
5811 int isField)
5812{
5813 xmlNodePtr node;
5814
5815 /*
5816 * c-selector-xpath:
5817 * Schema Component Constraint: Selector Value OK
5818 *
5819 * TODO: 1 The {selector} must be a valid XPath expression, as defined
5820 * in [XPath].
5821 */
5822 if (selector == NULL) {
5823 xmlSchemaPErr(ctxt, idc->node,
5824 XML_SCHEMAP_INTERNAL,
5825 "Internal error: xmlSchemaCheckCSelectorXPath, "
5826 "the selector is not specified.\n", NULL, NULL);
5827 return (-1);
5828 }
5829 if (attr == NULL)
5830 node = idc->node;
5831 else
5832 node = (xmlNodePtr) attr;
5833 if (selector->xpath == NULL) {
5834 xmlSchemaPCustomErr(ctxt,
5835 /* TODO: Adjust error code. */
5836 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5837 NULL, NULL, node,
5838 "The XPath expression of the selector is not valid", NULL);
5839 return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE);
5840 } else {
5841 /*
5842 * Compile the XPath expression.
5843 */
5844 /*
5845 * TODO: We need the array of in-scope namespaces for compilation.
5846 */
5847 selector->xpathComp = xmlXPathCompile(selector->xpath);
5848#ifdef IDC_XPATH_SUPPORT
5849 if ((selector->xpathComp == NULL) ||
5850 (xmlXPathWXSIDCValid(selector->xpathComp, isField) != 0)) {
5851 xmlSchemaPCustomErr(ctxt,
5852 /* TODO: Adjust error code? */
5853 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5854 NULL, NULL, node,
5855 "The XPath expression '%s' could not be "
5856 "compiled", selector->xpath);
5857 return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE);
5858 }
5859#endif
5860 }
5861 return (0);
5862}
5863
5864/**
5865 * xmlSchemaAssignAnnotation:
5866 * @item: the schema component
5867 * @annot: the annotation
5868 *
5869 * Adds the annotation to the given schema component.
5870 *
5871 * Returns the given annotaion.
5872 */
5873static xmlSchemaAnnotPtr
5874xmlSchemaAssignAnnotation(xmlSchemaBasicItemPtr item,
5875 xmlSchemaAnnotPtr annot)
5876{
5877 xmlSchemaAnnotPtr cur = item->annot;
5878
5879 if (item->annot == NULL) {
5880 item->annot = annot;
5881 return (annot);
5882 }
5883 cur = item->annot;
5884 if (cur->next != NULL) {
5885 cur = cur->next;
5886 }
5887 cur->next = annot;
5888 return (annot);
5889}
5890
5891/**
5892 * xmlSchemaParseIDCSelectorAndField:
5893 * @ctxt: a schema validation context
5894 * @schema: the schema being built
5895 * @node: a subtree containing XML Schema informations
5896 *
5897 * Parses a XML Schema identity-contraint definition's
5898 * <selector> and <field> elements.
5899 *
5900 * Returns the parsed identity-constraint definition.
5901 */
5902static xmlSchemaIDCSelectPtr
5903xmlSchemaParseIDCSelectorAndField(xmlSchemaParserCtxtPtr ctxt,
5904 xmlSchemaPtr schema,
5905 xmlSchemaIDCPtr idc,
5906 xmlNodePtr node,
5907 int isField)
5908{
5909 xmlSchemaIDCSelectPtr item;
5910 xmlNodePtr child = NULL;
5911 xmlAttrPtr attr;
5912
5913 /*
5914 * Check for illegal attributes.
5915 */
5916 attr = node->properties;
5917 while (attr != NULL) {
5918 if (attr->ns == NULL) {
5919 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
5920 (!xmlStrEqual(attr->name, BAD_CAST "xpath"))) {
5921 xmlSchemaPIllegalAttrErr(ctxt,
5922 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5923 NULL, NULL, attr);
5924 }
5925 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
5926 xmlSchemaPIllegalAttrErr(ctxt,
5927 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5928 NULL, NULL, attr);
5929 }
5930 attr = attr->next;
5931 }
5932 /*
5933 * Create the item.
5934 */
5935 item = (xmlSchemaIDCSelectPtr) xmlMalloc(sizeof(xmlSchemaIDCSelect));
5936 if (item == NULL) {
5937 xmlSchemaPErrMemory(ctxt,
5938 "allocating a 'selector' of an identity-constraint definition",
5939 NULL);
5940 return (NULL);
5941 }
5942 memset(item, 0, sizeof(xmlSchemaIDCSelect));
5943 /*
5944 * Attribute "xpath" (mandatory).
5945 */
5946 attr = xmlSchemaGetPropNode(node, "xpath");
5947 if (attr == NULL) {
5948 xmlSchemaPMissingAttrErr(ctxt,
5949 XML_SCHEMAP_S4S_ATTR_MISSING,
5950 NULL, NULL, node,
5951 "name", NULL);
5952 } else {
5953 item->xpath = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5954 /*
5955 * URGENT TODO: "field"s have an other syntax than "selector"s.
5956 */
5957
5958 if (xmlSchemaCheckCSelectorXPath(ctxt, schema,
5959 idc, item, node, attr, isField) == -1)
5960 {
5961 xmlSchemaPErr(ctxt,
5962 (xmlNodePtr) attr,
5963 XML_SCHEMAP_INTERNAL,
5964 "Internal error: xmlSchemaParseIDCSelectorAndField, "
5965 "validating the XPath expression of a IDC selector.\n",
5966 NULL, NULL);
5967 }
5968
5969 }
5970 /*
5971 * And now for the children...
5972 */
5973 child = node->children;
5974 if (IS_SCHEMA(child, "annotation")) {
5975 /*
5976 * Add the annotation to the parent IDC.
5977 */
5978 xmlSchemaAssignAnnotation((xmlSchemaBasicItemPtr) idc,
5979 xmlSchemaParseAnnotation(ctxt, schema, child));
5980 child = child->next;
5981 }
5982 if (child != NULL) {
5983 xmlSchemaPContentErr(ctxt,
5984 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
5985 NULL, NULL, node, child,
5986 NULL, "(annotation?)");
5987 }
5988
5989 return (item);
5990}
5991
5992/**
5993 * xmlSchemaParseIDC:
5994 * @ctxt: a schema validation context
5995 * @schema: the schema being built
5996 * @node: a subtree containing XML Schema informations
5997 *
5998 * Parses a XML Schema identity-contraint definition.
5999 *
6000 * Returns the parsed identity-constraint definition.
6001 */
6002static xmlSchemaIDCPtr
6003xmlSchemaParseIDC(xmlSchemaParserCtxtPtr ctxt,
6004 xmlSchemaPtr schema,
6005 xmlNodePtr node,
6006 xmlSchemaTypeType idcCategory,
6007 const xmlChar *targetNamespace)
6008{
6009 xmlSchemaIDCPtr item = NULL;
6010 xmlNodePtr child = NULL;
6011 xmlAttrPtr attr;
6012 const xmlChar *name = NULL;
6013 xmlSchemaIDCSelectPtr field = NULL, lastField = NULL;
6014 int resAdd;
6015
6016 /*
6017 * Check for illegal attributes.
6018 */
6019 attr = node->properties;
6020 while (attr != NULL) {
6021 if (attr->ns == NULL) {
6022 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6023 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
6024 ((idcCategory != XML_SCHEMA_TYPE_IDC_KEYREF) ||
6025 (!xmlStrEqual(attr->name, BAD_CAST "refer")))) {
6026 xmlSchemaPIllegalAttrErr(ctxt,
6027 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6028 NULL, NULL, attr);
6029 }
6030 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6031 xmlSchemaPIllegalAttrErr(ctxt,
6032 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6033 NULL, NULL, attr);
6034 }
6035 attr = attr->next;
6036 }
6037 /*
6038 * Attribute "name" (mandatory).
6039 */
6040 attr = xmlSchemaGetPropNode(node, "name");
6041 if (attr == NULL) {
6042 xmlSchemaPMissingAttrErr(ctxt,
6043 XML_SCHEMAP_S4S_ATTR_MISSING,
6044 NULL, NULL, node,
6045 "name", NULL);
6046 return (NULL);
6047 } else if (xmlSchemaPValAttrNode(ctxt,
6048 NULL, NULL, attr,
6049 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
6050 return (NULL);
6051 }
6052 /*
6053 * Create the component.
6054 */
6055 if (schema->idcDef == NULL)
6056 schema->idcDef = xmlHashCreateDict(10, ctxt->dict);
6057 if (schema->idcDef == NULL)
6058 return (NULL);
6059
6060 item = (xmlSchemaIDCPtr) xmlMalloc(sizeof(xmlSchemaIDC));
6061 if (item == NULL) {
6062 xmlSchemaPErrMemory(ctxt,
6063 "allocating an identity-constraint definition", NULL);
6064 return (NULL);
6065 }
6066 /*
6067 * Add the IDC to the list of IDCs on the schema component.
6068 */
6069 resAdd = xmlHashAddEntry2(schema->idcDef, name, targetNamespace, item);
6070 if (resAdd != 0) {
6071 xmlSchemaPCustomErrExt(ctxt,
6072 XML_SCHEMAP_REDEFINED_TYPE,
6073 NULL, NULL, node,
6074 "An identity-constraint definition with the name '%s' "
6075 "and targetNamespace '%s' does already exist",
6076 name, targetNamespace, NULL);
6077 xmlFree(item);
6078 return (NULL);
6079 }
6080
6081 memset(item, 0, sizeof(xmlSchemaIDC));
6082 item->name = name;
6083 item->type = idcCategory;
6084 item->node = node;
6085 /*
6086 * The target namespace of the parent element declaration.
6087 */
6088 item->targetNamespace = targetNamespace;
6089 /* TODO: Handle attribute "id". */
6090 if (idcCategory == XML_SCHEMA_TYPE_IDC_KEYREF) {
6091 /*
6092 * Attribute "refer" (mandatory).
6093 */
6094 attr = xmlSchemaGetPropNode(node, "refer");
6095 if (attr == NULL) {
6096 xmlSchemaPMissingAttrErr(ctxt,
6097 XML_SCHEMAP_S4S_ATTR_MISSING,
6098 NULL, NULL, node,
6099 "refer", NULL);
6100 } else {
6101 /*
6102 * Create a reference item.
6103 */
6104 item->ref = (xmlSchemaItemQNRefPtr) xmlMalloc(
6105 sizeof(xmlSchemaItemQNRef));
6106 if (item->ref == NULL) {
6107 xmlSchemaPErrMemory(ctxt,
6108 "allocating a QName reference item", NULL);
6109 return (NULL);
6110 }
6111 memset(item->ref, 0, sizeof(xmlSchemaItemQNRef));
6112 xmlSchemaPValAttrNodeQName(ctxt, schema,
6113 NULL, NULL, attr,
6114 &(item->ref->targetNamespace), 0,
6115 &(item->ref->name));
6116 }
6117 }
6118 /*
6119 * And now for the children...
6120 */
6121 child = node->children;
6122 if (IS_SCHEMA(child, "annotation")) {
6123 item->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6124 child = child->next;
6125 }
6126 /*
6127 * Child element <selector>.
6128 */
6129 if (IS_SCHEMA(child, "selector")) {
6130 item->selector = xmlSchemaParseIDCSelectorAndField(ctxt, schema,
6131 item, child, 0);
6132 child = child->next;
6133 /*
6134 * Child elements <field>.
6135 */
6136 if (IS_SCHEMA(child, "field")) {
6137 do {
6138 field = xmlSchemaParseIDCSelectorAndField(ctxt, schema,
6139 item, child, 1);
6140 if (field != NULL) {
6141 field->index = item->nbFields;
6142 item->nbFields++;
6143 if (lastField != NULL)
6144 lastField->next = field;
6145 else
6146 item->fields = field;
6147 lastField = field;
6148 }
6149 child = child->next;
6150 } while (IS_SCHEMA(child, "field"));
6151 } else {
6152 xmlSchemaPContentErr(ctxt,
6153 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6154 NULL, NULL, node, child,
6155 NULL, "(annotation?, (selector, field+))");
6156 }
6157 }
6158 if (child != NULL) {
6159 xmlSchemaPContentErr(ctxt,
6160 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6161 NULL, NULL, node, child,
6162 NULL, "(annotation?, (selector, field+))");
6163 }
6164
6165 return (item);
6166}
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006167#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006168
Daniel Veillardc0826a72004-08-10 14:17:33 +00006169/**
Daniel Veillard4255d502002-04-16 15:50:10 +00006170 * xmlSchemaParseElement:
6171 * @ctxt: a schema validation context
6172 * @schema: the schema being built
6173 * @node: a subtree containing XML Schema informations
6174 *
6175 * parse a XML schema Element declaration
6176 * *WARNING* this interface is highly subject to change
6177 *
William M. Bracke7091952004-05-11 15:09:58 +00006178 * Returns the parsed element declaration.
Daniel Veillard4255d502002-04-16 15:50:10 +00006179 */
6180static xmlSchemaElementPtr
6181xmlSchemaParseElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00006182 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00006183{
Daniel Veillardc0826a72004-08-10 14:17:33 +00006184 const xmlChar *name = NULL;
6185 const xmlChar *attrValue;
6186 xmlChar *repName = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00006187 xmlSchemaElementPtr ret;
6188 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006189 const xmlChar *oldcontainer;
6190 xmlAttrPtr attr, nameAttr;
6191 int minOccurs, maxOccurs;
6192 int isRef = 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006193#ifdef IDC_ENABLED
6194 xmlSchemaIDCPtr curIDC, lastIDC = NULL;
6195#endif
William M. Bracke7091952004-05-11 15:09:58 +00006196
6197 /* 3.3.3 Constraints on XML Representations of Element Declarations */
6198 /* TODO: Complete implementation of 3.3.6 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00006199
Daniel Veillard4255d502002-04-16 15:50:10 +00006200 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6201 return (NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006202
Daniel Veillardc0826a72004-08-10 14:17:33 +00006203 oldcontainer = ctxt->container;
6204
6205 nameAttr = xmlSchemaGetPropNode(node, "name");
6206 attr = xmlSchemaGetPropNode(node, "ref");
6207 if ((topLevel) || (attr == NULL)) {
6208 if (nameAttr == NULL) {
6209 xmlSchemaPMissingAttrErr(ctxt,
6210 XML_SCHEMAP_S4S_ATTR_MISSING,
6211 (xmlChar **) &xmlSchemaElemDesElemDecl, NULL, node,
6212 "name", NULL);
6213 return (NULL);
6214 }
6215 name = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) nameAttr);
6216 } else {
6217 isRef = 1;
6218
6219 }
6220 /*
6221 * ... unless minOccurs=maxOccurs=0, in which case the item corresponds
6222 * to no component at all
6223 * TODO: It might be better to validate the element, even if it won't be
6224 * used.
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006225 */
6226 minOccurs = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "nonNegativeInteger");
6227 maxOccurs = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1, "(nonNegativeInteger | unbounded)");
Daniel Veillardc0826a72004-08-10 14:17:33 +00006228 if ((minOccurs == 0) && (maxOccurs == 0))
6229 return (NULL);
6230 /*
6231 * If we get a "ref" attribute on a local <element> we will assume it's
6232 * a reference - even if there's a "name" attribute; this seems to be more
6233 * robust.
6234 */
6235 if (isRef) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006236 char buf[50];
Daniel Veillardc0826a72004-08-10 14:17:33 +00006237 const xmlChar *refNs = NULL, *ref = NULL, *refPrefix;
6238
6239 /*
6240 * Parse as a particle.
6241 */
6242 xmlSchemaPValAttrNodeQName(ctxt, schema,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006243 (xmlChar **) &xmlSchemaElemDesElemRef,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006244 NULL, attr, &refNs, &refPrefix, &ref);
6245
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006246 snprintf(buf, 49, "#eRef%d", ctxt->counter++ + 1);
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00006247 ret = xmlSchemaAddElement(ctxt, schema, (const xmlChar *) buf, NULL, node, 0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006248 if (ret == NULL) {
6249 if (repName != NULL)
6250 xmlFree(repName);
6251 return (NULL);
6252 }
6253 ret->type = XML_SCHEMA_TYPE_ELEMENT;
6254 ret->node = node;
6255 ret->ref = ref;
6256 ret->refNs = refNs;
6257 ret->refPrefix = refPrefix;
6258 ret->flags |= XML_SCHEMAS_ELEM_REF;
6259 /*
6260 * Check for illegal attributes.
6261 */
6262 /*
6263 * 3.3.3 : 2.1
6264 * One of ref or name must be present, but not both
6265 */
6266 if (nameAttr != NULL) {
6267 xmlSchemaPMutualExclAttrErr(ctxt,
6268 XML_SCHEMAP_SRC_ELEMENT_2_1,
6269 &repName, (xmlSchemaTypePtr) ret, nameAttr,
6270 "ref", "name");
6271 }
6272 /* 3.3.3 : 2.2 */
6273 attr = node->properties;
6274 while (attr != NULL) {
6275 if (attr->ns == NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006276 if (xmlStrEqual(attr->name, BAD_CAST "ref") ||
6277 xmlStrEqual(attr->name, BAD_CAST "name") ||
6278 xmlStrEqual(attr->name, BAD_CAST "id") ||
6279 xmlStrEqual(attr->name, BAD_CAST "maxOccurs") ||
6280 xmlStrEqual(attr->name, BAD_CAST "minOccurs"))
6281 {
6282 attr = attr->next;
6283 continue;
6284 } else {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006285 xmlSchemaPCustomAttrErr(ctxt,
6286 XML_SCHEMAP_SRC_ELEMENT_2_2,
6287 &repName, (xmlSchemaTypePtr) ret, attr,
6288 "Only the attributes 'minOccurs', 'maxOccurs' and "
6289 "'id' are allowed in addition to 'ref'");
6290 break;
6291 }
6292 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6293 xmlSchemaPIllegalAttrErr(ctxt,
6294 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6295 &repName, (xmlSchemaTypePtr) ret, attr);
6296 }
6297 attr = attr->next;
6298 }
6299 } else {
6300 const xmlChar *ns = NULL, *fixed;
6301
6302 /*
6303 * Parse as an element declaration.
6304 */
6305 if (xmlSchemaPValAttrNode(ctxt,
6306 (xmlChar **) &xmlSchemaElemDesElemDecl, NULL, nameAttr,
6307 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0)
6308 return (NULL);
6309 /*
6310 * Evaluate the target namespace.
6311 */
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006312 if (topLevel) {
6313 ns = schema->targetNamespace;
6314 } else {
6315 attr = xmlSchemaGetPropNode(node, "form");
6316 if (attr != NULL) {
6317 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6318 if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
William M. Bracke7091952004-05-11 15:09:58 +00006319 ns = schema->targetNamespace;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006320 } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) {
6321 xmlSchemaPSimpleTypeErr(ctxt,
6322 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6323 &repName, NULL, (xmlNodePtr) attr,
6324 NULL, "(qualified | unqualified)",
6325 attrValue, NULL, NULL, NULL);
6326 }
6327 } else if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
6328 ns = schema->targetNamespace;
William M. Brack2f2a6632004-08-20 23:09:47 +00006329 }
6330 ret = xmlSchemaAddElement(ctxt, schema, name, ns, node, topLevel);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006331 if (ret == NULL) {
6332 if (repName != NULL)
6333 xmlFree(repName);
6334 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00006335 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006336 ret->type = XML_SCHEMA_TYPE_ELEMENT;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006337 ret->node = node;
6338 ret->targetNamespace = ns;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006339 /*
6340 * Check for illegal attributes.
6341 */
William M. Bracke7091952004-05-11 15:09:58 +00006342 attr = node->properties;
6343 while (attr != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006344 if (attr->ns == NULL) {
6345 if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
6346 (!xmlStrEqual(attr->name, BAD_CAST "type")) &&
6347 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6348 (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
6349 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
6350 (!xmlStrEqual(attr->name, BAD_CAST "block")) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006351 (!xmlStrEqual(attr->name, BAD_CAST "nillable")))
6352 {
6353 if (topLevel == 0) {
6354 if ((!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00006355 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006356 (!xmlStrEqual(attr->name, BAD_CAST "form")))
6357 {
6358 if (xmlStrEqual(attr->name, BAD_CAST "substitutionGroup")) {
6359 /*
6360 * 3.3.6 : 3 If there is a non-·absent· {substitution
6361 * group affiliation}, then {scope} must be global.
6362 * TODO: This one is redundant, since the S4S does
6363 * prohibit this attribute on local declarations already;
6364 * so why an explicit error code? Weird spec.
6365 * TODO: Move this to the proper constraint layer.
6366 * TODO: Or better wait for spec 1.1 to come.
6367 */
6368 xmlSchemaPIllegalAttrErr(ctxt,
6369 XML_SCHEMAP_E_PROPS_CORRECT_3,
6370 &repName, (xmlSchemaTypePtr) ret, attr);
6371 } else {
6372 xmlSchemaPIllegalAttrErr(ctxt,
6373 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6374 &repName, (xmlSchemaTypePtr) ret, attr);
6375 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006376 }
6377 } else if ((!xmlStrEqual(attr->name, BAD_CAST "final")) &&
6378 (!xmlStrEqual(attr->name, BAD_CAST "abstract")) &&
6379 (!xmlStrEqual(attr->name, BAD_CAST "substitutionGroup"))) {
6380
6381 xmlSchemaPIllegalAttrErr(ctxt,
6382 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6383 &repName, (xmlSchemaTypePtr) ret, attr);
6384 }
6385 }
6386 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6387
6388 xmlSchemaPIllegalAttrErr(ctxt,
6389 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6390 &repName, (xmlSchemaTypePtr) ret, attr);
William M. Bracke7091952004-05-11 15:09:58 +00006391 }
6392 attr = attr->next;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006393 }
William M. Bracke7091952004-05-11 15:09:58 +00006394 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006395 * Extract/validate attributes.
6396 */
6397 if (topLevel) {
6398 /*
6399 * Process top attributes of global element declarations here.
6400 */
6401 ret->flags |= XML_SCHEMAS_ELEM_GLOBAL;
6402 ret->flags |= XML_SCHEMAS_ELEM_TOPLEVEL;
6403 xmlSchemaPValAttrQName(ctxt, schema, &repName,
6404 (xmlSchemaTypePtr) ret, node, "substitutionGroup",
6405 &(ret->substGroupNs), NULL, &(ret->substGroup));
6406 if (xmlGetBooleanProp(ctxt, &repName, (xmlSchemaTypePtr) ret,
6407 node, "abstract", 0))
6408 ret->flags |= XML_SCHEMAS_ELEM_ABSTRACT;
6409 /*
6410 * Attribute "final".
6411 */
6412 attr = xmlSchemaGetPropNode(node, "final");
6413 if (attr == NULL) {
6414 ret->flags |= XML_SCHEMAS_ELEM_FINAL_ABSENT;
6415 } else {
6416 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6417 if (xmlSchemaPValAttrBlockFinal(attrValue, &(ret->flags),
6418 -1,
6419 XML_SCHEMAS_ELEM_FINAL_EXTENSION,
6420 XML_SCHEMAS_ELEM_FINAL_RESTRICTION, -1, -1, -1) != 0) {
6421 xmlSchemaPSimpleTypeErr(ctxt,
6422 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6423 &repName, (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00006424 NULL, "(#all | List of (extension | restriction))",
Daniel Veillardc0826a72004-08-10 14:17:33 +00006425 attrValue, NULL, NULL, NULL);
6426 }
6427 }
6428 }
6429 /*
6430 * Attribute "block".
6431 */
6432 attr = xmlSchemaGetPropNode(node, "block");
6433 if (attr == NULL) {
6434 ret->flags |= XML_SCHEMAS_ELEM_BLOCK_ABSENT;
6435 } else {
6436 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6437 if (xmlSchemaPValAttrBlockFinal(attrValue, &(ret->flags),
6438 -1,
6439 XML_SCHEMAS_ELEM_BLOCK_EXTENSION,
6440 XML_SCHEMAS_ELEM_BLOCK_RESTRICTION,
6441 XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION, -1, -1) != 0) {
6442 xmlSchemaPSimpleTypeErr(ctxt,
6443 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6444 &repName, (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00006445 NULL, "(#all | List of (extension | "
Daniel Veillardc0826a72004-08-10 14:17:33 +00006446 "restriction | substitution))", attrValue,
6447 NULL, NULL, NULL);
6448 }
6449 }
6450 if (xmlGetBooleanProp(ctxt, &repName, (xmlSchemaTypePtr) ret,
6451 node, "nillable", 0))
6452 ret->flags |= XML_SCHEMAS_ELEM_NILLABLE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006453
Daniel Veillardc0826a72004-08-10 14:17:33 +00006454 xmlSchemaPValAttrQName(ctxt, schema,
6455 &repName, (xmlSchemaTypePtr) ret, node,
6456 "type", &(ret->namedTypeNs), NULL, &(ret->namedType));
Daniel Veillard4255d502002-04-16 15:50:10 +00006457
Daniel Veillardc0826a72004-08-10 14:17:33 +00006458 ret->value = xmlSchemaGetProp(ctxt, node, "default");
6459 attr = xmlSchemaGetPropNode(node, "fixed");
6460 if (attr != NULL) {
6461 fixed = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6462 if (ret->value != NULL) {
6463 /*
6464 * 3.3.3 : 1
6465 * default and fixed must not both be present.
6466 */
6467 xmlSchemaPMutualExclAttrErr(ctxt,
6468 XML_SCHEMAP_SRC_ELEMENT_1,
6469 &repName, (xmlSchemaTypePtr) ret, attr,
6470 "default", "fixed");
6471 } else {
6472 ret->flags |= XML_SCHEMAS_ELEM_FIXED;
6473 ret->value = fixed;
6474 }
6475 }
6476 }
6477 /*
6478 * Extract/validate common attributes.
6479 */
6480 /* TODO: Check ID: */
6481 ret->id = xmlSchemaGetProp(ctxt, node, "id");
6482 ret->minOccurs = minOccurs;
6483 ret->maxOccurs = maxOccurs;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006484 if (topLevel != 1)
6485 xmlSchemaPCheckParticleCorrect_2(ctxt, (xmlSchemaTypePtr) ret,
6486 node, minOccurs, maxOccurs);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006487 /*
6488 * And now for the children...
6489 */
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00006490 ctxt->container = ret->name;
Daniel Veillard4255d502002-04-16 15:50:10 +00006491 child = node->children;
6492 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006493 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6494 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006495 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006496 if (isRef) {
6497 if (child != NULL) {
6498 xmlSchemaPContentErr(ctxt,
6499 XML_SCHEMAP_SRC_ELEMENT_2_2,
6500 &repName, (xmlSchemaTypePtr) ret, node, child,
6501 NULL, "(annotation?)");
William M. Bracke7091952004-05-11 15:09:58 +00006502 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006503 } else {
William M. Bracke7091952004-05-11 15:09:58 +00006504 if (IS_SCHEMA(child, "complexType")) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006505 /*
6506 * 3.3.3 : 3
6507 * "type" and either <simpleType> or <complexType> are mutually
6508 * exclusive
6509 */
William M. Bracke7091952004-05-11 15:09:58 +00006510 if (ret->namedType != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006511 xmlSchemaPContentErr(ctxt,
6512 XML_SCHEMAP_SRC_ELEMENT_3,
6513 &repName, (xmlSchemaTypePtr) ret, node, child,
6514 "The attribute 'type' and the <complexType> child are "
6515 "mutually exclusive", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00006516 } else
Daniel Veillard3646d642004-06-02 19:19:14 +00006517 ret->subtypes = xmlSchemaParseComplexType(ctxt, schema, child, 0);
William M. Bracke7091952004-05-11 15:09:58 +00006518 child = child->next;
6519 } else if (IS_SCHEMA(child, "simpleType")) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006520 /*
6521 * 3.3.3 : 3
6522 * "type" and either <simpleType> or <complexType> are
6523 * mutually exclusive
6524 */
William M. Bracke7091952004-05-11 15:09:58 +00006525 if (ret->namedType != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006526 xmlSchemaPContentErr(ctxt,
6527 XML_SCHEMAP_SRC_ELEMENT_3,
6528 &repName, (xmlSchemaTypePtr) ret, node, child,
6529 "The attribute 'type' and the <simpleType> child are "
6530 "mutually exclusive", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00006531 } else
Daniel Veillard3646d642004-06-02 19:19:14 +00006532 ret->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
William M. Bracke7091952004-05-11 15:09:58 +00006533 child = child->next;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006534 }
William M. Bracke7091952004-05-11 15:09:58 +00006535 while ((IS_SCHEMA(child, "unique")) ||
Daniel Veillardc0826a72004-08-10 14:17:33 +00006536 (IS_SCHEMA(child, "key")) || (IS_SCHEMA(child, "keyref"))) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006537#ifdef IDC_ENABLED
6538 if (IS_SCHEMA(child, "unique")) {
6539 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
6540 XML_SCHEMA_TYPE_IDC_UNIQUE, ret->targetNamespace);
6541 } else if (IS_SCHEMA(child, "key")) {
6542 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
6543 XML_SCHEMA_TYPE_IDC_KEY, ret->targetNamespace);
6544 } else if (IS_SCHEMA(child, "keyref")) {
6545 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
6546 XML_SCHEMA_TYPE_IDC_KEYREF, ret->targetNamespace);
6547 }
6548 if (lastIDC != NULL)
6549 lastIDC->next = curIDC;
6550 else
6551 (xmlSchemaIDCPtr) ret->idcs = curIDC;
6552 lastIDC = curIDC;
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006553#else
6554 TODO
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00006555#endif
6556 child = child->next;
William M. Bracke7091952004-05-11 15:09:58 +00006557 }
6558 if (child != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006559 xmlSchemaPContentErr(ctxt,
6560 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6561 &repName, (xmlSchemaTypePtr) ret, node, child,
6562 NULL, "(annotation?, ((simpleType | complexType)?, "
6563 "(unique | key | keyref)*))");
6564 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006565
Daniel Veillardc0826a72004-08-10 14:17:33 +00006566 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006567 ctxt->container = oldcontainer;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006568 /*
6569 * Cleanup.
6570 */
6571 if (repName != NULL)
6572 xmlFree(repName);
6573 /*
6574 * NOTE: Element Declaration Representation OK 4. will be checked at a
6575 * different layer.
6576 */
Daniel Veillard4255d502002-04-16 15:50:10 +00006577 return (ret);
6578}
6579
6580/**
6581 * xmlSchemaParseUnion:
6582 * @ctxt: a schema validation context
6583 * @schema: the schema being built
6584 * @node: a subtree containing XML Schema informations
6585 *
6586 * parse a XML schema Union definition
6587 * *WARNING* this interface is highly subject to change
6588 *
William M. Bracke7091952004-05-11 15:09:58 +00006589 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00006590 * 1 in case of success.
6591 */
6592static xmlSchemaTypePtr
6593xmlSchemaParseUnion(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006594 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00006595{
6596 xmlSchemaTypePtr type, subtype, last = NULL;
6597 xmlNodePtr child = NULL;
6598 xmlChar name[30];
William M. Brack2f2a6632004-08-20 23:09:47 +00006599 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00006600
6601 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6602 return (NULL);
6603
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006604 snprintf((char *) name, 30, "#union%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00006605 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00006606 if (type == NULL)
6607 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00006608 type->type = XML_SCHEMA_TYPE_UNION;
Daniel Veillard4255d502002-04-16 15:50:10 +00006609 type->node = node;
William M. Brack2f2a6632004-08-20 23:09:47 +00006610 /*
6611 * Check for illegal attributes.
6612 */
6613 attr = node->properties;
6614 while (attr != NULL) {
6615 if (attr->ns == NULL) {
6616 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6617 (!xmlStrEqual(attr->name, BAD_CAST "memberTypes"))) {
6618 xmlSchemaPIllegalAttrErr(ctxt,
6619 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6620 NULL, type, attr);
6621 }
6622 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6623 xmlSchemaPIllegalAttrErr(ctxt,
6624 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6625 NULL, type, attr);
6626 }
6627 attr = attr->next;
6628 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006629 type->id = xmlSchemaGetProp(ctxt, node, "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00006630 /*
6631 * Attribute "memberTypes". This is a list of QNames.
6632 * TODO: Validate the QNames.
6633 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00006634 type->base = xmlSchemaGetProp(ctxt, node, "memberTypes");
William M. Brack2f2a6632004-08-20 23:09:47 +00006635 /*
6636 * And now for the children...
6637 */
Daniel Veillard4255d502002-04-16 15:50:10 +00006638 child = node->children;
6639 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006640 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6641 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006642 }
William M. Brack2f2a6632004-08-20 23:09:47 +00006643 while (IS_SCHEMA(child, "simpleType")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006644 subtype = (xmlSchemaTypePtr)
Daniel Veillard3646d642004-06-02 19:19:14 +00006645 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006646 if (subtype != NULL) {
6647 if (last == NULL) {
6648 type->subtypes = subtype;
6649 last = subtype;
6650 } else {
6651 last->next = subtype;
6652 last = subtype;
6653 }
6654 last->next = NULL;
6655 }
6656 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006657 }
6658 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00006659 /* TODO: Think about the error code. */
6660 xmlSchemaPContentErr(ctxt,
6661 XML_SCHEMAP_UNKNOWN_UNION_CHILD,
6662 NULL, type, node, child, NULL, "(annotation?, simpleType*)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006663 }
6664 return (type);
6665}
6666
6667/**
6668 * xmlSchemaParseList:
6669 * @ctxt: a schema validation context
6670 * @schema: the schema being built
6671 * @node: a subtree containing XML Schema informations
6672 *
6673 * parse a XML schema List definition
6674 * *WARNING* this interface is highly subject to change
6675 *
William M. Bracke7091952004-05-11 15:09:58 +00006676 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00006677 * 1 in case of success.
6678 */
6679static xmlSchemaTypePtr
6680xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006681 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00006682{
6683 xmlSchemaTypePtr type, subtype;
6684 xmlNodePtr child = NULL;
6685 xmlChar name[30];
William M. Brack2f2a6632004-08-20 23:09:47 +00006686 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00006687
6688 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6689 return (NULL);
6690
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006691 snprintf((char *) name, 30, "#list%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00006692 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00006693 if (type == NULL)
6694 return (NULL);
6695 type->node = node;
6696 type->type = XML_SCHEMA_TYPE_LIST;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006697 type->id = xmlSchemaGetProp(ctxt, node, "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00006698 /*
6699 * Check for illegal attributes.
6700 */
6701 attr = node->properties;
6702 while (attr != NULL) {
6703 if (attr->ns == NULL) {
6704 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6705 (!xmlStrEqual(attr->name, BAD_CAST "itemType"))) {
6706 xmlSchemaPIllegalAttrErr(ctxt,
6707 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6708 NULL, type, attr);
6709 }
6710 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6711 xmlSchemaPIllegalAttrErr(ctxt,
6712 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6713 NULL, type, attr);
6714 }
6715 attr = attr->next;
6716 }
6717 /*
6718 * Attribute "itemType".
6719 */
6720 xmlSchemaPValAttrQName(ctxt, schema, NULL, NULL,
6721 node, "itemType", &(type->baseNs), NULL, &(type->base));
6722 /*
6723 * And now for the children...
6724 */
Daniel Veillard4255d502002-04-16 15:50:10 +00006725 child = node->children;
6726 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006727 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6728 child = child->next;
William M. Brack2f2a6632004-08-20 23:09:47 +00006729 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006730 subtype = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00006731 if (IS_SCHEMA(child, "simpleType")) {
6732 if (type->base != NULL) {
6733 xmlSchemaPCustomErr(ctxt,
6734 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
6735 NULL, type, node,
6736 "The attribute 'itemType' and the <simpleType> child "
6737 "are mutually exclusive", NULL);
6738 } else {
6739 subtype = (xmlSchemaTypePtr)
6740 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
6741 type->subtypes = subtype;
6742 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00006743 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006744 }
6745 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00006746 /* TODO: Think about the error code. */
6747 xmlSchemaPContentErr(ctxt,
6748 XML_SCHEMAP_UNKNOWN_LIST_CHILD,
6749 NULL, type, node, child, NULL, "(annotation?, simpleType?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006750 }
6751 return (type);
6752}
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006753
Daniel Veillard4255d502002-04-16 15:50:10 +00006754/**
6755 * xmlSchemaParseSimpleType:
6756 * @ctxt: a schema validation context
6757 * @schema: the schema being built
6758 * @node: a subtree containing XML Schema informations
6759 *
6760 * parse a XML schema Simple Type definition
6761 * *WARNING* this interface is highly subject to change
6762 *
William M. Bracke7091952004-05-11 15:09:58 +00006763 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillardc0826a72004-08-10 14:17:33 +00006764 * 1 in case of success.
Daniel Veillard4255d502002-04-16 15:50:10 +00006765 */
6766static xmlSchemaTypePtr
6767xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00006768 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00006769{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006770 xmlSchemaTypePtr type, subtype, oldCtxtType, oldParentItem;
Daniel Veillard4255d502002-04-16 15:50:10 +00006771 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006772 const xmlChar *attrValue = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006773 xmlChar *des = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006774 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00006775
6776 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6777 return (NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006778
Daniel Veillardc0826a72004-08-10 14:17:33 +00006779 if (topLevel) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006780 attr = xmlSchemaGetPropNode(node, "name");
Daniel Veillardc0826a72004-08-10 14:17:33 +00006781 if (attr == NULL) {
6782 xmlSchemaPMissingAttrErr(ctxt,
6783 XML_SCHEMAP_S4S_ATTR_MISSING,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006784 (xmlChar **) &xmlSchemaElemDesST, NULL, node,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006785 "name", NULL);
6786 return (NULL);
6787 } else if (xmlSchemaPValAttrNode(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006788 (xmlChar **) &xmlSchemaElemDesST, NULL, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006789 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &attrValue) != 0) {
Daniel Veillard01fa6152004-06-29 17:04:39 +00006790 return (NULL);
6791 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006792 }
6793
6794 if (topLevel == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006795 char buf[40];
Daniel Veillardc0826a72004-08-10 14:17:33 +00006796
Daniel Veillard01fa6152004-06-29 17:04:39 +00006797 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006798 * Parse as local simple type definition.
Daniel Veillard01fa6152004-06-29 17:04:39 +00006799 */
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006800 snprintf(buf, 39, "#ST%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00006801 type = xmlSchemaAddType(ctxt, schema, (const xmlChar *)buf, NULL, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006802 if (type == NULL)
6803 return (NULL);
6804 type->node = node;
6805 type->type = XML_SCHEMA_TYPE_SIMPLE;
6806 /*
6807 * Check for illegal attributes.
6808 */
6809 attr = node->properties;
6810 while (attr != NULL) {
6811 if (attr->ns == NULL) {
6812 if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
6813 xmlSchemaPIllegalAttrErr(ctxt,
6814 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006815 &des, type, attr);
Daniel Veillard01fa6152004-06-29 17:04:39 +00006816 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006817 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6818 xmlSchemaPIllegalAttrErr(ctxt,
6819 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006820 &des, type, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006821 }
6822 attr = attr->next;
Daniel Veillard01fa6152004-06-29 17:04:39 +00006823 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006824 } else {
6825 /*
6826 * Parse as global simple type definition.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006827 *
6828 * Note that attrValue is the value of the attribute "name" here.
Daniel Veillardc0826a72004-08-10 14:17:33 +00006829 */
William M. Brack2f2a6632004-08-20 23:09:47 +00006830 type = xmlSchemaAddType(ctxt, schema, attrValue, schema->targetNamespace, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006831 if (type == NULL)
6832 return (NULL);
6833 type->node = node;
6834 type->type = XML_SCHEMA_TYPE_SIMPLE;
6835 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
6836 /*
6837 * Check for illegal attributes.
6838 */
6839 attr = node->properties;
6840 while (attr != NULL) {
6841 if (attr->ns == NULL) {
6842 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6843 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006844 (!xmlStrEqual(attr->name, BAD_CAST "final"))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006845 xmlSchemaPIllegalAttrErr(ctxt,
6846 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006847 &des, type, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006848 }
6849 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6850 xmlSchemaPIllegalAttrErr(ctxt,
6851 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006852 &des, type, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006853 }
6854 attr = attr->next;
6855 }
6856 /*
6857 * Attribute "final".
6858 */
6859 attr = xmlSchemaGetPropNode(node, "final");
6860 if (attr == NULL) {
6861 type->flags |= XML_SCHEMAS_TYPE_FINAL_DEFAULT;
6862 } else {
6863 attrValue = xmlSchemaGetProp(ctxt, node, "final");
6864 if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
6865 -1, -1, XML_SCHEMAS_TYPE_FINAL_RESTRICTION, -1,
6866 XML_SCHEMAS_TYPE_FINAL_LIST,
6867 XML_SCHEMAS_TYPE_FINAL_UNION) != 0) {
6868
6869 xmlSchemaPSimpleTypeErr(ctxt,
6870 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006871 &des, type, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00006872 NULL, "(#all | List of (list | union | restriction)",
Daniel Veillardc0826a72004-08-10 14:17:33 +00006873 attrValue, NULL, NULL, NULL);
6874 }
6875 }
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006876 }
6877 type->targetNamespace = schema->targetNamespace;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006878 /* TODO: Check id. */
6879 type->id = xmlSchemaGetProp(ctxt, node, "id");
6880 /*
6881 * And now for the children...
6882 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006883 oldCtxtType = ctxt->ctxtType;
6884 oldParentItem = ctxt->parentItem;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006885 ctxt->ctxtType = type;
6886 ctxt->parentItem = type;
Daniel Veillard4255d502002-04-16 15:50:10 +00006887 child = node->children;
6888 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006889 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6890 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006891 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006892 subtype = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00006893 if (IS_SCHEMA(child, "restriction")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006894 subtype = (xmlSchemaTypePtr)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00006895 xmlSchemaParseRestriction(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006896 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006897 } else if (IS_SCHEMA(child, "list")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006898 subtype = (xmlSchemaTypePtr)
6899 xmlSchemaParseList(ctxt, schema, child);
6900 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006901 } else if (IS_SCHEMA(child, "union")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006902 subtype = (xmlSchemaTypePtr)
6903 xmlSchemaParseUnion(ctxt, schema, child);
6904 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006905 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006906 type->subtypes = subtype;
6907 if ((child != NULL) || (subtype == NULL)) {
6908 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006909 &des, type, node, child, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006910 "(annotation?, (restriction | list | union))");
Daniel Veillard4255d502002-04-16 15:50:10 +00006911 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00006912 ctxt->parentItem = oldParentItem;
6913 ctxt->ctxtType = oldCtxtType;
6914 FREE_AND_NULL(des)
Daniel Veillard01fa6152004-06-29 17:04:39 +00006915
Daniel Veillard4255d502002-04-16 15:50:10 +00006916 return (type);
6917}
6918
6919
6920/**
6921 * xmlSchemaParseGroup:
6922 * @ctxt: a schema validation context
6923 * @schema: the schema being built
6924 * @node: a subtree containing XML Schema informations
6925 *
6926 * parse a XML schema Group definition
6927 * *WARNING* this interface is highly subject to change
6928 *
William M. Bracke7091952004-05-11 15:09:58 +00006929 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00006930 * 1 in case of success.
6931 */
6932static xmlSchemaTypePtr
6933xmlSchemaParseGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00006934 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00006935{
6936 xmlSchemaTypePtr type, subtype;
6937 xmlNodePtr child = NULL;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006938 const xmlChar *name, *ns = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006939 const xmlChar *ref = NULL, *refNs = NULL;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006940 char buf[50];
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00006941 int minOccurs, maxOccurs;
Daniel Veillard4255d502002-04-16 15:50:10 +00006942
6943 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6944 return (NULL);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00006945 /*
6946 * TODO: Validate the element even if no item is created
6947 * (i.e. min/maxOccurs == 0).
6948 */
6949 minOccurs = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "nonNegativeInteger");
6950 maxOccurs = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1, "(nonNegativeInteger | unbounded)");
6951 if ((minOccurs == 0) && (maxOccurs == 0)) {
6952 return (NULL);
6953 }
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006954 if (topLevel)
6955 ns = schema->targetNamespace;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006956 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00006957 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006958 ref = xmlGetQNameProp(ctxt, node, "ref", &refNs);
6959 if (ref == NULL) {
6960 xmlSchemaPErr2(ctxt, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006961 XML_SCHEMAP_GROUP_NONAME_NOREF,
6962 "Group definition or particle: One of the attributes \"name\" "
6963 "or \"ref\" must be present.\n", NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006964 return (NULL);
6965 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006966 if (refNs == NULL)
6967 refNs = schema->targetNamespace;
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006968 snprintf(buf, 49, "#grRef%d", ctxt->counter++ + 1);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006969 name = (const xmlChar *) buf;
Daniel Veillard4255d502002-04-16 15:50:10 +00006970 }
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006971 type = xmlSchemaAddGroup(ctxt, schema, name, ns, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00006972 if (type == NULL)
6973 return (NULL);
6974 type->node = node;
6975 type->type = XML_SCHEMA_TYPE_GROUP;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006976 if (topLevel)
6977 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006978 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00006979 type->ref = ref;
6980 type->refNs = refNs;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00006981 type->minOccurs = minOccurs;
6982 type->maxOccurs = maxOccurs;
6983 xmlSchemaPCheckParticleCorrect_2(ctxt, type,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006984 node, type->minOccurs, type->maxOccurs);
Daniel Veillard4255d502002-04-16 15:50:10 +00006985
6986 child = node->children;
6987 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006988 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6989 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006990 }
6991 subtype = NULL;
6992 if (IS_SCHEMA(child, "all")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006993 subtype = (xmlSchemaTypePtr)
6994 xmlSchemaParseAll(ctxt, schema, child);
6995 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006996 } else if (IS_SCHEMA(child, "choice")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006997 subtype = xmlSchemaParseChoice(ctxt, schema, child);
6998 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006999 } else if (IS_SCHEMA(child, "sequence")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007000 subtype = (xmlSchemaTypePtr)
7001 xmlSchemaParseSequence(ctxt, schema, child);
7002 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007003 }
7004 if (subtype != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007005 type->subtypes = subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00007006 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007007 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_GROUP_CHILD,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007008 "Group definition \"%s\" has unexpected content.\n", type->name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007009 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007010 }
7011
7012 return (type);
7013}
7014
7015/**
7016 * xmlSchemaParseAll:
7017 * @ctxt: a schema validation context
7018 * @schema: the schema being built
7019 * @node: a subtree containing XML Schema informations
7020 *
7021 * parse a XML schema All definition
7022 * *WARNING* this interface is highly subject to change
7023 *
William M. Bracke7091952004-05-11 15:09:58 +00007024 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00007025 * 1 in case of success.
7026 */
7027static xmlSchemaTypePtr
7028xmlSchemaParseAll(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007029 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00007030{
7031 xmlSchemaTypePtr type, subtype, last = NULL;
7032 xmlNodePtr child = NULL;
7033 xmlChar name[30];
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00007034 const xmlChar *oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00007035
7036 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7037 return (NULL);
7038
7039
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00007040 snprintf((char *) name, 30, "#all%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00007041 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00007042 if (type == NULL)
7043 return (NULL);
7044 type->node = node;
Daniel Veillard7646b182002-04-20 06:41:40 +00007045 type->type = XML_SCHEMA_TYPE_ALL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00007046 type->id = xmlSchemaGetProp(ctxt, node, "id");
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00007047
7048 type->minOccurs = xmlGetMinOccurs(ctxt, node, 0, 1, 1, "(0 | 1)");
7049 type->maxOccurs = xmlGetMaxOccurs(ctxt, node, 1, 1, 1, "1");
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00007050
7051 oldcontainer = ctxt->container;
7052 ctxt->container = (const xmlChar *) name;
Daniel Veillard4255d502002-04-16 15:50:10 +00007053 child = node->children;
7054 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007055 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7056 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007057 }
7058 while (IS_SCHEMA(child, "element")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007059 subtype = (xmlSchemaTypePtr)
7060 xmlSchemaParseElement(ctxt, schema, child, 0);
7061 if (subtype != NULL) {
William M. Brackb15351e2003-12-27 04:34:42 +00007062 if (subtype->minOccurs > 1)
7063 xmlSchemaPErr(ctxt, child, XML_SCHEMAP_INVALID_MINOCCURS,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007064 "invalid value for minOccurs (must be 0 or 1).\n",
William M. Brackb15351e2003-12-27 04:34:42 +00007065 NULL, NULL);
7066 if (subtype->maxOccurs > 1)
7067 xmlSchemaPErr(ctxt, child, XML_SCHEMAP_INVALID_MAXOCCURS,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007068 "invalid value for maxOccurs (must be 0 or 1).\n",
William M. Brackb15351e2003-12-27 04:34:42 +00007069 NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007070 if (last == NULL) {
7071 type->subtypes = subtype;
7072 last = subtype;
7073 } else {
7074 last->next = subtype;
7075 last = subtype;
7076 }
7077 last->next = NULL;
7078 }
7079 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00007080 }
7081 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007082 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_ALL_CHILD,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007083 "<all> has unexpected content.\n", type->name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007084 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007085 }
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00007086 ctxt->container = oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00007087 return (type);
7088}
7089
7090/**
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007091 * xmlSchemaCleanupDoc:
7092 * @ctxt: a schema validation context
7093 * @node: the root of the document.
7094 *
7095 * removes unwanted nodes in a schemas document tree
7096 */
7097static void
7098xmlSchemaCleanupDoc(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr root)
7099{
7100 xmlNodePtr delete, cur;
7101
7102 if ((ctxt == NULL) || (root == NULL)) return;
7103
7104 /*
7105 * Remove all the blank text nodes
7106 */
7107 delete = NULL;
7108 cur = root;
7109 while (cur != NULL) {
7110 if (delete != NULL) {
7111 xmlUnlinkNode(delete);
7112 xmlFreeNode(delete);
7113 delete = NULL;
7114 }
7115 if (cur->type == XML_TEXT_NODE) {
7116 if (IS_BLANK_NODE(cur)) {
7117 if (xmlNodeGetSpacePreserve(cur) != 1) {
7118 delete = cur;
7119 }
7120 }
7121 } else if ((cur->type != XML_ELEMENT_NODE) &&
7122 (cur->type != XML_CDATA_SECTION_NODE)) {
7123 delete = cur;
7124 goto skip_children;
7125 }
7126
7127 /*
7128 * Skip to next node
7129 */
7130 if (cur->children != NULL) {
7131 if ((cur->children->type != XML_ENTITY_DECL) &&
7132 (cur->children->type != XML_ENTITY_REF_NODE) &&
7133 (cur->children->type != XML_ENTITY_NODE)) {
7134 cur = cur->children;
7135 continue;
7136 }
7137 }
7138 skip_children:
7139 if (cur->next != NULL) {
7140 cur = cur->next;
7141 continue;
7142 }
7143
7144 do {
7145 cur = cur->parent;
7146 if (cur == NULL)
7147 break;
7148 if (cur == root) {
7149 cur = NULL;
7150 break;
7151 }
7152 if (cur->next != NULL) {
7153 cur = cur->next;
7154 break;
7155 }
7156 } while (cur != NULL);
7157 }
7158 if (delete != NULL) {
7159 xmlUnlinkNode(delete);
7160 xmlFreeNode(delete);
7161 delete = NULL;
7162 }
7163}
7164
William M. Brack2f2a6632004-08-20 23:09:47 +00007165
7166/**
7167 * xmlSchemaImportSchema
7168 *
7169 * @ctxt: a schema validation context
7170 * @schemaLocation: an URI defining where to find the imported schema
7171 *
7172 * import a XML schema
7173 * *WARNING* this interface is highly subject to change
7174 *
7175 * Returns -1 in case of error and 1 in case of success.
7176 */
7177#if 0
7178static xmlSchemaImportPtr
7179xmlSchemaImportSchema(xmlSchemaParserCtxtPtr ctxt,
7180 const xmlChar *schemaLocation)
7181{
7182 xmlSchemaImportPtr import;
7183 xmlSchemaParserCtxtPtr newctxt;
7184
7185 newctxt = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
7186 if (newctxt == NULL) {
7187 xmlSchemaPErrMemory(ctxt, "allocating schema parser context",
7188 NULL);
7189 return (NULL);
7190 }
7191 memset(newctxt, 0, sizeof(xmlSchemaParserCtxt));
7192 /* Keep the same dictionnary for parsing, really */
7193 xmlDictReference(ctxt->dict);
7194 newctxt->dict = ctxt->dict;
7195 newctxt->includes = 0;
7196 newctxt->URL = xmlDictLookup(newctxt->dict, schemaLocation, -1);
7197
7198 xmlSchemaSetParserErrors(newctxt, ctxt->error, ctxt->warning,
7199 ctxt->userData);
7200
7201 import = (xmlSchemaImport*) xmlMalloc(sizeof(xmlSchemaImport));
7202 if (import == NULL) {
7203 xmlSchemaPErrMemory(NULL, "allocating imported schema",
7204 NULL);
7205 xmlSchemaFreeParserCtxt(newctxt);
7206 return (NULL);
7207 }
7208
7209 memset(import, 0, sizeof(xmlSchemaImport));
7210 import->schemaLocation = xmlDictLookup(ctxt->dict, schemaLocation, -1);
7211 import->schema = xmlSchemaParse(newctxt);
7212
7213 if (import->schema == NULL) {
7214 /* FIXME use another error enum here ? */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00007215 xmlSchemaPErr(ctxt, NULL, XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +00007216 "Failed to import schema from location \"%s\".\n",
7217 schemaLocation, NULL);
7218
7219 xmlSchemaFreeParserCtxt(newctxt);
7220 /* The schemaLocation is held by the dictionary.
7221 if (import->schemaLocation != NULL)
7222 xmlFree((xmlChar *)import->schemaLocation);
7223 */
7224 xmlFree(import);
7225 return NULL;
7226 }
7227
7228 xmlSchemaFreeParserCtxt(newctxt);
7229 return import;
7230}
7231#endif
7232
7233static void
7234xmlSchemaClearSchemaDefaults(xmlSchemaPtr schema)
7235{
7236 if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
7237 schema->flags ^= XML_SCHEMAS_QUALIF_ELEM;
7238
7239 if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
7240 schema->flags ^= XML_SCHEMAS_QUALIF_ATTR;
7241
7242 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
7243 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_EXTENSION;
7244 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
7245 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION;
7246 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST)
7247 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_LIST;
7248 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION)
7249 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_UNION;
7250
7251 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
7252 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION;
7253 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
7254 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION;
7255 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
7256 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION;
7257}
7258
7259static void
7260xmlSchemaParseSchemaDefaults(xmlSchemaParserCtxtPtr ctxt,
7261 xmlSchemaPtr schema,
7262 xmlNodePtr node)
7263{
7264 xmlAttrPtr attr;
7265 const xmlChar *val;
7266
7267 attr = xmlSchemaGetPropNode(node, "elementFormDefault");
7268 if (attr != NULL) {
7269 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
7270 if (xmlSchemaPValAttrFormDefault(val, &schema->flags,
7271 XML_SCHEMAS_QUALIF_ELEM) != 0) {
7272 xmlSchemaPSimpleTypeErr(ctxt,
7273 XML_SCHEMAP_ELEMFORMDEFAULT_VALUE,
7274 NULL, NULL, (xmlNodePtr) attr, NULL,
7275 "(qualified | unqualified)", val, NULL, NULL, NULL);
7276 }
7277 }
7278
7279 attr = xmlSchemaGetPropNode(node, "attributeFormDefault");
7280 if (attr != NULL) {
7281 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
7282 if (xmlSchemaPValAttrFormDefault(val, &schema->flags,
7283 XML_SCHEMAS_QUALIF_ATTR) != 0) {
7284 xmlSchemaPSimpleTypeErr(ctxt,
7285 XML_SCHEMAP_ATTRFORMDEFAULT_VALUE,
7286 NULL, NULL, (xmlNodePtr) attr, NULL,
7287 "(qualified | unqualified)", val, NULL, NULL, NULL);
7288 }
7289 }
7290
7291 attr = xmlSchemaGetPropNode(node, "finalDefault");
7292 if (attr != NULL) {
7293 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
7294 if (xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
7295 XML_SCHEMAS_FINAL_DEFAULT_EXTENSION,
7296 XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION,
7297 -1,
7298 XML_SCHEMAS_FINAL_DEFAULT_LIST,
7299 XML_SCHEMAS_FINAL_DEFAULT_UNION) != 0) {
7300 xmlSchemaPSimpleTypeErr(ctxt,
7301 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
7302 NULL, NULL, (xmlNodePtr) attr, NULL,
7303 "(#all | List of (extension | restriction | list | union))",
7304 val, NULL, NULL, NULL);
7305 }
7306 }
7307
7308 attr = xmlSchemaGetPropNode(node, "blockDefault");
7309 if (attr != NULL) {
7310 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
7311 if (xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
7312 XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION,
7313 XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION,
7314 XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION, -1, -1) != 0) {
7315 xmlSchemaPSimpleTypeErr(ctxt,
7316 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
7317 NULL, NULL, (xmlNodePtr) attr, NULL,
7318 "(#all | List of (extension | restriction | substitution))",
7319 val, NULL, NULL, NULL);
7320 }
7321 }
7322}
7323
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007324/**
7325 * xmlSchemaParseSchemaTopLevel:
7326 * @ctxt: a schema validation context
7327 * @schema: the schemas
7328 * @nodes: the list of top level nodes
7329 *
7330 * Returns the internal XML Schema structure built from the resource or
7331 * NULL in case of error
7332 */
7333static void
7334xmlSchemaParseSchemaTopLevel(xmlSchemaParserCtxtPtr ctxt,
7335 xmlSchemaPtr schema, xmlNodePtr nodes)
7336{
7337 xmlNodePtr child;
7338 xmlSchemaAnnotPtr annot;
7339
7340 if ((ctxt == NULL) || (schema == NULL) || (nodes == NULL))
7341 return;
7342
7343 child = nodes;
7344 while ((IS_SCHEMA(child, "include")) ||
7345 (IS_SCHEMA(child, "import")) ||
7346 (IS_SCHEMA(child, "redefine")) ||
7347 (IS_SCHEMA(child, "annotation"))) {
7348 if (IS_SCHEMA(child, "annotation")) {
7349 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7350 if (schema->annot == NULL)
7351 schema->annot = annot;
7352 else
7353 xmlSchemaFreeAnnot(annot);
7354 } else if (IS_SCHEMA(child, "import")) {
7355 xmlSchemaParseImport(ctxt, schema, child);
7356 } else if (IS_SCHEMA(child, "include")) {
Daniel Veillardb0f397e2003-12-23 23:30:53 +00007357 ctxt->includes++;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007358 xmlSchemaParseInclude(ctxt, schema, child);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00007359 ctxt->includes--;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007360 } else if (IS_SCHEMA(child, "redefine")) {
7361 TODO
7362 }
7363 child = child->next;
7364 }
7365 while (child != NULL) {
7366 if (IS_SCHEMA(child, "complexType")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00007367 xmlSchemaParseComplexType(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007368 child = child->next;
7369 } else if (IS_SCHEMA(child, "simpleType")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00007370 xmlSchemaParseSimpleType(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007371 child = child->next;
7372 } else if (IS_SCHEMA(child, "element")) {
7373 xmlSchemaParseElement(ctxt, schema, child, 1);
7374 child = child->next;
7375 } else if (IS_SCHEMA(child, "attribute")) {
William M. Bracke7091952004-05-11 15:09:58 +00007376 xmlSchemaParseAttribute(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007377 child = child->next;
7378 } else if (IS_SCHEMA(child, "attributeGroup")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00007379 xmlSchemaParseAttributeGroup(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007380 child = child->next;
7381 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00007382 xmlSchemaParseGroup(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007383 child = child->next;
7384 } else if (IS_SCHEMA(child, "notation")) {
7385 xmlSchemaParseNotation(ctxt, schema, child);
7386 child = child->next;
7387 } else {
7388 xmlSchemaPErr2(ctxt, NULL, child,
7389 XML_SCHEMAP_UNKNOWN_SCHEMAS_CHILD,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007390 "Unexpected element \"%s\" as child of <schema>.\n",
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007391 child->name, NULL);
7392 child = child->next;
7393 }
7394 while (IS_SCHEMA(child, "annotation")) {
7395 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7396 if (schema->annot == NULL)
7397 schema->annot = annot;
7398 else
7399 xmlSchemaFreeAnnot(annot);
7400 child = child->next;
7401 }
7402 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00007403 ctxt->parentItem = NULL;
7404 ctxt->ctxtType = NULL;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007405}
7406
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007407static xmlSchemaImportPtr
7408xmlSchemaAddImport(xmlSchemaParserCtxtPtr ctxt,
7409 xmlHashTablePtr *imports,
7410 const xmlChar *nsName)
7411{
7412 xmlSchemaImportPtr ret;
7413
7414 if (*imports == NULL) {
Daniel Veillardb9e2f262005-01-23 23:48:34 +00007415 *imports = xmlHashCreateDict(10, ctxt->dict);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007416 if (*imports == NULL) {
7417 xmlSchemaPCustomErr(ctxt,
7418 XML_SCHEMAP_FAILED_BUILD_IMPORT,
7419 NULL, NULL, (xmlNodePtr) ctxt->doc,
7420 "Internal error: failed to build the import table",
7421 NULL);
7422 return (NULL);
7423 }
7424 }
7425 ret = (xmlSchemaImport*) xmlMalloc(sizeof(xmlSchemaImport));
7426 if (ret == NULL) {
7427 xmlSchemaPErrMemory(NULL, "allocating import struct", NULL);
7428 return (NULL);
7429 }
7430 memset(ret, 0, sizeof(xmlSchemaImport));
7431 if (nsName == NULL)
7432 nsName = XML_SCHEMAS_NO_NAMESPACE;
7433 xmlHashAddEntry(*imports, nsName, ret);
7434
7435 return (ret);
7436}
7437
7438static int
7439xmlSchemaAcquireSchemaDoc(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007440 xmlSchemaPtr schema,
7441 xmlNodePtr node,
7442 const xmlChar *nsName,
7443 const xmlChar *location,
7444 xmlDocPtr *doc,
7445 const xmlChar **targetNamespace,
7446 int absolute)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007447{
7448 xmlParserCtxtPtr parserCtxt;
7449 xmlSchemaImportPtr import;
7450 const xmlChar *ns;
7451 xmlNodePtr root;
7452
7453 /*
7454 * NOTE: This will be used for <import>, <xsi:schemaLocation> and
7455 * <xsi:noNamespaceSchemaLocation>.
7456 */
7457 *doc = NULL;
7458 /*
7459 * Given that the schemaLocation [attribute] is only a hint, it is open
7460 * to applications to ignore all but the first <import> for a given
7461 * namespace, regardless of the ·actual value· of schemaLocation, but
7462 * such a strategy risks missing useful information when new
7463 * schemaLocations are offered.
7464 *
7465 * XSV (ver 2.5-2) does use the first <import> which resolves to a valid schema.
7466 * Xerces-J (ver 2.5.1) ignores all but the first given <import> - regardless if
7467 * valid or not.
7468 * We will follow XSV here.
7469 */
7470 if (location == NULL) {
7471 /*
7472 * Schema Document Location Strategy:
7473 *
7474 * 3 Based on the namespace name, identify an existing schema document,
7475 * either as a resource which is an XML document or a <schema> element
7476 * information item, in some local schema repository;
7477 *
7478 * 5 Attempt to resolve the namespace name to locate such a resource.
7479 *
7480 * NOTE: Those stategies are not supported, so we will skip.
7481 */
7482 return (0);
7483 }
7484 if (nsName == NULL)
7485 ns = XML_SCHEMAS_NO_NAMESPACE;
7486 else
7487 ns = nsName;
7488
7489 import = xmlHashLookup(schema->schemasImports, ns);
7490 if (import != NULL) {
7491 /*
7492 * There was a valid resource for the specified namespace already
7493 * defined, so skip.
7494 * TODO: This might be changed someday to allow import of
7495 * components from multiple documents for a single target namespace.
7496 */
7497 return (0);
7498 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007499
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007500 /*
7501 * Schema Document Location Strategy:
7502 *
7503 * 2 Based on the location URI, identify an existing schema document,
7504 * either as a resource which is an XML document or a <schema> element
7505 * information item, in some local schema repository;
7506 *
7507 * 4 Attempt to resolve the location URI, to locate a resource on the
7508 * web which is or contains or references a <schema> element;
7509 * TODO: Hmm, I don't know if the reference stuff in 4. will work.
7510 *
7511 */
7512 if ((absolute == 0) && (node != NULL)) {
7513 xmlChar *base, *URI;
7514
7515 base = xmlNodeGetBase(node->doc, node);
7516 if (base == NULL) {
7517 URI = xmlBuildURI(location, node->doc->URL);
7518 } else {
7519 URI = xmlBuildURI(location, base);
7520 xmlFree(base);
7521 }
7522 if (URI != NULL) {
7523 location = xmlDictLookup(ctxt->dict, URI, -1);
7524 xmlFree(URI);
7525 }
7526 }
7527 parserCtxt = xmlNewParserCtxt();
7528 if (parserCtxt == NULL) {
7529 xmlSchemaPErrMemory(NULL, "xmlSchemaParseImport: "
7530 "allocating a parser context", NULL);
7531 return(-1);
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00007532 }
7533
7534 if ((ctxt->dict != NULL) && (parserCtxt->dict != NULL)) {
7535 xmlDictFree(parserCtxt->dict);
7536 parserCtxt->dict = ctxt->dict;
7537 xmlDictReference(parserCtxt->dict);
7538 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007539
7540 *doc = xmlCtxtReadFile(parserCtxt, (const char *) location,
7541 NULL, SCHEMAS_PARSE_OPTIONS);
7542
7543 /*
7544 * 2.1 The referent is (a fragment of) a resource which is an
7545 * XML document (see clause 1.1), which in turn corresponds to
7546 * a <schema> element information item in a well-formed information
7547 * set, which in turn corresponds to a valid schema.
7548 * TODO: What to do with the "fragment" stuff?
7549 *
7550 * 2.2 The referent is a <schema> element information item in
7551 * a well-formed information set, which in turn corresponds
7552 * to a valid schema.
7553 * NOTE: 2.2 won't apply, since only XML documents will be processed
7554 * here.
7555 */
7556 if (*doc == NULL) {
7557 xmlErrorPtr lerr;
7558 /*
7559 * It is *not* an error for the application schema reference
7560 * strategy to fail.
7561 *
7562 * If the doc is NULL and the parser error is an IO error we
7563 * will assume that the resource could not be located or accessed.
7564 *
7565 * TODO: Try to find specific error codes to react only on
7566 * localisation failures.
7567 *
7568 * TODO, FIXME: Check the spec: is a namespace added to the imported
7569 * namespaces, even if the schemaLocation did not provide
7570 * a resource? I guess so, since omitting the "schemaLocation"
7571 * attribute, imports a namespace as well.
7572 */
7573 lerr = xmlGetLastError();
7574 if ((lerr != NULL) && (lerr->domain == XML_FROM_IO)) {
7575 xmlFreeParserCtxt(parserCtxt);
7576 return(0);
7577 }
7578
7579 xmlSchemaPCustomErr(ctxt,
7580 XML_SCHEMAP_SRC_IMPORT_2_1,
7581 NULL, NULL, node,
7582 "Failed to parse the resource '%s' for import",
7583 location);
7584 xmlFreeParserCtxt(parserCtxt);
7585 return(XML_SCHEMAP_SRC_IMPORT_2_1);
7586 }
7587 xmlFreeParserCtxt(parserCtxt);
7588
7589 root = xmlDocGetRootElement(*doc);
7590 if (root == NULL) {
7591 xmlSchemaPCustomErr(ctxt,
7592 XML_SCHEMAP_SRC_IMPORT_2_1,
7593 NULL, NULL, node,
7594 "The XML document '%s' to be imported has no document "
7595 "element", location);
7596 xmlFreeDoc(*doc);
7597 *doc = NULL;
7598 return (XML_SCHEMAP_SRC_IMPORT_2_1);
7599 }
7600
7601 xmlSchemaCleanupDoc(ctxt, root);
7602
7603 if (!IS_SCHEMA(root, "schema")) {
7604 xmlSchemaPCustomErr(ctxt,
7605 XML_SCHEMAP_SRC_IMPORT_2_1,
7606 NULL, NULL, node,
7607 "The XML document '%s' to be imported is not a XML schema document",
7608 location);
7609 xmlFreeDoc(*doc);
7610 *doc = NULL;
7611 return (XML_SCHEMAP_SRC_IMPORT_2_1);
7612 }
7613 *targetNamespace = xmlSchemaGetProp(ctxt, root, "targetNamespace");
7614 /*
7615 * Schema Representation Constraint: Import Constraints and Semantics
7616 */
7617 if (nsName == NULL) {
7618 if (*targetNamespace != NULL) {
7619 xmlSchemaPCustomErr(ctxt,
7620 XML_SCHEMAP_SRC_IMPORT_3_2,
7621 NULL, NULL, node,
7622 "The XML schema to be imported is not expected "
7623 "to have a target namespace; this differs from "
7624 "its target namespace of '%s'", *targetNamespace);
7625 xmlFreeDoc(*doc);
7626 *doc = NULL;
7627 return (XML_SCHEMAP_SRC_IMPORT_3_2);
7628 }
7629 } else {
7630 if (*targetNamespace == NULL) {
7631 xmlSchemaPCustomErr(ctxt,
7632 XML_SCHEMAP_SRC_IMPORT_3_1,
7633 NULL, NULL, node,
7634 "The XML schema to be imported is expected to have a target "
7635 "namespace of '%s'", nsName);
7636 xmlFreeDoc(*doc);
7637 *doc = NULL;
7638 return (XML_SCHEMAP_SRC_IMPORT_3_1);
7639 } else if (!xmlStrEqual(*targetNamespace, nsName)) {
7640 xmlSchemaPCustomErrExt(ctxt,
7641 XML_SCHEMAP_SRC_IMPORT_3_1,
7642 NULL, NULL, node,
7643 "The XML schema to be imported is expected to have a "
7644 "target namespace of '%s'; this differs from "
7645 "its target namespace of '%s'",
7646 nsName, *targetNamespace, NULL);
7647 xmlFreeDoc(*doc);
7648 *doc = NULL;
7649 return (XML_SCHEMAP_SRC_IMPORT_3_1);
7650 }
7651 }
7652
7653 import = xmlSchemaAddImport(ctxt, &(schema->schemasImports), nsName);
7654 if (import == NULL) {
7655 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_FAILED_BUILD_IMPORT,
7656 NULL, NULL, NULL,
7657 "Internal error: xmlSchemaAcquireSchemaDoc, "
7658 "failed to build import table", NULL);
7659 xmlFreeDoc(*doc);
7660 *doc = NULL;
7661 return (-1);
7662 }
7663 import->schemaLocation = location;
7664 import->doc = *doc;
7665 return (0);
7666}
William M. Brack2f2a6632004-08-20 23:09:47 +00007667
7668/**
7669 * xmlSchemaParseImport:
7670 * @ctxt: a schema validation context
7671 * @schema: the schema being built
7672 * @node: a subtree containing XML Schema informations
7673 *
7674 * parse a XML schema Import definition
7675 * *WARNING* this interface is highly subject to change
7676 *
7677 * Returns 0 in case of success, a positive error code if
7678 * not valid and -1 in case of an internal error.
7679 */
7680static int
7681xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
7682 xmlNodePtr node)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007683{
7684 xmlNodePtr child;
7685 const xmlChar *namespace = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00007686 const xmlChar *schemaLocation = NULL;
7687 const xmlChar *targetNamespace, *oldTNS, *url;
7688 xmlAttrPtr attr;
7689 xmlDocPtr doc;
7690 xmlNodePtr root;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007691 int flags, ret = 0;
William M. Brack2f2a6632004-08-20 23:09:47 +00007692
7693
7694 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7695 return (-1);
7696
7697 /*
7698 * Check for illegal attributes.
7699 */
7700 attr = node->properties;
7701 while (attr != NULL) {
7702 if (attr->ns == NULL) {
7703 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7704 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
7705 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
7706 xmlSchemaPIllegalAttrErr(ctxt,
7707 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7708 NULL, NULL, attr);
7709 }
7710 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7711 xmlSchemaPIllegalAttrErr(ctxt,
7712 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7713 NULL, NULL, attr);
7714 }
7715 attr = attr->next;
7716 }
7717 /*
7718 * Extract and validate attributes.
7719 */
7720 if (xmlSchemaPValAttr(ctxt, NULL, NULL, node,
7721 "namespace", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
7722 &namespace) != 0) {
7723 xmlSchemaPSimpleTypeErr(ctxt,
7724 XML_SCHEMAP_IMPORT_NAMESPACE_NOT_URI,
7725 NULL, NULL, node,
7726 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
7727 NULL, namespace, NULL, NULL, NULL);
7728 return (XML_SCHEMAP_IMPORT_NAMESPACE_NOT_URI);
7729 }
7730
7731 if (xmlSchemaPValAttr(ctxt, NULL, NULL, node,
7732 "schemaLocation", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
7733 &schemaLocation) != 0) {
7734 xmlSchemaPSimpleTypeErr(ctxt,
7735 XML_SCHEMAP_IMPORT_SCHEMA_NOT_URI,
7736 NULL, NULL, node,
7737 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
7738 NULL, namespace, NULL, NULL, NULL);
7739 return (XML_SCHEMAP_IMPORT_SCHEMA_NOT_URI);
7740 }
7741 /*
7742 * And now for the children...
7743 */
7744 child = node->children;
7745 if (IS_SCHEMA(child, "annotation")) {
7746 /*
7747 * the annotation here is simply discarded ...
7748 */
7749 child = child->next;
7750 }
7751 if (child != NULL) {
7752 xmlSchemaPContentErr(ctxt,
7753 XML_SCHEMAP_UNKNOWN_IMPORT_CHILD,
7754 NULL, NULL, node, child, NULL,
7755 "(annotation?)");
7756 }
7757 /*
7758 * Apply additional constraints.
7759 */
7760 if (namespace != NULL) {
7761 /*
7762 * 1.1 If the namespace [attribute] is present, then its ·actual value·
7763 * must not match the ·actual value· of the enclosing <schema>'s
7764 * targetNamespace [attribute].
7765 */
7766 if (xmlStrEqual(schema->targetNamespace, namespace)) {
7767 xmlSchemaPCustomErr(ctxt,
7768 XML_SCHEMAP_SRC_IMPORT_1_1,
7769 NULL, NULL, node,
7770 "The value of the attribute 'namespace' must not match "
7771 "the target namespace '%s' of the importing schema",
7772 schema->targetNamespace);
7773 return (XML_SCHEMAP_SRC_IMPORT_1_1);
7774 }
7775 } else {
7776 /*
7777 * 1.2 If the namespace [attribute] is not present, then the enclosing
7778 * <schema> must have a targetNamespace [attribute].
7779 */
7780 if (schema->targetNamespace == NULL) {
7781 xmlSchemaPCustomErr(ctxt,
7782 XML_SCHEMAP_SRC_IMPORT_1_2,
7783 NULL, NULL, node,
7784 "The attribute 'namespace' must be existent if "
7785 "the importing schema has no target namespace",
7786 NULL);
7787 return (XML_SCHEMAP_SRC_IMPORT_1_2);
7788 }
7789 }
William M. Brack2f2a6632004-08-20 23:09:47 +00007790 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007791 * Locate and aquire the schema document.
William M. Brack2f2a6632004-08-20 23:09:47 +00007792 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007793 ret = xmlSchemaAcquireSchemaDoc(ctxt, schema, node, namespace,
7794 schemaLocation, &doc, &targetNamespace, 0);
7795 if (ret != 0) {
7796 if (doc != NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00007797 xmlFreeDoc(doc);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007798 return (ret);
7799 } else if (doc != NULL) {
7800 /*
7801 * Save and reset the context & schema.
7802 */
7803 url = ctxt->URL;
7804 /* TODO: Is using the doc->URL here correct? */
7805 ctxt->URL = doc->URL;
7806 flags = schema->flags;
7807 oldTNS = schema->targetNamespace;
7808 /*
7809 * Parse the schema.
7810 */
7811 root = xmlDocGetRootElement(doc);
7812 xmlSchemaClearSchemaDefaults(schema);
7813 xmlSchemaParseSchemaDefaults(ctxt, schema, root);
7814 schema->targetNamespace = targetNamespace;
7815 xmlSchemaParseSchemaTopLevel(ctxt, schema, root->children);
7816 /*
7817 * Restore the context & schema.
7818 */
7819 schema->flags = flags;
7820 schema->targetNamespace = oldTNS;
7821 ctxt->URL = url;
William M. Brack2f2a6632004-08-20 23:09:47 +00007822 }
William M. Brack2f2a6632004-08-20 23:09:47 +00007823
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00007824 return (0);
William M. Brack2f2a6632004-08-20 23:09:47 +00007825}
7826
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007827/**
7828 * xmlSchemaParseInclude:
7829 * @ctxt: a schema validation context
7830 * @schema: the schema being built
7831 * @node: a subtree containing XML Schema informations
7832 *
7833 * parse a XML schema Include definition
7834 *
William M. Bracke7091952004-05-11 15:09:58 +00007835 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007836 * 1 in case of success.
7837 */
7838static int
7839xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
7840 xmlNodePtr node)
7841{
7842 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007843 const xmlChar *schemaLocation, *targetNamespace;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007844 xmlDocPtr doc;
7845 xmlNodePtr root;
7846 xmlSchemaIncludePtr include;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007847 int wasConvertingNs = 0;
William M. Brack2f2a6632004-08-20 23:09:47 +00007848 xmlAttrPtr attr;
7849 int saveFlags;
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00007850 xmlParserCtxtPtr parserCtxt;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007851
7852
7853 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7854 return (-1);
7855
7856 /*
William M. Brack2f2a6632004-08-20 23:09:47 +00007857 * Check for illegal attributes.
7858 */
7859 attr = node->properties;
7860 while (attr != NULL) {
7861 if (attr->ns == NULL) {
7862 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7863 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
7864 xmlSchemaPIllegalAttrErr(ctxt,
7865 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7866 NULL, NULL, attr);
7867 }
7868 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7869 xmlSchemaPIllegalAttrErr(ctxt,
7870 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7871 NULL, NULL, attr);
7872 }
7873 attr = attr->next;
7874 }
7875 /*
7876 * Extract and validate attributes.
7877 */
7878 /*
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007879 * Preliminary step, extract the URI-Reference for the include and
7880 * make an URI from the base.
7881 */
William M. Brack2f2a6632004-08-20 23:09:47 +00007882 attr = xmlSchemaGetPropNode(node, "schemaLocation");
7883 if (attr != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007884 xmlChar *base = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00007885 xmlChar *uri = NULL;
7886
7887 if (xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
7888 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), &schemaLocation) != 0)
7889 return (-1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007890 base = xmlNodeGetBase(node->doc, node);
7891 if (base == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00007892 uri = xmlBuildURI(schemaLocation, node->doc->URL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007893 } else {
William M. Brack2f2a6632004-08-20 23:09:47 +00007894 uri = xmlBuildURI(schemaLocation, base);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007895 xmlFree(base);
7896 }
William M. Brack2f2a6632004-08-20 23:09:47 +00007897 if (uri != NULL) {
7898 schemaLocation = xmlDictLookup(ctxt->dict, uri, -1);
7899 xmlFree(uri);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007900 }
7901 } else {
William M. Brack2f2a6632004-08-20 23:09:47 +00007902 xmlSchemaPMissingAttrErr(ctxt,
7903 XML_SCHEMAP_INCLUDE_SCHEMA_NO_URI,
7904 NULL, NULL, node, "schemaLocation", NULL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007905 return (-1);
7906 }
William M. Brack2f2a6632004-08-20 23:09:47 +00007907 /*
7908 * And now for the children...
7909 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007910 child = node->children;
7911 while (IS_SCHEMA(child, "annotation")) {
7912 /*
7913 * the annotations here are simply discarded ...
7914 */
7915 child = child->next;
7916 }
7917 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00007918 xmlSchemaPContentErr(ctxt,
7919 XML_SCHEMAP_UNKNOWN_INCLUDE_CHILD,
7920 NULL, NULL, node, child, NULL,
7921 "(annotation?)");
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007922 }
7923
7924 /*
7925 * First step is to parse the input document into an DOM/Infoset
7926 */
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00007927 /*
7928 * TODO: Use xmlCtxtReadFile to share the dictionary.
7929 */
7930 parserCtxt = xmlNewParserCtxt();
7931 if (parserCtxt == NULL) {
7932 xmlSchemaPErrMemory(NULL, "xmlSchemaParseInclude: "
7933 "allocating a parser context", NULL);
7934 return(-1);
7935 }
7936
7937 if ((ctxt->dict != NULL) && (parserCtxt->dict != NULL)) {
7938 xmlDictFree(parserCtxt->dict);
7939 parserCtxt->dict = ctxt->dict;
7940 xmlDictReference(parserCtxt->dict);
7941 }
7942
7943 doc = xmlCtxtReadFile(parserCtxt, (const char *) schemaLocation,
7944 NULL, SCHEMAS_PARSE_OPTIONS);
7945 xmlFreeParserCtxt(parserCtxt);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007946 if (doc == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00007947 /*
7948 * TODO: It is not an error for the ·actual value· of the
7949 * schemaLocation [attribute] to fail to resolve it all, in which
7950 * case no corresponding inclusion is performed.
7951 * So do we need a warning report here?
7952 */
7953 xmlSchemaPCustomErr(ctxt,
7954 XML_SCHEMAP_FAILED_LOAD,
7955 NULL, NULL, node,
7956 "Failed to load the document '%s' for inclusion", schemaLocation);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007957 return(-1);
7958 }
7959
7960 /*
7961 * Then extract the root of the schema
7962 */
7963 root = xmlDocGetRootElement(doc);
7964 if (root == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00007965 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007966 XML_SCHEMAP_NOROOT,
William M. Brack2f2a6632004-08-20 23:09:47 +00007967 NULL, NULL, node,
7968 "The included document '%s' has no document "
7969 "element", schemaLocation);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007970 xmlFreeDoc(doc);
7971 return (-1);
7972 }
7973
7974 /*
7975 * Remove all the blank text nodes
7976 */
7977 xmlSchemaCleanupDoc(ctxt, root);
7978
7979 /*
7980 * Check the schemas top level element
7981 */
7982 if (!IS_SCHEMA(root, "schema")) {
William M. Brack2f2a6632004-08-20 23:09:47 +00007983 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007984 XML_SCHEMAP_NOT_SCHEMA,
William M. Brack2f2a6632004-08-20 23:09:47 +00007985 NULL, NULL, node,
7986 "The document '%s' to be included is not a schema document",
7987 schemaLocation);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00007988 xmlFreeDoc(doc);
7989 return (-1);
7990 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00007991
William M. Brack2f2a6632004-08-20 23:09:47 +00007992 targetNamespace = xmlSchemaGetProp(ctxt, root, "targetNamespace");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007993 /*
7994 * 2.1 SII has a targetNamespace [attribute], and its ·actual
7995 * value· is identical to the ·actual value· of the targetNamespace
7996 * [attribute] of SIIÂ’ (which must have such an [attribute]).
7997 */
7998 if (targetNamespace != NULL) {
7999 if (schema->targetNamespace == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008000 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008001 XML_SCHEMAP_SRC_INCLUDE,
William M. Brack2f2a6632004-08-20 23:09:47 +00008002 NULL, NULL, node,
8003 "The target namespace of the included schema "
8004 "'%s' has to be absent, since the including schema "
8005 "has no target namespace",
8006 schemaLocation);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008007 xmlFreeDoc(doc);
8008 return (-1);
William M. Brack2f2a6632004-08-20 23:09:47 +00008009 } else if (!xmlStrEqual(targetNamespace, schema->targetNamespace)) {
8010 xmlSchemaPCustomErrExt(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008011 XML_SCHEMAP_SRC_INCLUDE,
William M. Brack2f2a6632004-08-20 23:09:47 +00008012 NULL, NULL, node,
8013 "The target namespace '%s' of the included schema '%s' "
8014 "differs from '%s' of the including schema",
8015 targetNamespace, schemaLocation, schema->targetNamespace);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008016 xmlFreeDoc(doc);
8017 return (-1);
8018 }
8019 } else if (schema->targetNamespace != NULL) {
8020 if ((schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) == 0) {
8021 schema->flags |= XML_SCHEMAS_INCLUDING_CONVERT_NS;
8022 } else
8023 wasConvertingNs = 1;
8024 }
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008025 /*
8026 * register the include
8027 */
8028 include = (xmlSchemaIncludePtr) xmlMalloc(sizeof(xmlSchemaInclude));
8029 if (include == NULL) {
8030 xmlSchemaPErrMemory(ctxt, "allocating included schema", NULL);
8031 xmlFreeDoc(doc);
8032 return (-1);
8033 }
8034
8035 memset(include, 0, sizeof(xmlSchemaInclude));
8036 include->schemaLocation = xmlDictLookup(ctxt->dict, schemaLocation, -1);
8037 include->doc = doc;
8038 include->next = schema->includes;
8039 schema->includes = include;
8040
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008041 /*
8042 * parse the declarations in the included file like if they
8043 * were in the original file.
Daniel Veillardc0826a72004-08-10 14:17:33 +00008044 */
8045 /*
William M. Brack2f2a6632004-08-20 23:09:47 +00008046 * TODO: The complete validation of the <schema> element is not done.
Daniel Veillardc0826a72004-08-10 14:17:33 +00008047 */
William M. Brack2f2a6632004-08-20 23:09:47 +00008048 /*
8049 * The default values ("blockDefault", "elementFormDefault", etc.)
8050 * are set to the values of the included schema and restored afterwards.
8051 */
8052 saveFlags = schema->flags;
8053 xmlSchemaClearSchemaDefaults(schema);
8054 xmlSchemaParseSchemaDefaults(ctxt, schema, root);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008055 xmlSchemaParseSchemaTopLevel(ctxt, schema, root->children);
William M. Brack2f2a6632004-08-20 23:09:47 +00008056 schema->flags = saveFlags;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008057 /*
8058 * Remove the converting flag.
8059 */
William M. Brack2f2a6632004-08-20 23:09:47 +00008060 if ((wasConvertingNs == 0) &&
8061 (schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS))
Daniel Veillardc0826a72004-08-10 14:17:33 +00008062 schema->flags ^= XML_SCHEMAS_INCLUDING_CONVERT_NS;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008063 return (1);
8064}
8065
8066/**
Daniel Veillard4255d502002-04-16 15:50:10 +00008067 * xmlSchemaParseChoice:
8068 * @ctxt: a schema validation context
8069 * @schema: the schema being built
8070 * @node: a subtree containing XML Schema informations
8071 *
8072 * parse a XML schema Choice definition
8073 * *WARNING* this interface is highly subject to change
8074 *
William M. Bracke7091952004-05-11 15:09:58 +00008075 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00008076 * 1 in case of success.
8077 */
8078static xmlSchemaTypePtr
8079xmlSchemaParseChoice(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008080 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00008081{
8082 xmlSchemaTypePtr type, subtype, last = NULL;
8083 xmlNodePtr child = NULL;
8084 xmlChar name[30];
William M. Brack2f2a6632004-08-20 23:09:47 +00008085 xmlAttrPtr attr;
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00008086 const xmlChar *oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00008087
8088 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8089 return (NULL);
8090
8091
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00008092 snprintf((char *) name, 30, "#ch%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00008093 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00008094 if (type == NULL)
8095 return (NULL);
8096 type->node = node;
8097 type->type = XML_SCHEMA_TYPE_CHOICE;
William M. Brack2f2a6632004-08-20 23:09:47 +00008098 /*
8099 * Check for illegal attributes.
8100 */
8101 attr = node->properties;
8102 while (attr != NULL) {
8103 if (attr->ns == NULL) {
8104 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8105 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
8106 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs"))) {
8107 xmlSchemaPIllegalAttrErr(ctxt,
8108 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8109 NULL, type, attr);
8110 }
8111 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8112 xmlSchemaPIllegalAttrErr(ctxt,
8113 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8114 NULL, type, attr);
8115 }
8116 attr = attr->next;
8117 }
8118 /*
8119 * Extract and validate attributes.
8120 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008121 type->id = xmlSchemaGetProp(ctxt, node, "id");
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00008122 type->minOccurs = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "nonNegativeInteger");
8123 type->maxOccurs = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
8124 "(nonNegativeInteger | unbounded)");
William M. Brack2f2a6632004-08-20 23:09:47 +00008125 /*
8126 * And now for the children...
8127 */
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00008128 oldcontainer = ctxt->container;
8129 ctxt->container = (const xmlChar *) name;
Daniel Veillard4255d502002-04-16 15:50:10 +00008130 child = node->children;
8131 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008132 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8133 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008134 }
8135 while ((IS_SCHEMA(child, "element")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008136 (IS_SCHEMA(child, "group")) ||
8137 (IS_SCHEMA(child, "any")) ||
8138 (IS_SCHEMA(child, "choice")) ||
8139 (IS_SCHEMA(child, "sequence"))) {
8140 subtype = NULL;
8141 if (IS_SCHEMA(child, "element")) {
8142 subtype = (xmlSchemaTypePtr)
8143 xmlSchemaParseElement(ctxt, schema, child, 0);
8144 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00008145 subtype = xmlSchemaParseGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008146 } else if (IS_SCHEMA(child, "any")) {
8147 subtype = xmlSchemaParseAny(ctxt, schema, child);
8148 } else if (IS_SCHEMA(child, "sequence")) {
8149 subtype = xmlSchemaParseSequence(ctxt, schema, child);
8150 } else if (IS_SCHEMA(child, "choice")) {
8151 subtype = xmlSchemaParseChoice(ctxt, schema, child);
8152 }
8153 if (subtype != NULL) {
8154 if (last == NULL) {
8155 type->subtypes = subtype;
8156 last = subtype;
8157 } else {
8158 last->next = subtype;
8159 last = subtype;
8160 }
8161 last->next = NULL;
8162 }
8163 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008164 }
8165 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008166 /* TODO: error code. */
8167 xmlSchemaPContentErr(ctxt,
8168 XML_SCHEMAP_UNKNOWN_CHOICE_CHILD,
8169 NULL, type, node, child, NULL,
8170 "(annotation?, (element | group | choice | sequence | any)*)");
Daniel Veillard4255d502002-04-16 15:50:10 +00008171 }
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00008172 ctxt->container = oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00008173 return (type);
8174}
8175
8176/**
8177 * xmlSchemaParseSequence:
8178 * @ctxt: a schema validation context
8179 * @schema: the schema being built
8180 * @node: a subtree containing XML Schema informations
8181 *
8182 * parse a XML schema Sequence definition
8183 * *WARNING* this interface is highly subject to change
8184 *
William M. Bracke7091952004-05-11 15:09:58 +00008185 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00008186 * 1 in case of success.
8187 */
8188static xmlSchemaTypePtr
8189xmlSchemaParseSequence(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008190 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00008191{
8192 xmlSchemaTypePtr type, subtype, last = NULL;
8193 xmlNodePtr child = NULL;
8194 xmlChar name[30];
William M. Brack2f2a6632004-08-20 23:09:47 +00008195 xmlAttrPtr attr;
8196 const xmlChar *oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00008197
8198 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8199 return (NULL);
8200
William M. Brack2f2a6632004-08-20 23:09:47 +00008201 oldcontainer = ctxt->container;
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00008202 snprintf((char *) name, 30, "#seq%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00008203 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00008204 if (type == NULL)
8205 return (NULL);
8206 type->node = node;
8207 type->type = XML_SCHEMA_TYPE_SEQUENCE;
William M. Brack2f2a6632004-08-20 23:09:47 +00008208 /*
8209 * Check for illegal attributes.
8210 */
8211 attr = node->properties;
8212 while (attr != NULL) {
8213 if (attr->ns == NULL) {
8214 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8215 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
8216 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs"))) {
8217 xmlSchemaPIllegalAttrErr(ctxt,
8218 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8219 NULL, type, attr);
8220 }
8221 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8222 xmlSchemaPIllegalAttrErr(ctxt,
8223 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8224 NULL, type, attr);
8225 }
8226 attr = attr->next;
8227 }
8228 /*
8229 * Extract and validate attributes.
8230 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008231 type->id = xmlSchemaGetProp(ctxt, node, "id");
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00008232 type->minOccurs = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "nonNegativeInteger");
8233 type->maxOccurs = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
8234 "(nonNegativeInteger | unbounded)");
William M. Brack2f2a6632004-08-20 23:09:47 +00008235 /*
8236 * And now for the children...
8237 */
8238 ctxt->container = (const xmlChar *) name;
Daniel Veillard4255d502002-04-16 15:50:10 +00008239 child = node->children;
8240 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008241 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8242 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008243 }
8244 while ((IS_SCHEMA(child, "element")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008245 (IS_SCHEMA(child, "group")) ||
8246 (IS_SCHEMA(child, "any")) ||
8247 (IS_SCHEMA(child, "choice")) ||
8248 (IS_SCHEMA(child, "sequence"))) {
8249 subtype = NULL;
8250 if (IS_SCHEMA(child, "element")) {
8251 subtype = (xmlSchemaTypePtr)
8252 xmlSchemaParseElement(ctxt, schema, child, 0);
8253 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00008254 subtype = xmlSchemaParseGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008255 } else if (IS_SCHEMA(child, "any")) {
8256 subtype = xmlSchemaParseAny(ctxt, schema, child);
8257 } else if (IS_SCHEMA(child, "choice")) {
8258 subtype = xmlSchemaParseChoice(ctxt, schema, child);
8259 } else if (IS_SCHEMA(child, "sequence")) {
8260 subtype = xmlSchemaParseSequence(ctxt, schema, child);
8261 }
8262 if (subtype != NULL) {
8263 if (last == NULL) {
8264 type->subtypes = subtype;
8265 last = subtype;
8266 } else {
8267 last->next = subtype;
8268 last = subtype;
8269 }
8270 last->next = NULL;
8271 }
8272 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008273 }
8274 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008275 xmlSchemaPContentErr(ctxt,
8276 XML_SCHEMAP_UNKNOWN_SEQUENCE_CHILD,
8277 NULL, type, node, child, NULL,
8278 "(annotation?, (element | group | choice | sequence | any)*)");
Daniel Veillard4255d502002-04-16 15:50:10 +00008279 }
William M. Brack2f2a6632004-08-20 23:09:47 +00008280 ctxt->container = oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00008281
8282 return (type);
8283}
8284
8285/**
8286 * xmlSchemaParseRestriction:
8287 * @ctxt: a schema validation context
8288 * @schema: the schema being built
8289 * @node: a subtree containing XML Schema informations
Daniel Veillard4255d502002-04-16 15:50:10 +00008290 *
8291 * parse a XML schema Restriction definition
8292 * *WARNING* this interface is highly subject to change
8293 *
8294 * Returns the type definition or NULL in case of error
8295 */
8296static xmlSchemaTypePtr
8297xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00008298 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00008299{
Daniel Veillard01fa6152004-06-29 17:04:39 +00008300 xmlSchemaTypePtr type, subtype;
Daniel Veillard4255d502002-04-16 15:50:10 +00008301 xmlNodePtr child = NULL;
8302 xmlChar name[30];
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008303 const xmlChar *oldcontainer;
William M. Brack2f2a6632004-08-20 23:09:47 +00008304 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00008305
8306 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8307 return (NULL);
8308
8309 oldcontainer = ctxt->container;
8310
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00008311 snprintf((char *) name, 30, "#restr%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00008312 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00008313 if (type == NULL)
8314 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00008315 type->type = XML_SCHEMA_TYPE_RESTRICTION;
Daniel Veillard4255d502002-04-16 15:50:10 +00008316 type->node = node;
William M. Brack2f2a6632004-08-20 23:09:47 +00008317 /*
8318 * Check for illegal attributes.
8319 */
8320 attr = node->properties;
8321 while (attr != NULL) {
8322 if (attr->ns == NULL) {
8323 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8324 (!xmlStrEqual(attr->name, BAD_CAST "base"))) {
8325 xmlSchemaPIllegalAttrErr(ctxt,
8326 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8327 NULL, type, attr);
8328 }
8329 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8330 xmlSchemaPIllegalAttrErr(ctxt,
8331 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8332 NULL, type, attr);
8333 }
8334 attr = attr->next;
8335 }
8336 /*
8337 * Extract and validate attributes.
8338 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008339 type->id = xmlSchemaGetProp(ctxt, node, "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00008340 /*
8341 * Attribute "base".
8342 */
Daniel Veillard4255d502002-04-16 15:50:10 +00008343 type->base = xmlGetQNameProp(ctxt, node, "base", &(type->baseNs));
Daniel Veillard01fa6152004-06-29 17:04:39 +00008344 if ((type->base == NULL) &&
William M. Brack2f2a6632004-08-20 23:09:47 +00008345 (ctxt->ctxtType->type == XML_SCHEMA_TYPE_COMPLEX)) {
8346 /* TODO: Think about the error code. */
8347 xmlSchemaPMissingAttrErr(ctxt,
8348 XML_SCHEMAP_RESTRICTION_NONAME_NOREF,
8349 NULL, type, node, "base", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00008350 }
William M. Brack2f2a6632004-08-20 23:09:47 +00008351 /*
8352 * And now for the children...
8353 */
Daniel Veillard4255d502002-04-16 15:50:10 +00008354 ctxt->container = name;
Daniel Veillard4255d502002-04-16 15:50:10 +00008355 child = node->children;
8356 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008357 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8358 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008359 }
8360 subtype = NULL;
Daniel Veillard01fa6152004-06-29 17:04:39 +00008361 if (ctxt->parentItem->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
8362 if (IS_SCHEMA(child, "all")) {
8363 subtype = (xmlSchemaTypePtr)
8364 xmlSchemaParseAll(ctxt, schema, child);
8365 child = child->next;
8366 type->subtypes = subtype;
8367 } else if (IS_SCHEMA(child, "choice")) {
8368 subtype = xmlSchemaParseChoice(ctxt, schema, child);
8369 child = child->next;
8370 type->subtypes = subtype;
8371 } else if (IS_SCHEMA(child, "sequence")) {
8372 subtype = (xmlSchemaTypePtr)
8373 xmlSchemaParseSequence(ctxt, schema, child);
8374 child = child->next;
8375 type->subtypes = subtype;
8376 } else if (IS_SCHEMA(child, "group")) {
8377 subtype = (xmlSchemaTypePtr)
8378 xmlSchemaParseGroup(ctxt, schema, child, 0);
8379 child = child->next;
8380 type->subtypes = subtype;
8381 }
William M. Brack2f2a6632004-08-20 23:09:47 +00008382 } else if (ctxt->ctxtType->type == XML_SCHEMA_TYPE_SIMPLE) {
8383 if (IS_SCHEMA(child, "simpleType")) {
8384 if (type->base != NULL) {
8385 /*
8386 * src-restriction-base-or-simpleType
8387 * Either the base [attribute] or the simpleType [child] of the
8388 * <restriction> element must be present, but not both.
8389 */
8390 xmlSchemaPContentErr(ctxt,
8391 XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
8392 NULL, NULL, type->node, child,
8393 "The attribute 'base' and the <simpleType> child are "
8394 "mutually exclusive", NULL);
8395 } else {
8396 subtype = (xmlSchemaTypePtr)
8397 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
8398 type->baseType = subtype;
8399 }
8400 child = child->next;
8401 }
8402 } else if (ctxt->parentItem->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
Daniel Veillard01fa6152004-06-29 17:04:39 +00008403 if (IS_SCHEMA(child, "simpleType")) {
8404 subtype = (xmlSchemaTypePtr)
8405 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
Daniel Veillard01fa6152004-06-29 17:04:39 +00008406 type->subtypes = subtype;
8407 child = child->next;
William M. Brack2f2a6632004-08-20 23:09:47 +00008408 }
8409 }
8410 if ((ctxt->ctxtType->type == XML_SCHEMA_TYPE_SIMPLE) ||
8411 (ctxt->parentItem->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT)) {
8412 xmlSchemaFacetPtr facet, lastfacet = NULL;
8413
Daniel Veillard01fa6152004-06-29 17:04:39 +00008414 /*
8415 * Add the facets to the parent simpleType/complexType.
8416 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00008417 /*
8418 * TODO: Datatypes: 4.1.3 Constraints on XML Representation of
8419 * Simple Type Definition Schema Representation Constraint:
8420 * *Single Facet Value*
8421 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00008422 while ((IS_SCHEMA(child, "minInclusive")) ||
8423 (IS_SCHEMA(child, "minExclusive")) ||
8424 (IS_SCHEMA(child, "maxInclusive")) ||
8425 (IS_SCHEMA(child, "maxExclusive")) ||
8426 (IS_SCHEMA(child, "totalDigits")) ||
8427 (IS_SCHEMA(child, "fractionDigits")) ||
8428 (IS_SCHEMA(child, "pattern")) ||
8429 (IS_SCHEMA(child, "enumeration")) ||
8430 (IS_SCHEMA(child, "whiteSpace")) ||
8431 (IS_SCHEMA(child, "length")) ||
8432 (IS_SCHEMA(child, "maxLength")) ||
8433 (IS_SCHEMA(child, "minLength"))) {
8434 facet = xmlSchemaParseFacet(ctxt, schema, child);
8435 if (facet != NULL) {
8436 if (lastfacet == NULL)
8437 ctxt->ctxtType->facets = facet;
8438 else
8439 lastfacet->next = facet;
8440 lastfacet = facet;
8441 lastfacet->next = NULL;
8442 }
8443 child = child->next;
8444 }
8445 /*
8446 * Create links for derivation and validation.
8447 */
8448 if (lastfacet != NULL) {
8449 xmlSchemaFacetLinkPtr facetLink, lastFacetLink = NULL;
8450
8451 facet = ctxt->ctxtType->facets;
8452 do {
8453 facetLink = (xmlSchemaFacetLinkPtr) xmlMalloc(sizeof(xmlSchemaFacetLink));
8454 if (facetLink == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008455 xmlSchemaPErrMemory(ctxt, "allocating a facet link", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00008456 xmlFree(facetLink);
8457 return (NULL);
8458 }
8459 facetLink->facet = facet;
8460 facetLink->next = NULL;
8461 if (lastFacetLink == NULL)
8462 ctxt->ctxtType->facetSet = facetLink;
8463 else
8464 lastFacetLink->next = facetLink;
8465 lastFacetLink = facetLink;
8466 facet = facet->next;
8467 } while (facet != NULL);
8468 }
8469 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008470 if (ctxt->ctxtType->type == XML_SCHEMA_TYPE_COMPLEX) {
8471 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
8472 if (IS_SCHEMA(child, "anyAttribute")) {
8473 ctxt->ctxtType->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
8474 child = child->next;
8475 }
8476 }
Daniel Veillard4255d502002-04-16 15:50:10 +00008477 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008478 /* TODO: Think about the error code. */
8479 if (ctxt->parentItem->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
8480 xmlSchemaPContentErr(ctxt,
8481 XML_SCHEMAP_UNKNOWN_RESTRICTION_CHILD,
8482 NULL, type, node, child, NULL,
8483 "annotation?, (group | all | choice | sequence)?, "
8484 "((attribute | attributeGroup)*, anyAttribute?))");
8485 } else if (ctxt->parentItem->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
8486 xmlSchemaPContentErr(ctxt,
8487 XML_SCHEMAP_UNKNOWN_RESTRICTION_CHILD,
8488 NULL, type, node, child, NULL,
8489 "(annotation?, (simpleType?, (minExclusive | minInclusive | "
8490 "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
8491 "length | minLength | maxLength | enumeration | whiteSpace | "
8492 "pattern)*)?, ((attribute | attributeGroup)*, anyAttribute?))");
8493 } else {
8494 /* Simple type */
8495 xmlSchemaPContentErr(ctxt,
8496 XML_SCHEMAP_UNKNOWN_RESTRICTION_CHILD,
8497 NULL, type, node, child, NULL,
8498 "(annotation?, (simpleType?, (minExclusive | minInclusive | "
8499 "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
8500 "length | minLength | maxLength | enumeration | whiteSpace | "
8501 "pattern)*))");
8502 }
8503 }
Daniel Veillard4255d502002-04-16 15:50:10 +00008504 ctxt->container = oldcontainer;
8505 return (type);
8506}
8507
8508/**
8509 * xmlSchemaParseExtension:
8510 * @ctxt: a schema validation context
8511 * @schema: the schema being built
8512 * @node: a subtree containing XML Schema informations
8513 *
8514 * parse a XML schema Extension definition
8515 * *WARNING* this interface is highly subject to change
8516 *
8517 * Returns the type definition or NULL in case of error
8518 */
8519static xmlSchemaTypePtr
8520xmlSchemaParseExtension(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008521 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00008522{
8523 xmlSchemaTypePtr type, subtype;
8524 xmlNodePtr child = NULL;
8525 xmlChar name[30];
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008526 const xmlChar *oldcontainer;
Daniel Veillard4255d502002-04-16 15:50:10 +00008527
8528 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8529 return (NULL);
8530
8531 oldcontainer = ctxt->container;
8532
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00008533 snprintf((char *) name, 30, "#ext%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00008534 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00008535 if (type == NULL)
8536 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00008537 type->type = XML_SCHEMA_TYPE_EXTENSION;
Daniel Veillard4255d502002-04-16 15:50:10 +00008538 type->node = node;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008539 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00008540 ctxt->container = name;
8541
8542 type->base = xmlGetQNameProp(ctxt, node, "base", &(type->baseNs));
8543 if (type->base == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008544 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_EXTENSION_NO_BASE,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008545 "<extension>: The attribute \"base\" is missing.\n",
8546 type->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00008547 }
8548 child = node->children;
8549 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008550 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8551 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008552 }
8553 subtype = NULL;
8554
8555 if (IS_SCHEMA(child, "all")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008556 subtype = xmlSchemaParseAll(ctxt, schema, child);
8557 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008558 } else if (IS_SCHEMA(child, "choice")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008559 subtype = xmlSchemaParseChoice(ctxt, schema, child);
8560 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008561 } else if (IS_SCHEMA(child, "sequence")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008562 subtype = xmlSchemaParseSequence(ctxt, schema, child);
8563 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008564 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00008565 subtype = xmlSchemaParseGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008566 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008567 }
8568 if (subtype != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008569 type->subtypes = subtype;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008570 if ((ctxt->ctxtType != NULL) &&
8571 (ctxt->ctxtType->type == XML_SCHEMA_TYPE_COMPLEX)) {
8572 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
8573 if (IS_SCHEMA(child, "anyAttribute")) {
8574 ctxt->ctxtType->attributeWildcard =
8575 xmlSchemaParseAnyAttribute(ctxt, schema, child);
8576 child = child->next;
8577 }
8578 }
Daniel Veillard4255d502002-04-16 15:50:10 +00008579 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008580 xmlSchemaPErr2(ctxt, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008581 XML_SCHEMAP_UNKNOWN_EXTENSION_CHILD,
8582 "<extension> has unexpected content.\n", type->name,
8583 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00008584 }
8585 ctxt->container = oldcontainer;
8586 return (type);
8587}
8588
8589/**
8590 * xmlSchemaParseSimpleContent:
8591 * @ctxt: a schema validation context
8592 * @schema: the schema being built
8593 * @node: a subtree containing XML Schema informations
8594 *
8595 * parse a XML schema SimpleContent definition
8596 * *WARNING* this interface is highly subject to change
8597 *
8598 * Returns the type definition or NULL in case of error
8599 */
8600static xmlSchemaTypePtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008601xmlSchemaParseSimpleContent(xmlSchemaParserCtxtPtr ctxt,
8602 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00008603{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008604 xmlSchemaTypePtr type, subtype, oldParentItem;
Daniel Veillard4255d502002-04-16 15:50:10 +00008605 xmlNodePtr child = NULL;
8606 xmlChar name[30];
8607
8608 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8609 return (NULL);
8610
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00008611 snprintf((char *) name, 30, "#SC%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00008612 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00008613 if (type == NULL)
8614 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00008615 type->type = XML_SCHEMA_TYPE_SIMPLE_CONTENT;
Daniel Veillard4255d502002-04-16 15:50:10 +00008616 type->node = node;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008617 type->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00008618
8619 child = node->children;
8620 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008621 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8622 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008623 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008624 oldParentItem = ctxt->parentItem;
Daniel Veillard01fa6152004-06-29 17:04:39 +00008625 ctxt->parentItem = type;
8626 subtype = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00008627 if (IS_SCHEMA(child, "restriction")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008628 subtype = (xmlSchemaTypePtr)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00008629 xmlSchemaParseRestriction(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008630 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008631 } else if (IS_SCHEMA(child, "extension")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008632 subtype = (xmlSchemaTypePtr)
8633 xmlSchemaParseExtension(ctxt, schema, child);
8634 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008635 }
8636 type->subtypes = subtype;
8637 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008638 xmlSchemaPErr2(ctxt, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008639 XML_SCHEMAP_UNKNOWN_SIMPLECONTENT_CHILD,
8640 "<simpleContent> has unexpected content.\n",
8641 NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00008642 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008643 ctxt->parentItem = oldParentItem;
Daniel Veillard4255d502002-04-16 15:50:10 +00008644 return (type);
8645}
8646
8647/**
8648 * xmlSchemaParseComplexContent:
8649 * @ctxt: a schema validation context
8650 * @schema: the schema being built
8651 * @node: a subtree containing XML Schema informations
8652 *
8653 * parse a XML schema ComplexContent definition
8654 * *WARNING* this interface is highly subject to change
8655 *
8656 * Returns the type definition or NULL in case of error
8657 */
8658static xmlSchemaTypePtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008659xmlSchemaParseComplexContent(xmlSchemaParserCtxtPtr ctxt,
8660 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00008661{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008662 xmlSchemaTypePtr type, subtype, oldParentItem;
Daniel Veillard4255d502002-04-16 15:50:10 +00008663 xmlNodePtr child = NULL;
8664 xmlChar name[30];
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008665 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00008666
8667 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8668 return (NULL);
8669
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00008670 snprintf((char *) name, 30, "#CC%d", ctxt->counter++ + 1);
William M. Brack2f2a6632004-08-20 23:09:47 +00008671 type = xmlSchemaAddType(ctxt, schema, name, NULL, node);
Daniel Veillard4255d502002-04-16 15:50:10 +00008672 if (type == NULL)
8673 return (NULL);
Daniel Veillard4e5d6652004-06-29 21:01:12 +00008674 type->type = XML_SCHEMA_TYPE_COMPLEX_CONTENT;
Daniel Veillard01fa6152004-06-29 17:04:39 +00008675 type->node = node;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008676 /*
8677 * Check for illegal attributes.
8678 */
8679 attr = node->properties;
8680 while (attr != NULL) {
8681 if (attr->ns == NULL) {
8682 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8683 (!xmlStrEqual(attr->name, BAD_CAST "mixed")))
8684 {
8685 xmlSchemaPIllegalAttrErr(ctxt,
8686 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8687 NULL, NULL, attr);
8688 }
8689 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8690 xmlSchemaPIllegalAttrErr(ctxt,
8691 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8692 NULL, NULL, attr);
8693 }
8694 attr = attr->next;
8695 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008696 type->id = xmlSchemaGetProp(ctxt, node, "id");
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008697 /*
8698 * Handle attribute 'mixed'.
8699 */
8700 if (xmlGetBooleanProp(ctxt, NULL, type, node, "mixed", 0)) {
8701 if ((ctxt->ctxtType->flags & XML_SCHEMAS_TYPE_MIXED) == 0)
8702 ctxt->ctxtType->flags |= XML_SCHEMAS_TYPE_MIXED;
8703 }
Daniel Veillard4255d502002-04-16 15:50:10 +00008704 child = node->children;
8705 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008706 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8707 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008708 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008709 oldParentItem = ctxt->parentItem;
Daniel Veillard01fa6152004-06-29 17:04:39 +00008710 ctxt->parentItem = type;
Daniel Veillard4255d502002-04-16 15:50:10 +00008711 subtype = NULL;
8712 if (IS_SCHEMA(child, "restriction")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008713 subtype = (xmlSchemaTypePtr)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00008714 xmlSchemaParseRestriction(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008715 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008716 } else if (IS_SCHEMA(child, "extension")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008717 subtype = (xmlSchemaTypePtr)
8718 xmlSchemaParseExtension(ctxt, schema, child);
8719 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008720 }
8721 type->subtypes = subtype;
8722 if (child != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008723 xmlSchemaPContentErr(ctxt,
8724 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8725 NULL, NULL, node, child,
8726 NULL, "(annotation?, (restriction | extension))");
Daniel Veillard4255d502002-04-16 15:50:10 +00008727 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008728 ctxt->parentItem = oldParentItem;
Daniel Veillard4255d502002-04-16 15:50:10 +00008729 return (type);
8730}
8731
8732/**
8733 * xmlSchemaParseComplexType:
8734 * @ctxt: a schema validation context
8735 * @schema: the schema being built
8736 * @node: a subtree containing XML Schema informations
8737 *
8738 * parse a XML schema Complex Type definition
8739 * *WARNING* this interface is highly subject to change
8740 *
8741 * Returns the type definition or NULL in case of error
8742 */
8743static xmlSchemaTypePtr
8744xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00008745 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00008746{
Daniel Veillard01fa6152004-06-29 17:04:39 +00008747 xmlSchemaTypePtr type, subtype, ctxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +00008748 xmlNodePtr child = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008749 const xmlChar *name = NULL;
William M. Bracke7091952004-05-11 15:09:58 +00008750 const xmlChar *oldcontainer;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008751 xmlAttrPtr attr;
8752 const xmlChar *attrValue;
8753 xmlChar *des = NULL; /* The reported designation. */
Daniel Veillard1a380b82004-10-21 16:00:06 +00008754 char buf[40];
8755
Daniel Veillard4255d502002-04-16 15:50:10 +00008756
8757 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8758 return (NULL);
8759
Daniel Veillard01fa6152004-06-29 17:04:39 +00008760 ctxtType = ctxt->ctxtType;
8761
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008762 if (topLevel) {
8763 attr = xmlSchemaGetPropNode(node, "name");
8764 if (attr == NULL) {
8765 xmlSchemaPMissingAttrErr(ctxt,
8766 XML_SCHEMAP_S4S_ATTR_MISSING,
8767 (xmlChar **) &xmlSchemaElemDesCT, NULL, node,
8768 "name", NULL);
8769 return (NULL);
8770 } else if (xmlSchemaPValAttrNode(ctxt,
8771 (xmlChar **) &xmlSchemaElemDesCT, NULL, attr,
8772 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
8773 return (NULL);
8774 }
8775 }
8776
8777 if (topLevel == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008778 /*
8779 * Parse as local complex type definition.
8780 */
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00008781 snprintf(buf, 39, "#CT%d", ctxt->counter++ + 1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008782 type = xmlSchemaAddType(ctxt, schema, (const xmlChar *)buf, NULL, node);
8783 if (type == NULL)
8784 return (NULL);
8785 name = (const xmlChar *) buf;
8786 type->node = node;
8787 type->type = XML_SCHEMA_TYPE_COMPLEX;
8788 /*
8789 * TODO: We need the target namespace.
8790 */
8791 } else {
8792 /*
8793 * Parse as global complex type definition.
8794 */
William M. Brack2f2a6632004-08-20 23:09:47 +00008795 type = xmlSchemaAddType(ctxt, schema, name, schema->targetNamespace, node);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008796 if (type == NULL)
8797 return (NULL);
8798 type->node = node;
8799 type->type = XML_SCHEMA_TYPE_COMPLEX;
8800 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
8801 /*
8802 * Set defaults.
8803 */
8804 type->flags |= XML_SCHEMAS_TYPE_FINAL_DEFAULT;
8805 type->flags |= XML_SCHEMAS_TYPE_BLOCK_DEFAULT;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00008806 }
8807 type->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008808 /*
8809 * Handle attributes.
8810 */
8811 attr = node->properties;
8812 while (attr != NULL) {
8813 if (attr->ns == NULL) {
8814 if (xmlStrEqual(attr->name, BAD_CAST "id")) {
8815 /*
8816 * Attribute "id".
8817 */
8818 type->id = xmlSchemaGetProp(ctxt, node, "id");
8819 } else if (xmlStrEqual(attr->name, BAD_CAST "mixed")) {
8820 /*
8821 * Attribute "mixed".
8822 */
8823 if (xmlSchemaPGetBoolNodeValue(ctxt, &des, type,
8824 (xmlNodePtr) attr))
8825 type->flags |= XML_SCHEMAS_TYPE_MIXED;
8826 } else if (topLevel) {
8827 /*
8828 * Attributes of global complex type definitions.
8829 */
8830 if (xmlStrEqual(attr->name, BAD_CAST "name")) {
8831 /* Pass. */
8832 } else if (xmlStrEqual(attr->name, BAD_CAST "abstract")) {
8833 /*
8834 * Attribute "abstract".
8835 */
8836 if (xmlSchemaPGetBoolNodeValue(ctxt, &des, type,
8837 (xmlNodePtr) attr))
8838 type->flags |= XML_SCHEMAS_TYPE_ABSTRACT;
8839 } else if (xmlStrEqual(attr->name, BAD_CAST "final")) {
8840 /*
8841 * Attribute "final".
8842 */
8843 attrValue = xmlSchemaGetNodeContent(ctxt,
8844 (xmlNodePtr) attr);
8845 if (xmlSchemaPValAttrBlockFinal(attrValue,
8846 &(type->flags),
8847 -1,
8848 XML_SCHEMAS_TYPE_FINAL_EXTENSION,
8849 XML_SCHEMAS_TYPE_FINAL_RESTRICTION,
8850 -1, -1, -1) != 0)
8851 {
8852 xmlSchemaPSimpleTypeErr(ctxt,
8853 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8854 &des, type, (xmlNodePtr) attr,
8855 NULL,
8856 "(#all | List of (extension | restriction))",
8857 attrValue, NULL, NULL, NULL);
8858 }
8859 } else if (xmlStrEqual(attr->name, BAD_CAST "block")) {
8860 /*
8861 * Attribute "block".
8862 */
8863 attrValue = xmlSchemaGetNodeContent(ctxt,
8864 (xmlNodePtr) attr);
8865 if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
8866 -1,
8867 XML_SCHEMAS_TYPE_BLOCK_EXTENSION,
8868 XML_SCHEMAS_TYPE_BLOCK_RESTRICTION,
8869 -1, -1, -1) != 0) {
8870 xmlSchemaPSimpleTypeErr(ctxt,
8871 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8872 &des, type, (xmlNodePtr) attr,
8873 NULL,
8874 "(#all | List of (extension | restriction)) ",
8875 attrValue, NULL, NULL, NULL);
8876 }
8877 } else {
8878 xmlSchemaPIllegalAttrErr(ctxt,
8879 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8880 &des, type, attr);
8881 }
8882 } else {
8883 xmlSchemaPIllegalAttrErr(ctxt,
8884 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8885 &des, type, attr);
8886 }
8887 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8888 xmlSchemaPIllegalAttrErr(ctxt,
8889 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8890 &des, type, attr);
8891 }
8892 attr = attr->next;
8893 }
8894 /*
8895 * Set as default for attribute wildcards.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008896 * This will be only changed if a complex type
8897 * inherits an attribute wildcard from a base type.
8898 */
8899 type->flags |= XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008900 /*
8901 * And now for the children...
8902 */
8903 oldcontainer = ctxt->container;
8904 ctxt->container = name;
Daniel Veillard4255d502002-04-16 15:50:10 +00008905 child = node->children;
8906 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008907 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8908 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008909 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00008910 ctxt->ctxtType = type;
Daniel Veillard4255d502002-04-16 15:50:10 +00008911 if (IS_SCHEMA(child, "simpleContent")) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008912 /*
8913 * 3.4.3 : 2.2
8914 * Specifying mixed='true' when the <simpleContent>
8915 * alternative is chosen has no effect
8916 */
William M. Bracke7091952004-05-11 15:09:58 +00008917 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
8918 type->flags ^= XML_SCHEMAS_TYPE_MIXED;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008919 type->subtypes = xmlSchemaParseSimpleContent(ctxt, schema, child);
8920 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008921 } else if (IS_SCHEMA(child, "complexContent")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008922 type->subtypes = xmlSchemaParseComplexContent(ctxt, schema, child);
8923 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008924 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008925 subtype = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008926 /*
8927 * Parse model groups.
8928 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008929 if (IS_SCHEMA(child, "all")) {
8930 subtype = xmlSchemaParseAll(ctxt, schema, child);
8931 child = child->next;
8932 } else if (IS_SCHEMA(child, "choice")) {
8933 subtype = xmlSchemaParseChoice(ctxt, schema, child);
8934 child = child->next;
8935 } else if (IS_SCHEMA(child, "sequence")) {
8936 subtype = xmlSchemaParseSequence(ctxt, schema, child);
8937 child = child->next;
8938 } else if (IS_SCHEMA(child, "group")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00008939 subtype = xmlSchemaParseGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008940 child = child->next;
8941 }
8942 if (subtype != NULL)
8943 type->subtypes = subtype;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008944 /*
8945 * Parse attribute decls/refs.
8946 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008947 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008948 /*
8949 * Parse attribute wildcard.
8950 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008951 if (IS_SCHEMA(child, "anyAttribute")) {
8952 type->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
8953 child = child->next;
8954 }
Daniel Veillard4255d502002-04-16 15:50:10 +00008955 }
8956 if (child != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008957 xmlSchemaPContentErr(ctxt,
8958 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8959 &des, type, node, child,
8960 NULL, "(annotation?, (simpleContent | complexContent | "
8961 "((group | all | choice | sequence)?, ((attribute | "
8962 "attributeGroup)*, anyAttribute?))))");
Daniel Veillard4255d502002-04-16 15:50:10 +00008963 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008964 FREE_AND_NULL(des);
Daniel Veillard4255d502002-04-16 15:50:10 +00008965 ctxt->container = oldcontainer;
Daniel Veillard01fa6152004-06-29 17:04:39 +00008966 ctxt->ctxtType = ctxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +00008967 return (type);
8968}
8969
Daniel Veillard4255d502002-04-16 15:50:10 +00008970/**
8971 * xmlSchemaParseSchema:
8972 * @ctxt: a schema validation context
8973 * @node: a subtree containing XML Schema informations
8974 *
8975 * parse a XML schema definition from a node set
8976 * *WARNING* this interface is highly subject to change
8977 *
8978 * Returns the internal XML Schema structure built from the resource or
8979 * NULL in case of error
8980 */
8981static xmlSchemaPtr
8982xmlSchemaParseSchema(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
8983{
8984 xmlSchemaPtr schema = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00008985 const xmlChar *val;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00008986 int nberrors;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008987 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00008988
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008989 /*
8990 * This one is called by xmlSchemaParse only and is used if
8991 * the schema to be parsed was specified via the API; i.e. not
8992 * automatically by the validated instance document.
8993 */
Daniel Veillard4255d502002-04-16 15:50:10 +00008994 if ((ctxt == NULL) || (node == NULL))
8995 return (NULL);
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00008996 nberrors = ctxt->nberrors;
8997 ctxt->nberrors = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00008998 if (IS_SCHEMA(node, "schema")) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008999 xmlSchemaImportPtr import;
9000
Daniel Veillard4255d502002-04-16 15:50:10 +00009001 schema = xmlSchemaNewSchema(ctxt);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009002 if (schema == NULL)
9003 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009004 /*
9005 * Disable build of list of items.
9006 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00009007 attr = xmlSchemaGetPropNode(node, "targetNamespace");
9008 if (attr != NULL) {
9009 xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
9010 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), &val);
9011 /*
9012 * TODO: Should we proceed with an invalid target namespace?
9013 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00009014 schema->targetNamespace = xmlDictLookup(ctxt->dict, val, -1);
9015 } else {
9016 schema->targetNamespace = NULL;
9017 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009018 /*
9019 * Add the current ns name and location to the import table;
9020 * this is needed to have a consistent mechanism, regardless
9021 * if all schemata are constructed dynamically fired by the
9022 * instance or if the schema to be used was specified via
9023 * the API.
9024 */
9025 import = xmlSchemaAddImport(ctxt, &(schema->schemasImports),
9026 schema->targetNamespace);
9027 if (import == NULL) {
9028 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_FAILED_BUILD_IMPORT,
9029 NULL, NULL, (xmlNodePtr) ctxt->doc,
9030 "Internal error: xmlSchemaParseSchema, "
9031 "failed to add an import entry", NULL);
9032 xmlSchemaFree(schema);
9033 schema = NULL;
9034 return (NULL);
9035 }
9036 import->schemaLocation = ctxt->URL;
9037 /*
9038 * NOTE: We won't set the doc here, otherwise it will be freed
9039 * if the import struct is freed.
9040 * import->doc = ctxt->doc;
9041 */
9042
Daniel Veillardc0826a72004-08-10 14:17:33 +00009043 /* TODO: Check id. */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00009044 schema->id = xmlSchemaGetProp(ctxt, node, "id");
Daniel Veillardc0826a72004-08-10 14:17:33 +00009045 xmlSchemaPValAttr(ctxt, NULL, NULL, node, "version",
9046 xmlSchemaGetBuiltInType(XML_SCHEMAS_TOKEN), &(schema->version));
9047
William M. Brack2f2a6632004-08-20 23:09:47 +00009048 xmlSchemaParseSchemaDefaults(ctxt, schema, node);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009049 xmlSchemaParseSchemaTopLevel(ctxt, schema, node->children);
9050 } else {
9051 xmlDocPtr doc;
9052
9053 doc = node->doc;
9054
9055 if ((doc != NULL) && (doc->URL != NULL)) {
9056 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
9057 XML_SCHEMAP_NOT_SCHEMA,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009058 "The file \"%s\" is not a XML schema.\n", doc->URL, NULL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009059 } else {
9060 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
9061 XML_SCHEMAP_NOT_SCHEMA,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009062 "The file is not a XML schema.\n", NULL, NULL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009063 }
9064 return(NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00009065 }
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00009066 if (ctxt->nberrors != 0) {
9067 if (schema != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009068 xmlSchemaFree(schema);
9069 schema = NULL;
9070 }
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00009071 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009072 if (schema != NULL)
9073 schema->counter = ctxt->counter;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +00009074 ctxt->nberrors = nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +00009075#ifdef DEBUG
9076 if (schema == NULL)
9077 xmlGenericError(xmlGenericErrorContext,
9078 "xmlSchemaParse() failed\n");
9079#endif
Daniel Veillard4255d502002-04-16 15:50:10 +00009080 return (schema);
9081}
9082
9083/************************************************************************
9084 * *
9085 * Validating using Schemas *
9086 * *
9087 ************************************************************************/
9088
9089/************************************************************************
9090 * *
9091 * Reading/Writing Schemas *
9092 * *
9093 ************************************************************************/
9094
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009095#if 0 /* Will be enabled if it is clear what options are needed. */
9096/**
9097 * xmlSchemaParserCtxtSetOptions:
9098 * @ctxt: a schema parser context
9099 * @options: a combination of xmlSchemaParserOption
9100 *
9101 * Sets the options to be used during the parse.
9102 *
9103 * Returns 0 in case of success, -1 in case of an
9104 * API error.
9105 */
9106static int
9107xmlSchemaParserCtxtSetOptions(xmlSchemaParserCtxtPtr ctxt,
9108 int options)
9109
9110{
9111 int i;
9112
9113 if (ctxt == NULL)
9114 return (-1);
9115 /*
9116 * WARNING: Change the start value if adding to the
9117 * xmlSchemaParseOption.
9118 */
9119 for (i = 1; i < (int) sizeof(int) * 8; i++) {
9120 if (options & 1<<i) {
9121 return (-1);
9122 }
9123 }
9124 ctxt->options = options;
9125 return (0);
9126}
9127
9128/**
9129 * xmlSchemaValidCtxtGetOptions:
9130 * @ctxt: a schema parser context
9131 *
9132 * Returns the option combination of the parser context.
9133 */
9134static int
9135xmlSchemaParserCtxtGetOptions(xmlSchemaParserCtxtPtr ctxt)
9136
9137{
9138 if (ctxt == NULL)
9139 return (-1);
9140 else
9141 return (ctxt->options);
9142}
9143
9144 void *curItems; /* used for dynamic addition of schemata */
9145 int nbCurItems; /* used for dynamic addition of schemata */
9146 int sizeCurItems; /* used for dynamic addition of schemata */
9147
9148#endif
9149
Daniel Veillard4255d502002-04-16 15:50:10 +00009150/**
9151 * xmlSchemaNewParserCtxt:
9152 * @URL: the location of the schema
9153 *
9154 * Create an XML Schemas parse context for that file/resource expected
9155 * to contain an XML Schemas file.
9156 *
9157 * Returns the parser context or NULL in case of error
9158 */
9159xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009160xmlSchemaNewParserCtxt(const char *URL)
9161{
Daniel Veillard4255d502002-04-16 15:50:10 +00009162 xmlSchemaParserCtxtPtr ret;
9163
9164 if (URL == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009165 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00009166
9167 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
9168 if (ret == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009169 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009170 NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00009171 return (NULL);
9172 }
9173 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00009174 ret->dict = xmlDictCreate();
9175 ret->URL = xmlDictLookup(ret->dict, (const xmlChar *) URL, -1);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00009176 ret->includes = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00009177 return (ret);
9178}
9179
9180/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009181 * xmlSchemaNewParserCtxtUseDict:
9182 * @URL: the location of the schema
9183 * @dict: the dictionary to be used
9184 *
9185 * Create an XML Schemas parse context for that file/resource expected
9186 * to contain an XML Schemas file.
9187 *
9188 * Returns the parser context or NULL in case of error
9189 */
9190static xmlSchemaParserCtxtPtr
9191xmlSchemaNewParserCtxtUseDict(const char *URL, xmlDictPtr dict)
9192{
9193 xmlSchemaParserCtxtPtr ret;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009194 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009195 if (URL == NULL)
9196 return (NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009197 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009198
9199 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
9200 if (ret == NULL) {
9201 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
9202 NULL);
9203 return (NULL);
9204 }
9205 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
9206 ret->dict = dict;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009207 xmlDictReference(dict);
9208 if (URL != NULL)
9209 ret->URL = xmlDictLookup(dict, (const xmlChar *) URL, -1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009210 ret->includes = 0;
9211 return (ret);
9212}
9213
9214
9215/**
Daniel Veillard6045c902002-10-09 21:13:59 +00009216 * xmlSchemaNewMemParserCtxt:
9217 * @buffer: a pointer to a char array containing the schemas
9218 * @size: the size of the array
9219 *
9220 * Create an XML Schemas parse context for that memory buffer expected
9221 * to contain an XML Schemas file.
9222 *
9223 * Returns the parser context or NULL in case of error
9224 */
9225xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009226xmlSchemaNewMemParserCtxt(const char *buffer, int size)
9227{
Daniel Veillard6045c902002-10-09 21:13:59 +00009228 xmlSchemaParserCtxtPtr ret;
9229
9230 if ((buffer == NULL) || (size <= 0))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009231 return (NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +00009232
9233 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
9234 if (ret == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009235 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009236 NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +00009237 return (NULL);
9238 }
9239 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
9240 ret->buffer = buffer;
9241 ret->size = size;
William M. Brackcf9eadf2003-12-25 13:24:05 +00009242 ret->dict = xmlDictCreate();
Daniel Veillard6045c902002-10-09 21:13:59 +00009243 return (ret);
9244}
9245
9246/**
Daniel Veillard9d751502003-10-29 13:21:47 +00009247 * xmlSchemaNewDocParserCtxt:
9248 * @doc: a preparsed document tree
9249 *
9250 * Create an XML Schemas parse context for that document.
9251 * NB. The document may be modified during the parsing process.
9252 *
9253 * Returns the parser context or NULL in case of error
9254 */
9255xmlSchemaParserCtxtPtr
9256xmlSchemaNewDocParserCtxt(xmlDocPtr doc)
9257{
9258 xmlSchemaParserCtxtPtr ret;
9259
9260 if (doc == NULL)
9261 return (NULL);
9262
9263 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
9264 if (ret == NULL) {
9265 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
9266 NULL);
9267 return (NULL);
9268 }
9269 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
9270 ret->doc = doc;
William M. Brackcf9eadf2003-12-25 13:24:05 +00009271 ret->dict = xmlDictCreate();
Daniel Veillarddda22c12004-01-24 08:31:30 +00009272 /* The application has responsibility for the document */
9273 ret->preserve = 1;
Daniel Veillard9d751502003-10-29 13:21:47 +00009274
9275 return (ret);
9276}
9277
9278/**
Daniel Veillard4255d502002-04-16 15:50:10 +00009279 * xmlSchemaFreeParserCtxt:
9280 * @ctxt: the schema parser context
9281 *
9282 * Free the resources associated to the schema parser context
9283 */
9284void
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009285xmlSchemaFreeParserCtxt(xmlSchemaParserCtxtPtr ctxt)
9286{
Daniel Veillard4255d502002-04-16 15:50:10 +00009287 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009288 return;
Daniel Veillarddda22c12004-01-24 08:31:30 +00009289 if (ctxt->doc != NULL && !ctxt->preserve)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009290 xmlFreeDoc(ctxt->doc);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009291 if (ctxt->assemble != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009292 xmlFree((xmlSchemaTypePtr *) ctxt->assemble->items);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009293 xmlFree(ctxt->assemble);
9294 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009295 if (ctxt->vctxt != NULL) {
9296 xmlSchemaFreeValidCtxt(ctxt->vctxt);
9297 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00009298 xmlDictFree(ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00009299 xmlFree(ctxt);
9300}
9301
9302/************************************************************************
9303 * *
9304 * Building the content models *
9305 * *
9306 ************************************************************************/
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009307
Daniel Veillard4255d502002-04-16 15:50:10 +00009308/**
9309 * xmlSchemaBuildAContentModel:
9310 * @type: the schema type definition
9311 * @ctxt: the schema parser context
9312 * @name: the element name whose content is being built
9313 *
9314 * Generate the automata sequence needed for that type
9315 */
9316static void
9317xmlSchemaBuildAContentModel(xmlSchemaTypePtr type,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009318 xmlSchemaParserCtxtPtr ctxt,
9319 const xmlChar * name)
9320{
Daniel Veillard4255d502002-04-16 15:50:10 +00009321 if (type == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009322 xmlGenericError(xmlGenericErrorContext,
9323 "Found unexpected type = NULL in %s content model\n",
9324 name);
9325 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00009326 }
9327 switch (type->type) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009328 case XML_SCHEMA_TYPE_ANY: {
9329 xmlAutomataStatePtr start, end;
9330 xmlSchemaWildcardPtr wild;
9331 xmlSchemaWildcardNsPtr ns;
Daniel Veillard32370232002-10-16 14:08:14 +00009332
Daniel Veillardc0826a72004-08-10 14:17:33 +00009333 wild = type->attributeWildcard;
9334
9335 if (wild == NULL) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00009336 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009337 "Internal error: xmlSchemaBuildAContentModel, "
9338 "no wildcard on xsd:any.\n", NULL, NULL);
9339 return;
9340 }
9341
9342 start = ctxt->state;
9343 end = xmlAutomataNewState(ctxt->am);
9344
9345 if (type->maxOccurs == 1) {
9346 if (wild->any == 1) {
9347 /*
9348 * We need to add both transitions:
9349 *
9350 * 1. the {"*", "*"} for elements in a namespace.
9351 */
9352 ctxt->state =
9353 xmlAutomataNewTransition2(ctxt->am,
9354 start, NULL, BAD_CAST "*", BAD_CAST "*", type);
9355 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
9356 /*
9357 * 2. the {"*"} for elements in no namespace.
9358 */
9359 ctxt->state =
9360 xmlAutomataNewTransition2(ctxt->am,
9361 start, NULL, BAD_CAST "*", NULL, type);
9362 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
9363
9364 } else if (wild->nsSet != NULL) {
9365 ns = wild->nsSet;
9366 do {
9367 ctxt->state = start;
9368 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
9369 ctxt->state, NULL, BAD_CAST "*", ns->value, type);
9370 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
9371 ns = ns->next;
9372 } while (ns != NULL);
9373
9374 } else if (wild->negNsSet != NULL) {
9375 xmlAutomataStatePtr deadEnd;
9376
9377 deadEnd = xmlAutomataNewState(ctxt->am);
9378 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
9379 start, deadEnd, BAD_CAST "*", wild->negNsSet->value, type);
9380 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
9381 start, NULL, BAD_CAST "*", BAD_CAST "*", type);
9382 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
9383 }
9384 } else {
9385 int counter;
9386 xmlAutomataStatePtr hop;
9387 int maxOccurs =
9388 type->maxOccurs == UNBOUNDED ? UNBOUNDED : type->maxOccurs - 1;
9389 int minOccurs =
9390 type->minOccurs < 1 ? 0 : type->minOccurs - 1;
9391
9392 counter = xmlAutomataNewCounter(ctxt->am, minOccurs, maxOccurs);
9393 hop = xmlAutomataNewState(ctxt->am);
9394 if (wild->any == 1) {
9395 ctxt->state =
9396 xmlAutomataNewTransition2(ctxt->am,
9397 start, NULL, BAD_CAST "*", BAD_CAST "*", type);
9398 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
9399 ctxt->state =
9400 xmlAutomataNewTransition2(ctxt->am,
9401 start, NULL, BAD_CAST "*", NULL, type);
9402 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
9403 } else if (wild->nsSet != NULL) {
9404 ns = wild->nsSet;
9405 do {
9406 ctxt->state =
9407 xmlAutomataNewTransition2(ctxt->am,
9408 start, NULL, BAD_CAST "*", ns->value, type);
9409 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
9410 ns = ns->next;
9411 } while (ns != NULL);
9412
9413 } else if (wild->negNsSet != NULL) {
9414 xmlAutomataStatePtr deadEnd;
9415
9416 deadEnd = xmlAutomataNewState(ctxt->am);
9417 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
9418 start, deadEnd, BAD_CAST "*", wild->negNsSet->value, type);
9419 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
9420 start, NULL, BAD_CAST "*", BAD_CAST "*", type);
9421 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
9422 }
9423 xmlAutomataNewCountedTrans(ctxt->am, hop, start, counter);
9424 xmlAutomataNewCounterTrans(ctxt->am, hop, end, counter);
9425 }
9426 if (type->minOccurs == 0) {
9427 xmlAutomataNewEpsilon(ctxt->am, start, end);
9428 }
9429 ctxt->state = end;
9430 break;
9431 }
9432 case XML_SCHEMA_TYPE_ELEMENT:{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009433 xmlAutomataStatePtr oldstate;
9434 xmlSchemaElementPtr particle, elemDecl;
Daniel Veillard32370232002-10-16 14:08:14 +00009435
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009436 /*
9437 * IMPORTANT: This puts element declarations
9438 * (and never element decl. references) into the
9439 * automaton. This is crucial and should not be changed,
9440 * since validating functions rely now on it.
9441 */
9442 particle = (xmlSchemaElementPtr) type;
9443 if (particle->ref != NULL) {
9444 if (particle->refDecl == NULL) {
9445 /*
9446 * Skip content model creation if the reference
9447 * did not resolve to a declaration.
9448 */
9449 break;
9450 } else {
9451 /*
9452 * Referenced global element declaration.
9453 */
9454 elemDecl = particle->refDecl;
9455 }
9456 } else {
9457 /*
9458 * Anonymous element declaration.
9459 */
9460 elemDecl = particle;
9461 }
9462
9463 oldstate = ctxt->state;
9464
9465 if (particle->maxOccurs >= UNBOUNDED) {
9466 if (particle->minOccurs > 1) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009467 xmlAutomataStatePtr tmp;
9468 int counter;
Daniel Veillard32370232002-10-16 14:08:14 +00009469
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009470 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009471 oldstate, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009472 oldstate = ctxt->state;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009473 counter = xmlAutomataNewCounter(ctxt->am,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009474 particle->minOccurs - 1, UNBOUNDED);
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00009475 ctxt->state =
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009476 xmlAutomataNewTransition2(ctxt->am,
9477 ctxt->state, NULL,
9478 elemDecl->name,
9479 elemDecl->targetNamespace,
9480 (xmlSchemaTypePtr) elemDecl);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009481 tmp = ctxt->state;
9482 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009483 counter);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009484 ctxt->state =
9485 xmlAutomataNewCounterTrans(ctxt->am, tmp, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009486 counter);
Daniel Veillard32370232002-10-16 14:08:14 +00009487
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009488 } else {
9489 ctxt->state =
9490 xmlAutomataNewTransition2(ctxt->am,
9491 ctxt->state, NULL,
9492 elemDecl->name,
9493 elemDecl->targetNamespace,
9494 (xmlSchemaTypePtr) elemDecl);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009495 xmlAutomataNewEpsilon(ctxt->am, ctxt->state,
9496 oldstate);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009497 if (particle->minOccurs == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009498 /* basically an elem* */
9499 xmlAutomataNewEpsilon(ctxt->am, oldstate,
9500 ctxt->state);
9501 }
9502 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009503 } else if ((particle->maxOccurs > 1) || (particle->minOccurs > 1)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009504 xmlAutomataStatePtr tmp;
9505 int counter;
Daniel Veillard32370232002-10-16 14:08:14 +00009506
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009507 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
9508 oldstate, NULL);
9509 oldstate = ctxt->state;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009510 counter = xmlAutomataNewCounter(ctxt->am,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009511 particle->minOccurs - 1,
9512 particle->maxOccurs - 1);
9513 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
9514 ctxt->state,
9515 NULL,
9516 elemDecl->name,
9517 elemDecl->targetNamespace,
9518 (xmlSchemaTypePtr) elemDecl);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009519 tmp = ctxt->state;
9520 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009521 counter);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009522 ctxt->state = xmlAutomataNewCounterTrans(ctxt->am, tmp,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009523 NULL, counter);
9524 if (particle->minOccurs == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009525 /* basically an elem? */
9526 xmlAutomataNewEpsilon(ctxt->am, oldstate,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009527 ctxt->state);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009528 }
Daniel Veillardb39bc392002-10-26 19:29:51 +00009529
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009530 } else {
9531 ctxt->state = xmlAutomataNewTransition2(ctxt->am,
9532 ctxt->state,
9533 NULL,
9534 elemDecl->name,
9535 elemDecl->targetNamespace,
9536 (xmlSchemaTypePtr) elemDecl);
9537 if (particle->minOccurs == 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009538 /* basically an elem? */
9539 xmlAutomataNewEpsilon(ctxt->am, oldstate,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009540 ctxt->state);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009541 }
9542 }
9543 break;
9544 }
9545 case XML_SCHEMA_TYPE_SEQUENCE:{
9546 xmlSchemaTypePtr subtypes;
Daniel Veillardb39bc392002-10-26 19:29:51 +00009547
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009548 /*
9549 * If max and min occurances are default (1) then
9550 * simply iterate over the subtypes
9551 */
9552 if ((type->minOccurs == 1) && (type->maxOccurs == 1)) {
9553 subtypes = type->subtypes;
9554 while (subtypes != NULL) {
9555 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
9556 subtypes = subtypes->next;
9557 }
9558 } else {
9559 xmlAutomataStatePtr oldstate = ctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +00009560
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009561 if (type->maxOccurs >= UNBOUNDED) {
9562 if (type->minOccurs > 1) {
9563 xmlAutomataStatePtr tmp;
9564 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +00009565
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009566 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
9567 oldstate,
9568 NULL);
9569 oldstate = ctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +00009570
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009571 counter = xmlAutomataNewCounter(ctxt->am,
9572 type->
9573 minOccurs - 1,
9574 UNBOUNDED);
Daniel Veillardb39bc392002-10-26 19:29:51 +00009575
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009576 subtypes = type->subtypes;
9577 while (subtypes != NULL) {
9578 xmlSchemaBuildAContentModel(subtypes, ctxt,
9579 name);
9580 subtypes = subtypes->next;
9581 }
9582 tmp = ctxt->state;
9583 xmlAutomataNewCountedTrans(ctxt->am, tmp,
9584 oldstate, counter);
9585 ctxt->state =
9586 xmlAutomataNewCounterTrans(ctxt->am, tmp,
9587 NULL, counter);
Daniel Veillardb39bc392002-10-26 19:29:51 +00009588
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009589 } else {
9590 subtypes = type->subtypes;
9591 while (subtypes != NULL) {
9592 xmlSchemaBuildAContentModel(subtypes, ctxt,
9593 name);
9594 subtypes = subtypes->next;
9595 }
9596 xmlAutomataNewEpsilon(ctxt->am, ctxt->state,
9597 oldstate);
9598 if (type->minOccurs == 0) {
9599 xmlAutomataNewEpsilon(ctxt->am, oldstate,
9600 ctxt->state);
9601 }
9602 }
9603 } else if ((type->maxOccurs > 1)
9604 || (type->minOccurs > 1)) {
9605 xmlAutomataStatePtr tmp;
9606 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +00009607
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009608 ctxt->state = xmlAutomataNewEpsilon(ctxt->am,
9609 oldstate,
9610 NULL);
9611 oldstate = ctxt->state;
Daniel Veillard4255d502002-04-16 15:50:10 +00009612
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009613 counter = xmlAutomataNewCounter(ctxt->am,
9614 type->minOccurs -
9615 1,
9616 type->maxOccurs -
9617 1);
Daniel Veillard4255d502002-04-16 15:50:10 +00009618
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009619 subtypes = type->subtypes;
9620 while (subtypes != NULL) {
9621 xmlSchemaBuildAContentModel(subtypes, ctxt,
9622 name);
9623 subtypes = subtypes->next;
9624 }
9625 tmp = ctxt->state;
9626 xmlAutomataNewCountedTrans(ctxt->am, tmp, oldstate,
9627 counter);
9628 ctxt->state =
9629 xmlAutomataNewCounterTrans(ctxt->am, tmp, NULL,
9630 counter);
9631 if (type->minOccurs == 0) {
9632 xmlAutomataNewEpsilon(ctxt->am, oldstate,
9633 ctxt->state);
9634 }
Daniel Veillardb509f152002-04-17 16:28:10 +00009635
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009636 } else {
9637 subtypes = type->subtypes;
9638 while (subtypes != NULL) {
9639 xmlSchemaBuildAContentModel(subtypes, ctxt,
9640 name);
9641 subtypes = subtypes->next;
9642 }
9643 if (type->minOccurs == 0) {
9644 xmlAutomataNewEpsilon(ctxt->am, oldstate,
9645 ctxt->state);
9646 }
9647 }
9648 }
9649 break;
9650 }
9651 case XML_SCHEMA_TYPE_CHOICE:{
9652 xmlSchemaTypePtr subtypes;
9653 xmlAutomataStatePtr start, end;
Daniel Veillardb509f152002-04-17 16:28:10 +00009654
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009655 start = ctxt->state;
9656 end = xmlAutomataNewState(ctxt->am);
Daniel Veillard7646b182002-04-20 06:41:40 +00009657
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009658 /*
9659 * iterate over the subtypes and remerge the end with an
9660 * epsilon transition
9661 */
9662 if (type->maxOccurs == 1) {
9663 subtypes = type->subtypes;
9664 while (subtypes != NULL) {
9665 ctxt->state = start;
9666 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
9667 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
9668 subtypes = subtypes->next;
9669 }
9670 } else {
9671 int counter;
9672 xmlAutomataStatePtr hop;
9673 int maxOccurs = type->maxOccurs == UNBOUNDED ?
9674 UNBOUNDED : type->maxOccurs - 1;
9675 int minOccurs =
9676 type->minOccurs < 1 ? 0 : type->minOccurs - 1;
Daniel Veillard7646b182002-04-20 06:41:40 +00009677
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009678 /*
9679 * use a counter to keep track of the number of transtions
9680 * which went through the choice.
9681 */
9682 counter =
9683 xmlAutomataNewCounter(ctxt->am, minOccurs,
9684 maxOccurs);
9685 hop = xmlAutomataNewState(ctxt->am);
Daniel Veillard6231e842002-04-18 11:54:04 +00009686
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009687 subtypes = type->subtypes;
9688 while (subtypes != NULL) {
9689 ctxt->state = start;
9690 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
9691 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
9692 subtypes = subtypes->next;
9693 }
9694 xmlAutomataNewCountedTrans(ctxt->am, hop, start,
9695 counter);
9696 xmlAutomataNewCounterTrans(ctxt->am, hop, end,
9697 counter);
9698 }
9699 if (type->minOccurs == 0) {
9700 xmlAutomataNewEpsilon(ctxt->am, start, end);
9701 }
9702 ctxt->state = end;
9703 break;
9704 }
9705 case XML_SCHEMA_TYPE_ALL:{
9706 xmlAutomataStatePtr start;
9707 xmlSchemaTypePtr subtypes;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009708
Daniel Veillard3646d642004-06-02 19:19:14 +00009709 xmlSchemaElementPtr elem;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009710 int lax;
9711
9712 subtypes = type->subtypes;
9713 if (subtypes == NULL)
9714 break;
9715 start = ctxt->state;
9716 while (subtypes != NULL) {
9717 ctxt->state = start;
William M. Brack9989c7d2004-05-12 14:39:38 +00009718 /*
9719 * the following 'if' was needed to fix bug 139897
9720 * not quite sure why it only needs to be done for
9721 * elements with a 'ref', but it seems to work ok.
9722 */
9723 if (subtypes->ref != NULL)
9724 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009725 elem = (xmlSchemaElementPtr) subtypes;
9726 /*
9727 * NOTE: The {max occurs} of all the particles in the
9728 * {particles} of the group must be 0 or 1.
9729 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009730 if ((elem->minOccurs == 1) && (elem->maxOccurs == 1)) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009731 xmlAutomataNewOnceTrans2(ctxt->am, ctxt->state,
9732 ctxt->state,
9733 elem->name,
9734 elem->targetNamespace,
9735 1, 1, subtypes);
9736 } else if ((elem->minOccurs == 0) &&
9737 (elem->maxOccurs == 1)) {
9738
9739 xmlAutomataNewCountTrans2(ctxt->am, ctxt->state,
9740 ctxt->state,
9741 elem->name,
9742 elem->targetNamespace,
9743 0,
9744 1,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009745 subtypes);
9746 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009747 /*
9748 * NOTE: if maxOccurs == 0 then no transition will be
9749 * created.
9750 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009751 subtypes = subtypes->next;
9752 }
9753 lax = type->minOccurs == 0;
9754 ctxt->state =
9755 xmlAutomataNewAllTrans(ctxt->am, ctxt->state, NULL,
9756 lax);
9757 break;
9758 }
9759 case XML_SCHEMA_TYPE_RESTRICTION:
9760 if (type->subtypes != NULL)
9761 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
9762 break;
9763 case XML_SCHEMA_TYPE_EXTENSION:
9764 if (type->baseType != NULL) {
9765 xmlSchemaTypePtr subtypes;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009766
9767 /*
9768 * TODO: Circular definitions will be checked at the
9769 * constraint level. So remove this when the complex type
9770 * constraints are implemented.
9771 */
Daniel Veillardf7627552004-04-22 07:15:40 +00009772 if (type->recurse) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009773 /* TODO: Change the error code. */
9774 xmlSchemaPCustomErr(ctxt,
9775 XML_SCHEMAP_UNKNOWN_BASE_TYPE,
9776 NULL, type, type->node,
9777 "This item is circular", NULL);
Daniel Veillardf7627552004-04-22 07:15:40 +00009778 return;
9779 }
9780 type->recurse = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009781 xmlSchemaBuildAContentModel(type->baseType, ctxt, name);
Daniel Veillardf7627552004-04-22 07:15:40 +00009782 type->recurse = 0;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009783 subtypes = type->subtypes;
9784 while (subtypes != NULL) {
9785 xmlSchemaBuildAContentModel(subtypes, ctxt, name);
9786 subtypes = subtypes->next;
9787 }
9788 } else if (type->subtypes != NULL)
9789 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
9790 break;
9791 case XML_SCHEMA_TYPE_GROUP:
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00009792 /*
9793 * Handle model group definition references.
9794 * NOTE: type->subtypes is the referenced model grop definition;
9795 * and type->subtypes->subtypes is the model group (i.e. <all> or
9796 * <choice> or <sequence>).
9797 */
9798 if ((type->ref != NULL) && (type->subtypes != NULL) &&
9799 (type->subtypes->subtypes != NULL)) {
9800 xmlSchemaTypePtr modelGr;
9801 xmlAutomataStatePtr start, end;
9802
9803 modelGr = type->subtypes->subtypes;
9804 start = ctxt->state;
9805 end = xmlAutomataNewState(ctxt->am);
9806 if (type->maxOccurs == 1) {
9807 ctxt->state = start;
9808 xmlSchemaBuildAContentModel(modelGr, ctxt, name);
9809 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, end);
9810 } else {
9811 int counter;
9812 xmlAutomataStatePtr hop;
9813 int maxOccurs = type->maxOccurs == UNBOUNDED ?
9814 UNBOUNDED : type->maxOccurs - 1;
9815 int minOccurs =
9816 type->minOccurs < 1 ? 0 : type->minOccurs - 1;
9817
9818 counter =
9819 xmlAutomataNewCounter(ctxt->am, minOccurs, maxOccurs);
9820 hop = xmlAutomataNewState(ctxt->am);
9821 ctxt->state = start;
9822 xmlSchemaBuildAContentModel(modelGr, ctxt, name);
9823 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, hop);
9824 xmlAutomataNewCountedTrans(ctxt->am, hop, start,
9825 counter);
9826 xmlAutomataNewCounterTrans(ctxt->am, hop, end,
9827 counter);
9828 }
9829 if (type->minOccurs == 0) {
9830 xmlAutomataNewEpsilon(ctxt->am, start, end);
9831 }
9832 ctxt->state = end;
9833 break;
9834 }
9835 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009836 case XML_SCHEMA_TYPE_COMPLEX:
9837 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:
9838 if (type->subtypes != NULL)
9839 xmlSchemaBuildAContentModel(type->subtypes, ctxt, name);
9840 break;
William M. Brack2f2a6632004-08-20 23:09:47 +00009841 case XML_SCHEMA_TYPE_SIMPLE_CONTENT:
9842 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009843 default:
9844 xmlGenericError(xmlGenericErrorContext,
9845 "Found unexpected type %d in %s content model\n",
9846 type->type, name);
9847 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00009848 }
9849}
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009850
Daniel Veillard4255d502002-04-16 15:50:10 +00009851/**
9852 * xmlSchemaBuildContentModel:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009853 * @type: the type definition (or reference)
Daniel Veillard4255d502002-04-16 15:50:10 +00009854 * @ctxt: the schema parser context
Daniel Veillarda84c0b32003-06-02 16:58:46 +00009855 * @name: the element name
Daniel Veillard4255d502002-04-16 15:50:10 +00009856 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009857 * Builds the content model of the complex type.
Daniel Veillard4255d502002-04-16 15:50:10 +00009858 */
9859static void
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009860xmlSchemaBuildContentModel(xmlSchemaTypePtr type,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009861 xmlSchemaParserCtxtPtr ctxt,
9862 const xmlChar * name)
9863{
Daniel Veillard4255d502002-04-16 15:50:10 +00009864 xmlAutomataStatePtr start;
9865
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009866 if ((type->type != XML_SCHEMA_TYPE_COMPLEX) || (type->ref != NULL) ||
9867 (type->contentType == XML_SCHEMA_CONTENT_BASIC) ||
9868 (type->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
9869 (type->contModel != NULL))
9870 return;
Daniel Veillarddecd64d2002-04-18 14:41:51 +00009871
9872#ifdef DEBUG_CONTENT
9873 xmlGenericError(xmlGenericErrorContext,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009874 "Building content model for %s\n", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +00009875#endif
9876
Daniel Veillard4255d502002-04-16 15:50:10 +00009877 ctxt->am = xmlNewAutomata();
9878 if (ctxt->am == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009879 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009880 "Cannot create automata for complex tpye %s\n", name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009881 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00009882 }
9883 start = ctxt->state = xmlAutomataGetInitState(ctxt->am);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009884 xmlSchemaBuildAContentModel(type, ctxt, name);
Daniel Veillard4255d502002-04-16 15:50:10 +00009885 xmlAutomataSetFinalState(ctxt->am, ctxt->state);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009886 type->contModel = xmlAutomataCompile(ctxt->am);
9887 if (type->contModel == NULL) {
9888 xmlSchemaPCustomErr(ctxt,
9889 XML_SCHEMAP_INTERNAL,
9890 NULL, type, type->node,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009891 "Failed to compile the content model", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009892 } else if (xmlRegexpIsDeterminist(type->contModel) != 1) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00009893 xmlSchemaPCustomErr(ctxt,
9894 XML_SCHEMAP_NOT_DETERMINISTIC,
9895 /* XML_SCHEMAS_ERR_NOTDETERMINIST, */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009896 NULL, type, type->node,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009897 "The content model is not determinist", NULL);
Daniel Veillarde19fc232002-04-22 16:01:24 +00009898 } else {
Daniel Veillard118aed72002-09-24 14:13:13 +00009899#ifdef DEBUG_CONTENT_REGEXP
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009900 xmlGenericError(xmlGenericErrorContext,
9901 "Content model of %s:\n", name);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009902 xmlRegexpPrint(stderr, type->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +00009903#endif
Daniel Veillarde19fc232002-04-22 16:01:24 +00009904 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +00009905 ctxt->state = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00009906 xmlFreeAutomata(ctxt->am);
9907 ctxt->am = NULL;
9908}
9909
9910/**
9911 * xmlSchemaRefFixupCallback:
9912 * @elem: the schema element context
9913 * @ctxt: the schema parser context
9914 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00009915 * Resolves the references of an element declaration
9916 * or particle, which has an element declaration as it's
9917 * term.
Daniel Veillard4255d502002-04-16 15:50:10 +00009918 */
9919static void
9920xmlSchemaRefFixupCallback(xmlSchemaElementPtr elem,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009921 xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009922 const xmlChar * name ATTRIBUTE_UNUSED,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009923 const xmlChar * context ATTRIBUTE_UNUSED,
9924 const xmlChar * namespace ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +00009925{
Daniel Veillardc0826a72004-08-10 14:17:33 +00009926 if ((ctxt == NULL) || (elem == NULL) ||
9927 ((elem != NULL) && (elem->flags & XML_SCHEMAS_ELEM_INTERNAL_RESOLVED)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009928 return;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009929 elem->flags |= XML_SCHEMAS_ELEM_INTERNAL_RESOLVED;
Daniel Veillard4255d502002-04-16 15:50:10 +00009930 if (elem->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00009931 xmlSchemaElementPtr elemDecl;
Daniel Veillard4255d502002-04-16 15:50:10 +00009932
Daniel Veillardc0826a72004-08-10 14:17:33 +00009933 /*
9934 * TODO: Evaluate, what errors could occur if the declaration is not
9935 * found. It might be possible that the "typefixup" might crash if
9936 * no ref declaration was found.
9937 */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00009938 elemDecl = xmlSchemaGetElem(ctxt->schema, elem->ref, elem->refNs);
Daniel Veillardc0826a72004-08-10 14:17:33 +00009939 if (elemDecl == NULL) {
9940 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +00009941 XML_SCHEMAP_SRC_RESOLVE,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009942 NULL, (xmlSchemaTypePtr) elem, elem->node,
9943 "ref", elem->ref, elem->refNs,
9944 XML_SCHEMA_TYPE_ELEMENT, NULL);
9945 } else
9946 elem->refDecl = elemDecl;
9947 } else {
9948 if ((elem->subtypes == NULL) && (elem->namedType != NULL)) {
9949 xmlSchemaTypePtr type;
9950
9951 /* (type definition) ... otherwise the type definition ·resolved·
9952 * to by the ·actual value· of the type [attribute] ...
9953 */
9954 type = xmlSchemaGetType(ctxt->schema, elem->namedType,
9955 elem->namedTypeNs);
9956 if (type == NULL) {
9957 xmlSchemaPResCompAttrErr(ctxt,
9958 XML_SCHEMAP_SRC_RESOLVE,
9959 NULL, (xmlSchemaTypePtr) elem, elem->node,
9960 "type", elem->namedType, elem->namedTypeNs,
9961 XML_SCHEMA_TYPE_BASIC, "type definition");
9962 } else
9963 elem->subtypes = type;
9964 }
9965 if (elem->substGroup != NULL) {
9966 xmlSchemaElementPtr substHead;
9967
9968 /*
9969 * FIXME TODO: Do we need a new field in _xmlSchemaElement for
9970 * substitutionGroup?
9971 */
9972 substHead = xmlSchemaGetElem(ctxt->schema, elem->substGroup,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00009973 elem->substGroupNs);
Daniel Veillardc0826a72004-08-10 14:17:33 +00009974 if (substHead == NULL) {
9975 xmlSchemaPResCompAttrErr(ctxt,
9976 XML_SCHEMAP_SRC_RESOLVE,
9977 NULL, (xmlSchemaTypePtr) elem, NULL,
9978 "substitutionGroup", elem->substGroup, elem->substGroupNs,
9979 XML_SCHEMA_TYPE_ELEMENT, NULL);
9980 } else {
9981 xmlSchemaRefFixupCallback(substHead, ctxt, NULL, NULL, NULL);
9982 /*
9983 * (type definition)...otherwise the {type definition} of the
9984 * element declaration ·resolved· to by the ·actual value· of
9985 * the substitutionGroup [attribute], if present
9986 */
9987 if (elem->subtypes == NULL)
9988 elem->subtypes = substHead->subtypes;
9989 }
9990 }
9991 if ((elem->subtypes == NULL) && (elem->namedType == NULL) &&
9992 (elem->substGroup == NULL))
9993 elem->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
9994 }
Daniel Veillard4255d502002-04-16 15:50:10 +00009995}
9996
William M. Bracke7091952004-05-11 15:09:58 +00009997/**
9998 * xmlSchemaParseListRefFixup:
9999 * @type: the schema type definition
10000 * @ctxt: the schema parser context
10001 *
10002 * Fixup of the itemType reference of the list type.
10003 */
Daniel Veillard377e1a92004-04-16 16:30:05 +000010004static void
William M. Bracke7091952004-05-11 15:09:58 +000010005xmlSchemaParseListRefFixup(xmlSchemaTypePtr type, xmlSchemaParserCtxtPtr ctxt)
Daniel Veillard01fa6152004-06-29 17:04:39 +000010006{
Daniel Veillardc0826a72004-08-10 14:17:33 +000010007
Daniel Veillard01fa6152004-06-29 17:04:39 +000010008 if (((type->base == NULL) &&
10009 (type->subtypes == NULL)) ||
10010 ((type->base != NULL) &&
10011 (type->subtypes != NULL))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010012 /*
10013 * src-list-itemType-or-simpleType
10014 * Either the itemType [attribute] or the <simpleType> [child] of
10015 * the <list> element must be present, but not both.
Daniel Veillard01fa6152004-06-29 17:04:39 +000010016 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000010017 /*
10018 * TODO: Move this to the parse function.
10019 */
10020 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010021 XML_SCHEMAP_SRC_LIST_ITEMTYPE_OR_SIMPLETYPE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010022 NULL, type, type->node,
10023 "The attribute 'itemType' and the <simpleType> child "
10024 "are mutually exclusive", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010025 } else if (type->base!= NULL) {
10026 type->subtypes = xmlSchemaGetType(ctxt->schema, type->base, type->baseNs);
10027 if (type->subtypes == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010028 xmlSchemaPResCompAttrErr(ctxt,
10029 XML_SCHEMAP_SRC_RESOLVE,
10030 NULL, type, type->node,
10031 "itemType", type->base, type->baseNs,
10032 XML_SCHEMA_TYPE_SIMPLE, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010033 }
10034 }
10035 if ((type->subtypes != NULL) &&
10036 (type->subtypes->contentType == XML_SCHEMA_CONTENT_UNKNOWN))
10037 xmlSchemaTypeFixup(type->subtypes, ctxt, NULL);
William M. Bracke7091952004-05-11 15:09:58 +000010038}
10039
10040/**
10041 * xmlSchemaParseUnionRefCheck:
10042 * @typeDecl: the schema type definition
10043 * @ctxt: the schema parser context
10044 *
Daniel Veillard01fa6152004-06-29 17:04:39 +000010045 * Checks and builds the memberTypes of the union type.
10046 * Returns -1 in case of an internal error, 0 otherwise.
William M. Bracke7091952004-05-11 15:09:58 +000010047 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000010048static int
William M. Bracke7091952004-05-11 15:09:58 +000010049xmlSchemaParseUnionRefCheck(xmlSchemaTypePtr type,
Daniel Veillard377e1a92004-04-16 16:30:05 +000010050 xmlSchemaParserCtxtPtr ctxt)
10051{
Daniel Veillardc0826a72004-08-10 14:17:33 +000010052
Daniel Veillard01fa6152004-06-29 17:04:39 +000010053 xmlSchemaTypeLinkPtr link, lastLink = NULL, prevLink, subLink, newLink;
10054 xmlSchemaTypePtr memberType, ctxtType;
Daniel Veillard377e1a92004-04-16 16:30:05 +000010055
Daniel Veillard01fa6152004-06-29 17:04:39 +000010056 /* 1 If the <union> alternative is chosen, then [Definition:]
10057 * define the explicit members as the type definitions ·resolved·
10058 * to by the items in the ·actual value· of the memberTypes [attribute],
10059 * if any, followed by the type definitions corresponding to the
10060 * <simpleType>s among the [children] of <union>, if any.
10061 */
Daniel Veillard377e1a92004-04-16 16:30:05 +000010062
Daniel Veillard01fa6152004-06-29 17:04:39 +000010063 if (type->type != XML_SCHEMA_TYPE_UNION)
10064 return (-1);
10065 if (ctxt->ctxtType == NULL) {
10066 xmlSchemaPErr(ctxt, type->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000010067 XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010068 "Internal error: xmlSchemaParseUnionRefCheck, no parent type "
10069 "available", NULL, NULL);
10070 return (-1);
10071 }
10072 /*
10073 * src-union-memberTypes-or-simpleTypes
10074 * Either the memberTypes [attribute] of the <union> element must
10075 * be non-empty or there must be at least one simpleType [child].
10076 */
10077 if ((type->base == NULL) &&
10078 (type->subtypes == NULL)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010079 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000010080 XML_SCHEMAP_SRC_UNION_MEMBERTYPES_OR_SIMPLETYPES,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010081 NULL, NULL, type->node,
10082 "Either the attribute 'memberTypes' must be non-empty "
10083 "or there must be at least one <simpleType> child", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010084 }
10085
10086 ctxtType = ctxt->ctxtType;
10087 if (type->base != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010088 xmlAttrPtr attr;
10089 const xmlChar *cur, *end;
10090 xmlChar *tmp;
10091 const xmlChar *localName, *uri;
10092
10093 attr = xmlSchemaGetPropNode(type->node, "memberTypes");
Daniel Veillard01fa6152004-06-29 17:04:39 +000010094 cur = type->base;
10095 do {
10096 while (IS_BLANK_CH(*cur))
10097 cur++;
10098 end = cur;
10099 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
10100 end++;
10101 if (end == cur)
10102 break;
10103 tmp = xmlStrndup(cur, end - cur);
Daniel Veillardc0826a72004-08-10 14:17:33 +000010104 xmlSchemaPValAttrNodeQNameValue(ctxt, ctxt->schema, NULL,
10105 NULL, attr, BAD_CAST tmp, &uri, NULL, &localName);
10106 memberType = xmlSchemaGetType(ctxt->schema, localName, uri);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010107 if (memberType == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000010108 xmlSchemaPResCompAttrErr(ctxt,
10109 XML_SCHEMAP_UNKNOWN_MEMBER_TYPE,
10110 NULL, NULL, type->node, "memberTypes", localName, uri,
10111 XML_SCHEMA_TYPE_SIMPLE, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010112 } else {
10113 if (memberType->contentType == XML_SCHEMA_CONTENT_UNKNOWN)
10114 xmlSchemaTypeFixup(memberType, ctxt, NULL);
10115 link = (xmlSchemaTypeLinkPtr) xmlMalloc(sizeof(xmlSchemaTypeLink));
10116 if (link == NULL) {
10117 xmlSchemaPErrMemory(ctxt, "allocating a type link", NULL);
10118 return (-1);
10119 }
10120 link->type = memberType;
10121 link->next = NULL;
10122 if (lastLink == NULL)
10123 ctxtType->memberTypes = link;
10124 else
10125 lastLink->next = link;
10126 lastLink = link;
10127 }
10128 xmlFree(tmp);
10129 cur = end;
10130 } while (*cur != 0);
10131 }
10132 /*
10133 * Add local simple types,
10134 */
10135 memberType = type->subtypes;
10136 while (memberType != NULL) {
10137 if (memberType->contentType == XML_SCHEMA_CONTENT_UNKNOWN)
10138 xmlSchemaTypeFixup(memberType, ctxt, NULL);
10139 link = (xmlSchemaTypeLinkPtr) xmlMalloc(sizeof(xmlSchemaTypeLink));
10140 if (link == NULL) {
10141 xmlSchemaPErrMemory(ctxt, "allocating a type link", NULL);
10142 return (-1);
10143 }
10144 link->type = memberType;
10145 link->next = NULL;
10146 if (lastLink == NULL)
10147 ctxtType->memberTypes = link;
10148 else
10149 lastLink->next = link;
10150 lastLink = link;
10151 memberType = memberType->next;
10152 }
10153 /*
10154 * The actual value is then formed by replacing any union type
10155 * definition in the ·explicit members· with the members of their
10156 * {member type definitions}, in order.
10157 */
10158 link = ctxtType->memberTypes;
10159 while (link != NULL) {
10160 if (link->type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
10161 subLink = link->type->memberTypes;
10162 if (subLink != NULL) {
10163 link->type = subLink->type;
10164 if (subLink->next != NULL) {
10165 lastLink = link->next;
10166 subLink = subLink->next;
10167 prevLink = link;
10168 while (subLink != NULL) {
10169 newLink = (xmlSchemaTypeLinkPtr)
10170 xmlMalloc(sizeof(xmlSchemaTypeLink));
10171 if (newLink == NULL) {
10172 xmlSchemaPErrMemory(ctxt, "allocating a type link",
10173 NULL);
10174 return (-1);
10175 }
10176 newLink->type = memberType;
10177 prevLink->next = newLink;
10178 prevLink = newLink;
10179 newLink->next = lastLink;
10180
10181 subLink = subLink->next;
10182 }
10183 }
10184 }
10185 }
10186 link = link->next;
10187 }
10188
10189 return (0);
Daniel Veillard377e1a92004-04-16 16:30:05 +000010190}
10191
Daniel Veillard4255d502002-04-16 15:50:10 +000010192/**
Daniel Veillard3646d642004-06-02 19:19:14 +000010193 * xmlSchemaIsDerivedFromBuiltInType:
10194 * @ctxt: the schema parser context
10195 * @type: the type definition
10196 * @valType: the value type
10197 *
10198 *
10199 * Returns 1 if the type has the given value type, or
10200 * is derived from such a type.
10201 */
William M. Brack803812b2004-06-03 02:11:24 +000010202static int
Daniel Veillard3646d642004-06-02 19:19:14 +000010203xmlSchemaIsDerivedFromBuiltInType(xmlSchemaParserCtxtPtr ctxt,
10204 xmlSchemaTypePtr type, int valType)
10205{
10206 /* TODO: Check if this works in every case. */
Daniel Veillard01fa6152004-06-29 17:04:39 +000010207 if ((type->type == XML_SCHEMA_TYPE_BASIC) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000010208 (type->contentType == XML_SCHEMA_CONTENT_BASIC)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000010209 if (type->builtInType == valType)
Daniel Veillard3646d642004-06-02 19:19:14 +000010210 return(1);
10211 } else if (type->type == XML_SCHEMA_TYPE_ATTRIBUTE) {
10212 if (((xmlSchemaAttributePtr) type)->subtypes != NULL)
10213 return(xmlSchemaIsDerivedFromBuiltInType(ctxt,
10214 ((xmlSchemaAttributePtr) type)->subtypes, valType));
10215 } else if ((type->type == XML_SCHEMA_TYPE_RESTRICTION) ||
10216 (type->type == XML_SCHEMA_TYPE_EXTENSION)) {
10217 if (type->baseType != NULL)
10218 return(xmlSchemaIsDerivedFromBuiltInType(ctxt, type->baseType,
10219 valType));
10220 } else if ((type->subtypes != NULL) &&
10221 ((type->subtypes->type == XML_SCHEMA_TYPE_COMPLEX) ||
10222 (type->subtypes->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) ||
10223 (type->subtypes->type == XML_SCHEMA_TYPE_SIMPLE) ||
10224 (type->subtypes->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT))) {
10225 return(xmlSchemaIsDerivedFromBuiltInType(ctxt, type->subtypes,
10226 valType));
10227 }
10228
10229 return (0);
10230}
10231
10232/**
Daniel Veillard01fa6152004-06-29 17:04:39 +000010233 * xmlSchemaIsDerivedFromBuiltInType:
10234 * @type: the simpleType definition
10235 *
10236 * Returns the primitive type of the given type or
10237 * NULL in case of error.
10238 */
10239static xmlSchemaTypePtr
10240xmlSchemaGetPrimitiveType(xmlSchemaTypePtr type)
10241{
10242 while (type != NULL) {
10243 if (type->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE)
10244 return (type);
10245 type = type->baseType;
10246 }
10247
10248 return (NULL);
10249}
10250
10251
10252/**
Daniel Veillard3646d642004-06-02 19:19:14 +000010253 * xmlSchemaBuildAttributeUsesOwned:
10254 * @ctxt: the schema parser context
10255 * @type: the complex type definition
10256 * @cur: the attribute declaration list
10257 * @lastUse: the top of the attribute use list
10258 *
10259 * Builds the attribute uses list on the given complex type.
10260 * This one is supposed to be called by
10261 * xmlSchemaBuildAttributeValidation only.
10262 */
10263static int
10264xmlSchemaBuildAttributeUsesOwned(xmlSchemaParserCtxtPtr ctxt,
10265 xmlSchemaAttributePtr cur,
10266 xmlSchemaAttributeLinkPtr *uses,
10267 xmlSchemaAttributeLinkPtr *lastUse)
10268{
10269 xmlSchemaAttributeLinkPtr tmp;
10270 while (cur != NULL) {
10271 if (cur->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
10272 /*
10273 * W3C: "2 The {attribute uses} of the attribute groups ·resolved·
10274 * to by the ·actual value·s of the ref [attribute] of the
10275 * <attributeGroup> [children], if any."
10276 */
10277 if (xmlSchemaBuildAttributeUsesOwned(ctxt,
10278 ((xmlSchemaAttributeGroupPtr) cur)->attributes, uses,
10279 lastUse) == -1) {
10280 return (-1);
10281 }
10282 } else {
10283 /* W3C: "1 The set of attribute uses corresponding to the
10284 * <attribute> [children], if any."
10285 */
10286 tmp = (xmlSchemaAttributeLinkPtr)
10287 xmlMalloc(sizeof(xmlSchemaAttributeLink));
10288 if (tmp == NULL) {
10289 xmlSchemaPErrMemory(ctxt, "building attribute uses", NULL);
10290 return (-1);
10291 }
10292 tmp->attr = cur;
10293 tmp->next = NULL;
10294 if (*uses == NULL)
10295 *uses = tmp;
10296 else
10297 (*lastUse)->next = tmp;
10298 *lastUse = tmp;
10299 }
10300 cur = cur->next;
10301 }
10302 return (0);
10303}
10304
Daniel Veillard50355f02004-06-08 17:52:16 +000010305/**
10306 * xmlSchemaCloneWildcardNsConstraints:
10307 * @ctxt: the schema parser context
10308 * @dest: the destination wildcard
10309 * @source: the source wildcard
10310 *
10311 * Clones the namespace constraints of source
10312 * and assignes them to dest.
10313 * Returns -1 on internal error, 0 otherwise.
10314 */
Daniel Veillard3646d642004-06-02 19:19:14 +000010315static int
10316xmlSchemaCloneWildcardNsConstraints(xmlSchemaParserCtxtPtr ctxt,
10317 xmlSchemaWildcardPtr *dest,
10318 xmlSchemaWildcardPtr source)
10319{
10320 xmlSchemaWildcardNsPtr cur, tmp, last;
10321
10322 if ((source == NULL) || (*dest == NULL))
10323 return(-1);
10324 (*dest)->any = source->any;
10325 cur = source->nsSet;
10326 last = NULL;
10327 while (cur != NULL) {
10328 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
10329 if (tmp == NULL)
10330 return(-1);
10331 tmp->value = cur->value;
10332 if (last == NULL)
10333 (*dest)->nsSet = tmp;
10334 else
10335 last->next = tmp;
10336 last = tmp;
10337 cur = cur->next;
10338 }
10339 if ((*dest)->negNsSet != NULL)
10340 xmlSchemaFreeWildcardNsSet((*dest)->negNsSet);
10341 if (source->negNsSet != NULL) {
10342 (*dest)->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
10343 if ((*dest)->negNsSet == NULL)
10344 return(-1);
10345 (*dest)->negNsSet->value = source->negNsSet->value;
10346 } else
10347 (*dest)->negNsSet = NULL;
10348 return(0);
10349}
10350
Daniel Veillard50355f02004-06-08 17:52:16 +000010351/**
10352 * xmlSchemaUnionWildcards:
10353 * @ctxt: the schema parser context
10354 * @completeWild: the first wildcard
10355 * @curWild: the second wildcard
10356 *
10357 * Unions the namespace constraints of the given wildcards.
10358 * @completeWild will hold the resulting union.
10359 * Returns a positive error code on failure, -1 in case of an
10360 * internal error, 0 otherwise.
10361 */
Daniel Veillard3646d642004-06-02 19:19:14 +000010362static int
10363xmlSchemaUnionWildcards(xmlSchemaParserCtxtPtr ctxt,
10364 xmlSchemaWildcardPtr completeWild,
10365 xmlSchemaWildcardPtr curWild)
10366{
10367 xmlSchemaWildcardNsPtr cur, curB, tmp;
10368
10369 /*
10370 * 1 If O1 and O2 are the same value, then that value must be the
10371 * value.
10372 */
10373 if ((completeWild->any == curWild->any) &&
10374 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
10375 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
10376
10377 if ((completeWild->negNsSet == NULL) ||
10378 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
10379
10380 if (completeWild->nsSet != NULL) {
William M. Brack803812b2004-06-03 02:11:24 +000010381 int found = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000010382
10383 /*
10384 * Check equality of sets.
10385 */
10386 cur = completeWild->nsSet;
10387 while (cur != NULL) {
10388 found = 0;
10389 curB = curWild->nsSet;
10390 while (curB != NULL) {
10391 if (cur->value == curB->value) {
10392 found = 1;
10393 break;
10394 }
10395 curB = curB->next;
10396 }
10397 if (!found)
10398 break;
10399 cur = cur->next;
10400 }
10401 if (found)
10402 return(0);
10403 } else
10404 return(0);
10405 }
10406 }
10407 /*
10408 * 2 If either O1 or O2 is any, then any must be the value
10409 */
Daniel Veillard50355f02004-06-08 17:52:16 +000010410 if (completeWild->any != curWild->any) {
Daniel Veillard3646d642004-06-02 19:19:14 +000010411 if (completeWild->any == 0) {
10412 completeWild->any = 1;
10413 if (completeWild->nsSet != NULL) {
10414 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
10415 completeWild->nsSet = NULL;
10416 }
10417 if (completeWild->negNsSet != NULL) {
10418 xmlFree(completeWild->negNsSet);
10419 completeWild->negNsSet = NULL;
10420 }
10421 }
Daniel Veillard50355f02004-06-08 17:52:16 +000010422 return (0);
Daniel Veillard3646d642004-06-02 19:19:14 +000010423 }
10424 /*
10425 * 3 If both O1 and O2 are sets of (namespace names or ·absent·),
10426 * then the union of those sets must be the value.
10427 */
10428 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
10429 int found;
10430 xmlSchemaWildcardNsPtr start;
10431
10432 cur = curWild->nsSet;
10433 start = completeWild->nsSet;
10434 while (cur != NULL) {
10435 found = 0;
10436 curB = start;
10437 while (curB != NULL) {
10438 if (cur->value == curB->value) {
10439 found = 1;
10440 break;
10441 }
10442 curB = curB->next;
10443 }
10444 if (!found) {
10445 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
10446 if (tmp == NULL)
10447 return (-1);
10448 tmp->value = cur->value;
10449 tmp->next = completeWild->nsSet;
10450 completeWild->nsSet = tmp;
10451 }
10452 cur = cur->next;
10453 }
10454
10455 return(0);
10456 }
10457 /*
10458 * 4 If the two are negations of different values (namespace names
10459 * or ·absent·), then a pair of not and ·absent· must be the value.
10460 */
10461 if ((completeWild->negNsSet != NULL) &&
10462 (curWild->negNsSet != NULL) &&
10463 (completeWild->negNsSet->value != curWild->negNsSet->value)) {
10464 completeWild->negNsSet->value = NULL;
Daniel Veillard50355f02004-06-08 17:52:16 +000010465
10466 return(0);
Daniel Veillard3646d642004-06-02 19:19:14 +000010467 }
10468 /*
10469 * 5.
10470 */
10471 if (((completeWild->negNsSet != NULL) &&
10472 (completeWild->negNsSet->value != NULL) &&
10473 (curWild->nsSet != NULL)) ||
10474 ((curWild->negNsSet != NULL) &&
10475 (curWild->negNsSet->value != NULL) &&
10476 (completeWild->nsSet != NULL))) {
10477
10478 int nsFound, absentFound = 0;
10479
10480 if (completeWild->nsSet != NULL) {
10481 cur = completeWild->nsSet;
10482 curB = curWild->negNsSet;
10483 } else {
10484 cur = curWild->nsSet;
10485 curB = completeWild->negNsSet;
10486 }
10487 nsFound = 0;
10488 while (cur != NULL) {
10489 if (cur->value == NULL)
10490 absentFound = 1;
10491 else if (cur->value == curB->value)
10492 nsFound = 1;
10493 if (nsFound && absentFound)
10494 break;
10495 cur = cur->next;
10496 }
10497
10498 if (nsFound && absentFound) {
10499 /*
10500 * 5.1 If the set S includes both the negated namespace
10501 * name and ·absent·, then any must be the value.
10502 */
10503 completeWild->any = 1;
10504 if (completeWild->nsSet != NULL) {
10505 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
10506 completeWild->nsSet = NULL;
10507 }
10508 if (completeWild->negNsSet != NULL) {
10509 xmlFree(completeWild->negNsSet);
10510 completeWild->negNsSet = NULL;
10511 }
10512 } else if (nsFound && (!absentFound)) {
10513 /*
10514 * 5.2 If the set S includes the negated namespace name
10515 * but not ·absent·, then a pair of not and ·absent· must
10516 * be the value.
10517 */
10518 if (completeWild->nsSet != NULL) {
10519 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
10520 completeWild->nsSet = NULL;
10521 }
10522 if (completeWild->negNsSet == NULL) {
10523 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
10524 if (completeWild->negNsSet == NULL)
10525 return (-1);
10526 }
10527 completeWild->negNsSet->value = NULL;
10528 } else if ((!nsFound) && absentFound) {
10529 /*
10530 * 5.3 If the set S includes ·absent· but not the negated
10531 * namespace name, then the union is not expressible.
10532 */
10533 xmlSchemaPErr(ctxt, completeWild->node,
10534 XML_SCHEMAP_UNION_NOT_EXPRESSIBLE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010535 "The union of the wilcard is not expressible.\n",
Daniel Veillard3646d642004-06-02 19:19:14 +000010536 NULL, NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +000010537 return(XML_SCHEMAP_UNION_NOT_EXPRESSIBLE);
Daniel Veillard3646d642004-06-02 19:19:14 +000010538 } else if ((!nsFound) && (!absentFound)) {
10539 /*
10540 * 5.4 If the set S does not include either the negated namespace
10541 * name or ·absent·, then whichever of O1 or O2 is a pair of not
10542 * and a namespace name must be the value.
10543 */
10544 if (completeWild->negNsSet == NULL) {
10545 if (completeWild->nsSet != NULL) {
10546 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
10547 completeWild->nsSet = NULL;
10548 }
10549 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
10550 if (completeWild->negNsSet == NULL)
10551 return (-1);
10552 completeWild->negNsSet->value = curWild->negNsSet->value;
10553 }
10554 }
10555 return (0);
10556 }
10557 /*
10558 * 6.
10559 */
10560 if (((completeWild->negNsSet != NULL) &&
10561 (completeWild->negNsSet->value == NULL) &&
10562 (curWild->nsSet != NULL)) ||
10563 ((curWild->negNsSet != NULL) &&
10564 (curWild->negNsSet->value == NULL) &&
10565 (completeWild->nsSet != NULL))) {
10566
10567 if (completeWild->nsSet != NULL) {
10568 cur = completeWild->nsSet;
10569 } else {
10570 cur = curWild->nsSet;
10571 }
10572 while (cur != NULL) {
10573 if (cur->value == NULL) {
10574 /*
10575 * 6.1 If the set S includes ·absent·, then any must be the
10576 * value.
10577 */
10578 completeWild->any = 1;
10579 if (completeWild->nsSet != NULL) {
10580 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
10581 completeWild->nsSet = NULL;
10582 }
10583 if (completeWild->negNsSet != NULL) {
10584 xmlFree(completeWild->negNsSet);
10585 completeWild->negNsSet = NULL;
10586 }
10587 return (0);
10588 }
10589 cur = cur->next;
10590 }
10591 if (completeWild->negNsSet == NULL) {
10592 /*
10593 * 6.2 If the set S does not include ·absent·, then a pair of not
10594 * and ·absent· must be the value.
10595 */
10596 if (completeWild->nsSet != NULL) {
10597 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
10598 completeWild->nsSet = NULL;
10599 }
10600 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
10601 if (completeWild->negNsSet == NULL)
10602 return (-1);
10603 completeWild->negNsSet->value = NULL;
10604 }
10605 return (0);
10606 }
10607 return (0);
10608
10609}
10610
Daniel Veillard50355f02004-06-08 17:52:16 +000010611/**
10612 * xmlSchemaIntersectWildcards:
10613 * @ctxt: the schema parser context
10614 * @completeWild: the first wildcard
10615 * @curWild: the second wildcard
10616 *
10617 * Intersects the namespace constraints of the given wildcards.
10618 * @completeWild will hold the resulting intersection.
10619 * Returns a positive error code on failure, -1 in case of an
10620 * internal error, 0 otherwise.
10621 */
Daniel Veillard3646d642004-06-02 19:19:14 +000010622static int
10623xmlSchemaIntersectWildcards(xmlSchemaParserCtxtPtr ctxt,
10624 xmlSchemaWildcardPtr completeWild,
10625 xmlSchemaWildcardPtr curWild)
10626{
William M. Brack803812b2004-06-03 02:11:24 +000010627 xmlSchemaWildcardNsPtr cur, curB, prev, tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000010628
10629 /*
10630 * 1 If O1 and O2 are the same value, then that value must be the
10631 * value.
10632 */
10633 if ((completeWild->any == curWild->any) &&
10634 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
10635 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
10636
10637 if ((completeWild->negNsSet == NULL) ||
10638 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
10639
10640 if (completeWild->nsSet != NULL) {
William M. Brack803812b2004-06-03 02:11:24 +000010641 int found = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000010642
10643 /*
10644 * Check equality of sets.
10645 */
10646 cur = completeWild->nsSet;
10647 while (cur != NULL) {
10648 found = 0;
10649 curB = curWild->nsSet;
10650 while (curB != NULL) {
10651 if (cur->value == curB->value) {
10652 found = 1;
10653 break;
10654 }
10655 curB = curB->next;
10656 }
10657 if (!found)
10658 break;
10659 cur = cur->next;
10660 }
10661 if (found)
10662 return(0);
10663 } else
10664 return(0);
10665 }
10666 }
10667 /*
10668 * 2 If either O1 or O2 is any, then the other must be the value.
10669 */
10670 if ((completeWild->any != curWild->any) && (completeWild->any)) {
10671 if (xmlSchemaCloneWildcardNsConstraints(ctxt, &completeWild, curWild) == -1)
10672 return(-1);
10673 return(0);
10674 }
10675 /*
10676 * 3 If either O1 or O2 is a pair of not and a value (a namespace
10677 * name or ·absent·) and the other is a set of (namespace names or
10678 * ·absent·), then that set, minus the negated value if it was in
10679 * the set, minus ·absent· if it was in the set, must be the value.
10680 */
10681 if (((completeWild->negNsSet != NULL) && (curWild->nsSet != NULL)) ||
10682 ((curWild->negNsSet != NULL) && (completeWild->nsSet != NULL))) {
10683 const xmlChar *neg;
10684
10685 if (completeWild->nsSet == NULL) {
10686 neg = completeWild->negNsSet->value;
10687 if (xmlSchemaCloneWildcardNsConstraints(ctxt, &completeWild, curWild) == -1)
10688 return(-1);
10689 } else
10690 neg = curWild->negNsSet->value;
10691 /*
10692 * Remove absent and negated.
10693 */
10694 prev = NULL;
10695 cur = completeWild->nsSet;
10696 while (cur != NULL) {
10697 if (cur->value == NULL) {
10698 if (prev == NULL)
10699 completeWild->nsSet = cur->next;
10700 else
10701 prev->next = cur->next;
10702 xmlFree(cur);
10703 break;
10704 }
10705 prev = cur;
10706 cur = cur->next;
10707 }
10708 if (neg != NULL) {
10709 prev = NULL;
10710 cur = completeWild->nsSet;
10711 while (cur != NULL) {
10712 if (cur->value == neg) {
10713 if (prev == NULL)
10714 completeWild->nsSet = cur->next;
10715 else
10716 prev->next = cur->next;
10717 xmlFree(cur);
10718 break;
10719 }
10720 prev = cur;
10721 cur = cur->next;
10722 }
10723 }
10724
10725 return(0);
10726 }
10727 /*
10728 * 4 If both O1 and O2 are sets of (namespace names or ·absent·),
10729 * then the intersection of those sets must be the value.
10730 */
10731 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
10732 int found;
10733
10734 cur = completeWild->nsSet;
10735 prev = NULL;
10736 while (cur != NULL) {
10737 found = 0;
10738 curB = curWild->nsSet;
10739 while (curB != NULL) {
10740 if (cur->value == curB->value) {
10741 found = 1;
10742 break;
10743 }
10744 curB = curB->next;
10745 }
10746 if (!found) {
10747 if (prev == NULL)
10748 completeWild->nsSet = cur->next;
10749 else
10750 prev->next = cur->next;
10751 tmp = cur->next;
10752 xmlFree(cur);
10753 cur = tmp;
10754 continue;
10755 }
10756 prev = cur;
10757 cur = cur->next;
10758 }
10759
10760 return(0);
10761 }
10762 /* 5 If the two are negations of different namespace names,
10763 * then the intersection is not expressible
10764 */
10765 if ((completeWild->negNsSet != NULL) &&
10766 (curWild->negNsSet != NULL) &&
10767 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
10768 (completeWild->negNsSet->value != NULL) &&
10769 (curWild->negNsSet->value != NULL)) {
10770
10771 xmlSchemaPErr(ctxt, completeWild->node, XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000010772 "The intersection of the wilcard is not expressible.\n",
Daniel Veillard3646d642004-06-02 19:19:14 +000010773 NULL, NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +000010774 return(XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE);
Daniel Veillard3646d642004-06-02 19:19:14 +000010775 }
10776 /*
10777 * 6 If the one is a negation of a namespace name and the other
10778 * is a negation of ·absent·, then the one which is the negation
10779 * of a namespace name must be the value.
10780 */
10781 if ((completeWild->negNsSet != NULL) && (curWild->negNsSet != NULL) &&
10782 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
10783 (completeWild->negNsSet->value == NULL)) {
10784 completeWild->negNsSet->value = curWild->negNsSet->value;
10785 }
10786 return(0);
10787}
10788
Daniel Veillard50355f02004-06-08 17:52:16 +000010789/**
10790 * xmlSchemaIsWildcardNsConstraintSubset:
10791 * @ctxt: the schema parser context
10792 * @wildA: the first wildcard
10793 * @wildB: the second wildcard
10794 *
10795 * Returns 1 if the namespace constraint of @wildA is an intensional
10796 * subset of @wildB, 0 otherwise.
10797 */
10798static int
Daniel Veillardc0826a72004-08-10 14:17:33 +000010799xmlSchemaIsWildcardNsConstraintSubset(xmlSchemaWildcardPtr wildA,
10800 xmlSchemaWildcardPtr wildB)
Daniel Veillard50355f02004-06-08 17:52:16 +000010801{
Daniel Veillard3646d642004-06-02 19:19:14 +000010802
Daniel Veillard50355f02004-06-08 17:52:16 +000010803 /*
10804 * Schema Component Constraint: Wildcard Subset
10805 */
10806 /*
10807 * 1 super must be any.
10808 */
10809 if (wildB->any)
10810 return (1);
10811 /*
10812 * 2.1 sub must be a pair of not and a namespace name or ·absent·.
10813 * 2.2 super must be a pair of not and the same value.
10814 */
10815 if ((wildA->negNsSet != NULL) &&
10816 (wildB->negNsSet != NULL) &&
10817 (wildA->negNsSet->value == wildA->negNsSet->value))
10818 return (1);
10819 /*
10820 * 3.1 sub must be a set whose members are either namespace names or ·absent·.
10821 */
10822 if (wildA->nsSet != NULL) {
10823 /*
10824 * 3.2.1 super must be the same set or a superset thereof.
10825 */
10826 if (wildB->nsSet != NULL) {
10827 xmlSchemaWildcardNsPtr cur, curB;
10828 int found = 0;
10829
10830 cur = wildA->nsSet;
10831 while (cur != NULL) {
10832 found = 0;
10833 curB = wildB->nsSet;
10834 while (curB != NULL) {
10835 if (cur->value == curB->value) {
10836 found = 1;
10837 break;
10838 }
10839 curB = curB->next;
10840 }
10841 if (!found)
10842 return (0);
10843 cur = cur->next;
10844 }
10845 if (found)
10846 return (1);
10847 } else if (wildB->negNsSet != NULL) {
10848 xmlSchemaWildcardNsPtr cur;
10849 /*
10850 * 3.2.2 super must be a pair of not and a namespace name or
10851 * ·absent· and that value must not be in sub's set.
10852 */
10853 cur = wildA->nsSet;
10854 while (cur != NULL) {
10855 if (cur->value == wildB->negNsSet->value)
10856 return (0);
10857 cur = cur->next;
10858 }
10859 return (1);
10860 }
10861 }
10862 return (0);
10863}
10864
10865/**
10866 * xmlSchemaBuildCompleteAttributeWildcard:
10867 * @ctxt: the schema parser context
10868 * @attrs: the attribute list
10869 * @completeWild: the resulting complete wildcard
10870 *
10871 * Returns -1 in case of an internal error, 0 otherwise.
10872 */
10873static int
10874xmlSchemaBuildCompleteAttributeWildcard(xmlSchemaParserCtxtPtr ctxt,
10875 xmlSchemaAttributePtr attrs,
10876 xmlSchemaWildcardPtr *completeWild)
Daniel Veillard3646d642004-06-02 19:19:14 +000010877{
10878 while (attrs != NULL) {
10879 if (attrs->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
10880 xmlSchemaAttributeGroupPtr group;
10881
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010882 group = (xmlSchemaAttributeGroupPtr) attrs;
10883 /*
10884 * Handle attribute group references.
10885 */
10886 if (group->ref != NULL) {
10887 if (group->refItem == NULL) {
10888 /*
10889 * TODO: Should we raise a warning here?
10890 */
10891 /*
10892 * The referenced attribute group definition could not
10893 * be resolved beforehand, so skip.
10894 */
10895 attrs = attrs->next;
10896 continue;
10897 } else
10898 group = group->refItem;
10899 }
10900 /*
10901 * For every attribute group definition, an intersected wildcard
10902 * will be created (assumed that a wildcard exists on the
10903 * particular attr. gr. def. or on any contained attr. gr. def
10904 * at all).
10905 * The flag XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED ensures
10906 * that the intersection will be performed only once.
10907 */
Daniel Veillard3646d642004-06-02 19:19:14 +000010908 if ((group->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED) == 0) {
10909 if (group->attributes != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000010910 if (xmlSchemaBuildCompleteAttributeWildcard(ctxt,
10911 group->attributes, &group->attributeWildcard) == -1)
10912 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000010913 }
10914 group->flags |= XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED;
10915 }
10916 if (group->attributeWildcard != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000010917 if (*completeWild == NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +000010918 /*
10919 * Copy the first encountered wildcard as context, except for the annotation.
10920 */
Daniel Veillard50355f02004-06-08 17:52:16 +000010921 *completeWild = xmlSchemaAddWildcard(ctxt);
10922 (*completeWild)->type = XML_SCHEMA_TYPE_ANY_ATTRIBUTE;
10923 if (xmlSchemaCloneWildcardNsConstraints(ctxt,
10924 completeWild, group->attributeWildcard) == -1)
10925 return (-1);
10926 (*completeWild)->processContents = group->attributeWildcard->processContents;
Daniel Veillard3646d642004-06-02 19:19:14 +000010927 /*
10928 * Although the complete wildcard might not correspond to any
10929 * node in the schema, we will save this context node.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010930 * TODO: Hmm, is this sane?
Daniel Veillard3646d642004-06-02 19:19:14 +000010931 */
Daniel Veillard50355f02004-06-08 17:52:16 +000010932 (*completeWild)->node = group->attributeWildcard->node;
10933
10934 } else if (xmlSchemaIntersectWildcards(ctxt, *completeWild, group->attributeWildcard) == -1) {
10935 xmlSchemaFreeWildcard(*completeWild);
10936 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000010937 }
10938 }
10939 }
10940 attrs = attrs->next;
10941 }
10942
Daniel Veillard50355f02004-06-08 17:52:16 +000010943 return (0);
Daniel Veillard3646d642004-06-02 19:19:14 +000010944}
10945
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010946static int
10947xmlSchemaGetEffectiveValueConstraint(xmlSchemaAttributePtr item,
10948 int *fixed,
10949 const xmlChar **value,
10950 xmlSchemaValPtr *val)
10951{
10952 *fixed = 0;
10953 *value = NULL;
10954 if (val != 0)
10955 *val = NULL;
10956
10957 if (item->defValue == NULL)
10958 item = item->refDecl;
10959
10960 if (item == NULL)
10961 return (0);
10962
10963 if (item->defValue != NULL) {
10964 *value = item->defValue;
10965 if (val != 0)
10966 *val = item->defVal;
10967 if (item->flags & XML_SCHEMAS_ATTR_FIXED)
10968 *fixed = 1;
10969 return (1);
10970 }
10971 return (0);
10972}
Daniel Veillard3646d642004-06-02 19:19:14 +000010973/**
10974 * xmlSchemaMatchesWildcardNs:
10975 * @wild: the wildcard
10976 * @ns: the namespace
10977 *
10978 *
10979 * Returns 1 if the given namespace matches the wildcard,
10980 * 0 otherwise.
10981 */
10982static int
10983xmlSchemaMatchesWildcardNs(xmlSchemaWildcardPtr wild, const xmlChar* ns)
10984{
10985 if (wild == NULL)
10986 return(0);
10987
10988 if (wild->any)
10989 return(1);
10990 else if (wild->nsSet != NULL) {
10991 xmlSchemaWildcardNsPtr cur;
10992
10993 cur = wild->nsSet;
10994 while (cur != NULL) {
10995 if (xmlStrEqual(cur->value, ns))
10996 return(1);
10997 cur = cur->next;
10998 }
10999 } else if ((wild->negNsSet != NULL) && (ns != NULL) &&
11000 (!xmlStrEqual(wild->negNsSet->value, ns)))
11001 return(1);
11002
11003 return(0);
11004}
11005
11006/**
11007 * xmlSchemaBuildAttributeValidation:
11008 * @ctxt: the schema parser context
11009 * @type: the complex type definition
11010 *
11011 *
11012 * Builds the wildcard and the attribute uses on the given complex type.
11013 * Returns -1 if an internal error occurs, 0 otherwise.
11014 */
11015static int
11016xmlSchemaBuildAttributeValidation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaTypePtr type)
11017{
11018 xmlSchemaTypePtr baseType = NULL;
11019 xmlSchemaAttributeLinkPtr cur, base, tmp, id = NULL, prev = NULL, uses = NULL,
William M. Brack803812b2004-06-03 02:11:24 +000011020 lastUse = NULL, lastBaseUse = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000011021 xmlSchemaAttributePtr attrs;
Daniel Veillard01fa6152004-06-29 17:04:39 +000011022 xmlSchemaTypePtr anyType;
Daniel Veillard50355f02004-06-08 17:52:16 +000011023 int baseIsAnyType = 0;
Daniel Veillardc0826a72004-08-10 14:17:33 +000011024 xmlChar *str = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000011025 int err = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000011026
Daniel Veillard01fa6152004-06-29 17:04:39 +000011027 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
Daniel Veillard3646d642004-06-02 19:19:14 +000011028 /*
11029 * Complex Type Definition with complex content Schema Component.
11030 *
11031 * Attribute uses.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011032 * TODO: Add checks for absent referenced attribute declarations and
11033 * simple types.
Daniel Veillard3646d642004-06-02 19:19:14 +000011034 */
11035 if (type->attributeUses != NULL) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000011036 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011037 "Internal error: xmlSchemaBuildAttributeValidation: "
Daniel Veillard3646d642004-06-02 19:19:14 +000011038 "attribute uses already builded.\n",
11039 NULL, NULL);
11040 return (-1);
11041 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000011042 if (type->baseType == NULL) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000011043 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011044 "Internal error: xmlSchemaBuildAttributeValidation: "
Daniel Veillardc0826a72004-08-10 14:17:33 +000011045 "complex type '%s' has no base type.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000011046 type->name, NULL);
11047 return (-1);
11048 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011049 baseType = type->baseType;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011050 if (baseType == anyType)
11051 baseIsAnyType = 1;
11052 /*
11053 * Inherit the attribute uses of the base type.
11054 */
11055 /*
11056 * NOTE: It is allowed to "extend" the anyType complex type.
11057 */
11058 if (!baseIsAnyType) {
11059 if (baseType != NULL) {
11060 for (cur = baseType->attributeUses; cur != NULL; cur = cur->next) {
11061 tmp = (xmlSchemaAttributeLinkPtr)
11062 xmlMalloc(sizeof(xmlSchemaAttributeLink));
11063 if (tmp == NULL) {
11064 xmlSchemaPErrMemory(ctxt,
11065 "building attribute uses of complexType", NULL);
11066 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000011067 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011068 tmp->attr = cur->attr;
11069 tmp->next = NULL;
11070 if (type->attributeUses == NULL) {
11071 type->attributeUses = tmp;
11072 } else
11073 lastBaseUse->next = tmp;
11074 lastBaseUse = tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000011075 }
11076 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011077 }
11078 if ((type->subtypes != NULL) &&
11079 ((type->subtypes->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) ||
11080 (type->subtypes->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT))) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011081 /*
11082 * type --> (<simpleContent>|<complexContent>)
11083 * --> (<restriction>|<extension>) --> attributes
11084 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011085 attrs = type->subtypes->subtypes->attributes;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011086 } else {
11087 /* Short hand form of the complexType. */
11088 attrs = type->attributes;
11089 }
11090 /*
11091 * Handle attribute wildcards.
11092 */
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000011093 err = xmlSchemaBuildCompleteAttributeWildcard(ctxt,
11094 attrs, &type->attributeWildcard);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011095 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011096 * NOTE: During the parse time, the wildcard is created on the complexType
11097 * directly, if encountered in a <restriction> or <extension> element.
Daniel Veillard01fa6152004-06-29 17:04:39 +000011098 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011099 if (err == -1) {
11100 xmlSchemaPErr(ctxt, type->node, XML_SCHEMAP_INTERNAL,
11101 "Internal error: xmlSchemaBuildAttributeValidation: "
11102 "failed to build an intersected attribute wildcard.\n",
11103 NULL, NULL);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000011104 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011105 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011106
11107 if ((type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) &&
11108 ((baseIsAnyType) ||
11109 ((baseType != NULL) &&
11110 (baseType->type == XML_SCHEMA_TYPE_COMPLEX) &&
11111 (baseType->attributeWildcard != NULL)))) {
11112 if (type->attributeWildcard != NULL) {
11113 /*
11114 * Union the complete wildcard with the base wildcard.
11115 */
11116 if (xmlSchemaUnionWildcards(ctxt, type->attributeWildcard,
11117 baseType->attributeWildcard) == -1)
11118 return (-1);
11119 } else {
11120 /*
11121 * Just inherit the wildcard.
11122 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011123 /*
11124 * NOTE: This is the only case where an attribute
11125 * wildcard is shared.
11126 */
11127 if (type->flags & XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD)
11128 type->flags ^= XML_SCHEMAS_TYPE_OWNED_ATTR_WILDCARD;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011129 type->attributeWildcard = baseType->attributeWildcard;
Daniel Veillard50355f02004-06-08 17:52:16 +000011130 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011131 }
11132
11133 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
11134 if (type->attributeWildcard != NULL) {
11135 /*
11136 * Derivation Valid (Restriction, Complex)
11137 * 4.1 The {base type definition} must also have one.
11138 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000011139 if (baseType->attributeWildcard == NULL) {
11140 xmlSchemaPCustomErr(ctxt,
11141 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_1,
11142 NULL, type, NULL,
11143 "The type has an attribute wildcard, "
11144 "but the base type %s does not have one",
11145 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
11146 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011147 return (1);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011148 } else if (xmlSchemaIsWildcardNsConstraintSubset(
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011149 type->attributeWildcard, baseType->attributeWildcard) == 0) {
11150 /* 4.2 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000011151 xmlSchemaPCustomErr(ctxt,
11152 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_2,
11153 NULL, type, NULL,
11154 "The attribute wildcard is not a valid "
11155 "subset of the wildcard in the base type %s",
11156 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
11157 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011158 return (1);
11159 }
11160 /* 4.3 Unless the {base type definition} is the ·ur-type
11161 * definition·, the complex type definition's {attribute
11162 * wildcard}'s {process contents} must be identical to or
11163 * stronger than the {base type definition}'s {attribute
11164 * wildcard}'s {process contents}, where strict is stronger
11165 * than lax is stronger than skip.
11166 */
11167 if ((type->baseType != anyType) &&
11168 (type->attributeWildcard->processContents <
11169 baseType->attributeWildcard->processContents)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011170 xmlSchemaPCustomErr(ctxt,
11171 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_3,
11172 NULL, type, NULL,
11173 "The 'process contents' of the attribute wildcard is weaker than "
11174 "the one in the base type %s",
11175 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
11176 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011177 return (1);
11178 }
11179 }
11180 } else if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
11181 /*
11182 * Derivation Valid (Extension)
11183 * At this point the type and the base have both, either
11184 * no wildcard or a wildcard.
11185 */
11186 if ((baseType->attributeWildcard != NULL) &&
11187 (baseType->attributeWildcard != type->attributeWildcard)) {
11188 /* 1.3 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000011189 if (xmlSchemaIsWildcardNsConstraintSubset(
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011190 baseType->attributeWildcard, type->attributeWildcard) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011191 xmlSchemaPCustomErr(ctxt,
11192 XML_SCHEMAP_COS_CT_EXTENDS_1_3,
11193 NULL, type, NULL,
11194 "The attribute wildcard is not a valid "
11195 "superset of the one in the base type %s",
11196 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
11197 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011198 return (1);
11199 }
11200 }
11201 }
11202
Daniel Veillard3646d642004-06-02 19:19:14 +000011203 /*
11204 * Gather attribute uses defined by this type.
11205 */
11206 if (attrs != NULL) {
11207 if (xmlSchemaBuildAttributeUsesOwned(ctxt, attrs,
11208 &uses, &lastUse) == -1) {
11209 return (-1);
11210 }
11211 }
11212 /* 3.4.6 -> Complex Type Definition Properties Correct 4.
11213 * "Two distinct attribute declarations in the {attribute uses} must
11214 * not have identical {name}s and {target namespace}s."
11215 *
11216 * For "extension" this is done further down.
11217 */
11218 if ((uses != NULL) && ((type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) == 0)) {
11219 cur = uses;
11220 while (cur != NULL) {
11221 tmp = cur->next;
11222 while (tmp != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011223 if ((xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
11224 xmlSchemaGetAttrName(tmp->attr))) &&
11225 (xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr ),
11226 xmlSchemaGetAttrTargetNsURI(tmp->attr)))) {
11227
11228 xmlSchemaPAttrUseErr(ctxt,
11229 XML_SCHEMAP_CT_PROPS_CORRECT_4,
11230 NULL, type, NULL, cur->attr,
11231 "Duplicate attribute use %s specified",
11232 xmlSchemaFormatNsUriLocal(&str,
11233 xmlSchemaGetAttrTargetNsURI(tmp->attr),
11234 xmlSchemaGetAttrName(tmp->attr))
11235 );
11236 FREE_AND_NULL(str)
Daniel Veillard3646d642004-06-02 19:19:14 +000011237 break;
11238 }
11239 tmp = tmp->next;
11240 }
11241 cur = cur->next;
11242 }
11243 }
11244 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
11245 /*
11246 * Derive by restriction.
11247 */
11248 if (baseIsAnyType) {
11249 type->attributeUses = uses;
11250 } else {
11251 int found;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011252 const xmlChar *bEffValue;
11253 int effFixed;
Daniel Veillard3646d642004-06-02 19:19:14 +000011254
11255 cur = uses;
11256 while (cur != NULL) {
11257 found = 0;
11258 base = type->attributeUses;
11259 while (base != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011260 if (xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
11261 xmlSchemaGetAttrName(base->attr)) &&
11262 xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr),
11263 xmlSchemaGetAttrTargetNsURI(base->attr))) {
Daniel Veillard3646d642004-06-02 19:19:14 +000011264
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011265 found = 1;
11266
Daniel Veillard3646d642004-06-02 19:19:14 +000011267 if ((cur->attr->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
11268 (base->attr->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED)) {
11269 /*
11270 * derivation-ok-restriction 2.1.1
Daniel Veillardc0826a72004-08-10 14:17:33 +000011271 */
11272 xmlSchemaPAttrUseErr(ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +000011273 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011274 NULL, type, NULL, cur->attr,
11275 "The 'optional' use is inconsistent with a matching "
11276 "'required' use of the base type", NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +000011277 } else if ((cur->attr->occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) &&
11278 (base->attr->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED)) {
11279 /*
11280 * derivation-ok-restriction 3
11281 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000011282 xmlSchemaPCustomErr(ctxt,
11283 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_3,
11284 NULL, type, NULL,
11285 "A matching attribute use for the 'required' "
11286 "attribute use %s of the base type is missing",
11287 xmlSchemaFormatNsUriLocal(&str,
11288 xmlSchemaGetAttrTargetNsURI(base->attr),
11289 xmlSchemaGetAttrName(base->attr)));
11290 FREE_AND_NULL(str)
Daniel Veillard3646d642004-06-02 19:19:14 +000011291 } else {
11292 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011293 * 2.1.3 [Definition:] Let the effective value
11294 * constraint of an attribute use be its {value
11295 * constraint}, if present, otherwise its {attribute
11296 * declaration}'s {value constraint} .
11297 */
11298 xmlSchemaGetEffectiveValueConstraint(base->attr, &effFixed,
11299 &bEffValue, 0);
11300 /*
11301 * 2.1.3 ... one of the following must be true
11302 *
11303 * 2.1.3.1 B's ·effective value constraint· is
11304 * ·absent· or default.
11305 */
11306 if ((bEffValue != NULL) &&
11307 (effFixed == 1)) {
11308 const xmlChar *rEffValue = NULL;
11309
11310 xmlSchemaGetEffectiveValueConstraint(base->attr, &effFixed,
11311 &rEffValue, 0);
11312 /*
11313 * 2.1.3.2 R's ·effective value constraint· is
11314 * fixed with the same string as B's.
11315 */
11316 if ((effFixed == 0) ||
11317 (! xmlStrEqual(rEffValue, bEffValue))) {
11318 xmlSchemaPAttrUseErr(ctxt,
11319 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_3,
11320 NULL, type, NULL, cur->attr,
11321 "The effective value constraint of the "
11322 "attribute use is inconsistent with "
11323 "its correspondent of the base type",
11324 NULL);
11325 }
11326 }
11327 /*
11328 * TODO: derivation-ok-restriction 2.1.2 ({type definition} must be validly derived)
11329 */
11330 /*
Daniel Veillard3646d642004-06-02 19:19:14 +000011331 * Override the attribute use.
11332 */
11333 base->attr = cur->attr;
11334 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011335
Daniel Veillard3646d642004-06-02 19:19:14 +000011336 break;
11337 }
11338 base = base->next;
11339 }
11340
11341 if (!found) {
11342 if (cur->attr->occurs != XML_SCHEMAS_ATTR_USE_PROHIBITED) {
11343 /*
11344 * derivation-ok-restriction 2.2
11345 */
11346 if ((type->attributeWildcard != NULL) &&
11347 xmlSchemaMatchesWildcardNs(type->attributeWildcard,
11348 cur->attr->targetNamespace))
11349 found = 1;
11350
11351 if (!found) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011352 xmlSchemaPAttrUseErr(ctxt,
11353 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_2,
11354 NULL, type, NULL, cur->attr,
11355 "Neither a matching attribute use, "
11356 "nor a matching wildcard in the base type does exist",
11357 NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +000011358 } else {
11359 /*
11360 * Add the attribute use.
11361 *
11362 * Note that this may lead to funny derivation error reports, if
11363 * multiple equal attribute uses exist; but this is not
11364 * allowed anyway, and it will be reported beforehand.
11365 */
11366 tmp = cur;
11367 if (prev != NULL)
11368 prev->next = cur->next;
11369 else
11370 uses = cur->next;
11371 cur = cur->next;
11372 if (type->attributeUses == NULL) {
11373 type->attributeUses = tmp;
11374 } else
11375 lastBaseUse->next = tmp;
11376 lastBaseUse = tmp;
11377
11378 continue;
11379 }
11380 }
11381 }
11382 prev = cur;
11383 cur = cur->next;
11384 }
11385 if (uses != NULL)
11386 xmlSchemaFreeAttributeUseList(uses);
11387 }
11388 } else if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
11389 /*
11390 * The spec allows only appending, and not other kinds of extensions.
11391 *
11392 * This ensures: Schema Component Constraint: Derivation Valid (Extension) : 1.2
11393 */
11394 if (uses != NULL) {
11395 if (type->attributeUses == NULL) {
11396 type->attributeUses = uses;
11397 } else
11398 lastBaseUse->next = uses;
Daniel Veillard50355f02004-06-08 17:52:16 +000011399 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011400 } else {
11401 /*
Daniel Veillard50355f02004-06-08 17:52:16 +000011402 * Derive implicitely from the ur-type.
11403 */
Daniel Veillard3646d642004-06-02 19:19:14 +000011404 type->attributeUses = uses;
Daniel Veillard50355f02004-06-08 17:52:16 +000011405 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011406 /*
11407 * 3.4.6 -> Complex Type Definition Properties Correct
11408 */
11409 if (type->attributeUses != NULL) {
11410 cur = type->attributeUses;
11411 prev = NULL;
11412 while (cur != NULL) {
11413 /*
11414 * 4. Two distinct attribute declarations in the {attribute uses} must
11415 * not have identical {name}s and {target namespace}s.
Daniel Veillard50355f02004-06-08 17:52:16 +000011416 *
Daniel Veillard3646d642004-06-02 19:19:14 +000011417 * Note that this was already done for "restriction" and types derived from
11418 * the ur-type.
Daniel Veillard50355f02004-06-08 17:52:16 +000011419 */
Daniel Veillard3646d642004-06-02 19:19:14 +000011420 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
11421 tmp = cur->next;
11422 while (tmp != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011423 if ((xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
11424 xmlSchemaGetAttrName(tmp->attr))) &&
11425 (xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr ),
11426 xmlSchemaGetAttrTargetNsURI(tmp->attr)))) {
Daniel Veillard3646d642004-06-02 19:19:14 +000011427
Daniel Veillardc0826a72004-08-10 14:17:33 +000011428 xmlSchemaPAttrUseErr(ctxt,
11429 XML_SCHEMAP_CT_PROPS_CORRECT_4,
11430 NULL, type, NULL, tmp->attr,
11431 "Duplicate attribute use specified", NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +000011432 break;
11433 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011434 tmp = tmp->next;
Daniel Veillard50355f02004-06-08 17:52:16 +000011435 }
11436 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011437 /*
11438 * 5. Two distinct attribute declarations in the {attribute uses} must
11439 * not have {type definition}s which are or are derived from ID.
11440 */
11441 if ((cur->attr->subtypes != NULL) &&
Daniel Veillard01fa6152004-06-29 17:04:39 +000011442 (xmlSchemaIsDerivedFromBuiltInType(ctxt, (xmlSchemaTypePtr) cur->attr, XML_SCHEMAS_ID))) {
Daniel Veillard3646d642004-06-02 19:19:14 +000011443 if (id != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011444 xmlSchemaPAttrUseErr(ctxt,
11445 XML_SCHEMAP_CT_PROPS_CORRECT_5,
11446 NULL, type, NULL, cur->attr,
11447 "There must not exist more than one attribute use, "
11448 "declared of type 'ID' or derived from it",
11449 NULL);
11450 FREE_AND_NULL(str)
Daniel Veillard50355f02004-06-08 17:52:16 +000011451 }
Daniel Veillard3646d642004-06-02 19:19:14 +000011452 id = cur;
11453 }
11454 /*
11455 * Remove "prohibited" attribute uses. The reason this is done at this late
11456 * stage is to be able to catch dublicate attribute uses. So we had to keep
11457 * prohibited uses in the list as well.
11458 */
11459 if (cur->attr->occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) {
11460 tmp = cur;
11461 if (prev == NULL)
11462 type->attributeUses = cur->next;
11463 else
11464 prev->next = cur->next;
11465 cur = cur->next;
Daniel Veillard50355f02004-06-08 17:52:16 +000011466 xmlFree(tmp);
Daniel Veillard3646d642004-06-02 19:19:14 +000011467 } else {
11468 prev = cur;
11469 cur = cur->next;
11470 }
11471 }
11472 }
11473 /*
11474 * TODO: This check should be removed if we are 100% sure of
11475 * the base type attribute uses already being built.
11476 */
11477 if ((baseType != NULL) && (!baseIsAnyType) &&
11478 (baseType->type == XML_SCHEMA_TYPE_COMPLEX) &&
11479 (baseType->contentType == XML_SCHEMA_CONTENT_UNKNOWN)) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000011480 xmlSchemaPErr(ctxt, baseType->node, XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011481 "Internal error: xmlSchemaBuildAttributeValidation: "
Daniel Veillardc0826a72004-08-10 14:17:33 +000011482 "attribute uses not builded on base type '%s'.\n",
Daniel Veillard3646d642004-06-02 19:19:14 +000011483 baseType->name, NULL);
11484 }
11485 return (0);
11486}
11487
11488/**
Daniel Veillard01fa6152004-06-29 17:04:39 +000011489 * xmlSchemaTypeFinalContains:
11490 * @schema: the schema
11491 * @type: the type definition
11492 * @final: the final
11493 *
11494 * Evaluates if a type definition contains the given "final".
11495 * This does take "finalDefault" into account as well.
11496 *
11497 * Returns 1 if the type does containt the given "final",
11498 * 0 otherwise.
11499 */
11500static int
11501xmlSchemaTypeFinalContains(xmlSchemaPtr schema, xmlSchemaTypePtr type, int final)
11502{
11503 int tfinal = final, tflags = type->flags;
11504
11505 if (type == NULL)
11506 return (0);
11507 if (type->flags & XML_SCHEMAS_TYPE_FINAL_DEFAULT) {
11508 switch (final) {
11509 case XML_SCHEMAS_TYPE_FINAL_RESTRICTION:
11510 tfinal = XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION;
11511 break;
11512 case XML_SCHEMAS_TYPE_FINAL_EXTENSION:
11513 tfinal = XML_SCHEMAS_FINAL_DEFAULT_EXTENSION;
11514 break;
11515 case XML_SCHEMAS_TYPE_FINAL_LIST:
11516 tfinal = XML_SCHEMAS_FINAL_DEFAULT_LIST;
11517 break;
11518 case XML_SCHEMAS_TYPE_FINAL_UNION:
11519 tfinal = XML_SCHEMAS_FINAL_DEFAULT_UNION;
11520 break;
11521 }
11522 tflags = schema->flags;
11523 }
11524 if (tflags & tfinal)
11525 return (1);
11526 else
11527 return (0);
11528
11529}
11530
11531/**
11532 * xmlSchemaGetUnionSimpleTypeMemberTypes:
11533 * @type: the Union Simple Type
11534 *
11535 * Returns a list of member types of @type if existing,
11536 * returns NULL otherwise.
11537 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000011538static xmlSchemaTypeLinkPtr
Daniel Veillard01fa6152004-06-29 17:04:39 +000011539xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type)
11540{
11541 while (type != NULL) {
11542 if (type->memberTypes != NULL)
11543 return (type->memberTypes);
11544 else
11545 type = type->baseType;
11546 }
11547 return (NULL);
11548}
11549
11550/**
11551 * xmlSchemaGetListSimpleTypeItemType:
11552 * @type: the simple type definition
11553 *
11554 * Returns the item type definition of the list simple type.
11555 */
11556static xmlSchemaTypePtr
11557xmlSchemaGetListSimpleTypeItemType(xmlSchemaTypePtr type)
11558{
11559 if ((type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) == 0)
11560 return (NULL);
11561 /*
11562 * Note: In libxml2, the built-in types do not reflect
11563 * the datatype hierarchy (yet?) - we have to treat them
11564 * in a special way.
11565 */
11566 if (type->type == XML_SCHEMA_TYPE_BASIC)
11567 return (xmlSchemaGetBuiltInListSimpleTypeItemType(type));
11568 if (type->subtypes->type == XML_SCHEMA_TYPE_LIST)
11569 /* 1 If the <list> alternative is chosen, then the type
11570 * definition ·resolved· to by the ·actual value· of the
11571 * itemType [attribute] of <list>, if present, otherwise
11572 * the type definition corresponding to the <simpleType>
11573 * among the [children] of <list>.
11574 */
11575 return (type->subtypes->subtypes);
11576 else {
11577 /* 2 If the <restriction> option is chosen, then the
11578 * {item type definition} of the {base type definition}.
11579 */
11580 return (xmlSchemaGetListSimpleTypeItemType(type->baseType));
11581 }
11582}
11583
11584/**
11585 * xmlSchemaCheckCOSSTDerivedOK:
11586 * @type: the derived simple type definition
11587 * @baseType: the base type definition
11588 *
11589 * Checks wheter @type can be validly
11590 * derived from @baseType.
11591 *
11592 * Returns 0 on success, an positive error code otherwise.
11593 */
11594static int
11595xmlSchemaCheckCOSSTDerivedOK(xmlSchemaPtr schema,
11596 xmlSchemaTypePtr type,
11597 xmlSchemaTypePtr baseType,
11598 int subset)
11599{
11600 /*
11601 * Schema Component Constraint: Type Derivation OK (Simple)
11602 *
11603 *
11604 * 1 They are the same type definition.
11605 * TODO: The identy check might have to be more complex than this.
11606 */
11607 if (type == baseType)
11608 return (0);
11609 /*
11610 * 2.1 restriction is not in the subset, or in the {final}
11611 * of its own {base type definition};
11612 */
11613 if ((subset & XML_SCHEMAS_TYPE_FINAL_RESTRICTION) ||
11614 (xmlSchemaTypeFinalContains(schema,
11615 type->baseType, XML_SCHEMAS_TYPE_FINAL_RESTRICTION))) {
11616 return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_1);
11617 }
11618 /* 2.2 */
11619 if (type->baseType == baseType) {
11620 /*
11621 * 2.2.1 D's ·base type definition· is B.
11622 */
11623 return (0);
11624 }
11625 /*
11626 * 2.2.2 D's ·base type definition· is not the ·ur-type definition·
11627 * and is validly derived from B given the subset, as defined by this
11628 * constraint.
11629 */
11630 if ((type->baseType != xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE)) &&
11631 (xmlSchemaCheckCOSSTDerivedOK(schema, type->baseType, baseType, subset) == 0)) {
11632 return (0);
11633 }
11634 /*
11635 * 2.2.3 D's {variety} is list or union and B is the ·simple ur-type
11636 * definition·.
11637 */
11638 if (((type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) ||
11639 (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION)) &&
11640 (baseType == xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE))) {
11641 return (0);
11642 }
11643 /*
11644 * 2.2.4 B's {variety} is union and D is validly derived from a type
11645 * definition in B's {member type definitions} given the subset, as
11646 * defined by this constraint.
11647 *
11648 * NOTE: This seems not to involve built-in types, since there is no
11649 * built-in Union Simple Type.
11650 */
11651 if (baseType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
11652 xmlSchemaTypeLinkPtr cur;
11653
11654 cur = baseType->memberTypes;
11655 while (cur != NULL) {
11656 if (xmlSchemaCheckCOSSTDerivedOK(schema, type,
11657 cur->type, subset) == 0)
11658 return (0);
11659 cur = cur->next;
11660 }
11661 }
11662
11663 return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_2);
11664}
11665
11666
11667/**
11668 * xmlSchemaCheckSTPropsCorrect:
11669 * @ctxt: the schema parser context
11670 * @type: the simple type definition
11671 *
11672 * Checks st-props-correct.
11673 *
11674 * Returns 0 if the properties are correct,
11675 * if not, a positive error code and -1 on internal
11676 * errors.
11677 */
11678static int
11679xmlSchemaCheckSTPropsCorrect(xmlSchemaParserCtxtPtr ctxt,
11680 xmlSchemaTypePtr type)
11681{
11682 xmlSchemaTypePtr baseType = type->baseType, anySimpleType,
11683 anyType;
Daniel Veillardc0826a72004-08-10 14:17:33 +000011684 xmlChar *str = NULL;
Daniel Veillard01fa6152004-06-29 17:04:39 +000011685
Daniel Veillardc0826a72004-08-10 14:17:33 +000011686 /* STATE: error funcs converted. */
Daniel Veillard01fa6152004-06-29 17:04:39 +000011687 /*
11688 * Schema Component Constraint: Simple Type Definition Properties Correct
11689 *
11690 * NOTE: This is somehow redundant, since we actually built a simple type
11691 * to have all the needed information; this acts as an self test.
11692 */
11693 anySimpleType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
11694 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
11695 /*
11696 * TODO: 1 The values of the properties of a simple type definition must be as
11697 * described in the property tableau in Datatype definition, modulo the
11698 * impact of Missing Sub-components (§5.3).
11699 */
11700 /* Base type: If the datatype has been ·derived· by ·restriction·
11701 * then the Simple Type Definition component from which it is ·derived·,
11702 * otherwise the Simple Type Definition for anySimpleType (§4.1.6).
11703 */
11704 if (baseType == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011705 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011706 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011707 NULL, type, NULL,
11708 "No base type existent", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011709 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
11710 }
11711 if ((baseType->type != XML_SCHEMA_TYPE_SIMPLE) &&
11712 ((baseType->type != XML_SCHEMA_TYPE_BASIC) ||
11713 (baseType == anyType))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011714 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011715 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011716 NULL, type, NULL,
11717 "The base type %s is not a simple type",
11718 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
11719 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011720 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
11721 }
11722 if ((baseType != anySimpleType) &&
11723 (type->subtypes->type != XML_SCHEMA_TYPE_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011724 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011725 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011726 NULL, type, NULL,
11727 "A type, derived by list or union, must have"
11728 "the simple ur-type definition as base type, not %s",
11729 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
11730 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011731 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
11732 }
11733 /*
11734 * Variety: One of {atomic, list, union}.
11735 */
11736 if (((type->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) &&
11737 ((type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) == 0) &&
11738 ((type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) == 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011739 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011740 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011741 NULL, type, NULL,
11742 "The variety is absent", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011743 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
11744 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000011745 /* TODO: Finish this. Hmm, is this finished? */
Daniel Veillard01fa6152004-06-29 17:04:39 +000011746
11747 /*
11748 * 2 All simple type definitions must be derived ultimately from the ·simple
11749 * ur-type definition (so· circular definitions are disallowed). That is, it
11750 * must be possible to reach a built-in primitive datatype or the ·simple
11751 * ur-type definition· by repeatedly following the {base type definition}.
11752 */
11753 baseType = type->baseType;
11754 while ((baseType != NULL) && (baseType->type != XML_SCHEMA_TYPE_BASIC)) {
11755 if (baseType->contentType == XML_SCHEMA_CONTENT_UNKNOWN)
11756 xmlSchemaTypeFixup(baseType, ctxt, NULL);
11757 if (baseType == anySimpleType)
11758 break;
11759 else if (baseType == type) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011760 xmlSchemaPCustomErr(ctxt,
11761 XML_SCHEMAP_ST_PROPS_CORRECT_2,
11762 NULL, type, NULL,
11763 "The definition is circular", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011764 return (XML_SCHEMAP_ST_PROPS_CORRECT_2);
11765 }
11766 baseType = baseType->baseType;
11767 }
11768 /*
11769 * 3 The {final} of the {base type definition} must not contain restriction.
11770 */
11771 if (xmlSchemaTypeFinalContains(ctxt->schema, baseType,
11772 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011773 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011774 XML_SCHEMAP_ST_PROPS_CORRECT_3,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011775 NULL, type, NULL,
11776 "The 'final' of its base type %s must not contain "
11777 "'restriction'",
11778 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL, 1));
11779 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011780 return (XML_SCHEMAP_ST_PROPS_CORRECT_3);
11781 }
11782 return (0);
11783}
11784
11785/**
11786 * xmlSchemaCheckDerivationValidSimpleRestriction:
11787 * @ctxt: the schema parser context
11788 * @type: the simple type definition
11789 *
11790 * Checks if the given @type (simpleType) is derived
11791 * validly by restriction.
11792 *
11793 * Returns -1 on internal errors, 0 if the type is validly derived,
11794 * a positive error code otherwise.
11795 */
11796static int
11797xmlSchemaCheckCOSSTRestricts(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011798 xmlSchemaTypePtr type)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011799{
Daniel Veillardc0826a72004-08-10 14:17:33 +000011800 xmlChar *str = NULL;
11801
11802 /* STATE: error funcs converted. */
Daniel Veillard01fa6152004-06-29 17:04:39 +000011803
11804 if (type->type != XML_SCHEMA_TYPE_SIMPLE) {
11805 xmlSchemaPErr(ctxt, type->node,
11806 XML_ERR_INTERNAL_ERROR,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011807 "xmlSchemaCheckDerivationValidSimpleRestriction: The given "
11808 "type '%s' is not a user-derived simpleType.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000011809 type->name, NULL);
11810 return (-1);
11811 }
11812
11813 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) {
11814 xmlSchemaTypePtr primitive;
11815 /*
11816 * 1.1 The {base type definition} must be an atomic simple
11817 * type definition or a built-in primitive datatype.
11818 */
11819 if ((type->baseType->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011820 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011821 XML_SCHEMAP_COS_ST_RESTRICTS_1_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011822 NULL, type, NULL,
11823 "The base type %s is not an atomic simple type",
11824 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
11825 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011826 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_1);
11827 }
11828 /* 1.2 The {final} of the {base type definition} must not contain
11829 * restriction.
11830 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000011831 /* OPTIMIZE TODO : This is already done in xmlSchemaCheckStPropsCorrect */
Daniel Veillard01fa6152004-06-29 17:04:39 +000011832 if (xmlSchemaTypeFinalContains(ctxt->schema, type->baseType,
11833 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011834 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011835 XML_SCHEMAP_COS_ST_RESTRICTS_1_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011836 NULL, type, NULL,
11837 "The final of its base type %s must not contain 'restriction'",
11838 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
11839 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011840 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_2);
11841 }
11842
11843 /*
11844 * 1.3.1 DF must be an allowed constraining facet for the {primitive
11845 * type definition}, as specified in the appropriate subsection of 3.2
11846 * Primitive datatypes.
11847 */
11848 if (type->facets != NULL) {
11849 xmlSchemaFacetPtr facet;
11850 int ok = 1;
11851
11852 primitive = xmlSchemaGetPrimitiveType(type);
11853 if (primitive == NULL) {
11854 xmlSchemaPErr(ctxt, type->node,
11855 XML_ERR_INTERNAL_ERROR,
11856 "xmlSchemaCheckDerivationValidSimpleRestriction: failed "
Daniel Veillardc0826a72004-08-10 14:17:33 +000011857 "to get primitive type of type '%s'.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000011858 type->name, NULL);
11859 return (-1);
11860 }
11861 facet = type->facets;
11862 do {
11863 if (xmlSchemaIsBuiltInTypeFacet(primitive, facet->type) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011864 ok = 0;
11865 xmlSchemaPIllegalFacetAtomicErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011866 XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011867 NULL, type, primitive, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011868 }
11869 facet = facet->next;
11870 } while (facet != NULL);
11871 if (ok == 0)
Daniel Veillardc0826a72004-08-10 14:17:33 +000011872 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011873 }
11874 /*
11875 * TODO: 1.3.2 (facet derivation)
11876 */
11877 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
11878 xmlSchemaTypePtr itemType = NULL;
11879
11880 itemType = xmlSchemaGetListSimpleTypeItemType(type);
11881 if (itemType == NULL) {
11882 xmlSchemaPErr(ctxt, type->node,
11883 XML_ERR_INTERNAL_ERROR,
11884 "Internal error: xmlSchemaCheckDerivationValidSimpleRestriction: "
Daniel Veillardc0826a72004-08-10 14:17:33 +000011885 "failed to evaluate the item type of type '%s'.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000011886 type->name, NULL);
11887 return (-1);
11888 }
11889 /*
11890 * 2.1 The {item type definition} must have a {variety} of atomic or
11891 * union (in which case all the {member type definitions}
11892 * must be atomic).
11893 */
11894 if (((itemType->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) &&
11895 ((itemType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) == 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011896 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011897 XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011898 NULL, type, NULL,
11899 "The item type %s must have a variety of atomic or union",
11900 xmlSchemaFormatItemForReport(&str, NULL, itemType, NULL, 1));
11901 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011902 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
11903 } else if (itemType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
11904 xmlSchemaTypeLinkPtr member;
11905
11906 member = itemType->memberTypes;
11907 while (member != NULL) {
11908 if ((member->type->flags &
11909 XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011910 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011911 XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011912 NULL, type, NULL,
11913 "The item type is a union type, but the "
11914 "member type %s of this item type is not atomic",
11915 xmlSchemaFormatItemForReport(&str, NULL, member->type, NULL, 1));
11916 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011917 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
11918 }
11919 member = member->next;
11920 }
11921 }
11922
11923 if (type->baseType == xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE)) {
11924 xmlSchemaFacetPtr facet;
11925 /*
11926 * This is the case if we have: <simpleType><list ..
11927 */
11928 /*
11929 * 2.3.1
11930 * 2.3.1.1 The {final} of the {item type definition} must not
11931 * contain list.
11932 */
11933 if (xmlSchemaTypeFinalContains(ctxt->schema,
11934 itemType, XML_SCHEMAS_TYPE_FINAL_LIST)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011935 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011936 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011937 NULL, type, NULL,
11938 "The final of its item type %s must not contain 'list'",
11939 xmlSchemaFormatItemForReport(&str, NULL, itemType, NULL, 1));
11940 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011941 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1);
11942 }
11943 /*
11944 * 2.3.1.2 The {facets} must only contain the whiteSpace
11945 * facet component.
11946 */
11947 if (type->facets != NULL) {
11948 facet = type->facets;
11949 do {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011950 if (facet->type != XML_SCHEMA_FACET_WHITESPACE) {
11951 xmlSchemaPIllegalFacetListUnionErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011952 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011953 NULL, type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000011954 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2);
11955 }
11956 facet = facet->next;
11957 } while (facet != NULL);
11958 }
11959 /*
11960 * TODO: Datatypes states:
11961 * A ·list· datatype can be ·derived· from an ·atomic· datatype
11962 * whose ·lexical space· allows space (such as string or anyURI)or
11963 * a ·union· datatype any of whose {member type definitions}'s
11964 * ·lexical space· allows space.
11965 */
11966 } else {
11967 /*
11968 * This is the case if we have: <simpleType><restriction ...
11969 */
11970 /*
11971 * 2.3.2
11972 * 2.3.2.1 The {base type definition} must have a {variety} of list.
11973 */
11974 if ((type->baseType->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011975 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011976 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011977 NULL, type, NULL,
11978 "The base type %s must be a list type",
11979 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
11980 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011981 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1);
11982 }
11983 /*
11984 * 2.3.2.2 The {final} of the {base type definition} must not
11985 * contain restriction.
11986 */
11987 if (xmlSchemaTypeFinalContains(ctxt->schema, type->baseType,
11988 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011989 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011990 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011991 NULL, type, NULL,
11992 "The final of the base type %s must not contain 'restriction'",
11993 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
11994 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000011995 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2);
11996 }
11997 /*
11998 * 2.3.2.3 The {item type definition} must be validly derived
11999 * from the {base type definition}'s {item type definition} given
12000 * the empty set, as defined in Type Derivation OK (Simple) (§3.14.6).
12001 */
12002 {
12003 xmlSchemaTypePtr baseItemType;
12004
12005 baseItemType = xmlSchemaGetListSimpleTypeItemType(type->baseType);
12006 if (baseItemType == NULL) {
12007 xmlSchemaPErr(ctxt, type->node,
12008 XML_ERR_INTERNAL_ERROR,
12009 "xmlSchemaCheckDerivationValidSimpleRestriction: "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012010 "List simple type '%s': Failed to "
12011 "evaluate the item type of its base type '%s'.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000012012 type->name, type->baseType->name);
12013 return (-1);
12014 }
12015 if ((itemType != baseItemType) &&
12016 (xmlSchemaCheckCOSSTDerivedOK(ctxt->schema, itemType,
12017 baseItemType, 0) != 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012018 xmlChar *strBIT = NULL, *strBT = NULL;
12019 xmlSchemaPCustomErrExt(ctxt,
12020 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3,
12021 NULL, type, NULL,
12022 "The item type %s is not validly derived from the "
12023 "item type %s of the base type %s",
12024 xmlSchemaFormatItemForReport(&str, NULL, itemType, NULL, 1),
12025 xmlSchemaFormatItemForReport(&strBIT, NULL, baseItemType, NULL, 1),
12026 xmlSchemaFormatItemForReport(&strBT, NULL, type->baseType, NULL, 1));
12027
12028 FREE_AND_NULL(str)
12029 FREE_AND_NULL(strBIT)
12030 FREE_AND_NULL(strBT)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012031 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3);
12032 }
12033 }
12034
12035 if (type->facets != NULL) {
12036 xmlSchemaFacetPtr facet;
12037 int ok = 1;
12038 /*
12039 * 2.3.2.4 Only length, minLength, maxLength, whiteSpace, pattern
12040 * and enumeration facet components are allowed among the {facets}.
12041 */
12042 facet = type->facets;
12043 do {
12044 switch (facet->type) {
12045 case XML_SCHEMA_FACET_LENGTH:
12046 case XML_SCHEMA_FACET_MINLENGTH:
12047 case XML_SCHEMA_FACET_MAXLENGTH:
12048 case XML_SCHEMA_FACET_WHITESPACE:
12049 /*
12050 * TODO: 2.5.1.2 List datatypes
12051 * The value of ·whiteSpace· is fixed to the value collapse.
12052 */
12053 case XML_SCHEMA_FACET_PATTERN:
12054 case XML_SCHEMA_FACET_ENUMERATION:
12055 break;
12056 default: {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012057 xmlSchemaPIllegalFacetListUnionErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012058 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012059 NULL, type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012060 /*
12061 * We could return, but it's nicer to report all
12062 * invalid facets.
12063 */
12064 ok = 0;
12065 }
12066 }
12067 facet = facet->next;
12068 } while (facet != NULL);
12069 if (ok == 0)
12070 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4);
12071 /*
12072 * TODO: 2.3.2.5 For each facet in the {facets} (call this DF), if there
12073 * is a facet of the same kind in the {facets} of the {base type
12074 * definition} (call this BF),then the DF's {value} must be a valid
12075 * restriction of BF's {value} as defined in [XML Schemas: Datatypes].
12076 */
12077 }
12078
12079
12080 }
12081 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
12082 /*
12083 * 3.1 The {member type definitions} must all have {variety} of
12084 * atomic or list.
12085 */
12086 xmlSchemaTypeLinkPtr member;
12087
12088 member = type->memberTypes;
12089 while (member != NULL) {
12090 if (((member->type->flags &
12091 XML_SCHEMAS_TYPE_VARIETY_ATOMIC) == 0) &&
12092 ((member->type->flags &
12093 XML_SCHEMAS_TYPE_VARIETY_LIST) == 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012094 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012095 XML_SCHEMAP_COS_ST_RESTRICTS_3_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012096 NULL, type, NULL,
12097 "The member type %s is neither an atomic, nor a list type",
12098 xmlSchemaFormatItemForReport(&str, NULL, member->type, NULL, 1));
12099 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012100 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_1);
12101 }
12102 member = member->next;
12103 }
12104 /*
12105 * 3.3.1 If the {base type definition} is the ·simple ur-type
12106 * definition·
12107 */
12108 if (type->baseType == xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE)) {
12109 /*
12110 * 3.3.1.1 All of the {member type definitions} must have a
12111 * {final} which does not contain union.
12112 */
12113 member = type->memberTypes;
12114 while (member != NULL) {
12115 if (xmlSchemaTypeFinalContains(ctxt->schema, member->type,
12116 XML_SCHEMAS_TYPE_FINAL_UNION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012117 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012118 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012119 NULL, type, NULL,
12120 "The final of member type %s contains 'union'",
12121 xmlSchemaFormatItemForReport(&str, NULL, member->type, NULL, 1));
12122 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012123 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1);
12124 }
12125 member = member->next;
12126 }
12127 /*
12128 * 3.3.1.2 The {facets} must be empty.
12129 */
12130 if (type->facetSet != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012131 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012132 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012133 NULL, type, NULL,
12134 "No facets allowed", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012135 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2);
12136 }
12137 } else {
12138 /*
12139 * 3.3.2.1 The {base type definition} must have a {variety} of union.
12140 */
12141 if ((type->baseType->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012142 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012143 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012144 NULL, type, NULL,
12145 "The base type %s is not a union type",
12146 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
12147 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012148 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1);
12149 }
12150 /*
12151 * 3.3.2.2 The {final} of the {base type definition} must not contain restriction.
12152 */
12153 if (xmlSchemaTypeFinalContains(ctxt->schema, type->baseType,
12154 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012155 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012156 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012157 NULL, type, NULL,
12158 "The final of its base type %s must not contain 'restriction'",
12159 xmlSchemaFormatItemForReport(&str, NULL, type->baseType, NULL, 1));
12160 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012161 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2);
12162 }
12163 /*
12164 * 3.3.2.3 The {member type definitions}, in order, must be validly
12165 * derived from the corresponding type definitions in the {base
12166 * type definition}'s {member type definitions} given the empty set,
12167 * as defined in Type Derivation OK (Simple) (§3.14.6).
12168 */
12169 {
12170 xmlSchemaTypeLinkPtr baseMember;
12171
12172 /*
12173 * OPTIMIZE: if the type is restricting, it has no local defined
12174 * member types and inherits the member types of the base type;
12175 * thus a check for equality can be skipped.
12176 */
12177 /*
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000012178 * Even worse: I cannot see a scenario where a restricting
Daniel Veillard01fa6152004-06-29 17:04:39 +000012179 * union simple type can have other member types as the member
12180 * types of it's base type. This check seems not necessary with
12181 * respect to the derivation process in libxml2.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000012182 * But necessary if constructing types with an API.
Daniel Veillard01fa6152004-06-29 17:04:39 +000012183 */
12184 if (type->memberTypes != NULL) {
12185 member = type->memberTypes;
12186 baseMember = xmlSchemaGetUnionSimpleTypeMemberTypes(type->baseType);
12187 if ((member == NULL) && (baseMember != NULL)) {
12188 xmlSchemaPErr(ctxt, type->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012189 XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012190 "Internal error: "
12191 "xmlSchemaCheckDerivationValidSimpleRestriction "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012192 "(3.3.2.3), union simple type '%s', unequal number "
Daniel Veillard01fa6152004-06-29 17:04:39 +000012193 "of member types in the base type\n",
12194 type->name, NULL);
12195 }
12196 while (member != NULL) {
12197 if (baseMember == NULL) {
12198 xmlSchemaPErr(ctxt, type->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012199 XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012200 "Internal error: "
12201 "xmlSchemaCheckDerivationValidSimpleRestriction "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012202 "(3.3.2.3), union simple type '%s', unequal number "
12203 "of member types in the base type.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000012204 type->name, NULL);
12205 }
12206 if ((member->type != baseMember->type) &&
12207 (xmlSchemaCheckCOSSTDerivedOK(ctxt->schema,
12208 member->type, baseMember->type, 0) != 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012209 xmlChar *strBMT = NULL, *strBT = NULL;
12210
12211 xmlSchemaPCustomErrExt(ctxt,
12212 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3,
12213 NULL, type, NULL,
12214 "The member type %s is not validly derived from its "
12215 "corresponding member type %s of the base type %s",
12216 xmlSchemaFormatItemForReport(&str, NULL, member->type, NULL, 1),
12217 xmlSchemaFormatItemForReport(&strBMT, NULL, baseMember->type, NULL, 1),
12218 xmlSchemaFormatItemForReport(&strBT, NULL, type->baseType, NULL, 1));
12219 FREE_AND_NULL(str)
12220 FREE_AND_NULL(strBMT)
12221 FREE_AND_NULL(strBT)
Daniel Veillard01fa6152004-06-29 17:04:39 +000012222 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3);
12223 }
12224 member = member->next;
12225 baseMember = baseMember->next;
12226 }
12227 }
12228 }
12229 /*
12230 * 3.3.2.4 Only pattern and enumeration facet components are
12231 * allowed among the {facets}.
12232 */
12233 if (type->facets != NULL) {
12234 xmlSchemaFacetPtr facet;
12235 int ok = 1;
12236
12237 facet = type->facets;
12238 do {
12239 if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
12240 (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012241 xmlSchemaPIllegalFacetListUnionErr(ctxt,
12242 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4,
12243 NULL, type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012244 ok = 0;
12245 }
12246 facet = facet->next;
12247 } while (facet != NULL);
12248 if (ok == 0)
12249 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4);
12250
12251 }
12252 /*
12253 * TODO: 3.3.2.5 (facet derivation)
12254 */
12255 }
12256 }
12257
12258 return (0);
12259}
12260
12261/**
12262 * xmlSchemaCheckSRCSimpleType:
12263 * @ctxt: the schema parser context
12264 * @type: the simple type definition
12265 *
12266 * Checks crc-simple-type constraints.
12267 *
12268 * Returns 0 if the constraints are satisfied,
12269 * if not a positive error code and -1 on internal
12270 * errors.
12271 */
12272static int
12273xmlSchemaCheckSRCSimpleType(xmlSchemaParserCtxtPtr ctxt,
12274 xmlSchemaTypePtr type)
12275{
12276 /*
12277 * NOTE: src-simple-type 2-4 are redundant, since the checks
12278 * were are done for the corresponding <restriction>, <list> and <union>
12279 * elements, but W3C wants a <simpleType> error as well, so it gets one.
12280 * Maby this can be skipped in the future, if we get sure it's not needed.
12281 */
12282 if (type->subtypes == NULL) {
12283 xmlSchemaPErr(ctxt, type->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012284 XML_SCHEMAP_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012285 "Internal error: xmlSchemaCheckSRCSimpleType, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000012286 "no subtype on simple type '%s'.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000012287 type->name, NULL);
12288 return (-1);
12289 }
12290 /*
12291 * src-simple-type.1 The corresponding simple type definition, if any,
12292 * must satisfy the conditions set out in Constraints on Simple Type
12293 * Definition Schema Components (§3.14.6).
12294 */
12295 if ((xmlSchemaCheckSTPropsCorrect(ctxt, type) != 0) ||
12296 (xmlSchemaCheckCOSSTRestricts(ctxt, type) != 0)) {
12297 /*
12298 * TODO: Removed this, since it got annoying to get an
12299 * extra error report, if anything failed until now.
12300 * Enable this if needed.
12301 */
12302 /*
12303 xmlSchemaPErr(ctxt, type->node,
12304 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012305 "Simple type '%s' does not satisfy the constraints "
Daniel Veillard01fa6152004-06-29 17:04:39 +000012306 "on simple type definitions.\n",
12307 type->name, NULL);
12308 */
12309 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_1);
12310 }
12311
12312 if (type->subtypes->type == XML_SCHEMA_TYPE_RESTRICTION) {
12313 /*
12314 * src-simple-type.2 If the <restriction> alternative is chosen,
12315 * either it must have a base [attribute] or a <simpleType> among its
12316 * [children], but not both.
12317 */
William M. Brack2f2a6632004-08-20 23:09:47 +000012318 /*
12319 * XML_SCHEMAP_SRC_SIMPLE_TYPE_2
12320 * NOTE: This was removed, since this will be already handled
12321 * in the parse function for <restriction>.
12322 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000012323 } else if (type->subtypes->type == XML_SCHEMA_TYPE_LIST) {
12324 /* src-simple-type.3 If the <list> alternative is chosen, either it must have
12325 * an itemType [attribute] or a <simpleType> among its [children],
12326 * but not both.
12327 * NOTE: baseType is set to the local simple type definiton,
12328 * if existent, at parse time. This is a hack and not nice.
12329 */
William M. Brack2f2a6632004-08-20 23:09:47 +000012330 /*
12331 * TODO: Remove this, and add the check to the parse function of <list>.
12332 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000012333 if (((type->subtypes->base == NULL) &&
12334 (type->baseType == NULL)) ||
12335 ((type->subtypes->base != NULL) &&
12336 (type->subtypes->baseType != NULL))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012337 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012338 XML_SCHEMAP_SRC_SIMPLE_TYPE_3,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012339 NULL, type, NULL,
12340 "Either the attribute 'itemType' or the <simpleType> child "
12341 "must be present on the <list> child ", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012342 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_3);
12343 }
12344
12345
12346 } else if (type->subtypes->type == XML_SCHEMA_TYPE_UNION) {
12347 xmlSchemaTypeLinkPtr member;
12348 xmlSchemaTypePtr ancestor, anySimpleType;
12349
12350 anySimpleType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
12351
12352 /* src-simple-type.4 Circular union type definition is disallowed. That is, if
12353 * the <union> alternative is chosen, there must not be any entries
12354 * in the memberTypes [attribute] at any depth which resolve to the
12355 * component corresponding to the <simpleType>.
12356 */
12357 member = type->memberTypes;
12358 while (member != NULL) {
12359 ancestor = member->type;
12360 while ((ancestor != NULL) && (ancestor->type != XML_SCHEMA_TYPE_BASIC)) {
12361 if (ancestor->contentType == XML_SCHEMA_CONTENT_UNKNOWN)
12362 xmlSchemaTypeFixup(ancestor, ctxt, NULL);
12363 if (ancestor == anySimpleType)
12364 break;
12365 else if (ancestor == type) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000012366 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000012367 XML_SCHEMAP_SRC_SIMPLE_TYPE_4,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012368 NULL, type, NULL,
12369 "The definition is circular", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000012370 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_4);
12371 } else if (ancestor->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
12372 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000012373 * TODO, FIXME: Although a list simple type must not have a union ST
Daniel Veillard01fa6152004-06-29 17:04:39 +000012374 * type as item type, which in turn has a list ST as member
12375 * type, we will assume this here as well, since this check
12376 * was not yet performed.
12377 */
12378
12379 }
12380 ancestor = ancestor->baseType;
12381 }
12382 member = member->next;
12383 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000012384 }
12385
12386 return (0);
12387}
12388
William M. Brack2f2a6632004-08-20 23:09:47 +000012389#if 0 /* Not yet used code for CT schema validation */
12390static int
12391xmlSchemaCheckCVCSimpleType(xmlSchemaValidCtxtPtr ctxt,
12392 const xmlChar * value,
12393 xmlSchemaTypePtr type,
12394 int fireErrors)
12395{
12396 int ret;
12397 /*
12398 * 3.14.4 Simple Type Definition Validation Rules
12399 * Validation Rule: String Valid
12400 */
12401 /*
12402 * 1 It is schema-valid with respect to that definition as defined
12403 * by Datatype Valid in [XML Schemas: Datatypes].
12404 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012405 ret = xmlSchemaValidateSimpleTypeValue(ctxt, type, value,
12406 fireErrors, 1, 1, 1);
William M. Brack2f2a6632004-08-20 23:09:47 +000012407 return (ret);
12408 /*
12409 * 2.1 If The definition is ENTITY or is validly derived from ENTITY given
12410 * the empty set, as defined in Type Derivation OK (Simple) (§3.14.6), then
12411 * the string must be a ·declared entity name·.
12412 */
12413 /*
12414 * 2.2 If The definition is ENTITIES or is validly derived from ENTITIES
12415 * given the empty set, as defined in Type Derivation OK (Simple) (§3.14.6),
12416 * then every whitespace-delimited substring of the string must be a ·declared
12417 * entity name·.
12418 */
12419 /*
12420 * 2.3 otherwise no further condition applies.
12421 */
12422
12423 return (0);
12424}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012425#endif
12426
William M. Brack2f2a6632004-08-20 23:09:47 +000012427
12428static int
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012429xmlSchemaCreatePCtxtOnVCtxt(xmlSchemaValidCtxtPtr vctxt)
12430{
12431 if (vctxt->pctxt == NULL) {
12432 vctxt->pctxt =xmlSchemaNewParserCtxtUseDict("*", vctxt->schema->dict);
12433 /* vctxt->pctxt = xmlSchemaNewParserCtxt("*"); */
12434 if (vctxt->pctxt == NULL) {
12435 xmlSchemaVErr(vctxt, NULL,
12436 XML_SCHEMAV_INTERNAL,
12437 "Internal error: xmlSchemaCreatePCtxtOnVCtxt, "
12438 "failed to create a temp. parser context.\n",
William M. Brack2f2a6632004-08-20 23:09:47 +000012439 NULL, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012440 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012441 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012442 /* TODO: Pass user data. */
12443 xmlSchemaSetParserErrors(vctxt->pctxt, vctxt->error, vctxt->warning, NULL);
12444 }
12445 return (0);
12446}
12447
12448static int
12449xmlSchemaCreateVCtxtOnPCtxt(xmlSchemaParserCtxtPtr ctxt)
12450{
12451 if (ctxt->vctxt == NULL) {
12452 ctxt->vctxt = xmlSchemaNewValidCtxt(NULL);
12453 if (ctxt->vctxt == NULL) {
12454 xmlSchemaPErr(ctxt, NULL,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012455 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012456 "Internal error: xmlSchemaCreatePCtxtOnVCtxt, "
12457 "failed to create a temp. validation context.\n",
12458 NULL, NULL);
12459 return (-1);
12460 }
12461 /* TODO: Pass user data. */
12462 xmlSchemaSetValidErrors(ctxt->vctxt, ctxt->error, ctxt->warning, NULL);
12463 }
12464 return (0);
12465}
12466
12467/**
12468 * xmlSchemaCheckCOSValidDefault:
12469 * @ctxt: the schema parser context
12470 * @type: the simple type definition
12471 * @value: the default value
12472 * @node: an optional node (the holder of the value)
12473 *
12474 * Checks the "cos-valid-default" constraints.
12475 *
12476 * Returns 0 if the constraints are satisfied,
12477 * if not, a positive error code and -1 on internal
12478 * errors.
12479 */
12480static int
12481xmlSchemaCheckCOSValidDefault(xmlSchemaParserCtxtPtr pctxt,
12482 xmlSchemaValidCtxtPtr vctxt,
12483 xmlSchemaTypePtr type,
12484 const xmlChar *value,
12485 xmlNodePtr node)
12486{
12487 int ret = 0;
12488
12489 /*
12490 * cos-valid-default:
12491 * Schema Component Constraint: Element Default Valid (Immediate)
12492 * For a string to be a valid default with respect to a type
12493 * definition the appropriate case among the following must be true:
12494 */
12495 /*
12496 * NOTE: This has to work without a given node (the holder of the
12497 * value), since it should work on the component, i.e. an underlying
12498 * DOM must not be mandatory.
12499 */
12500 if ((pctxt == NULL) || (vctxt == NULL)) {
12501 xmlSchemaPErr(pctxt, node,
12502 XML_SCHEMAP_INTERNAL,
12503 "Internal error: xmlSchemaCheckCOSValidDefault, "
12504 "bad arguments: the parser and/or validation context is "
12505 "missing.\n",
12506 NULL, NULL);
12507 return (-1);
12508 }
12509 if IS_COMPLEX_TYPE(type) {
William M. Brack2f2a6632004-08-20 23:09:47 +000012510 /*
12511 * Complex type.
12512 *
12513 * 2.1 its {content type} must be a simple type definition or mixed.
12514 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012515 /*
12516 * TODO: Adjust this when the content type will be computed
12517 * correctly.
12518 */
12519 if ((type->contentType != XML_SCHEMA_CONTENT_SIMPLE) &&
12520 (type->contentType != XML_SCHEMA_CONTENT_BASIC) &&
12521 (type->contentType != XML_SCHEMA_CONTENT_MIXED)) {
12522 xmlSchemaPSimpleTypeErr(pctxt,
12523 XML_SCHEMAP_COS_VALID_DEFAULT_2_1,
12524 NULL, NULL, node,
12525 type, NULL, NULL,
12526 "If the type of a constraint value is complex, its content "
12527 "type must be mixed or a simple type",
12528 NULL, NULL);
12529 return(XML_SCHEMAP_COS_VALID_DEFAULT_2_1);
12530 }
12531 if (type->contentType == XML_SCHEMA_CONTENT_MIXED) {
William M. Brack2f2a6632004-08-20 23:09:47 +000012532 /*
12533 * 2.2.2 If the {content type} is mixed, then the {content type}'s
12534 * particle must be ·emptiable· as defined by Particle Emptiable
12535 * (§3.9.6).
12536 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012537
William M. Brack2f2a6632004-08-20 23:09:47 +000012538 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012539 * URGENT TODO: Implement this.
William M. Brack2f2a6632004-08-20 23:09:47 +000012540 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012541 return (0);
William M. Brack2f2a6632004-08-20 23:09:47 +000012542 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012543 }
12544 /*
12545 * 1 If the type definition is a simple type definition, then the string
12546 * must be ·valid· with respect to that definition as defined by String
12547 * Valid (§3.14.4).
12548 *
12549 * AND
12550 *
12551 * 2.2.1 If the {content type} is a simple type definition, then the
12552 * string must be ·valid· with respect to that simple type definition
12553 * as defined by String Valid (§3.14.4).
12554 */
12555 vctxt->node = node;
12556 vctxt->cur = NULL;
12557 ret = xmlSchemaValidateSimpleTypeValue(vctxt, type, value, 1, 1, 1, 0);
12558 /* ret = xmlSchemaCheckCVCSimpleType(vctxt, elemDecl->value, typeDef, 0); */
12559 if (ret < 0) {
12560 xmlSchemaPErr(pctxt, node,
12561 /* NOTNICE: error code: This function will be used during
12562 * schema construction and xsi:type validation.
12563 */
12564 XML_SCHEMAP_INTERNAL,
12565 "Internal error: xmlSchemaCheckCOSValidDefault, "
12566 "while validating a value constaint value.\n",
12567 NULL, NULL);
12568
12569 }
12570 return (ret);
William M. Brack2f2a6632004-08-20 23:09:47 +000012571}
12572
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012573#if 0 /* Not yet used code for CT schema validation */
William M. Brack2f2a6632004-08-20 23:09:47 +000012574/**
12575 * xmlSchemaGetSTContentOfCT:
12576 * @ctxt: the schema parser context
12577 * @type: the complex type definition
12578 *
12579 *
12580 * Returns the corresponding simple type for the content of
12581 * the complex type.
12582 */
12583static xmlSchemaTypePtr
12584xmlSchemaGetSTContentOfCT(xmlSchemaParserCtxtPtr ctxt,
12585 xmlSchemaTypePtr type)
12586{
12587 xmlSchemaTypePtr orig = type, anyType;
12588
12589 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
12590 while ((type != NULL) && (type != anyType) &&
12591 (type->type == XML_SCHEMA_TYPE_COMPLEX)) {
12592 if (type->type == XML_SCHEMA_TYPE_SIMPLE)
12593 return(type);
12594 type = type->baseType;
12595 }
12596 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012597 XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000012598 NULL, orig, NULL,
12599 "Internal error: xmlSchemaGetSTContentTypeOfCT, "
12600 "no simple type for the content of complex type '%s' could be "
12601 "computed", orig->name);
12602 return (NULL);
12603}
12604
12605
William M. Brack2f2a6632004-08-20 23:09:47 +000012606
William M. Brack2f2a6632004-08-20 23:09:47 +000012607
12608/**
12609 * xmlSchemaCheckCOSCTExtends:
12610 * @ctxt: the schema parser context
12611 * @type: the complex type definition
12612 *
12613 * Schema Component Constraint: Derivation Valid (Extension)
12614 *
12615 * Returns 0 if the constraints are satisfied, a positive
12616 * error code if not and -1 if an internal error occured.
12617 */
12618static int
12619xmlSchemaCheckCOSCTExtends(xmlSchemaParserCtxtPtr ctxt,
12620 xmlSchemaTypePtr type)
12621{
12622 xmlSchemaTypePtr base;
12623 /*
12624 * 1 If the {base type definition} is a complex type definition,
12625 * then all of the following must be true:
12626 */
12627 base = type->baseType;
12628 if (base == NULL) {
12629 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000012630 XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000012631 NULL, type, NULL,
12632 "Internal error: xmlSchemaCheckCOSCTExtends, "
12633 "the complex type '%s' has no base type", type->name);
12634 return (-1);
12635 }
12636 if (base->type == XML_SCHEMA_TYPE_COMPLEX) {
12637 /*
12638 * 1.1 The {final} of the {base type definition} must not
12639 * contain extension.
12640 */
12641 if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
12642 xmlSchemaPCustomErr(ctxt,
12643 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
12644 NULL, type, NULL,
12645 "The 'final' of the base type definition "
12646 "contains extension", NULL);
12647 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
12648 }
12649 /*
12650 * 1.2 Its {attribute uses} must be a subset of the {attribute uses}
12651 * of the complex type definition itself, that is, for every attribute
12652 * use in the {attribute uses} of the {base type definition}, there
12653 * must be an attribute use in the {attribute uses} of the complex
12654 * type definition itself whose {attribute declaration} has the same
12655 * {name}, {target namespace} and {type definition} as its attribute
12656 * declaration
12657 *
12658 * NOTE: This will be already satisfied by the way the attribute uses
12659 * are extended in xmlSchemaBuildAttributeValidation; thus this check
12660 * is not needed.
12661 */
12662
12663 /*
12664 * 1.3 If it has an {attribute wildcard}, the complex type definition
12665 * must also have one, and the base type definition's {attribute
12666 * wildcard}'s {namespace constraint} must be a subset of the complex
12667 * type definition's {attribute wildcard}'s {namespace constraint},
12668 * as defined by Wildcard Subset (§3.10.6).
12669 *
12670 * This is already checked in xmlSchemaBuildAttributeValidation; thus
12671 * this check is not needed.
12672 */
12673
12674 /*
12675 * 1.4 One of the following must be true:
12676 *
12677 * 1.4.1 The {content type} of the {base type definition} and the
12678 * {content type} of the complex type definition itself must be the same
12679 * simple type definition
12680 */
12681
12682
12683
12684 } else {
12685 /*
12686 * 2 If the {base type definition} is a simple type definition,
12687 * then all of the following must be true:
12688 */
12689 /*
12690 * 2.1 The {content type} must be the same simple type definition.
12691 */
12692 /*
12693 * 2.2 The {final} of the {base type definition} must not contain
12694 * extension
12695 */
12696 }
12697
12698}
12699
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012700static int
12701xmlSchemaCheckSRCCT(xmlSchemaParserCtxtPtr ctxt,
12702 xmlSchemaTypePtr type)
12703{
12704 xmlSchemaTypePtr base, content;
12705 int OK = 0;
12706
12707 /*
12708 * TODO: Adjust the error codes here, as I used
12709 * XML_SCHEMAP_SRC_CT_1 only yet.
12710 */
12711 /*
12712 * Schema Representation Constraint:
12713 * Complex Type Definition Representation OK
12714 */
12715 base = type->baseType;
12716 if (base == NULL) {
12717 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL, NULL, type, NULL,
12718 "Internal error: xmlSchemaCheckSRCCT, '%s', no base type",
12719 type->name);
12720 return (-1);
12721 }
12722
12723 if (type->subtypes != NULL) {
12724 if (type->subtypes->type == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
12725 if IS_COMPLEX_TYPE(base) {
12726 /*
12727 * 1 If the <complexContent> alternative is chosen, the type definition
12728 * ·resolved· to by the ·actual value· of the base [attribute]
12729 * must be a complex type definition;
12730 */
12731 xmlSchemaPCustomErr(ctxt,
12732 XML_SCHEMAP_SRC_CT_1,
12733 NULL, type, NULL,
12734 "The base type is not a complex type", NULL);
12735 return (XML_SCHEMAP_SRC_CT_1);
12736 }
12737 } else if (type->subtypes->type == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
12738
12739 if IS_SIMPLE_TYPE(base) {
12740 if (type->flags &
12741 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
12742 /*
12743 * 2.1.3 only if the <extension> alternative is also
12744 * chosen, a simple type definition.
12745 */
12746 /* TODO: Change error code to ..._SRC_CT_2_1_3. */
12747 xmlSchemaPCustomErr(ctxt,
12748 XML_SCHEMAP_SRC_CT_1,
12749 NULL, type, NULL,
12750 "A complex type (simple content) cannot restrict "
12751 "an other simple type",
12752 NULL);
12753 return (XML_SCHEMAP_SRC_CT_1);
12754 }
12755 OK = 1;
12756
12757 } else { /* if IS_SIMPLE_TYPE(base) */
12758 if (base->contentType = XML_SCHEMA_CONTENT_MIXED) {
12759 /*
12760 * 2.1.2 only if the <restriction> alternative is also
12761 * chosen, a complex type definition whose {content type}
12762 * is mixed and a particle emptyable.
12763 */
12764 /*
12765 * FIXME TODO: Check for *empiable particle* is missing.
12766 */
12767 if ((type->flags &
12768 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) == 0) {
12769 xmlSchemaPCustomErr(ctxt,
12770 XML_SCHEMAP_SRC_CT_1,
12771 NULL, type, NULL,
12772 "A complex type (simple content) cannot "
12773 "extend an other complex type which has a "
12774 "content type of: 'mixed' and emptiable particle",
12775 NULL);
12776 return (XML_SCHEMAP_SRC_CT_1);
12777 }
12778 /*
12779 * NOTE: This will be fired as well, if the base type
12780 * is *'anyType'*.
12781 * NOTE: type->subtypes->subtypes will be the
12782 * <restriction> item.
12783 */
12784 if (type->subtypes->subtypes == NULL) {
12785 /* Yes, this is paranoid programming. */
12786 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
12787 NULL, type, NULL,
12788 "Internal error: xmlSchemaCheckSRCCT, "
12789 "'%s', <simpleContent> has no <restriction>",
12790 type->name);
12791 return (-1);
12792 }
12793 /*
12794 * 2.2 If clause 2.1.2 above is satisfied, then there
12795 * must be a <simpleType> among the [children] of
12796 * <restriction>.
12797 */
12798 if (type->subtypes->subtypes->type !=
12799 XML_SCHEMA_TYPE_SIMPLE) {
12800 /* TODO: Change error code to ..._SRC_CT_2_2. */
12801 xmlSchemaPCustomErr(ctxt,
12802 XML_SCHEMAP_SRC_CT_1,
12803 NULL, type, NULL,
12804 "A <simpleType> is expected among the children "
12805 "of <restriction>", NULL);
12806 return (XML_SCHEMAP_SRC_CT_1);
12807 }
12808 OK = 1;
12809 } else { /* if (base->contentType = XML_SCHEMA_CONTENT_MIXED)*/
12810 /*
12811 * 2.1.1 a complex type definition whose {content type} is a
12812 * simple type definition;
12813 */
12814 if (base->contentType == XML_SCHEMA_CONTENT_ELEMENTS) {
12815 xmlSchemaPCustomErr(ctxt,
12816 XML_SCHEMAP_SRC_CT_1,
12817 NULL, type, NULL,
12818 "A complex type (simple content) cannot "
12819 "be derived from the complex type '%s'",
12820 base->name);
12821 return (XML_SCHEMAP_SRC_CT_1);
12822 }
12823 content = base->contentTypeDef;
12824 if (content == NULL) {
12825 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
12826 NULL, type, NULL,
12827 "Internal error: xmlSchemaCheckSRCCT, "
12828 "'%s', base type has no content type",
12829 type->name);
12830 return (-1);
12831 }
12832 if (content->type != XML_SCHEMA_TYPE_SIMPLE) {
12833 xmlSchemaPCustomErr(ctxt,
12834 XML_SCHEMAP_SRC_CT_1,
12835 NULL, type, NULL,
12836 "A complex type (simple content) cannot "
12837 "be derived from the complex type '%s'",
12838 base->name);
12839 return (XML_SCHEMAP_SRC_CT_1);
12840 }
12841 }
12842 }
12843 }
12844 }
12845 /*
12846 * TODO: 3 The corresponding complex type definition component must
12847 * satisfy the conditions set out in Constraints on Complex Type
12848 * Definition Schema Components (§3.4.6);
12849 *
12850 * TODO: 4 If clause 2.2.1 or clause 2.2.2 in the correspondence specification
12851 * above for {attribute wildcard} is satisfied, the intensional
12852 * intersection must be expressible, as defined in Attribute Wildcard
12853 * Intersection (§3.10.6).
12854 */
12855
12856}
William M. Brack2f2a6632004-08-20 23:09:47 +000012857#endif
12858
Daniel Veillard01fa6152004-06-29 17:04:39 +000012859/**
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000012860 * xmlSchemaGroupDefFixup:
12861 * @typeDecl: the schema model group definition
12862 * @ctxt: the schema parser context
12863 *
12864 * Fixes model group definitions.
12865 */
12866static void
12867xmlSchemaGroupDefFixup(xmlSchemaTypePtr group,
12868 xmlSchemaParserCtxtPtr ctxt,
12869 const xmlChar * name ATTRIBUTE_UNUSED)
12870{
12871 group->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
12872 if ((group->ref != NULL) && (group->subtypes == NULL)) {
12873 xmlSchemaTypePtr groupDef;
12874 /*
12875 * Resolve the reference.
12876 */
12877 groupDef = xmlSchemaGetGroup(ctxt->schema, group->ref,
12878 group->refNs);
12879 if (groupDef == NULL) {
12880 xmlSchemaPResCompAttrErr(ctxt,
12881 XML_SCHEMAP_SRC_RESOLVE,
12882 NULL, group, NULL,
12883 "ref", group->ref, group->refNs,
12884 XML_SCHEMA_TYPE_GROUP, NULL);
12885 return;
12886 }
12887 group->subtypes = groupDef;
12888 }
12889}
12890
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012891#if 0 /* Enable when the content type will be computed. */
12892static int
12893xmlSchemaComputeContentType(xmlSchemaParserCtxtPtr ctxt,
12894 xmlSchemaTypePtr type)
12895{
12896 xmlSchemaTypePtr base, res = NULL;
12897
12898 base = type->baseType;
12899 if (base == NULL) {
12900 xmlSchemaPCustomErr(ctxt,
12901 XML_SCHEMAP_INTERNAL,
12902 NULL, type, NULL,
12903 "Internal error: xmlSchemaGetContentType, "
12904 "the complex type '%s' has no base type", type->name);
12905 return (-1);
12906 }
12907 if (IS_ANYTYPE(base) || (type->subtypes->type ==
12908 XML_SCHEMA_TYPE_COMPLEX_CONTENT)) {
12909 xmlSchemaTypePtr start;
12910 /*
12911 * Effective 'mixed'.
12912 */
12913 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
12914 type->contentType = XML_SCHEMA_CONTENT_MIXED;
12915 /*
12916 * Effective content.
12917 */
12918 if (IS_ANYTYPE(base))
12919 start = type;
12920 else
12921 start = type->subtypes;
12922
12923 } else { /* if XML_SCHEMA_TYPE_COMPLEX_CONTENT */
12924 xmlSchemaTypePtr baseContentItem;
12925
12926 /*
12927 * Complex type with simple content.
12928 */
12929 if IS_COMPLEX_TYPE(base) {
12930 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
12931 /*
12932 * Summary: a complex type (simple content) can *restrict*
12933 * a complex type with the following content type:
12934 * 1. 'mixed' and an emptiable particle
12935 * 2. simple type
12936 */
12937 if (base->contentType == XML_SCHEMA_CONTENT_MIXED) {
12938 /*
12939 * 2 if the {content type} of the base type is mixed and a
12940 * particle which is ·emptiable·,
12941 * [...]
12942 * then starting from the simple type definition
12943 * corresponding to the <simpleType> among the [children]
12944 * of <restriction> (**which must be present**)
12945 *
12946 * FIXME TODO: Handle "emptiable particle".
12947 */
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): <simpleContent> has no "
12955 "<restriction>",
12956 type->name);
12957 return (-1);
12958 }
12959
12960 res->subtypes;
12961 if (res == NULL) {
12962 xmlSchemaPCustomErr(ctxt,
12963 XML_SCHEMAP_INTERNAL,
12964 NULL, type, NULL,
12965 "Internal error: xmlSchemaGetContentType, "
12966 "CT '%s' (restricting): <restriction> has no "
12967 "mandatory <simpleType>",
12968 type->name);
12969 return (-1);
12970 }
12971 } else {
12972 baseContentItem = base->contentTypeDef;
12973 if (baseContentItem == NULL) {
12974 xmlSchemaPCustomErr(ctxt,
12975 XML_SCHEMAP_INTERNAL,
12976 NULL, type, NULL,
12977 "Internal error: xmlSchemaGetContentType, "
12978 "CT '%s' (restricting), the base type has no "
12979 "content type", type->name);
12980 return (-1);
12981 }
12982 if IS_SIMPLE_TYPE(baseContentItem) {
12983 /*
12984 * 1 If the base type is a complex type whose own
12985 * {content type} is a simple type and the <restriction>
12986 * alternative is chosen
12987 */
12988 /* type->subtypes->subtypes will be the restriction item.*/
12989 res = type->subtypes->subtypes;
12990 if (res == NULL) {
12991 xmlSchemaPCustomErr(ctxt,
12992 XML_SCHEMAP_INTERNAL,
12993 NULL, type, NULL,
12994 "Internal error: xmlSchemaGetContentType, "
12995 "CT '%s' (restricting): <simpleType> has no "
12996 "<restriction>", type->name);
12997 return (-1);
12998 }
12999 /*
13000 * 1.1 the simple type definition corresponding to the
13001 * <simpleType> among the [children] of <restriction>if
13002 * there is one;
13003 */
13004 res = res->subtypes;
13005 if (res == NULL) {
13006 /*
13007 * 1.2 otherwise the {content type}
13008 * of the base type .
13009 */
13010 res = baseContentItem;
13011 }
13012 }
13013 }
13014 /*
13015 * SPECIAL TODO: If *restricting* the spec wants us to
13016 * create an *additional* simple type which restricts the
13017 * located simple type; we won't do this yet, and look how
13018 * far we get with it.
13019 */
13020 } else { /* if XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION */
13021 /*
13022 * Summary: a complex type (simple content) can *extend*
13023 * only a complex base with a simple type as content.
13024 */
13025 /*
13026 * 3 If the type definition ·resolved· to by the ·actual
13027 * value· of the base [attribute] is a complex type
13028 * definition (whose own {content type} *must be* a simple
13029 * type definition, see below) and the *<extension>*
13030 * alternative is chosen, then the {content type} of that
13031 * complex type definition;
13032 */
13033 res = base->contentTypeDef;
13034 if (res == NULL) {
13035 xmlSchemaPCustomErr(ctxt,
13036 XML_SCHEMAP_INTERNAL,
13037 NULL, type, NULL,
13038 "Internal error: xmlSchemaGetContentType, "
13039 "CT '%s' (extending), the base type has no content "
13040 "type", type->name);
13041 return (-1);
13042 }
13043 if (! IS_SIMPLE_TYPE(res)) {
13044 xmlSchemaPCustomErr(ctxt,
13045 XML_SCHEMAP_INTERNAL,
13046 NULL, type, NULL,
13047 "Internal error: xmlSchemaGetContentType, "
13048 "CT '%s' (extending), the content type of the "
13049 "base is not a simple type", type->name);
13050 return (-1);
13051 }
13052 }
13053 } else /* if IS_COMPLEX_TYPE(base) */
13054 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
13055 /*
13056 * 4 otherwise (the type definition ·resolved· to by the
13057 * ·actual value· of the base [attribute] is a simple type
13058 * definition and the <extension> alternative is chosen),
13059 * then that simple type definition.
13060 */
13061 res = base;
13062 }
13063 type->contentTypeDef = res;
13064 if (res == NULL) {
13065 xmlSchemaPCustomErr(ctxt,
13066 XML_SCHEMAP_INTERNAL,
13067 NULL, type, NULL,
13068 "Internal error: xmlSchemaGetContentType, "
13069 "'%s', the content type could not be determined",
13070 type->name);
13071 return (-1);
13072 }
13073
13074 }
13075
13076}
13077#endif
13078
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000013079/**
Daniel Veillard4255d502002-04-16 15:50:10 +000013080 * xmlSchemaTypeFixup:
13081 * @typeDecl: the schema type definition
13082 * @ctxt: the schema parser context
13083 *
13084 * Fixes the content model of the type.
13085 */
13086static void
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013087xmlSchemaTypeFixup(xmlSchemaTypePtr item,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013088 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +000013089{
Daniel Veillard01fa6152004-06-29 17:04:39 +000013090 xmlSchemaTypePtr ctxtType;
13091
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013092 if (item == NULL)
Daniel Veillard82bbbd42003-05-11 20:16:09 +000013093 return;
Daniel Veillard4e5d6652004-06-29 21:01:12 +000013094 /*
13095 * Do not allow the following types to be typefixed, prior to
13096 * the corresponding simple/complex types.
13097 */
13098 if (ctxt->ctxtType == NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013099 switch (item->type) {
Daniel Veillard4e5d6652004-06-29 21:01:12 +000013100 case XML_SCHEMA_TYPE_SIMPLE_CONTENT:
13101 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:
13102 case XML_SCHEMA_TYPE_UNION:
13103 case XML_SCHEMA_TYPE_RESTRICTION:
13104 case XML_SCHEMA_TYPE_EXTENSION:
13105 return;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000013106 default:
13107 break;
Daniel Veillard4e5d6652004-06-29 21:01:12 +000013108 }
13109 }
Daniel Veillard4255d502002-04-16 15:50:10 +000013110 if (name == NULL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013111 name = item->name;
13112 if (item->contentType == XML_SCHEMA_CONTENT_UNKNOWN) {
13113 switch (item->type) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013114 case XML_SCHEMA_TYPE_SIMPLE_CONTENT:{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013115 if (item->subtypes != NULL) {
13116 if (item->subtypes->contentType ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013117 XML_SCHEMA_CONTENT_UNKNOWN) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013118 xmlSchemaTypeFixup(item->subtypes, ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013119 NULL);
13120 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013121 item->contentType =
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013122 XML_SCHEMA_CONTENT_SIMPLE;
13123 /* item->subtypes->contentType; */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013124 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013125 break;
13126 }
13127 case XML_SCHEMA_TYPE_RESTRICTION:{
Daniel Veillard01fa6152004-06-29 17:04:39 +000013128 xmlSchemaTypePtr base = NULL;
13129
13130 ctxt->ctxtType->flags |=
13131 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013132 if (item->baseType != NULL)
13133 base = item->baseType;
13134 else if (item->base != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013135 base =
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013136 xmlSchemaGetType(ctxt->schema, item->base,
13137 item->baseNs);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013138 if (base == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013139 xmlSchemaPResCompAttrErr(ctxt,
13140 XML_SCHEMAP_SRC_RESOLVE,
William M. Brack2f2a6632004-08-20 23:09:47 +000013141 NULL, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013142 (xmlNodePtr) xmlSchemaGetPropNode(item->node, "base"),
13143 "base", item->base, item->baseNs,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013144 XML_SCHEMA_TYPE_BASIC, "type definition");
Daniel Veillard01fa6152004-06-29 17:04:39 +000013145 } else if (base->contentType ==
Daniel Veillard3646d642004-06-02 19:19:14 +000013146 XML_SCHEMA_CONTENT_UNKNOWN) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013147 xmlSchemaTypeFixup(base, ctxt, NULL);
13148 }
William M. Brack2f2a6632004-08-20 23:09:47 +000013149 }
13150 ctxt->ctxtType->baseType = base;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013151 if (ctxt->ctxtType->type == XML_SCHEMA_TYPE_COMPLEX) {
13152 /*
13153 * ComplexType restriction.
William M. Brack2f2a6632004-08-20 23:09:47 +000013154 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013155 /*
13156 * Content type.
13157 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013158 if (item->subtypes == NULL)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013159 /* 1.1.1 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013160 item->contentType = XML_SCHEMA_CONTENT_EMPTY;
13161 else if ((item->subtypes->subtypes == NULL) &&
13162 ((item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013163 XML_SCHEMA_TYPE_ALL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013164 || (item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013165 XML_SCHEMA_TYPE_SEQUENCE)))
13166 /* 1.1.2 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013167 item->contentType = XML_SCHEMA_CONTENT_EMPTY;
13168 else if ((item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013169 XML_SCHEMA_TYPE_CHOICE)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013170 && (item->subtypes->subtypes == NULL))
Daniel Veillard01fa6152004-06-29 17:04:39 +000013171 /* 1.1.3 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013172 item->contentType = XML_SCHEMA_CONTENT_EMPTY;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013173 else {
13174 /* 1.2 and 2.X are applied at the other layer */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013175 item->contentType =
Daniel Veillard01fa6152004-06-29 17:04:39 +000013176 XML_SCHEMA_CONTENT_ELEMENTS;
13177 }
13178 } else {
13179 /*
13180 * SimpleType restriction.
13181 */
William M. Brack2f2a6632004-08-20 23:09:47 +000013182 /* TODO: Nothing? */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013183 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013184 break;
13185 }
13186 case XML_SCHEMA_TYPE_EXTENSION:{
Daniel Veillard01fa6152004-06-29 17:04:39 +000013187 xmlSchemaTypePtr base = NULL;
13188 xmlSchemaContentType explicitContentType;
13189
13190 /*
13191 * An extension does exist on a complexType only.
13192 */
13193 ctxt->ctxtType->flags |=
13194 XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013195 if (item->recurse) {
Daniel Veillard3646d642004-06-02 19:19:14 +000013196 /* TODO: The word "recursive" should be changed to "circular" here. */
Daniel Veillardc0826a72004-08-10 14:17:33 +000013197 xmlSchemaPCustomErr(ctxt,
13198 XML_SCHEMAP_UNKNOWN_BASE_TYPE,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013199 NULL, item, item->node,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013200 "This item is circular", NULL);
Daniel Veillard2582a332004-04-18 19:49:46 +000013201 return;
13202 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013203 if (item->base != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013204 base =
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013205 xmlSchemaGetType(ctxt->schema, item->base,
13206 item->baseNs);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013207 if (base == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013208 xmlSchemaPResCompAttrErr(ctxt,
13209 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013210 NULL, item, item->node,
13211 "base", item->base, item->baseNs,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013212 XML_SCHEMA_TYPE_BASIC, "type definition");
Daniel Veillard01fa6152004-06-29 17:04:39 +000013213 } else if (base->contentType ==
13214 XML_SCHEMA_CONTENT_UNKNOWN) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013215 item->recurse = 1;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013216 xmlSchemaTypeFixup(base, ctxt, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013217 item->recurse = 0;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013218 }
13219 /*
13220 * The type definition ·resolved· to by the ·actual
13221 * value· of the base [attribute]
13222 */
13223 ctxt->ctxtType->baseType = base;
13224 /*
13225 * TODO: This one is still needed for computation of
13226 * the content model by xmlSchemaBuildAContentModel.
13227 * Try to get rid of it.
13228 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013229 item->baseType = base;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013230 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013231 if ((item->subtypes != NULL) &&
13232 (item->subtypes->contentType == XML_SCHEMA_CONTENT_UNKNOWN))
13233 xmlSchemaTypeFixup(item->subtypes, ctxt, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013234
13235 explicitContentType = XML_SCHEMA_CONTENT_ELEMENTS;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013236 if (item->subtypes == NULL)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013237 /* 1.1.1 */
13238 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013239 else if ((item->subtypes->subtypes == NULL) &&
13240 ((item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013241 XML_SCHEMA_TYPE_ALL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013242 || (item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013243 XML_SCHEMA_TYPE_SEQUENCE)))
13244 /* 1.1.2 */
13245 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013246 else if ((item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013247 XML_SCHEMA_TYPE_CHOICE)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013248 && (item->subtypes->subtypes == NULL))
Daniel Veillard01fa6152004-06-29 17:04:39 +000013249 /* 1.1.3 */
13250 explicitContentType = XML_SCHEMA_CONTENT_EMPTY;
13251 if (base != NULL) {
13252 /* It will be reported later, if the base is missing. */
13253 if (explicitContentType == XML_SCHEMA_CONTENT_EMPTY) {
13254 /* 2.1 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013255 item->contentType = base->contentType;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013256 } else if (base->contentType ==
13257 XML_SCHEMA_CONTENT_EMPTY) {
13258 /* 2.2 imbitable ! */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013259 item->contentType =
Daniel Veillard01fa6152004-06-29 17:04:39 +000013260 XML_SCHEMA_CONTENT_ELEMENTS;
13261 } else {
13262 /* 2.3 imbitable pareil ! */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013263 item->contentType =
Daniel Veillard01fa6152004-06-29 17:04:39 +000013264 XML_SCHEMA_CONTENT_ELEMENTS;
13265 }
13266 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013267 break;
13268 }
13269 case XML_SCHEMA_TYPE_COMPLEX:{
Daniel Veillard4e5d6652004-06-29 21:01:12 +000013270 ctxtType = ctxt->ctxtType;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013271 ctxt->ctxtType = item;
13272 /*
13273 * Start with an empty content-type type.
13274 */
13275 if (item->subtypes == NULL)
13276 item->contentType = XML_SCHEMA_CONTENT_EMPTY;
13277
13278 if ((item->subtypes == NULL) ||
13279 ((item->subtypes->type !=
Daniel Veillard01fa6152004-06-29 17:04:39 +000013280 XML_SCHEMA_TYPE_SIMPLE_CONTENT) &&
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013281 (item->subtypes->type !=
Daniel Veillard01fa6152004-06-29 17:04:39 +000013282 XML_SCHEMA_TYPE_COMPLEX_CONTENT))) {
13283 /*
13284 * This case is understood as shorthand for complex
13285 * content restricting the ur-type definition, and
13286 * the details of the mappings should be modified as
13287 * necessary.
13288 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013289 item->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
13290 item->flags |=
Daniel Veillard01fa6152004-06-29 17:04:39 +000013291 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013292 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013293 * Assume that we inherit the content-type type
13294 * from 'anyType', which is 'mixed' and a particle
13295 * emptiable.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013296 */
13297 item->contentType = item->baseType->contentType;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013298 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013299 /*
13300 * Fixup the sub components.
13301 */
13302 if ((item->subtypes != NULL) &&
13303 (item->subtypes->contentType ==
13304 XML_SCHEMA_CONTENT_UNKNOWN)) {
13305 xmlSchemaTypeFixup(item->subtypes, ctxt, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013306 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013307 if (item->flags & XML_SCHEMAS_TYPE_MIXED) {
13308 item->contentType = XML_SCHEMA_CONTENT_MIXED;
13309 } else if (item->subtypes != NULL) {
13310 /*
13311 * Use the content-type type of the model groups
13312 * defined, if 'mixed' is not set. If 'mixed' is set
13313 * it will expand the content-type by allowing character
13314 * content to appear.
13315 */
13316 item->contentType =
13317 item->subtypes->contentType;
13318 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000013319
13320 /*
13321 * Some optimization for validation:
13322 * If there are no facets beside the "whitespace" facet,
13323 * then a value needs not to checked against against a
13324 * facet, thus no computed value is needed.
13325 * TODO URGENT: This is just a workaround, we need to
13326 * introduce the correct usage of contentType to store the
13327 * facets in!
13328 */
13329 if (item->baseType->flags && XML_SCHEMAS_TYPE_FACETSNEEDVALUE)
13330 item->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
13331 else {
13332 xmlSchemaFacetLinkPtr cur;
13333
13334 for (cur = item->facetSet; cur != NULL;
13335 cur = cur->next) {
13336 if (cur->facet->type != XML_SCHEMA_FACET_WHITESPACE) {
13337 item->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
13338 break;
13339 }
13340 }
13341 }
13342
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013343 xmlSchemaBuildAttributeValidation(ctxt, item);
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +000013344 xmlSchemaCheckDefaults(item, ctxt, item->name);
Daniel Veillard4e5d6652004-06-29 21:01:12 +000013345 ctxt->ctxtType = ctxtType;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013346 break;
13347 }
13348 case XML_SCHEMA_TYPE_COMPLEX_CONTENT:{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013349 if (item->subtypes == NULL) {
13350 item->contentType = XML_SCHEMA_CONTENT_EMPTY;
13351 if (item->flags & XML_SCHEMAS_TYPE_MIXED)
13352 item->contentType =
Daniel Veillard1aefc862004-03-04 11:40:48 +000013353 XML_SCHEMA_CONTENT_MIXED;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013354 } else {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013355 if (item->flags & XML_SCHEMAS_TYPE_MIXED) {
13356 item->contentType =
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013357 XML_SCHEMA_CONTENT_MIXED;
Daniel Veillard3646d642004-06-02 19:19:14 +000013358 } else {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013359 xmlSchemaTypeFixup(item->subtypes, ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013360 NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013361 if (item->subtypes != NULL)
13362 item->contentType =
13363 item->subtypes->contentType;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013364 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013365 /*
13366 * Removed due to implementation of the build of attribute uses.
13367 */
13368 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013369 if (item->attributes == NULL)
13370 item->attributes =
13371 item->subtypes->attributes;
Daniel Veillard3646d642004-06-02 19:19:14 +000013372 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013373 }
13374 break;
13375 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013376 case XML_SCHEMA_TYPE_SIMPLE:
13377 /*
13378 * Simple Type Definition Schema Component
13379 *
13380 */
Daniel Veillard4e5d6652004-06-29 21:01:12 +000013381 ctxtType = ctxt->ctxtType;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013382 item->contentType = XML_SCHEMA_CONTENT_SIMPLE;
13383 if (item->subtypes->contentType ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013384 XML_SCHEMA_CONTENT_UNKNOWN) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013385 ctxt->ctxtType = item;
13386 xmlSchemaTypeFixup(item->subtypes, ctxt, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013387 }
13388 /* Fixup base type */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013389 if ((item->baseType != NULL) &&
13390 (item->baseType->contentType ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013391 XML_SCHEMA_CONTENT_UNKNOWN)) {
13392 /* OPTIMIZE: Actually this one will never by hit, since
13393 * the base type is already type-fixed in <restriction>.
13394 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013395 ctxt->ctxtType = item;
13396 xmlSchemaTypeFixup(item->baseType, ctxt, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013397 }
13398 /* Base type:
13399 * 2 If the <list> or <union> alternative is chosen,
13400 * then the ·simple ur-type definition·.
13401 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013402 if (item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013403 XML_SCHEMA_TYPE_LIST) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013404 item->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
13405 item->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
13406 } else if (item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013407 XML_SCHEMA_TYPE_UNION) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013408 item->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
13409 item->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
13410 } else if (item->subtypes->type ==
Daniel Veillard01fa6152004-06-29 17:04:39 +000013411 XML_SCHEMA_TYPE_RESTRICTION) {
13412 xmlSchemaFacetLinkPtr facet, cur, last = NULL;
13413
13414 /*
13415 * Variety
13416 * If the <restriction> alternative is chosen, then the
13417 * {variety} of the {base type definition}.
13418 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013419 if (item->baseType != NULL) {
13420 if (item->baseType->flags &
Daniel Veillard01fa6152004-06-29 17:04:39 +000013421 XML_SCHEMAS_TYPE_VARIETY_ATOMIC)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013422 item->flags |= XML_SCHEMAS_TYPE_VARIETY_ATOMIC;
13423 else if (item->baseType->flags &
Daniel Veillard01fa6152004-06-29 17:04:39 +000013424 XML_SCHEMAS_TYPE_VARIETY_LIST)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013425 item->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
13426 else if (item->baseType->flags &
Daniel Veillard01fa6152004-06-29 17:04:39 +000013427 XML_SCHEMAS_TYPE_VARIETY_UNION)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013428 item->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013429 /*
13430 * Schema Component Constraint: Simple Type Restriction
13431 * (Facets)
13432 * NOTE: Satisfaction of 1 and 2 arise from the fixup
13433 * applied beforehand.
13434 *
13435 * 3 The {facets} of R are the union of S and the {facets}
13436 * of B, eliminating duplicates. To eliminate duplicates,
13437 * when a facet of the same kind occurs in both S and the
13438 * {facets} of B, the one in the {facets} of B is not
13439 * included, with the exception of enumeration and pattern
13440 * facets, for which multiple occurrences with distinct values
13441 * are allowed.
13442 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013443 if (item->baseType->facetSet != NULL) {
13444 last = item->facetSet;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013445 if (last != NULL)
13446 while (last->next != NULL)
13447 last = last->next;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000013448 cur = item->baseType->facetSet;
13449 for (; cur != NULL; cur = cur->next) {
13450 /*
13451 * Base patterns won't be add here:
13452 * they are ORed in a type and
13453 * ANDed in derived types. This will
13454 * happed at validation level by
13455 * walking the base axis of the type.
13456 */
13457 if (cur->facet->type ==
13458 XML_SCHEMA_FACET_PATTERN)
13459 continue;
13460 facet = NULL;
13461 if ((item->facetSet != NULL) &&
13462 /* REMOVED: a check for
13463 * XML_SCHEMA_FACET_PATTERN was already
13464 * performed above.
13465
13466 * (cur->facet->type !=
13467 * XML_SCHEMA_FACET_PATTERN) &&
Daniel Veillard01fa6152004-06-29 17:04:39 +000013468 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000013469 (cur->facet->type !=
13470 XML_SCHEMA_FACET_ENUMERATION)) {
13471 facet = item->facetSet;
13472 do {
13473 if (cur->facet->type ==
13474 facet->facet->type)
13475 break;
13476 facet = facet->next;
13477 } while (facet != NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013478 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000013479 if (facet == NULL) {
13480 facet = (xmlSchemaFacetLinkPtr)
13481 xmlMalloc(sizeof(xmlSchemaFacetLink));
13482 if (facet == NULL) {
13483 xmlSchemaPErrMemory(ctxt,
13484 "fixing simpleType", NULL);
13485 return;
13486 }
13487 /*
13488 * The facets are not copied but referenced
13489 * via the facet link.
13490 */
13491 facet->facet = cur->facet;
13492 facet->next = NULL;
13493 if (last == NULL)
13494 item->facetSet = facet;
13495 else
13496 last->next = facet;
13497 last = facet;
13498 }
13499 }
13500 }
13501 /*
13502 * Some optimization for validation:
13503 * If there are no facets beside the "whitespace" facet,
13504 * then a value needs not to checked against against a
13505 * facet, thus no computed value is needed.
13506 */
13507 if (item->baseType->flags && XML_SCHEMAS_TYPE_FACETSNEEDVALUE)
13508 item->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
13509 else {
13510 for (cur = item->facetSet; cur != NULL;
13511 cur = cur->next) {
13512 if (cur->facet->type != XML_SCHEMA_FACET_WHITESPACE) {
13513 item->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
13514 break;
13515 }
13516 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013517 }
13518 }
13519 }
13520 /*
13521 * Check constraints.
13522 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013523 xmlSchemaCheckSRCSimpleType(ctxt, item);
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +000013524 xmlSchemaCheckDefaults(item, ctxt, item->name);
Daniel Veillard4e5d6652004-06-29 21:01:12 +000013525 ctxt->ctxtType = ctxtType;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013526 break;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000013527 case XML_SCHEMA_TYPE_SEQUENCE:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013528 case XML_SCHEMA_TYPE_ALL:
13529 case XML_SCHEMA_TYPE_CHOICE:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013530 item->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013531 break;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000013532 case XML_SCHEMA_TYPE_GROUP:
13533 /*
13534 * TODO: Handling was moved to xmlSchemaGroupDefFixup.
13535 */
13536 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013537 case XML_SCHEMA_TYPE_LIST:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013538 xmlSchemaParseListRefFixup(item, ctxt);
13539 item->contentType = XML_SCHEMA_CONTENT_SIMPLE;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013540 break;
13541 case XML_SCHEMA_TYPE_UNION:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013542 xmlSchemaParseUnionRefCheck(item, ctxt);
13543 item->contentType = XML_SCHEMA_CONTENT_SIMPLE;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013544 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013545 case XML_SCHEMA_TYPE_BASIC:
13546 case XML_SCHEMA_TYPE_ANY:
13547 case XML_SCHEMA_TYPE_FACET:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013548 case XML_SCHEMA_TYPE_UR:
13549 case XML_SCHEMA_TYPE_ELEMENT:
13550 case XML_SCHEMA_TYPE_ATTRIBUTE:
13551 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
William M. Brack29aa7722004-05-12 00:27:56 +000013552 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013553 case XML_SCHEMA_TYPE_NOTATION:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013554 case XML_SCHEMA_FACET_MININCLUSIVE:
13555 case XML_SCHEMA_FACET_MINEXCLUSIVE:
13556 case XML_SCHEMA_FACET_MAXINCLUSIVE:
13557 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
13558 case XML_SCHEMA_FACET_TOTALDIGITS:
13559 case XML_SCHEMA_FACET_FRACTIONDIGITS:
13560 case XML_SCHEMA_FACET_PATTERN:
13561 case XML_SCHEMA_FACET_ENUMERATION:
13562 case XML_SCHEMA_FACET_WHITESPACE:
13563 case XML_SCHEMA_FACET_LENGTH:
13564 case XML_SCHEMA_FACET_MAXLENGTH:
13565 case XML_SCHEMA_FACET_MINLENGTH:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013566 item->contentType = XML_SCHEMA_CONTENT_SIMPLE;
13567 if (item->subtypes != NULL)
13568 xmlSchemaTypeFixup(item->subtypes, ctxt, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013569 break;
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +000013570 case XML_SCHEMA_TYPE_IDC_UNIQUE:
13571 case XML_SCHEMA_TYPE_IDC_KEY:
13572 case XML_SCHEMA_TYPE_IDC_KEYREF:
13573 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013574 }
13575 }
Daniel Veillard8651f532002-04-17 09:06:27 +000013576#ifdef DEBUG_TYPE
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013577 if (item->node != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013578 xmlGenericError(xmlGenericErrorContext,
13579 "Type of %s : %s:%d :", name,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013580 item->node->doc->URL,
13581 xmlGetLineNo(item->node));
Daniel Veillarddecd64d2002-04-18 14:41:51 +000013582 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013583 xmlGenericError(xmlGenericErrorContext, "Type of %s :", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +000013584 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013585 switch (item->contentType) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013586 case XML_SCHEMA_CONTENT_SIMPLE:
13587 xmlGenericError(xmlGenericErrorContext, "simple\n");
13588 break;
13589 case XML_SCHEMA_CONTENT_ELEMENTS:
13590 xmlGenericError(xmlGenericErrorContext, "elements\n");
13591 break;
Daniel Veillard8651f532002-04-17 09:06:27 +000013592 case XML_SCHEMA_CONTENT_UNKNOWN:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013593 xmlGenericError(xmlGenericErrorContext, "unknown !!!\n");
13594 break;
Daniel Veillard8651f532002-04-17 09:06:27 +000013595 case XML_SCHEMA_CONTENT_EMPTY:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013596 xmlGenericError(xmlGenericErrorContext, "empty\n");
13597 break;
Daniel Veillard8651f532002-04-17 09:06:27 +000013598 case XML_SCHEMA_CONTENT_MIXED:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013599 xmlGenericError(xmlGenericErrorContext, "mixed\n");
13600 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013601 /* Removed, since not used. */
13602 /*
Daniel Veillard8651f532002-04-17 09:06:27 +000013603 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013604 xmlGenericError(xmlGenericErrorContext, "mixed or elems\n");
13605 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013606 */
Daniel Veillard8651f532002-04-17 09:06:27 +000013607 case XML_SCHEMA_CONTENT_BASIC:
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013608 xmlGenericError(xmlGenericErrorContext, "basic\n");
13609 break;
13610 default:
13611 xmlGenericError(xmlGenericErrorContext,
13612 "not registered !!!\n");
13613 break;
Daniel Veillard8651f532002-04-17 09:06:27 +000013614 }
13615#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000013616}
13617
13618/**
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000013619 * xmlSchemaCheckFacet:
13620 * @facet: the facet
13621 * @typeDecl: the schema type definition
13622 * @ctxt: the schema parser context or NULL
13623 * @name: name of the type
13624 *
13625 * Checks the default values types, especially for facets
13626 *
13627 * Returns 0 if okay or -1 in cae of error
13628 */
13629int
13630xmlSchemaCheckFacet(xmlSchemaFacetPtr facet,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013631 xmlSchemaTypePtr typeDecl,
13632 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000013633{
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +000013634 xmlSchemaTypePtr nonNegativeIntegerType = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013635 int ret = 0, reuseValCtxt = 0;
13636
Daniel Veillardce682bc2004-11-05 17:22:25 +000013637 if ((facet == NULL) || (typeDecl == NULL))
13638 return(-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013639 /*
13640 * TODO: will the parser context be given if used from
13641 * the relaxNG module?
13642 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000013643
13644 if (nonNegativeIntegerType == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013645 nonNegativeIntegerType =
Daniel Veillard01fa6152004-06-29 17:04:39 +000013646 xmlSchemaGetBuiltInType(XML_SCHEMAS_NNINTEGER);
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000013647 }
13648 switch (facet->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013649 case XML_SCHEMA_FACET_MININCLUSIVE:
13650 case XML_SCHEMA_FACET_MINEXCLUSIVE:
13651 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Daniel Veillardf4b05d02004-07-05 13:10:37 +000013652 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
13653 case XML_SCHEMA_FACET_ENUMERATION: {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013654 /*
13655 * Okay we need to validate the value
13656 * at that point.
13657 */
13658 xmlSchemaValidCtxtPtr vctxt;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013659 xmlSchemaTypePtr base;
Daniel Veillardf4b05d02004-07-05 13:10:37 +000013660
13661 /* 4.3.5.5 Constraints on enumeration Schema Components
13662 * Schema Component Constraint: enumeration valid restriction
13663 * It is an ·error· if any member of {value} is not in the
13664 * ·value space· of {base type definition}.
13665 *
13666 * minInclusive, maxInclusive, minExclusive, maxExclusive:
13667 * The value ·must· be in the
13668 * ·value space· of the ·base type·.
13669 */
13670 /*
13671 * This function is intended to deliver a compiled value
13672 * on the facet. In XML Schemas the type holding a facet,
13673 * cannot be a built-in type. Thus to ensure that other API
13674 * calls (relaxng) do work, if the given type is a built-in
13675 * type, we will assume that the given built-in type *is
13676 * already* the base type.
13677 */
13678 if (typeDecl->type != XML_SCHEMA_TYPE_BASIC) {
13679 base = typeDecl->baseType;
13680 if (base == NULL) {
13681 xmlSchemaPErr(ctxt, typeDecl->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013682 XML_SCHEMAP_INTERNAL,
Daniel Veillardf4b05d02004-07-05 13:10:37 +000013683 "Internal error: xmlSchemaCheckFacet, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000013684 "the type '%s' has no base type.\n",
Daniel Veillardf4b05d02004-07-05 13:10:37 +000013685 typeDecl->name, NULL);
13686 return (-1);
13687 }
13688 } else
13689 base = typeDecl;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013690 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013691 * This avoids perseverative creation of the
13692 * validation context if a parser context is
13693 * used.
Daniel Veillard01fa6152004-06-29 17:04:39 +000013694 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013695 if (ctxt != NULL) {
13696 reuseValCtxt = 1;
13697 if (ctxt->vctxt == NULL) {
13698 if (xmlSchemaCreateVCtxtOnPCtxt(ctxt) == -1)
13699 return (-1);
13700 }
13701 vctxt = ctxt->vctxt;
13702 } else {
13703 vctxt = xmlSchemaNewValidCtxt(NULL);
13704 if (vctxt == NULL) {
13705 xmlSchemaPErr(ctxt, typeDecl->node,
13706 XML_SCHEMAP_INTERNAL,
13707 "Internal error: xmlSchemaCheckFacet, "
13708 "creating a new validation context.\n",
13709 NULL, NULL);
13710 return (-1);
13711 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013712 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013713
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013714 vctxt->node = facet->node;
13715 vctxt->cur = NULL;
13716 /*
13717 * NOTE: This call does not check the content nodes,
13718 * since they are not available:
13719 * facet->node is just the node holding the facet
13720 * definition, *not* the attribute holding the *value*
13721 * of the facet.
13722 */
13723 ret = xmlSchemaValidateSimpleTypeValue(vctxt, base,
13724 facet->value, 0, 1, 1, 0);
Daniel Veillardf4b05d02004-07-05 13:10:37 +000013725 facet->val = vctxt->value;
13726 vctxt->value = NULL;
13727 if (ret > 0) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013728 /* error code */
13729 if (ctxt != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013730 xmlSchemaPErrExt(ctxt, facet->node,
13731 XML_SCHEMAP_INVALID_FACET,
13732 NULL, NULL, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013733 "Type definition '%s': The value '%s' of the "
13734 "facet '%s' is not valid.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000013735 name, facet->value,
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000013736 BAD_CAST xmlSchemaFacetTypeToString(facet->type),
Daniel Veillard01fa6152004-06-29 17:04:39 +000013737 NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013738 }
13739 ret = -1;
Daniel Veillardf4b05d02004-07-05 13:10:37 +000013740 } else if (ret < 0) {
13741 xmlSchemaPErrExt(ctxt, facet->node,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000013742 XML_SCHEMAP_INTERNAL,
Daniel Veillardf4b05d02004-07-05 13:10:37 +000013743 NULL, NULL, NULL,
13744 "Internal error: xmlSchemaCheckFacet, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000013745 "failed to validate the value '%s' name of the "
13746 "facet '%s' against the base type '%s'.\n",
Daniel Veillardf4b05d02004-07-05 13:10:37 +000013747 facet->value,
13748 BAD_CAST xmlSchemaFacetTypeToString(facet->type),
13749 base->name, NULL, NULL);
13750 ret = -1;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013751 }
13752 if (reuseValCtxt == 0)
13753 xmlSchemaFreeValidCtxt(vctxt);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013754 break;
13755 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013756 case XML_SCHEMA_FACET_PATTERN:
13757 facet->regexp = xmlRegexpCompile(facet->value);
13758 if (facet->regexp == NULL) {
13759 xmlSchemaPErr(ctxt, typeDecl->node,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013760 XML_SCHEMAP_REGEXP_INVALID,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013761 "Type definition '%s': The value '%s' of the "
13762 "facet 'pattern' is not valid.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000013763 name, facet->value);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013764 ret = -1;
13765 }
13766 break;
13767 case XML_SCHEMA_FACET_TOTALDIGITS:
13768 case XML_SCHEMA_FACET_FRACTIONDIGITS:
13769 case XML_SCHEMA_FACET_LENGTH:
13770 case XML_SCHEMA_FACET_MAXLENGTH:
13771 case XML_SCHEMA_FACET_MINLENGTH:{
13772 int tmp;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000013773
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013774 tmp =
13775 xmlSchemaValidatePredefinedType(nonNegativeIntegerType,
13776 facet->value,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +000013777 &(facet->val));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013778 if (tmp != 0) {
13779 /* error code */
13780 if (ctxt != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013781 xmlSchemaPErrExt(ctxt, facet->node,
13782 XML_SCHEMAP_INVALID_FACET_VALUE,
13783 NULL, NULL, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013784 "Type definition '%s': The value '%s' of the "
13785 "facet '%s' is not valid.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000013786 name, facet->value,
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000013787 BAD_CAST xmlSchemaFacetTypeToString(facet->type),
Daniel Veillard01fa6152004-06-29 17:04:39 +000013788 NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013789 }
13790 ret = -1;
13791 }
13792 break;
13793 }
13794 case XML_SCHEMA_FACET_WHITESPACE:{
13795 if (xmlStrEqual(facet->value, BAD_CAST "preserve")) {
13796 facet->whitespace = XML_SCHEMAS_FACET_PRESERVE;
13797 } else if (xmlStrEqual(facet->value, BAD_CAST "replace")) {
13798 facet->whitespace = XML_SCHEMAS_FACET_REPLACE;
13799 } else if (xmlStrEqual(facet->value, BAD_CAST "collapse")) {
13800 facet->whitespace = XML_SCHEMAS_FACET_COLLAPSE;
13801 } else {
13802 if (ctxt != NULL) {
13803 xmlSchemaPErr(ctxt, facet->node,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013804 XML_SCHEMAP_INVALID_WHITE_SPACE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013805 "Type definition '%s': The value '%s' of the "
13806 "facet 'whiteSpace' is not valid.\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000013807 name, facet->value);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013808 }
13809 ret = -1;
13810 }
13811 }
13812 default:
13813 break;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000013814 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013815 return (ret);
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000013816}
13817
13818/**
Daniel Veillard4255d502002-04-16 15:50:10 +000013819 * xmlSchemaCheckDefaults:
13820 * @typeDecl: the schema type definition
13821 * @ctxt: the schema parser context
13822 *
13823 * Checks the default values types, especially for facets
13824 */
13825static void
13826xmlSchemaCheckDefaults(xmlSchemaTypePtr typeDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000013827 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +000013828{
Daniel Veillard4255d502002-04-16 15:50:10 +000013829 if (name == NULL)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013830 name = typeDecl->name;
13831 /*
13832 * NOTE: It is intended to use the facets list, instead
13833 * of facetSet.
13834 */
13835 if (typeDecl->facets != NULL) {
13836 xmlSchemaFacetPtr facet = typeDecl->facets;
13837
13838 while (facet != NULL) {
13839 xmlSchemaCheckFacet(facet, typeDecl, ctxt, name);
13840 facet = facet->next;
13841 }
13842 }
Daniel Veillard4255d502002-04-16 15:50:10 +000013843}
13844
13845/**
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000013846 * xmlSchemaGetCircModelGrDefRef:
13847 * @ctxtGr: the searched model group
13848 * @list: the list of model groups to be processed
13849 *
13850 * This one is intended to be used by
13851 * xmlSchemaCheckGroupDefCircular only.
13852 *
13853 * Returns the circular model group definition reference, otherwise NULL.
13854 */
13855static xmlSchemaTypePtr
13856xmlSchemaGetCircModelGrDefRef(xmlSchemaTypePtr ctxtGrDef,
13857 xmlSchemaTypePtr gr)
13858{
13859 xmlSchemaTypePtr circ = NULL;
13860 int marked;
13861 /*
13862 * We will search for an model group reference which
13863 * references the context model group definition.
13864 */
13865 while (gr != NULL) {
13866 if (((gr->type == XML_SCHEMA_TYPE_GROUP) ||
13867 (gr->type == XML_SCHEMA_TYPE_ALL) ||
13868 (gr->type == XML_SCHEMA_TYPE_SEQUENCE) ||
13869 (gr->type == XML_SCHEMA_TYPE_CHOICE)) &&
13870 (gr->subtypes != NULL)) {
13871 marked = 0;
13872 if ((gr->type == XML_SCHEMA_TYPE_GROUP) &&
13873 (gr->ref != NULL)) {
13874 if (gr->subtypes == ctxtGrDef)
13875 return (gr);
13876 else if (gr->subtypes->flags &
13877 XML_SCHEMAS_TYPE_MARKED) {
13878 gr = gr->next;
13879 continue;
13880 } else {
13881 /*
13882 * Mark to avoid infinite recursion on
13883 * circular references not yet examined.
13884 */
13885 gr->subtypes->flags |= XML_SCHEMAS_TYPE_MARKED;
13886 marked = 1;
13887 }
13888 if (gr->subtypes->subtypes != NULL)
13889 circ = xmlSchemaGetCircModelGrDefRef(ctxtGrDef,
13890 gr->subtypes->subtypes);
13891 /*
13892 * Unmark the visited model group definition.
13893 */
13894 if (marked)
13895 gr->subtypes->flags ^= XML_SCHEMAS_TYPE_MARKED;
13896 if (circ != NULL)
13897 return (circ);
13898 } else {
13899 circ = xmlSchemaGetCircModelGrDefRef(ctxtGrDef,
13900 (xmlSchemaTypePtr) gr->subtypes);
13901 if (circ != NULL)
13902 return (circ);
13903 }
13904
13905 }
13906 gr = gr->next;
13907 }
13908 return (NULL);
13909}
13910
13911/**
13912 * xmlSchemaCheckGroupDefCircular:
13913 * attrGr: the model group definition
13914 * @ctxt: the parser context
13915 * @name: the name
13916 *
13917 * Checks for circular references to model group definitions.
13918 */
13919static void
13920xmlSchemaCheckGroupDefCircular(xmlSchemaTypePtr modelGrDef,
13921 xmlSchemaParserCtxtPtr ctxt,
13922 const xmlChar * name ATTRIBUTE_UNUSED)
13923{
13924 /*
13925 * Schema Component Constraint: Model Group Correct
13926 * 2 Circular groups are disallowed. That is, within the {particles}
13927 * of a group there must not be at any depth a particle whose {term}
13928 * is the group itself.
13929 */
13930 /*
13931 * NOTE: "gr->subtypes" holds the referenced group.
13932 */
13933 if ((modelGrDef->type != XML_SCHEMA_TYPE_GROUP) ||
13934 ((modelGrDef->flags & XML_SCHEMAS_TYPE_GLOBAL) == 0) ||
13935 (modelGrDef->subtypes == NULL))
13936 return;
13937 else {
13938 xmlSchemaTypePtr circ;
13939
13940 circ = xmlSchemaGetCircModelGrDefRef(modelGrDef, modelGrDef->subtypes);
13941 if (circ != NULL) {
13942 /*
13943 * TODO: Report the referenced attr group as QName.
13944 */
13945 xmlSchemaPCustomErr(ctxt,
13946 XML_SCHEMAP_MG_PROPS_CORRECT_2,
13947 NULL, NULL, circ->node,
13948 "Circular reference to the model group definition '%s' "
13949 "defined", modelGrDef->name);
13950 /*
13951 * NOTE: We will cut the reference to avoid further
13952 * confusion of the processor.
13953 * TODO: SPEC: Does the spec define how to process here?
13954 */
13955 circ->subtypes = NULL;
13956 }
13957 }
13958}
13959
13960
13961/**
13962 * xmlSchemaGetCircAttrGrRef:
13963 * @ctxtGr: the searched attribute group
13964 * @attr: the current attribute list to be processed
13965 *
13966 * This one is intended to be used by
13967 * xmlSchemaCheckSRCAttributeGroupCircular only.
13968 *
13969 * Returns the circular attribute grou reference, otherwise NULL.
13970 */
13971static xmlSchemaAttributeGroupPtr
13972xmlSchemaGetCircAttrGrRef(xmlSchemaAttributeGroupPtr ctxtGr,
13973 xmlSchemaAttributePtr attr)
13974{
13975 xmlSchemaAttributeGroupPtr circ = NULL, gr;
13976 int marked;
13977 /*
13978 * We will search for an attribute group reference which
13979 * references the context attribute group.
13980 */
13981 while (attr != NULL) {
13982 marked = 0;
13983 if (attr->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
13984 gr = (xmlSchemaAttributeGroupPtr) attr;
13985 if (gr->refItem != NULL) {
13986 if (gr->refItem == ctxtGr)
13987 return (gr);
13988 else if (gr->refItem->flags &
13989 XML_SCHEMAS_ATTRGROUP_MARKED) {
13990 attr = attr->next;
13991 continue;
13992 } else {
13993 /*
13994 * Mark as visited to avoid infinite recursion on
13995 * circular references not yet examined.
13996 */
13997 gr->refItem->flags |= XML_SCHEMAS_ATTRGROUP_MARKED;
13998 marked = 1;
13999 }
14000 }
14001 if (gr->attributes != NULL)
14002 circ = xmlSchemaGetCircAttrGrRef(ctxtGr, gr->attributes);
14003 /*
14004 * Unmark the visited group's attributes.
14005 */
14006 if (marked)
14007 gr->refItem->flags ^= XML_SCHEMAS_ATTRGROUP_MARKED;
14008 if (circ != NULL)
14009 return (circ);
14010 }
14011 attr = attr->next;
14012 }
14013 return (NULL);
14014}
14015
14016/**
14017 * xmlSchemaCheckSRCAttributeGroupCircular:
14018 * attrGr: the attribute group definition
14019 * @ctxt: the parser context
14020 * @name: the name
14021 *
14022 * Checks for circular references of attribute groups.
14023 */
14024static void
14025xmlSchemaCheckAttributeGroupCircular(xmlSchemaAttributeGroupPtr attrGr,
14026 xmlSchemaParserCtxtPtr ctxt,
14027 const xmlChar * name ATTRIBUTE_UNUSED)
14028{
14029 /*
14030 * Schema Representation Constraint:
14031 * Attribute Group Definition Representation OK
14032 * 3 Circular group reference is disallowed outside <redefine>.
14033 * That is, unless this element information item's parent is
14034 * <redefine>, then among the [children], if any, there must
14035 * not be an <attributeGroup> with ref [attribute] which resolves
14036 * to the component corresponding to this <attributeGroup>. Indirect
14037 * circularity is also ruled out. That is, when QName resolution
14038 * (Schema Document) (§3.15.3) is applied to a ·QName· arising from
14039 * any <attributeGroup>s with a ref [attribute] among the [children],
14040 * it must not be the case that a ·QName· is encountered at any depth
14041 * which resolves to the component corresponding to this <attributeGroup>.
14042 */
14043 /*
14044 * Only global components can be referenced.
14045 */
14046 if (((attrGr->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL) == 0) ||
14047 (attrGr->attributes == NULL))
14048 return;
14049 else {
14050 xmlSchemaAttributeGroupPtr circ;
14051
14052 circ = xmlSchemaGetCircAttrGrRef(attrGr, attrGr->attributes);
14053 if (circ != NULL) {
14054 /*
14055 * TODO: Report the referenced attr group as QName.
14056 */
14057 xmlSchemaPCustomErr(ctxt,
14058 XML_SCHEMAP_SRC_ATTRIBUTE_GROUP_3,
14059 NULL, NULL, circ->node,
14060 "Circular reference to the attribute group '%s' "
14061 "defined", attrGr->name);
14062 /*
14063 * NOTE: We will cut the reference to avoid further
14064 * confusion of the processor.
14065 * BADSPEC: The spec should define how to process in this case.
14066 */
14067 circ->attributes = NULL;
14068 circ->refItem = NULL;
14069 }
14070 }
14071}
14072
14073/**
Daniel Veillard13e04c62002-04-23 17:51:29 +000014074 * xmlSchemaAttrGrpFixup:
14075 * @attrgrpDecl: the schema attribute definition
14076 * @ctxt: the schema parser context
14077 * @name: the attribute name
14078 *
14079 * Fixes finish doing the computations on the attributes definitions
14080 */
14081static void
Daniel Veillard3646d642004-06-02 19:19:14 +000014082xmlSchemaAttrGrpFixup(xmlSchemaAttributeGroupPtr attrgrp,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014083 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard13e04c62002-04-23 17:51:29 +000014084{
14085 if (name == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000014086 name = attrgrp->name;
14087 if (attrgrp->attributes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014088 return;
Daniel Veillard3646d642004-06-02 19:19:14 +000014089 if (attrgrp->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014090 xmlSchemaAttributeGroupPtr ref;
Daniel Veillard13e04c62002-04-23 17:51:29 +000014091
Daniel Veillardc0826a72004-08-10 14:17:33 +000014092 ref = xmlSchemaGetAttributeGroup(ctxt->schema, attrgrp->ref,
14093 attrgrp->refNs);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014094 if (ref == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000014095 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014096 XML_SCHEMAP_SRC_RESOLVE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014097 NULL, (xmlSchemaTypePtr) attrgrp, attrgrp->node,
14098 "ref", attrgrp->ref, attrgrp->refNs,
14099 XML_SCHEMA_TYPE_ATTRIBUTEGROUP, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014100 return;
14101 }
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000014102 attrgrp->refItem = ref;
14103 /*
14104 * Check for self reference!
14105 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014106 xmlSchemaAttrGrpFixup(ref, ctxt, NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +000014107 attrgrp->attributes = ref->attributes;
14108 attrgrp->attributeWildcard = ref->attributeWildcard;
14109 }
Daniel Veillard13e04c62002-04-23 17:51:29 +000014110}
14111
14112/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014113 * xmlSchemaAttrCheckValConstr:
14114 * @item: an schema attribute declaration/use
14115 * @ctxt: a schema parser context
14116 * @name: the name of the attribute
14117 *
14118 * Validates the value constraints of an attribute declaration/use.
Daniel Veillard4255d502002-04-16 15:50:10 +000014119 *
14120 * Fixes finish doing the computations on the attributes definitions
14121 */
14122static void
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014123xmlSchemaCheckAttrValConstr(xmlSchemaAttributePtr item,
14124 xmlSchemaParserCtxtPtr ctxt,
14125 const xmlChar * name ATTRIBUTE_UNUSED)
14126{
14127
14128 /*
14129 * a-props-correct
14130 * Schema Component Constraint: Attribute Declaration Properties Correct
14131 *
14132 * 2 if there is a {value constraint}, the canonical lexical
14133 * representation of its value must be ·valid· with respect
14134 * to the {type definition} as defined in String Valid (§3.14.4).
14135 */
14136
14137 if (item->defValue != NULL) {
14138 int ret;
14139 xmlNodePtr node;
14140 xmlSchemaTypePtr type;
14141
14142 if (item->subtypes == NULL) {
14143 xmlSchemaPErr(ctxt, item->node,
14144 XML_SCHEMAP_INTERNAL,
14145 "Internal error: xmlSchemaCheckAttrValConstr, "
14146 "type is missing... skipping validation of "
14147 "value constraint", NULL, NULL);
14148 return;
14149 }
14150
14151 /*
14152 * TODO: Try to avoid creating a new context.
14153 * TODO: This all is not very performant.
14154 */
14155 type = item->subtypes;
14156 /*
14157 * Ensure there's validation context.
14158 */
14159 if (ctxt->vctxt == NULL) {
14160 if (xmlSchemaCreateVCtxtOnPCtxt(ctxt) == -1) {
14161 xmlSchemaPErr(ctxt, item->node,
14162 XML_SCHEMAP_INTERNAL,
14163 "Internal error: xmlSchemaCheckAttrValConstr, "
14164 "creating a new validation context.\n",
14165 NULL, NULL);
14166 return;
14167 }
14168 }
14169
14170 if (item->flags & XML_SCHEMAS_ATTR_FIXED)
14171 node = (xmlNodePtr) xmlHasProp(item->node, BAD_CAST "fixed");
14172 else
14173 node = (xmlNodePtr) xmlHasProp(item->node, BAD_CAST "default");
14174 ctxt->vctxt->node = node;
14175 ctxt->vctxt->cur = NULL;
14176 /*
14177 * NOTE: This call does not check the content nodes,
14178 * since they are not available:
14179 * facet->node is just the node holding the facet
14180 * definition, *not* the attribute holding the *value*
14181 * of the facet.
14182 */
14183 ret = xmlSchemaValidateSimpleTypeValue(ctxt->vctxt, type,
14184 item->defValue, 0, 1, 1, 0);
14185 if (ret == 0) {
14186 /*
14187 * Store the computed value.
14188 */
14189 item->defVal = ctxt->vctxt->value;
14190 ctxt->vctxt->value = NULL;
14191 } else if (ret > 0) {
14192 if (ctxt != NULL) {
14193 xmlSchemaPSimpleTypeErr(ctxt,
14194 XML_SCHEMAP_A_PROPS_CORRECT_2,
14195 NULL, NULL, node,
14196 type, NULL, item->defValue,
14197 NULL, NULL, NULL);
14198 }
14199 } else if (ret < 0) {
14200 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
14201 NULL, NULL, node,
14202 "Internal error: xmlSchemaAttrCheckValConstr, "
14203 "failed to validate the value constraint of the "
14204 "attribute decl/use against the type '%s'",
14205 type->name);
14206 }
14207 }
14208}
14209
14210#if 0 /* Not used yet. */
14211static int
14212xmlSchemaCheckElemPropsCorrect(xmlSchemaParserCtxtPtr ctxt,
14213 xmlSchemaElementPtr edecl)
14214{
14215 /*
14216 * TODO: 1 The values of the properties of an element declaration must be as
14217 * described in the property tableau in The Element Declaration Schema
14218 * Component (§3.3.1), modulo the impact of Missing Sub-components (§5.3).
14219 */
14220 /*
14221 * 2 If there is a {value constraint}, the canonical lexical
14222 * representation of its value must be ·valid· with respect to the {type
14223 * definition} as defined in Element Default Valid (Immediate) (§3.3.6).
14224 *
14225 * NOTE: This is done in xmlSchemaCheckElemValConstr.
14226 */
14227 /*
14228 * 3 If there is a non-·absent· {substitution group affiliation},
14229 * then {scope} must be global.
14230 *
14231 * NOTE: This is done in xmlSchemaParseElement.
14232 * TODO: Move it to this layer here.
14233 */
14234 /*
14235 * TODO: 4 If there is a {substitution group affiliation}, the {type definition}
14236 * of the element declaration must be validly derived from the {type
14237 * definition} of the {substitution group affiliation}, given the value
14238 * of the {substitution group exclusions} of the {substitution group
14239 * affiliation}, as defined in Type Derivation OK (Complex) (§3.4.6)
14240 * (if the {type definition} is complex) or as defined in
14241 * Type Derivation OK (Simple) (§3.14.6) (if the {type definition} is
14242 * simple).
14243 */
14244 /*
14245 * TODO: 5 If the {type definition} or {type definition}'s {content type}
14246 * is or is derived from ID then there must not be a {value constraint}.
14247 * Note: The use of ID as a type definition for elements goes beyond
14248 * XML 1.0, and should be avoided if backwards compatibility is desired
14249 */
14250 /*
14251 * TODO: 6 Circular substitution groups are disallowed. That is, it must not
14252 * be possible to return to an element declaration by repeatedly following
14253 * the {substitution group affiliation} property.
14254 */
14255}
14256#endif
14257
14258/**
14259 * xmlSchemaCheckElemValConstr:
14260 * @item: an schema element declaration/particle
14261 * @ctxt: a schema parser context
14262 * @name: the name of the attribute
14263 *
14264 * Validates the value constraints of an element declaration.
14265 *
14266 * Fixes finish doing the computations on the element declarations.
14267 */
14268static void
14269xmlSchemaCheckElemValConstr(xmlSchemaElementPtr decl,
14270 xmlSchemaParserCtxtPtr ctxt,
14271 const xmlChar * name ATTRIBUTE_UNUSED)
14272{
14273 if (decl->value != NULL) {
14274 int ret;
14275 xmlNodePtr node = NULL;
14276 xmlSchemaTypePtr type;
14277
14278 /*
14279 * 2 If there is a {value constraint}, the canonical lexical
14280 * representation of its value must be ·valid· with respect to the {type
14281 * definition} as defined in Element Default Valid (Immediate) (§3.3.6).
14282 */
14283 if (decl->subtypes == NULL) {
14284 xmlSchemaPErr(ctxt, decl->node,
14285 XML_SCHEMAP_INTERNAL,
14286 "Internal error: xmlSchemaCheckElemValConstr, "
14287 "type is missing... skipping validation of "
14288 "the value constraint", NULL, NULL);
14289 return;
14290 }
14291 /*
14292 * Ensure there's a validation context.
14293 */
14294 if (xmlSchemaCreateVCtxtOnPCtxt(ctxt) == -1)
14295 return;
14296
14297 type = decl->subtypes;
14298
14299 if (decl->node != NULL) {
14300 if (decl->flags & XML_SCHEMAS_ELEM_FIXED)
14301 node = (xmlNodePtr) xmlHasProp(decl->node, BAD_CAST "fixed");
14302 else
14303 node = (xmlNodePtr) xmlHasProp(decl->node, BAD_CAST "default");
14304 }
14305 ctxt->vctxt->node = node;
14306 ctxt->vctxt->cur = NULL;
14307 ret = xmlSchemaCheckCOSValidDefault(ctxt, ctxt->vctxt, type, decl->value,
14308 node);
14309 if (ret == 0) {
14310 /*
14311 * Consume the computed value.
14312 */
14313 decl->defVal = ctxt->vctxt->value;
14314 ctxt->vctxt->value = NULL;
14315 } else if (ret < 0) {
14316 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
14317 NULL, NULL, node,
14318 "Internal error: xmlSchemaElemCheckValConstr, "
14319 "failed to validate the value constraint of the "
14320 "element declaration '%s'",
14321 decl->name);
14322 }
14323 }
14324}
14325
14326/**
14327 * xmlSchemaAttrFixup:
14328 * @item: an schema attribute declaration/use.
14329 * @ctxt: a schema parser context
14330 * @name: the name of the attribute
14331 *
14332 * Fixes finish doing the computations on attribute declarations/uses.
14333 */
14334static void
14335xmlSchemaAttrFixup(xmlSchemaAttributePtr item,
14336 xmlSchemaParserCtxtPtr ctxt,
14337 const xmlChar * name ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +000014338{
Daniel Veillardc0826a72004-08-10 14:17:33 +000014339 /*
14340 * TODO: If including this is done twice (!) for every attribute.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014341 * -> Hmm, check if this is still done.
Daniel Veillardc0826a72004-08-10 14:17:33 +000014342 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000014343 /*
14344 * The simple type definition corresponding to the <simpleType> element
14345 * information item in the [children], if present, otherwise the simple
14346 * type definition ·resolved· to by the ·actual value· of the type
14347 * [attribute], if present, otherwise the ·simple ur-type definition·.
14348 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014349 if (item->flags & XML_SCHEMAS_ATTR_INTERNAL_RESOLVED)
Daniel Veillardc0826a72004-08-10 14:17:33 +000014350 return;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014351 item->flags |= XML_SCHEMAS_ATTR_INTERNAL_RESOLVED;
14352 if (item->subtypes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014353 return;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014354 if (item->typeName != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014355 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000014356
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014357 type = xmlSchemaGetType(ctxt->schema, item->typeName,
14358 item->typeNs);
14359 if ((type == NULL) || (! IS_SIMPLE_TYPE(type))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000014360 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014361 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014362 NULL, (xmlSchemaTypePtr) item, item->node,
14363 "type", item->typeName, item->typeNs,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014364 XML_SCHEMA_TYPE_SIMPLE, NULL);
14365 } else
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014366 item->subtypes = type;
14367
14368 } else if (item->ref != NULL) {
14369 xmlSchemaAttributePtr decl;
Daniel Veillard4255d502002-04-16 15:50:10 +000014370
Daniel Veillardc0826a72004-08-10 14:17:33 +000014371 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014372 * We have an attribute use here; assign the referenced
14373 * attribute declaration.
14374 */
14375 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000014376 * TODO: Evaluate, what errors could occur if the declaration is not
14377 * found. It might be possible that the "typefixup" might crash if
14378 * no ref declaration was found.
14379 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014380 decl = xmlSchemaGetAttribute(ctxt->schema, item->ref, item->refNs);
14381 if (decl == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000014382 xmlSchemaPResCompAttrErr(ctxt,
14383 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014384 NULL, (xmlSchemaTypePtr) item, item->node,
14385 "ref", item->ref, item->refNs,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014386 XML_SCHEMA_TYPE_ATTRIBUTE, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014387 return;
14388 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014389 item->refDecl = decl;
14390 xmlSchemaAttrFixup(decl, ctxt, NULL);
14391
14392 item->subtypes = decl->subtypes;
14393 /*
14394 * Attribute Use Correct
14395 * au-props-correct.2: If the {attribute declaration} has a fixed
14396 * {value constraint}, then if the attribute use itself has a
14397 * {value constraint}, it must also be fixed and its value must match
14398 * that of the {attribute declaration}'s {value constraint}.
14399 */
14400 if ((decl->flags & XML_SCHEMAS_ATTR_FIXED) &&
14401 (item->defValue != NULL)) {
14402 if (((item->flags & XML_SCHEMAS_ATTR_FIXED) == 0) ||
14403 (!xmlStrEqual(item->defValue, decl->defValue))) {
14404 xmlSchemaPCustomErr(ctxt,
14405 XML_SCHEMAP_AU_PROPS_CORRECT_2,
14406 NULL, NULL, item->node,
14407 "The value constraint must be fixed "
14408 "and match the referenced attribute "
14409 "declarations's value constraint '%s'",
14410 decl->defValue);
14411 }
14412 /*
14413 * FUTURE: One should change the values of the attr. use
14414 * if ever validation should be attempted even if the
14415 * schema itself was not fully valid.
14416 */
14417 }
Daniel Veillard3646d642004-06-02 19:19:14 +000014418 } else {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014419 item->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
14420 }
Daniel Veillard4255d502002-04-16 15:50:10 +000014421}
14422
14423/**
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000014424 * xmlSchemaResolveIDCKeyRef:
14425 * @idc: the identity-constraint definition
14426 * @ctxt: the schema parser context
14427 * @name: the attribute name
14428 *
14429 * Resolve keyRef references to key/unique IDCs.
14430 */
14431static void
14432xmlSchemaResolveIDCKeyRef(xmlSchemaIDCPtr idc,
14433 xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +000014434 const xmlChar * name ATTRIBUTE_UNUSED)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000014435{
14436 if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF)
14437 return;
14438 if (idc->ref->name != NULL) {
14439 idc->ref->item = (xmlSchemaBasicItemPtr) xmlHashLookup2(
14440 ctxt->schema->idcDef,
14441 idc->ref->name,
14442 idc->ref->targetNamespace);
14443 if (idc->ref->item == NULL) {
14444 /*
14445 * TODO: It is actually not an error to fail to resolve.
14446 */
14447 xmlSchemaPResCompAttrErr(ctxt,
14448 XML_SCHEMAP_SRC_RESOLVE,
14449 NULL, (xmlSchemaTypePtr) idc, idc->node,
14450 "refer", idc->ref->name,
14451 idc->ref->targetNamespace,
14452 XML_SCHEMA_TYPE_IDC_KEYREF, NULL);
14453 return;
14454 }
14455 }
14456}
14457
14458/**
Daniel Veillard4255d502002-04-16 15:50:10 +000014459 * xmlSchemaParse:
14460 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +000014461 *
Daniel Veillard01c13b52002-12-10 15:19:08 +000014462 * parse a schema definition resource and build an internal
Daniel Veillard4255d502002-04-16 15:50:10 +000014463 * XML Shema struture which can be used to validate instances.
14464 * *WARNING* this interface is highly subject to change
14465 *
14466 * Returns the internal XML Schema structure built from the resource or
14467 * NULL in case of error
14468 */
14469xmlSchemaPtr
14470xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt)
14471{
14472 xmlSchemaPtr ret = NULL;
14473 xmlDocPtr doc;
Daniel Veillardbd2904b2003-11-25 15:38:59 +000014474 xmlNodePtr root;
Daniel Veillarddda22c12004-01-24 08:31:30 +000014475 int preserve = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000014476
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014477 /*
14478 * This one is used if the schema to be parsed was specified via
14479 * the API; i.e. not automatically by the validated instance document.
14480 */
14481
Daniel Veillard4255d502002-04-16 15:50:10 +000014482 xmlSchemaInitTypes();
14483
Daniel Veillard6045c902002-10-09 21:13:59 +000014484 if (ctxt == NULL)
Daniel Veillard4255d502002-04-16 15:50:10 +000014485 return (NULL);
14486
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000014487 ctxt->nberrors = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000014488 ctxt->counter = 0;
14489 ctxt->container = NULL;
14490
14491 /*
14492 * First step is to parse the input document into an DOM/Infoset
14493 */
Daniel Veillard6045c902002-10-09 21:13:59 +000014494 if (ctxt->URL != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +000014495 doc = xmlReadFile((const char *) ctxt->URL, NULL,
14496 SCHEMAS_PARSE_OPTIONS);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014497 if (doc == NULL) {
14498 xmlSchemaPErr(ctxt, NULL,
14499 XML_SCHEMAP_FAILED_LOAD,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014500 "xmlSchemaParse: could not load '%s'.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014501 ctxt->URL, NULL);
14502 return (NULL);
14503 }
Daniel Veillard6045c902002-10-09 21:13:59 +000014504 } else if (ctxt->buffer != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +000014505 doc = xmlReadMemory(ctxt->buffer, ctxt->size, NULL, NULL,
14506 SCHEMAS_PARSE_OPTIONS);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014507 if (doc == NULL) {
14508 xmlSchemaPErr(ctxt, NULL,
14509 XML_SCHEMAP_FAILED_PARSE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014510 "xmlSchemaParse: could not parse.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014511 NULL, NULL);
14512 return (NULL);
14513 }
14514 doc->URL = xmlStrdup(BAD_CAST "in_memory_buffer");
Daniel Veillard65765282004-01-08 16:59:30 +000014515 ctxt->URL = xmlDictLookup(ctxt->dict, BAD_CAST "in_memory_buffer", -1);
Daniel Veillard9d751502003-10-29 13:21:47 +000014516 } else if (ctxt->doc != NULL) {
14517 doc = ctxt->doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +000014518 preserve = 1;
Daniel Veillard6045c902002-10-09 21:13:59 +000014519 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014520 xmlSchemaPErr(ctxt, NULL,
14521 XML_SCHEMAP_NOTHING_TO_PARSE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014522 "xmlSchemaParse: could not parse.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014523 NULL, NULL);
14524 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000014525 }
14526
14527 /*
14528 * Then extract the root and Schema parse it
14529 */
14530 root = xmlDocGetRootElement(doc);
14531 if (root == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014532 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
14533 XML_SCHEMAP_NOROOT,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014534 "The schema has no document element.\n", NULL, NULL);
Daniel Veillarddda22c12004-01-24 08:31:30 +000014535 if (!preserve) {
14536 xmlFreeDoc(doc);
14537 }
Daniel Veillard4255d502002-04-16 15:50:10 +000014538 return (NULL);
14539 }
14540
14541 /*
14542 * Remove all the blank text nodes
14543 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +000014544 xmlSchemaCleanupDoc(ctxt, root);
Daniel Veillard4255d502002-04-16 15:50:10 +000014545
14546 /*
14547 * Then do the parsing for good
14548 */
14549 ret = xmlSchemaParseSchema(ctxt, root);
Daniel Veillard1d913862003-11-21 00:28:39 +000014550 if (ret == NULL) {
Daniel Veillarddda22c12004-01-24 08:31:30 +000014551 if (!preserve) {
14552 xmlFreeDoc(doc);
14553 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014554 return (NULL);
Daniel Veillard1d913862003-11-21 00:28:39 +000014555 }
Daniel Veillard4255d502002-04-16 15:50:10 +000014556 ret->doc = doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +000014557 ret->preserve = preserve;
Daniel Veillard4255d502002-04-16 15:50:10 +000014558 ctxt->schema = ret;
Daniel Veillardc0826a72004-08-10 14:17:33 +000014559 ctxt->ctxtType = NULL;
14560 ctxt->parentItem = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000014561 /*
Daniel Veillardf2a12832003-11-24 13:04:35 +000014562 * Then fixup all attributes declarations
14563 */
14564 xmlHashScan(ret->attrDecl, (xmlHashScanner) xmlSchemaAttrFixup, ctxt);
14565
14566 /*
14567 * Then fixup all attributes group declarations
14568 */
14569 xmlHashScan(ret->attrgrpDecl, (xmlHashScanner) xmlSchemaAttrGrpFixup,
14570 ctxt);
14571
14572 /*
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000014573 * Resolve identity-constraint keyRefs.
14574 */
14575 xmlHashScan(ret->idcDef, (xmlHashScanner) xmlSchemaResolveIDCKeyRef, ctxt);
14576
14577 /*
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000014578 * Check attribute groups for circular references.
14579 */
14580 xmlHashScan(ret->attrgrpDecl, (xmlHashScanner)
14581 xmlSchemaCheckAttributeGroupCircular, ctxt);
14582
14583 /*
14584 * Then fixup all model group definitions.
14585 */
14586 xmlHashScan(ret->groupDecl, (xmlHashScanner) xmlSchemaGroupDefFixup, ctxt);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014587
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000014588 /*
Daniel Veillard4255d502002-04-16 15:50:10 +000014589 * Then fixup all types properties
Daniel Veillardc0826a72004-08-10 14:17:33 +000014590 */
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000014591 xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaTypeFixup, ctxt);
Daniel Veillardc0826a72004-08-10 14:17:33 +000014592
14593 /*
14594 * Then fix references of element declaration; apply constraints.
14595 */
14596 xmlHashScanFull(ret->elemDecl,
14597 (xmlHashScannerFull) xmlSchemaRefFixupCallback, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +000014598
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000014599 /*
14600 * Check model groups defnitions for circular references.
14601 */
14602 xmlHashScan(ret->groupDecl, (xmlHashScanner)
14603 xmlSchemaCheckGroupDefCircular, ctxt);
14604
Daniel Veillard4255d502002-04-16 15:50:10 +000014605 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014606 * Then build the content model for all complex types
Daniel Veillard4255d502002-04-16 15:50:10 +000014607 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014608 xmlHashScan(ret->typeDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014609 (xmlHashScanner) xmlSchemaBuildContentModel, ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +000014610
14611 /*
14612 * Then check the defaults part of the type like facets values
14613 */
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +000014614 /* OLD: xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaCheckDefaults, ctxt); */
Daniel Veillard4255d502002-04-16 15:50:10 +000014615
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014616 /*
14617 * Validate the value constraint of attribute declarations/uses.
14618 */
14619 xmlHashScan(ret->attrDecl, (xmlHashScanner) xmlSchemaCheckAttrValConstr, ctxt);
14620
14621 /*
14622 * Validate the value constraint of element declarations.
14623 */
14624 xmlHashScan(ret->elemDecl, (xmlHashScanner) xmlSchemaCheckElemValConstr, ctxt);
14625
Daniel Veillardc0826a72004-08-10 14:17:33 +000014626
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000014627 if (ctxt->nberrors != 0) {
14628 xmlSchemaFree(ret);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014629 ret = NULL;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000014630 }
Daniel Veillard4255d502002-04-16 15:50:10 +000014631 return (ret);
14632}
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014633
Daniel Veillard4255d502002-04-16 15:50:10 +000014634/**
Daniel Veillard01c13b52002-12-10 15:19:08 +000014635 * xmlSchemaSetParserErrors:
Daniel Veillard4255d502002-04-16 15:50:10 +000014636 * @ctxt: a schema validation context
Daniel Veillard01c13b52002-12-10 15:19:08 +000014637 * @err: the error callback
14638 * @warn: the warning callback
14639 * @ctx: contextual data for the callbacks
Daniel Veillard4255d502002-04-16 15:50:10 +000014640 *
Daniel Veillard01c13b52002-12-10 15:19:08 +000014641 * Set the callback functions used to handle errors for a validation context
Daniel Veillard4255d502002-04-16 15:50:10 +000014642 */
14643void
14644xmlSchemaSetParserErrors(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014645 xmlSchemaValidityErrorFunc err,
14646 xmlSchemaValidityWarningFunc warn, void *ctx)
14647{
Daniel Veillard4255d502002-04-16 15:50:10 +000014648 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014649 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000014650 ctxt->error = err;
14651 ctxt->warning = warn;
14652 ctxt->userData = ctx;
14653}
14654
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000014655/**
Daniel Veillard259f0df2004-08-18 09:13:18 +000014656 * xmlSchemaGetParserErrors:
14657 * @ctxt: a XMl-Schema parser context
14658 * @err: the error callback result
14659 * @warn: the warning callback result
14660 * @ctx: contextual data for the callbacks result
14661 *
14662 * Get the callback information used to handle errors for a parser context
14663 *
14664 * Returns -1 in case of failure, 0 otherwise
14665 */
14666int
14667xmlSchemaGetParserErrors(xmlSchemaParserCtxtPtr ctxt,
14668 xmlSchemaValidityErrorFunc * err,
14669 xmlSchemaValidityWarningFunc * warn, void **ctx)
14670{
14671 if (ctxt == NULL)
14672 return(-1);
14673 if (err != NULL)
14674 *err = ctxt->error;
14675 if (warn != NULL)
14676 *warn = ctxt->warning;
14677 if (ctx != NULL)
14678 *ctx = ctxt->userData;
14679 return(0);
14680}
14681
14682/**
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000014683 * xmlSchemaFacetTypeToString:
14684 * @type: the facet type
14685 *
14686 * Convert the xmlSchemaTypeType to a char string.
14687 *
14688 * Returns the char string representation of the facet type if the
14689 * type is a facet and an "Internal Error" string otherwise.
14690 */
14691static const char *
14692xmlSchemaFacetTypeToString(xmlSchemaTypeType type)
14693{
14694 switch (type) {
14695 case XML_SCHEMA_FACET_PATTERN:
14696 return ("pattern");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014697 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000014698 return ("maxExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014699 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000014700 return ("maxInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014701 case XML_SCHEMA_FACET_MINEXCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000014702 return ("minExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014703 case XML_SCHEMA_FACET_MININCLUSIVE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000014704 return ("minInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014705 case XML_SCHEMA_FACET_WHITESPACE:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000014706 return ("whiteSpace");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014707 case XML_SCHEMA_FACET_ENUMERATION:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000014708 return ("enumeration");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014709 case XML_SCHEMA_FACET_LENGTH:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000014710 return ("length");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014711 case XML_SCHEMA_FACET_MAXLENGTH:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000014712 return ("maxLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014713 case XML_SCHEMA_FACET_MINLENGTH:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000014714 return ("minLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014715 case XML_SCHEMA_FACET_TOTALDIGITS:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000014716 return ("totalDigits");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014717 case XML_SCHEMA_FACET_FRACTIONDIGITS:
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000014718 return ("fractionDigits");
14719 default:
14720 break;
14721 }
14722 return ("Internal Error");
14723}
14724
Daniel Veillardc0826a72004-08-10 14:17:33 +000014725
Daniel Veillardc0826a72004-08-10 14:17:33 +000014726
14727static int
14728xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type)
14729{
14730 xmlSchemaTypePtr anc;
14731
14732 /*
14733 * The normalization type can be changed only for types which are derived
14734 * from xsd:string.
14735 */
14736 if (type->type == XML_SCHEMA_TYPE_BASIC) {
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +000014737 if (type->builtInType == XML_SCHEMAS_STRING)
Daniel Veillardc0826a72004-08-10 14:17:33 +000014738 return(XML_SCHEMAS_VAL_WTSP_PRESERVE);
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +000014739 else if (type->builtInType == XML_SCHEMAS_NORMSTRING)
14740 return(XML_SCHEMAS_VAL_WTSP_REPLACE);
Daniel Veillardc0826a72004-08-10 14:17:33 +000014741 else {
14742 /*
14743 * For all ·atomic· datatypes other than string (and types ·derived·
14744 * by ·restriction· from it) the value of whiteSpace is fixed to
14745 * collapse
14746 */
14747 return(XML_SCHEMAS_VAL_WTSP_COLLAPSE);
14748 }
14749 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
14750 /*
14751 * For list types the facet "whiteSpace" is fixed to "collapse".
14752 */
14753 return (XML_SCHEMAS_VAL_WTSP_COLLAPSE);
14754 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
14755 return (-1);
14756 } else if (type->facetSet != NULL) {
14757 xmlSchemaTypePtr anyST;
14758 xmlSchemaFacetLinkPtr lin;
14759
14760 /*
14761 * Atomic types.
14762 */
14763 anyST = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
14764 anc = type->baseType;
14765 do {
14766 /*
14767 * For all ·atomic· datatypes other than string (and types ·derived·
14768 * by ·restriction· from it) the value of whiteSpace is fixed to
14769 * collapse
14770 */
14771 if ((anc->type == XML_SCHEMA_TYPE_BASIC) &&
14772 (anc->builtInType == XML_SCHEMAS_STRING)) {
14773
14774 lin = type->facetSet;
14775 do {
14776 if (lin->facet->type == XML_SCHEMA_FACET_WHITESPACE) {
14777 if (lin->facet->whitespace ==
14778 XML_SCHEMAS_FACET_COLLAPSE) {
14779 return(XML_SCHEMAS_VAL_WTSP_COLLAPSE);
14780 } else if (lin->facet->whitespace ==
14781 XML_SCHEMAS_FACET_REPLACE) {
14782 return(XML_SCHEMAS_VAL_WTSP_REPLACE);
14783 } else
14784 return(XML_SCHEMAS_VAL_WTSP_PRESERVE);
14785 break;
14786 }
14787 lin = lin->next;
14788 } while (lin != NULL);
14789 break;
14790 }
14791 anc = anc->baseType;
14792 } while (anc != anyST);
14793 return (XML_SCHEMAS_VAL_WTSP_COLLAPSE);
14794 }
14795 return (-1);
14796}
14797
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000014798/**
Daniel Veillard377e1a92004-04-16 16:30:05 +000014799 * xmlSchemaValidateFacetsInternal:
14800 * @ctxt: a schema validation context
Daniel Veillardc0826a72004-08-10 14:17:33 +000014801 * @type: the type holding the facets
Daniel Veillard377e1a92004-04-16 16:30:05 +000014802 * @facets: the list of facets to check
14803 * @value: the lexical repr of the value to validate
14804 * @val: the precomputed value
William M. Bracke7091952004-05-11 15:09:58 +000014805 * @fireErrors: if 0, only internal errors will be fired;
14806 * otherwise all errors will be fired.
Daniel Veillard377e1a92004-04-16 16:30:05 +000014807 *
14808 * Check a value against all facet conditions
14809 *
14810 * Returns 0 if the element is schemas valid, a positive error code
14811 * number otherwise and -1 in case of internal or API error.
14812 */
14813static int
14814xmlSchemaValidateFacetsInternal(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014815 xmlSchemaTypePtr type,
14816 const xmlChar * value,
14817 unsigned long length,
14818 int fireErrors)
Daniel Veillard377e1a92004-04-16 16:30:05 +000014819{
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000014820 int ret = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014821 xmlNodePtr node;
Daniel Veillardc0826a72004-08-10 14:17:33 +000014822 xmlSchemaTypePtr biType; /* The build-in type. */
14823 xmlSchemaTypePtr tmpType;
14824 xmlSchemaFacetLinkPtr facetLink;
Daniel Veillardc7e3cc42004-09-28 12:33:52 +000014825 int retFacet;
Daniel Veillardc0826a72004-08-10 14:17:33 +000014826 xmlSchemaFacetPtr facet;
14827 unsigned long len = 0;
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000014828
Daniel Veillardc0826a72004-08-10 14:17:33 +000014829#ifdef DEBUG_UNION_VALIDATION
14830 printf("Facets of type: '%s'\n", (const char *) type->name);
14831 printf(" fireErrors: %d\n", fireErrors);
14832#endif
14833
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014834 node = ctxt->node;
Daniel Veillardc0826a72004-08-10 14:17:33 +000014835 /*
14836 * NOTE: Do not jump away, if the facetSet of the given type is
14837 * empty: until now, "pattern" facets of the *base types* need to
14838 * be checked as well.
14839 */
14840 biType = type->baseType;
14841 while ((biType != NULL) && (biType->type != XML_SCHEMA_TYPE_BASIC))
14842 biType = biType->baseType;
14843 if (biType == NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014844 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014845 "Internal error: xmlSchemaValidateFacetsInternal, "
14846 "the base type axis of the given type '%s' does not resolve to "
14847 "a built-in type.\n",
14848 type->name, NULL);
14849 return (-1);
14850 }
14851
14852 if (type->facetSet != NULL) {
14853 facetLink = type->facetSet;
14854 while (facetLink != NULL) {
14855 facet = facetLink->facet;
14856 /*
14857 * Skip the pattern "whiteSpace": it is used to
14858 * format the character content beforehand.
14859 */
14860 switch (facet->type) {
14861 case XML_SCHEMA_FACET_WHITESPACE:
14862 case XML_SCHEMA_FACET_PATTERN:
14863 case XML_SCHEMA_FACET_ENUMERATION:
14864 break;
14865 case XML_SCHEMA_FACET_LENGTH:
14866 case XML_SCHEMA_FACET_MINLENGTH:
14867 case XML_SCHEMA_FACET_MAXLENGTH:
14868 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
14869 ret = xmlSchemaValidateListSimpleTypeFacet(facet,
14870 value, length, 0);
14871 len = length;
14872 } else
14873 ret = xmlSchemaValidateLengthFacet(biType, facet,
14874 value, ctxt->value, &len);
14875 break;
14876 default:
14877 ret = xmlSchemaValidateFacet(biType, facet, value,
14878 ctxt->value);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014879 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000014880 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014881 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014882 "Internal error: xmlSchemaValidateFacetsInternal, "
14883 "validating facet of type '%s'.\n",
14884 type->name, NULL);
14885 break;
14886 } else if ((ret > 0) && (fireErrors)) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014887 xmlSchemaVFacetErr(ctxt, ret, node, value, len,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014888 type, facet, NULL, NULL, NULL, NULL);
14889 }
14890
14891 facetLink = facetLink->next;
14892 }
14893 if (ret >= 0) {
14894 /*
14895 * Process enumerations.
14896 */
14897 retFacet = 0;
14898 facetLink = type->facetSet;
14899 while (facetLink != NULL) {
14900 if (facetLink->facet->type == XML_SCHEMA_FACET_ENUMERATION) {
14901 retFacet = xmlSchemaValidateFacet(biType, facetLink->facet,
14902 value, ctxt->value);
14903 if (retFacet <= 0)
14904 break;
14905 }
14906 facetLink = facetLink->next;
14907 }
14908 if (retFacet > 0) {
14909 ret = XML_SCHEMAV_CVC_ENUMERATION_VALID;
14910 if (fireErrors)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014911 xmlSchemaVFacetErr(ctxt, ret, node,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014912 value, 0, type, NULL, NULL, NULL, NULL, NULL);
14913 } else if (retFacet < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014914 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014915 "Internal error: xmlSchemaValidateFacetsInternal, "
14916 "validating facet of type '%s'.\n",
14917 BAD_CAST "enumeration", NULL);
14918 ret = -1;
14919 }
14920 }
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000014921 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000014922 if (ret >= 0) {
14923 /*
14924 * Process patters. Pattern facets are ORed at type level
14925 * and ANDed if derived. Walk the base type axis.
14926 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000014927 tmpType = type;
14928 facet = NULL;
14929 do {
14930 retFacet = 0;
14931 for (facetLink = tmpType->facetSet; facetLink != NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014932 facetLink = facetLink->next) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000014933 if (facetLink->facet->type != XML_SCHEMA_FACET_PATTERN)
14934 continue;
14935 retFacet = xmlSchemaValidateFacet(biType, facetLink->facet,
14936 value, ctxt->value);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014937 if (retFacet == 0)
Daniel Veillardc0826a72004-08-10 14:17:33 +000014938 break;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014939 else if (retFacet < 0) {
14940 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
14941 "Internal error: xmlSchemaValidateFacetsInternal, "
14942 "validating 'pattern' facet '%s' of type '%s'.\n",
14943 facetLink->facet->value, tmpType->name);
14944 ret = -1;
14945 break;
14946 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +000014947 /* Save the last non-validating facet. */
14948 facet = facetLink->facet;
14949 }
14950 if (retFacet != 0)
14951 break;
14952 tmpType = tmpType->baseType;
14953 } while ((tmpType != NULL) && (tmpType->type != XML_SCHEMA_TYPE_BASIC));
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014954 if (retFacet > 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000014955 ret = XML_SCHEMAV_CVC_PATTERN_VALID;
14956 if (fireErrors) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014957 xmlSchemaVFacetErr(ctxt, ret, node, value, 0, type, facet,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014958 NULL, NULL, NULL, NULL);
14959 }
14960 }
14961 }
14962
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000014963 return (ret);
14964}
14965
Daniel Veillard4255d502002-04-16 15:50:10 +000014966/************************************************************************
14967 * *
14968 * Simple type validation *
14969 * *
14970 ************************************************************************/
Daniel Veillard377e1a92004-04-16 16:30:05 +000014971
Daniel Veillard4255d502002-04-16 15:50:10 +000014972
14973/************************************************************************
14974 * *
14975 * DOM Validation code *
14976 * *
14977 ************************************************************************/
14978
Daniel Veillard4255d502002-04-16 15:50:10 +000014979static int xmlSchemaValidateAttributes(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000014980 xmlNodePtr elem,
Daniel Veillard3646d642004-06-02 19:19:14 +000014981 xmlSchemaTypePtr type);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000014982static int xmlSchemaValidateElementByType(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014983 xmlSchemaTypePtr type,
14984 int valSimpleContent);
Daniel Veillard4255d502002-04-16 15:50:10 +000014985
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000014986static void xmlSchemaBeginElement(xmlSchemaValidCtxtPtr vctxt);
14987static void xmlSchemaEndElement(xmlSchemaValidCtxtPtr vctxt);
14988
14989#ifdef ELEM_INFO_ENABLED
14990/**
14991 * xmlSchemaGetFreshElemInfo:
14992 * @vctxt: the schema validation context
14993 *
14994 * Creates/reuses and initializes the element info item for
14995 * the currect tree depth.
14996 *
14997 * Returns the element info item or NULL on API or internal errors.
14998 */
14999static xmlSchemaElemInfoPtr
15000xmlSchemaGetFreshElemInfo(xmlSchemaValidCtxtPtr vctxt)
15001{
15002 xmlSchemaElemInfoPtr info = NULL;
15003
15004 if (vctxt->depth > vctxt->sizeElemInfos) {
15005 xmlSchemaVErr(vctxt, NULL, XML_SCHEMAV_INTERNAL,
15006 "Internal error: xmlSchemaPushDepthInfo, "
15007 "an inconsistent depth encountered.\n",
15008 NULL, NULL);
15009 return (NULL);
15010 }
15011 if (vctxt->elemInfos == NULL) {
15012 vctxt->elemInfos = (xmlSchemaElemInfoPtr *)
15013 xmlMalloc(10 * sizeof(xmlSchemaElemInfoPtr));
15014 if (vctxt->elemInfos == NULL) {
15015 xmlSchemaVErrMemory(vctxt,
15016 "allocating the element info array", NULL);
15017 return (NULL);
15018 }
15019 memset(vctxt->elemInfos, 0, 10 * sizeof(xmlSchemaElemInfoPtr));
15020 vctxt->sizeElemInfos = 10;
15021 } else if (vctxt->sizeElemInfos == vctxt->depth) {
15022 int i = vctxt->sizeElemInfos;
15023
15024 vctxt->sizeElemInfos *= 2;
15025 vctxt->elemInfos = (xmlSchemaElemInfoPtr *)
15026 xmlRealloc(vctxt->elemInfos, vctxt->sizeElemInfos *
15027 sizeof(xmlSchemaElemInfoPtr));
15028 if (vctxt->elemInfos == NULL) {
15029 xmlSchemaVErrMemory(vctxt,
15030 "re-allocating the element info array", NULL);
15031 return (NULL);
15032 }
15033 /*
15034 * We need the new memory to be NULLed.
15035 * TODO: Use memset instead?
15036 */
15037 for (; i < vctxt->sizeElemInfos; i++)
15038 vctxt->elemInfos[i] = NULL;
15039 } else
15040 info = vctxt->elemInfos[vctxt->depth];
15041
15042 if (info == NULL) {
15043 info = (xmlSchemaElemInfoPtr)
15044 xmlMalloc(sizeof(xmlSchemaElemInfo));
15045 if (info == NULL) {
15046 xmlSchemaVErrMemory(vctxt,
15047 "allocating an element info", NULL);
15048 return (NULL);
15049 }
15050 vctxt->elemInfos[vctxt->depth] = info;
15051 }
15052 memset(info, 0, sizeof(xmlSchemaElemInfo));
15053 info->depth = vctxt->depth;
15054
15055 return (info);
15056}
15057#endif /* ELEM_INFO_ENABLED */
15058
Daniel Veillard3646d642004-06-02 19:19:14 +000015059
15060/**
15061 * xmlSchemaFreeAttrStates:
15062 * @state: a list of attribute states
15063 *
15064 * Free the given list of attribute states
15065 *
15066 */
15067static void
15068xmlSchemaFreeAttributeStates(xmlSchemaAttrStatePtr state)
15069{
15070 xmlSchemaAttrStatePtr tmp;
15071 while (state != NULL) {
15072 tmp = state;
15073 state = state->next;
15074 xmlFree(tmp);
15075 }
15076}
15077
Daniel Veillard4255d502002-04-16 15:50:10 +000015078/**
15079 * xmlSchemaRegisterAttributes:
15080 * @ctxt: a schema validation context
15081 * @attrs: a list of attributes
15082 *
15083 * Register the list of attributes as the set to be validated on that element
15084 *
15085 * Returns -1 in case of error, 0 otherwise
15086 */
15087static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015088xmlSchemaRegisterAttributes(xmlSchemaValidCtxtPtr ctxt, xmlAttrPtr attrs)
15089{
Daniel Veillard3646d642004-06-02 19:19:14 +000015090 xmlSchemaAttrStatePtr tmp;
15091
15092 ctxt->attr = NULL;
15093 ctxt->attrTop = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000015094 while (attrs != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015095 if ((attrs->ns != NULL) &&
15096 (xmlStrEqual(attrs->ns->href, xmlSchemaInstanceNs))) {
15097 attrs = attrs->next;
15098 continue;
15099 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000015100 tmp = (xmlSchemaAttrStatePtr)
15101 xmlMalloc(sizeof(xmlSchemaAttrState));
15102 if (tmp == NULL) {
15103 xmlSchemaVErrMemory(ctxt, "registering attributes", NULL);
15104 return (-1);
15105 }
Daniel Veillard3646d642004-06-02 19:19:14 +000015106 tmp->attr = attrs;
15107 tmp->state = XML_SCHEMAS_ATTR_UNKNOWN;
15108 tmp->next = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015109 tmp->decl = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000015110 if (ctxt->attr == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015111 ctxt->attr = tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000015112 else
15113 ctxt->attrTop->next = tmp;
15114 ctxt->attrTop = tmp;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015115 attrs = attrs->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000015116 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015117 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000015118}
15119
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015120#if 0 /* Currently not used */
Daniel Veillard4255d502002-04-16 15:50:10 +000015121/**
Daniel Veillard4255d502002-04-16 15:50:10 +000015122 * xmlSchemaValidateCheckNodeList
15123 * @nodelist: the list of nodes
15124 *
15125 * Check the node list is only made of text nodes and entities pointing
15126 * to text nodes
15127 *
15128 * Returns 1 if true, 0 if false and -1 in case of error
15129 */
15130static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015131xmlSchemaValidateCheckNodeList(xmlNodePtr nodelist)
15132{
Daniel Veillard4255d502002-04-16 15:50:10 +000015133 while (nodelist != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015134 if (nodelist->type == XML_ENTITY_REF_NODE) {
15135 TODO /* implement recursion in the entity content */
15136 }
15137 if ((nodelist->type != XML_TEXT_NODE) &&
15138 (nodelist->type != XML_COMMENT_NODE) &&
15139 (nodelist->type != XML_PI_NODE) &&
William M. Bracke7091952004-05-11 15:09:58 +000015140 (nodelist->type != XML_CDATA_SECTION_NODE)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015141 return (0);
15142 }
15143 nodelist = nodelist->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000015144 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015145 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +000015146}
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015147#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000015148
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015149static void
15150xmlSchemaPostSchemaAssembleFixup(xmlSchemaParserCtxtPtr ctxt)
15151{
15152 int i, nbItems;
15153 xmlSchemaTypePtr item, *items;
15154
15155
15156 /*
15157 * During the Assemble of the schema ctxt->curItems has
15158 * been filled with the relevant new items. Fix those up.
15159 */
15160 nbItems = ctxt->assemble->nbItems;
15161 items = (xmlSchemaTypePtr *) ctxt->assemble->items;
15162
15163 for (i = 0; i < nbItems; i++) {
15164 item = items[i];
15165 switch (item->type) {
15166 case XML_SCHEMA_TYPE_ATTRIBUTE:
15167 xmlSchemaAttrFixup((xmlSchemaAttributePtr) item, ctxt, NULL);
15168 break;
15169 case XML_SCHEMA_TYPE_ELEMENT:
15170 xmlSchemaRefFixupCallback((xmlSchemaElementPtr) item, ctxt,
15171 NULL, NULL, NULL);
15172 break;
15173 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
15174 xmlSchemaAttrGrpFixup((xmlSchemaAttributeGroupPtr) item,
15175 ctxt, NULL);
15176 break;
15177 case XML_SCHEMA_TYPE_GROUP:
15178 xmlSchemaGroupDefFixup(item, ctxt, NULL);
15179 default:
15180 break;
15181 }
15182 }
15183 /*
15184 * Circularity checks.
15185 */
15186 for (i = 0; i < nbItems; i++) {
15187 item = items[i];
15188 switch (item->type) {
15189 case XML_SCHEMA_TYPE_GROUP:
15190 xmlSchemaCheckGroupDefCircular(item, ctxt, NULL);
15191 break;
15192 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
15193 xmlSchemaCheckAttributeGroupCircular(
15194 (xmlSchemaAttributeGroupPtr) item, ctxt, NULL);
15195 break;
15196 default:
15197 break;
15198 }
15199 }
15200 /*
15201 * Fixup for all other item.
15202 * TODO: Hmm, not sure if starting from complex/simple types,
15203 * all subsequent items will be reached.
15204 */
15205 for (i = 0; i < nbItems; i++) {
15206 item = items[i];
15207 switch (item->type) {
15208 case XML_SCHEMA_TYPE_SIMPLE:
15209 case XML_SCHEMA_TYPE_COMPLEX:
15210 xmlSchemaTypeFixup(item, ctxt, NULL);
15211 break;
15212 default:
15213 break;
15214 }
15215 }
15216 /*
15217 * Check facet values. Note that facets are
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +000015218 * hold by simple type components only (and
15219 * by complex types in the current implementation).
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015220 */
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +000015221 /* OLD:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015222 for (i = 0; i < nbItems; i++) {
15223 item = items[i];
15224 switch (item->type) {
15225 case XML_SCHEMA_TYPE_SIMPLE:
15226 case XML_SCHEMA_TYPE_COMPLEX:
15227 xmlSchemaCheckDefaults(item, ctxt, NULL);
15228 break;
15229 default:
15230 break;
15231 }
15232 }
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +000015233 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015234 /*
15235 * Build the content model for complex types.
15236 */
15237 for (i = 0; i < nbItems; i++) {
15238 item = items[i];
15239 switch (item->type) {
15240 case XML_SCHEMA_TYPE_COMPLEX:
15241 xmlSchemaBuildContentModel(item, ctxt, NULL);
15242 break;
15243 default:
15244 break;
15245 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015246 }
15247 /*
15248 * Validate value contraint values.
15249 */
15250 for (i = 0; i < nbItems; i++) {
15251 item = items[i];
15252 switch (item->type) {
15253 case XML_SCHEMA_TYPE_ATTRIBUTE:
15254 xmlSchemaCheckAttrValConstr((xmlSchemaAttributePtr) item, ctxt, NULL);
15255 break;
15256 case XML_SCHEMA_TYPE_ELEMENT:
15257 xmlSchemaCheckElemValConstr((xmlSchemaElementPtr) item, ctxt, NULL);
15258 break;
15259 default:
15260 break;
15261 }
15262 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015263}
15264
15265/**
15266 * xmlSchemaAssembleByLocation:
15267 * @pctxt: a schema parser context
15268 * @vctxt: a schema validation context
15269 * @schema: the existing schema
15270 * @node: the node that fired the assembling
15271 * @nsName: the namespace name of the new schema
15272 * @location: the location of the schema
15273 *
15274 * Expands an existing schema by an additional schema.
15275 *
15276 * Returns 0 if the new schema is correct, a positive error code
15277 * number otherwise and -1 in case of an internal or API error.
15278 */
15279static int
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015280xmlSchemaAssembleByLocation(xmlSchemaValidCtxtPtr vctxt,
15281 xmlSchemaPtr schema,
15282 xmlNodePtr node,
15283 const xmlChar *nsName,
15284 const xmlChar *location)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015285{
15286 const xmlChar *targetNs, *oldtns;
15287 xmlDocPtr doc, olddoc;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015288 int oldflags, ret = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015289 xmlNodePtr docElem;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015290 xmlSchemaParserCtxtPtr pctxt;
15291
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015292 /*
15293 * This should be used:
15294 * 1. on <import>(s)
15295 * 2. if requested by the validated instance
15296 * 3. if requested via the API
15297 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015298 if ((vctxt == NULL) || (schema == NULL))
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015299 return (-1);
15300 /*
15301 * Create a temporary parser context.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015302 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015303 if ((vctxt->pctxt == NULL) &&
15304 (xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1)) {
15305 xmlSchemaVErr(vctxt, node,
15306 XML_SCHEMAV_INTERNAL,
15307 "Internal error: xmlSchemaAssembleByLocation, "
15308 "failed to create a temp. parser context.\n",
15309 NULL, NULL);
15310 return (-1);
15311 }
15312 pctxt = vctxt->pctxt;
15313 /*
15314 * Set the counter to produce unique names for anonymous items.
15315 */
15316 pctxt->counter = schema->counter;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015317 /*
15318 * Acquire the schema document.
15319 */
15320 ret = xmlSchemaAcquireSchemaDoc(pctxt, schema, node,
15321 nsName, location, &doc, &targetNs, 0);
15322 if (ret != 0) {
15323 if (doc != NULL)
15324 xmlFreeDoc(doc);
15325 } else if (doc != NULL) {
15326 docElem = xmlDocGetRootElement(doc);
15327 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015328 * Create new assemble info.
15329 */
15330 if (pctxt->assemble == NULL) {
15331 pctxt->assemble = xmlSchemaNewAssemble();
15332 if (pctxt->assemble == NULL) {
15333 xmlSchemaVErrMemory(vctxt,
15334 "Memory error: xmlSchemaAssembleByLocation, "
15335 "allocating assemble info", NULL);
15336 xmlFreeDoc(doc);
15337 return (-1);
15338 }
15339 }
15340 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015341 * Save and reset the context & schema.
15342 */
15343 oldflags = schema->flags;
15344 oldtns = schema->targetNamespace;
15345 olddoc = schema->doc;
15346
15347 xmlSchemaClearSchemaDefaults(schema);
15348 schema->targetNamespace = targetNs;
15349 /* schema->nbCurItems = 0; */
15350 pctxt->schema = schema;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015351 pctxt->ctxtType = NULL;
15352 pctxt->parentItem = NULL;
15353
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015354 xmlSchemaParseSchemaDefaults(pctxt, schema, docElem);
15355 xmlSchemaParseSchemaTopLevel(pctxt, schema, docElem->children);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015356 xmlSchemaPostSchemaAssembleFixup(pctxt);
15357 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015358 * Set the counter of items.
15359 */
15360 schema->counter = pctxt->counter;
15361 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015362 * Free the list of assembled components.
15363 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015364 pctxt->assemble->nbItems = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015365 /*
15366 * Restore the context & schema.
15367 */
15368 schema->flags = oldflags;
15369 schema->targetNamespace = oldtns;
15370 schema->doc = olddoc;
15371 ret = pctxt->err;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015372 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015373 return (ret);
15374}
15375
15376/**
15377 * xmlSchemaAssembleByXSIAttr:
15378 * @vctxt: a schema validation context
15379 * @xsiAttr: an xsi attribute
15380 * @noNamespace: whether a schema with no target namespace is exptected
15381 *
15382 * Expands an existing schema by an additional schema using
15383 * the xsi:schemaLocation or xsi:noNamespaceSchemaLocation attribute
15384 * of an instance. If xsi:noNamespaceSchemaLocation is used, @noNamespace
15385 * must be set to 1.
15386 *
15387 * Returns 0 if the new schema is correct, a positive error code
15388 * number otherwise and -1 in case of an internal or API error.
15389 */
15390static int
15391xmlSchemaAssembleByXSIAttr(xmlSchemaValidCtxtPtr vctxt,
15392 xmlAttrPtr xsiAttr,
15393 int noNamespace)
15394{
15395 xmlChar *value;
15396 const xmlChar *cur, *end;
15397 const xmlChar *nsname = NULL, *location;
15398 int count = 0;
15399 int ret = 0;
15400
15401 if (xsiAttr == NULL) {
15402 xmlSchemaVCustomErr(vctxt, XML_SCHEMAV_INTERNAL,
15403 NULL, NULL,
15404 "Internal error: xmlSchemaAssembleByXSIAttr, "
15405 "bad arguments", NULL);
15406 return (-1);
15407 }
15408 /*
15409 * Parse the value; we will assume an even number of values
15410 * to be given (this is how Xerces and XSV work).
15411 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015412 value = xmlNodeGetContent((xmlNodePtr) xsiAttr);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015413 cur = value;
15414 do {
15415 if (noNamespace != 1) {
15416 /*
15417 * Get the namespace name.
15418 */
15419 while (IS_BLANK_CH(*cur))
15420 cur++;
15421 end = cur;
15422 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
15423 end++;
15424 if (end == cur)
15425 break;
15426 count++;
15427 nsname = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
15428 cur = end;
15429 }
15430 /*
15431 * Get the URI.
15432 */
15433 while (IS_BLANK_CH(*cur))
15434 cur++;
15435 end = cur;
15436 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
15437 end++;
15438 if (end == cur)
15439 break;
15440 count++;
15441 location = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015442 cur = end;
15443 ret = xmlSchemaAssembleByLocation(vctxt, vctxt->schema,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015444 xsiAttr->parent, nsname, location);
15445 if (ret == -1) {
15446 xmlSchemaVCustomErr(vctxt,
15447 XML_SCHEMAV_INTERNAL,
15448 (xmlNodePtr) xsiAttr, NULL,
15449 "Internal error: xmlSchemaAssembleByXSIAttr, "
15450 "assembling schemata", NULL);
15451 if (value != NULL)
15452 xmlFree(value);
15453 return (-1);
15454 }
15455 } while (*cur != 0);
15456 if (value != NULL)
15457 xmlFree(value);
15458 return (ret);
15459}
15460
15461/**
15462 * xmlSchemaAssembleByXSIElem:
15463 * @vctxt: a schema validation context
15464 * @elem: an element node possibly holding xsi attributes
15465 * @noNamespace: whether a schema with no target namespace is exptected
15466 *
15467 * Assembles an existing schema by an additional schema using
15468 * the xsi:schemaLocation or xsi:noNamespaceSchemaLocation attributes
15469 * of the given @elem.
15470 *
15471 * Returns 0 if the new schema is correct, a positive error code
15472 * number otherwise and -1 in case of an internal or API error.
15473 */
15474static int
15475xmlSchemaAssembleByXSIElem(xmlSchemaValidCtxtPtr vctxt,
15476 xmlNodePtr elem)
15477{
15478 int ret = 0, retNs = 0;
15479 xmlAttrPtr attr;
15480
15481 attr = xmlHasNsProp(elem, BAD_CAST "schemaLocation", xmlSchemaInstanceNs);
15482 if (attr != NULL) {
15483 retNs = xmlSchemaAssembleByXSIAttr(vctxt, attr, 0);
15484 if (retNs == -1)
15485 return (-1);
15486 }
15487 attr = xmlHasNsProp(elem, BAD_CAST "noNamespaceSchemaLocation", xmlSchemaInstanceNs);
15488 if (attr != NULL) {
15489 ret = xmlSchemaAssembleByXSIAttr(vctxt, attr, 1);
15490 if (ret == -1)
15491 return (-1);
15492 }
15493 if (retNs != 0)
15494 return (retNs);
15495 else
15496 return (ret);
15497}
15498
Daniel Veillard4255d502002-04-16 15:50:10 +000015499/**
Daniel Veillard4255d502002-04-16 15:50:10 +000015500 * xmlSchemaValidateCallback:
15501 * @ctxt: a schema validation context
15502 * @name: the name of the element detected (might be NULL)
15503 * @type: the type
15504 *
15505 * A transition has been made in the automata associated to an element
15506 * content model
15507 */
15508static void
15509xmlSchemaValidateCallback(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015510 const xmlChar * name ATTRIBUTE_UNUSED,
15511 xmlSchemaTypePtr type, xmlNodePtr node)
15512{
Daniel Veillard4255d502002-04-16 15:50:10 +000015513 xmlSchemaTypePtr oldtype = ctxt->type;
15514 xmlNodePtr oldnode = ctxt->node;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015515
Daniel Veillard4255d502002-04-16 15:50:10 +000015516#ifdef DEBUG_CONTENT
Daniel Veillard8651f532002-04-17 09:06:27 +000015517 xmlGenericError(xmlGenericErrorContext,
15518 "xmlSchemaValidateCallback: %s, %s, %s\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000015519 name, type->name, node->name);
Daniel Veillard4255d502002-04-16 15:50:10 +000015520#endif
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015521 /*
15522 * @type->type will be XML_SCHEMA_TYPE_ANY or XML_SCHEMA_TYPE_ELEMENT.
15523 */
Daniel Veillard4255d502002-04-16 15:50:10 +000015524 ctxt->type = type;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015525 ctxt->node = node;
15526 ctxt->cur = node->children;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015527
15528#ifdef ELEM_INFO_ENABLED
15529 xmlSchemaBeginElement(ctxt);
15530#endif
15531
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015532 /*
15533 * Assemble new schemata using xsi.
15534 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015535 if (ctxt->xsiAssemble) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015536 int ret;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015537
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015538 ret = xmlSchemaAssembleByXSIElem(ctxt, ctxt->node);
15539 if (ret == -1) {
15540 xmlSchemaVCustomErr(ctxt,
15541 XML_SCHEMAV_INTERNAL,
15542 ctxt->node, NULL,
15543 "Internal error: xmlSchemaValidateElement, "
15544 "assembling schema by xsi", NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015545 goto leave;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015546 }
15547 /*
15548 * NOTE: We won't react on schema parser errors here.
15549 * TODO: But a warning would be nice.
15550 */
15551 }
15552 switch (type->type) {
15553 case XML_SCHEMA_TYPE_ELEMENT: {
15554 /*
15555 * NOTE: The build of the content model
15556 * (xmlSchemaBuildAContentModel) ensures that the element
15557 * declaration (and not a reference to it) will be given.
15558 */
15559 if (((xmlSchemaElementPtr) ctxt->type)->ref != NULL) {
15560 /*
15561 * This is paranoid coding ;-)... it should not
15562 * happen here any more.
15563 */
15564 xmlSchemaVCustomErr(ctxt,
15565 XML_SCHEMAV_INTERNAL,
15566 node, NULL,
15567 "Internal error: xmlSchemaValidateCallback, "
15568 "element declaration 'reference' encountered, "
15569 "but an element declaration was expected",
15570 NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015571 goto leave;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015572 }
15573 xmlSchemaValidateElementByDeclaration(ctxt,
15574 (xmlSchemaElementPtr) type);
15575 break;
15576 }
15577 case XML_SCHEMA_TYPE_ANY:
15578 xmlSchemaValidateElementByWildcard(ctxt, type);
15579 break;
15580 default:
15581 break;
15582 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000015583leave:
15584
15585#ifdef ELEM_INFO_ENABLED
15586 xmlSchemaEndElement(ctxt);
15587 /*
15588 xmlSchemaDebugDumpIDCTable(stdout,
15589 NULL,
15590 ctxt->node->name,
15591 ctxt->elemInfo->idcTable);
15592 */
15593#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000015594 ctxt->type = oldtype;
15595 ctxt->node = oldnode;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015596}
Daniel Veillard4255d502002-04-16 15:50:10 +000015597
Daniel Veillard01fa6152004-06-29 17:04:39 +000015598/**
15599 * xmlSchemaValidateSimpleTypeValue:
15600 * @ctxt: a schema validation context
15601 * @value: the value to be validated
15602 * @fireErrors: shall errors be reported?
15603 * @applyFacets: shall facets be applied?
Daniel Veillardc0826a72004-08-10 14:17:33 +000015604 * @normalize: shall the value be normalized?
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015605 * @checkNodes: shall the content nodes be checked?
Daniel Veillard01fa6152004-06-29 17:04:39 +000015606 *
15607 * Validates a value by the given type (user derived or built-in).
15608 *
15609 * Returns 0 if the value is valid, a positive error code
15610 * number otherwise and -1 in case of an internal or API error.
Daniel Veillard01fa6152004-06-29 17:04:39 +000015611 */
15612static int
15613xmlSchemaValidateSimpleTypeValue(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015614 xmlSchemaTypePtr type,
15615 const xmlChar *value,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015616 int fireErrors,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015617 int applyFacets,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015618 int normalize,
15619 int checkNodes)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015620{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015621 xmlNodePtr node;
Daniel Veillardc0826a72004-08-10 14:17:33 +000015622 int ret = 0;
15623 xmlChar *normValue = NULL;
15624 int wtsp;
15625
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015626 node = ctxt->node;
15627 /* Save the current whitespace normalization type. */
Daniel Veillardc0826a72004-08-10 14:17:33 +000015628 wtsp = ctxt->valueWS;
15629 /*
15630 * Normalize the value.
15631 */
15632 if (normalize &&
15633 (ctxt->valueWS != XML_SCHEMAS_VAL_WTSP_COLLAPSE)) {
15634 int norm = xmlSchemaGetWhiteSpaceFacetValue(type);
15635
15636 if ((norm != -1) && (norm > ctxt->valueWS)) {
15637 if (norm == XML_SCHEMAS_VAL_WTSP_COLLAPSE)
15638 normValue = xmlSchemaCollapseString(value);
15639 else
15640 normValue = xmlSchemaWhiteSpaceReplace(value);
15641 ctxt->valueWS = norm;
15642 if (normValue != NULL)
15643 value = (const xmlChar *) normValue;
15644 }
15645 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015646 /*
15647 * The nodes of a content must be checked only once,
15648 * this is not working since list types will fire this
15649 * multiple times.
15650 */
15651 if ((checkNodes == 1) && (ctxt->cur != NULL)) {
15652 xmlNodePtr cur = ctxt->cur;
15653
15654 do {
15655 switch (cur->type) {
15656 case XML_TEXT_NODE:
15657 case XML_CDATA_SECTION_NODE:
15658 case XML_PI_NODE:
15659 case XML_COMMENT_NODE:
15660 case XML_XINCLUDE_START:
15661 case XML_XINCLUDE_END:
15662 break;
15663 case XML_ENTITY_REF_NODE:
15664 case XML_ENTITY_NODE:
15665 /* TODO: Scour the entities for illegal nodes. */
15666 TODO break;
15667 case XML_ELEMENT_NODE: {
15668 /* NOTE: Changed to an internal error, since the
15669 * existence of an element node will be already checked in
15670 * xmlSchemaValidateElementBySimpleType and in
15671 * xmlSchemaValidateElementByComplexType.
15672 */
15673 xmlSchemaVCustomErr(ctxt,
15674 XML_SCHEMAV_INTERNAL,
15675 /* XML_SCHEMAS_ERR_INVALIDELEM, */
15676 node, type,
15677 "Element '%s' found in simple type content",
15678 cur->name);
15679 return (XML_SCHEMAV_INTERNAL);
15680 }
15681 case XML_ATTRIBUTE_NODE:
15682 case XML_DOCUMENT_NODE:
15683 case XML_DOCUMENT_TYPE_NODE:
15684 case XML_DOCUMENT_FRAG_NODE:
15685 case XML_NOTATION_NODE:
15686 case XML_HTML_DOCUMENT_NODE:
15687 case XML_DTD_NODE:
15688 case XML_ELEMENT_DECL:
15689 case XML_ATTRIBUTE_DECL:
15690 case XML_ENTITY_DECL:
15691 case XML_NAMESPACE_DECL:
15692#ifdef LIBXML_DOCB_ENABLED
15693 case XML_DOCB_DOCUMENT_NODE:
15694#endif
15695 xmlSchemaVCustomErr(ctxt,
15696 XML_SCHEMAV_INTERNAL,
15697 /* XML_SCHEMAS_ERR_INVALIDELEM, */
15698 node, NULL,
15699 "Node of unexpected type found in simple type content",
15700 NULL);
15701 return (XML_SCHEMAV_INTERNAL);
15702 }
15703 cur = cur->next;
15704 } while (cur != NULL);
15705 }
15706
William M. Brack2f2a6632004-08-20 23:09:47 +000015707 if (type->type == XML_SCHEMA_TYPE_COMPLEX) {
15708 xmlSchemaTypePtr base, anyType;
15709
15710 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
15711
15712 base = type->baseType;
15713 while ((base != NULL) &&
15714 (base->type != XML_SCHEMA_TYPE_SIMPLE) &&
15715 (base->type != XML_SCHEMA_TYPE_BASIC) &&
15716 (base != anyType)) {
15717 base = base->baseType;
15718 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015719 ret = xmlSchemaValidateSimpleTypeValue(ctxt, base, value, 1, 0, 1, 0);
William M. Brack2f2a6632004-08-20 23:09:47 +000015720 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015721 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000015722 "Internal error: xmlSchemaValidateSimpleTypeValue, "
15723 "validating complex type '%s'\n",
15724 type->name, NULL);
15725 } else if ((ret == 0) && (applyFacets) && (type->facetSet != NULL)) {
15726 /*
15727 * Check facets.
15728 */
15729 /*
15730 * This is somehow not nice, since if an error occurs
15731 * the reported type will be the complex type; the spec
15732 * wants a simple type to be created on the complex type
15733 * if it has a simple content. For now we have to live with
15734 * it.
15735 */
15736 ret = xmlSchemaValidateFacetsInternal(ctxt, type,
15737 value, 0, fireErrors);
15738 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015739 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000015740 "Internal error: xmlSchemaValidateSimpleTypeValue, "
15741 "validating facets of complex type '%s'\n",
15742 type->name, NULL);
15743 } else if (ret > 0) {
15744 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
William M. Brack2f2a6632004-08-20 23:09:47 +000015745 if (fireErrors)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015746 xmlSchemaVSimpleTypeErr(ctxt, ret, node, value, type);
William M. Brack2f2a6632004-08-20 23:09:47 +000015747 }
15748 }
15749 } else if (type->type == XML_SCHEMA_TYPE_BASIC) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000015750
15751 if (ctxt->value != NULL) {
15752 xmlSchemaFreeValue(ctxt->value);
15753 ctxt->value = NULL;
15754 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015755 /*
15756 * STREAM-READ-CHILDREN.
15757 */
15758 ret = xmlSchemaValPredefTypeNodeNoNorm(type, value, &(ctxt->value), node);
Daniel Veillardc0826a72004-08-10 14:17:33 +000015759 if (ret > 0) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000015760 if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST)
15761 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
15762 else
15763 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
Daniel Veillardc0826a72004-08-10 14:17:33 +000015764 if (fireErrors)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015765 xmlSchemaVSimpleTypeErr(ctxt, ret, node, value, type);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015766 } else if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015767 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015768 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000015769 "validating built-in type '%s'\n", type->name, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015770 }
15771 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC) {
15772 /* 1.2.1 if {variety} is ·atomic· then the string must ·match·
15773 * a literal in the ·lexical space· of {base type definition}
15774 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015775 ret = xmlSchemaValidateSimpleTypeValue(ctxt, type->baseType, value, 0, 0, 0, 0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015776 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015777 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015778 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000015779 "validating atomic simple type '%s'\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000015780 type->name, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +000015781 } else if (ret > 0) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000015782 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
Daniel Veillardc0826a72004-08-10 14:17:33 +000015783 if (fireErrors)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015784 xmlSchemaVSimpleTypeErr(ctxt, ret, node, value, type);
Daniel Veillardc0826a72004-08-10 14:17:33 +000015785 } else if ((applyFacets) && (type->facetSet != NULL)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000015786 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000015787 * Check facets.
Daniel Veillard01fa6152004-06-29 17:04:39 +000015788 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000015789 ret = xmlSchemaValidateFacetsInternal(ctxt, type,
15790 value, 0, fireErrors);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015791 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015792 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015793 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000015794 "validating facets of atomic simple type '%s'\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000015795 type->name, NULL);
15796 } else if (ret > 0) {
15797 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
Daniel Veillardc0826a72004-08-10 14:17:33 +000015798 /*
15799 Disabled, since the facet validation already reports errors.
15800 if (fireErrors)
15801 xmlSchemaVSimpleTypeErr(ctxt, ret, ctxt->cur, value, type);
15802 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000015803 }
15804 }
15805 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) {
15806
15807 xmlSchemaTypePtr tmpType;
15808 const xmlChar *cur, *end;
15809 xmlChar *tmp;
Daniel Veillardc0826a72004-08-10 14:17:33 +000015810 unsigned long len = 0;
Daniel Veillard01fa6152004-06-29 17:04:39 +000015811
15812 /* 1.2.2 if {variety} is ·list· then the string must be a sequence
15813 * of white space separated tokens, each of which ·match·es a literal
15814 * in the ·lexical space· of {item type definition}
15815 */
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +000015816
Kasimier T. Buchcikde938cd2005-01-13 12:25:57 +000015817 if (value == NULL)
15818 value = BAD_CAST "";
Daniel Veillardc0826a72004-08-10 14:17:33 +000015819 tmpType = xmlSchemaGetListSimpleTypeItemType(type);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015820 cur = value;
15821 do {
15822 while (IS_BLANK_CH(*cur))
15823 cur++;
15824 end = cur;
15825 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
15826 end++;
15827 if (end == cur)
15828 break;
15829 tmp = xmlStrndup(cur, end - cur);
15830 len++;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015831 ret = xmlSchemaValidateSimpleTypeValue(ctxt, tmpType, tmp, 0, 1, 0, 0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015832 xmlFree(tmp);
Daniel Veillardc0826a72004-08-10 14:17:33 +000015833 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015834 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015835 "Internal error: xmlSchemaValidateSimpleTypeValue, "
15836 "validating an item of list simple type '%s'\n",
15837 type->name, NULL);
15838 break;
15839 } else if (ret > 0) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000015840 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
Daniel Veillardc0826a72004-08-10 14:17:33 +000015841 if (fireErrors)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015842 xmlSchemaVSimpleTypeErr(ctxt, ret, node, value, type);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015843 break;
Daniel Veillardc0826a72004-08-10 14:17:33 +000015844 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000015845 cur = end;
15846 } while (*cur != 0);
15847 /*
15848 * Check facets.
15849 */
15850 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015851 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015852 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000015853 "validating list simple type '%s'\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000015854 type->name, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +000015855 } else if ((ret == 0) && (applyFacets)) {
15856 ret = xmlSchemaValidateFacetsInternal(ctxt, type,
15857 value, len, fireErrors);
15858 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015859 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015860 "Internal error: xmlSchemaValidateSimpleTypeValue, "
15861 "validating facets of list simple type '%s'\n",
15862 type->name, NULL);
15863 } else if (ret > 0) {
15864 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
Daniel Veillard01fa6152004-06-29 17:04:39 +000015865 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000015866 Disabled, since the facet validation already reports errors.
15867 if (fireErrors)
15868 xmlSchemaVSimpleTypeErr(ctxt, ret, ctxt->cur, value, type);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015869 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000015870 }
15871
Daniel Veillard01fa6152004-06-29 17:04:39 +000015872 }
15873 } else if (type->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) {
15874 xmlSchemaTypeLinkPtr memberLink;
15875
15876 /*
15877 * TODO: For all datatypes ·derived· by ·union· whiteSpace does
15878 * not apply directly; however, the normalization behavior of ·union·
15879 * types is controlled by the value of whiteSpace on that one of the
15880 * ·memberTypes· against which the ·union· is successfully validated.
15881 *
15882 * This means that the value is normalized by the first validating
15883 * member type, then the facets of the union type are applied. This
15884 * needs changing of the value!
15885 */
15886
15887 /*
15888 * 1.2.3 if {variety} is ·union· then the string must ·match· a
15889 * literal in the ·lexical space· of at least one member of
15890 * {member type definitions}
15891 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000015892#ifdef DEBUG_UNION_VALIDATION
15893 printf("Union ST : '%s'\n", (const char *) type->name);
15894 printf(" fireErrors : %d\n", fireErrors);
15895 printf(" applyFacets: %d\n", applyFacets);
15896#endif
Daniel Veillard01fa6152004-06-29 17:04:39 +000015897 memberLink = xmlSchemaGetUnionSimpleTypeMemberTypes(type);
15898 if (memberLink == NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015899 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015900 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000015901 "union simple type '%s' has no member types\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000015902 type->name, NULL);
15903 ret = -1;
15904 }
15905 if (ret == 0) {
15906 while (memberLink != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015907 ret = xmlSchemaValidateSimpleTypeValue(ctxt, memberLink->type,
15908 value, 0, 1, 1, 0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015909 if ((ret <= 0) || (ret == 0))
15910 break;
15911 memberLink = memberLink->next;
15912 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000015913 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015914 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000015915 "Internal error: xmlSchemaValidateSimpleTypeValue, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000015916 "validating members of union simple type '%s'\n",
Daniel Veillard01fa6152004-06-29 17:04:39 +000015917 type->name, NULL);
15918 } else if (ret > 0) {
15919 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
Daniel Veillardc0826a72004-08-10 14:17:33 +000015920 if (fireErrors)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015921 xmlSchemaVSimpleTypeErr(ctxt, ret, node, value, type);
Daniel Veillardc0826a72004-08-10 14:17:33 +000015922 }
15923 }
15924 /*
15925 * Apply facets (pattern, enumeration).
15926 */
15927 if ((ret == 0) && (applyFacets) && (type->facetSet != NULL)) {
15928 int mws;
15929 /*
15930 * The normalization behavior of ·union· types is controlled by
15931 * the value of whiteSpace on that one of the ·memberTypes·
15932 * against which the ·union· is successfully validated.
15933 */
15934 if (normValue != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015935 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015936 "Internal error: xmlSchemaValidateSimpleTypeValue, "
15937 "the value was already normalized for the union simple "
15938 "type '%s'.\n", type->name, NULL);
15939 }
15940 mws = xmlSchemaGetWhiteSpaceFacetValue(memberLink->type);
15941 if (mws > ctxt->valueWS) {
15942 if (mws == XML_SCHEMAS_VAL_WTSP_COLLAPSE)
15943 normValue = xmlSchemaCollapseString(value);
15944 else
15945 normValue = xmlSchemaWhiteSpaceReplace(value);
15946 if (normValue != NULL)
15947 value = (const xmlChar *) normValue;
15948 }
15949
15950 ret = xmlSchemaValidateFacetsInternal(ctxt, type,
15951 value, 0, fireErrors);
15952 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015953 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000015954 "Internal error: xmlSchemaValidateSimpleTypeValue, "
15955 "validating facets of union simple type '%s'\n",
15956 type->name, NULL);
15957 } else if (ret > 0) {
15958 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
15959 /*
15960 if (fireErrors)
15961 xmlSchemaVSimpleTypeErr(ctxt, ret, ctxt->cur, value, type);
15962 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000015963 }
15964 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000015965 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000015966 ctxt->valueWS = wtsp;
15967 if (normValue != NULL)
15968 xmlFree(normValue);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015969 return (ret);
15970}
15971
15972/**
15973 * xmlSchemaValidateSimpleTypeElement:
15974 * @ctxt: a schema validation context
15975 * @node: the element node to be validated.
15976 *
15977 * Validate the element against a simple type.
15978 *
15979 * Returns 0 if the element is valid, a positive error code
15980 * number otherwise and -1 in case of an internal or API error.
15981 */
15982static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015983xmlSchemaValidateElementBySimpleType(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015984 xmlSchemaTypePtr type,
15985 int valSimpleContent)
Daniel Veillard01fa6152004-06-29 17:04:39 +000015986{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015987 xmlSchemaTypePtr oldtype;
15988 xmlNodePtr node;
Daniel Veillard01fa6152004-06-29 17:04:39 +000015989 xmlAttrPtr attr;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000015990 xmlNodePtr cur;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015991 int ret = 0, retval = 0;
15992
Daniel Veillard01fa6152004-06-29 17:04:39 +000015993 if ((ctxt == NULL) || (type == NULL)) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000015994 xmlSchemaVCustomErr(ctxt, XML_SCHEMAV_INTERNAL, NULL, NULL,
15995 "Internal error: xmlSchemaValidateElementBySimpleType, "
15996 "bad arguments", NULL);
15997 return (-1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000015998 }
15999
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016000 oldtype = ctxt->type;
16001 node = ctxt->node;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000016002 /*
16003 * cvc-type: 3.1.2 The element information item must have no element
16004 * information item [children].
16005 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016006 /*
16007 * STREAM: Child nodes are processed.
16008 */
16009 cur = node->children;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000016010 while (cur != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016011 /*
16012 * TODO: Entities, will they produce elements as well?
16013 */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000016014 if (cur->type == XML_ELEMENT_NODE) {
16015 xmlSchemaVCustomErr(ctxt,
16016 XML_SCHEMAV_CVC_TYPE_3_1_2,
16017 node, type,
16018 "No element content allowed", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016019 ret = XML_SCHEMAV_CVC_TYPE_3_1_2;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000016020 }
16021 cur = cur->next;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016022 }
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000016023
Daniel Veillard01fa6152004-06-29 17:04:39 +000016024 /*
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000016025 * cvc-type 3.1.1:
16026 *
16027 * The attributes of must be empty, excepting those whose namespace name
16028 * is identical to http://www.w3.org/2001/XMLSchema-instance and whose local
16029 * name is one of type, nil, schemaLocation or noNamespaceSchemaLocation.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016030 */
16031 /*
16032 * STREAM: Attribute nodes are processed.
16033 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000016034 attr = node->properties;
16035 while (attr != NULL) {
16036 if ((attr->ns == NULL) ||
16037 (!xmlStrEqual(attr->ns->href, xmlSchemaInstanceNs)) ||
16038 ((!xmlStrEqual(attr->name, BAD_CAST "type")) &&
16039 (!xmlStrEqual(attr->name, BAD_CAST "nil")) &&
16040 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation")) &&
16041 (!xmlStrEqual
16042 (attr->name, BAD_CAST "noNamespaceSchemaLocation")))) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000016043 xmlSchemaVIllegalAttrErr(ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016044 XML_SCHEMAV_CVC_TYPE_3_1_1, attr);
16045 ret = XML_SCHEMAV_CVC_TYPE_3_1_1;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016046 }
16047 attr = attr->next;
16048 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016049 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016050 * This will skip validation if the type is 'anySimpleType' and
16051 * if the value was already validated (e.g. default values).
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016052 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016053 if ((valSimpleContent == 1) &&
16054 ((type->type != XML_SCHEMA_TYPE_BASIC) ||
16055 (type->builtInType != XML_SCHEMAS_ANYSIMPLETYPE))) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016056 xmlChar *value;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016057
16058 value = xmlNodeGetContent(node);
16059 /*
16060 * NOTE: This call will not check the content nodes, since
16061 * this should be checked here already.
16062 */
16063 retval = xmlSchemaValidateSimpleTypeValue(ctxt, type, value,
16064 1, 1, 1, 0);
William M. Brack2f2a6632004-08-20 23:09:47 +000016065 if (value != NULL)
16066 xmlFree(value);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016067 if (retval != 0)
16068 ret = retval;
William M. Brack2f2a6632004-08-20 23:09:47 +000016069 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016070 ctxt->type = oldtype;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016071 return (ret);
16072}
Daniel Veillard4255d502002-04-16 15:50:10 +000016073
16074/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016075 * xmlSchemaValQNameAcquire:
16076 * @value: the lexical represantation of the QName value
16077 * @node: the node to search for the corresponding namespace declaration
16078 * @nsName: the resulting namespace name if found
16079 *
16080 * Checks that a value conforms to the lexical space of the type QName;
16081 * if valid, the corresponding namespace name is searched and retured
16082 * as a copy in @nsName. The local name is returned in @localName as
16083 * a copy.
16084 *
16085 * Returns 0 if valid, 1 if not valid by type, 2 if no corresponding
16086 * namespace declaration was found in scope; -1 in case of an internal or
16087 * API error.
16088 */
16089static int
16090xmlSchemaValQNameAcquire(const xmlChar *value, xmlNodePtr node,
16091 xmlChar **nsName, xmlChar **localName)
16092{
16093 int ret;
16094 xmlChar *local = NULL;
16095
16096 if ((nsName == NULL) || (localName == NULL) || (node == NULL))
16097 return (-1);
16098 *nsName = NULL;
16099 *localName = NULL;
16100 ret = xmlValidateQName(value, 1);
16101 if (ret == 0) {
16102 xmlChar *prefix;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016103 xmlNsPtr ns;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016104
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016105 /*
16106 * NOTE: xmlSplitQName2 will return a duplicated
16107 * string.
16108 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016109 local = xmlSplitQName2(value, &prefix);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016110 if (local == NULL)
16111 local = xmlStrdup(value);
16112 ns = xmlSearchNs(node->doc, node, prefix);
16113 /*
16114 * A namespace need not to be found if the prefix is NULL.
16115 */
16116 if (ns != NULL) {
16117 /*
16118 * TODO: Is it necessary to duplicate the URI here?
16119 */
16120 *nsName = xmlStrdup(ns->href);
16121 } else if (prefix != NULL) {
16122 xmlFree(prefix);
16123 if (local != NULL)
16124 xmlFree(local);
16125 return (2);
16126 }
16127 *localName = local;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016128 if (prefix != NULL)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016129 xmlFree(prefix);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000016130 } else
16131 return (1);
16132 return (ret);
16133}
16134
16135/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016136 * xmlSchemaHasElemContent:
16137 * @node: the node
16138 *
16139 * Scours the content of the given node for element
16140 * nodes.
16141 *
16142 * Returns 1 if an element node is found,
16143 * 0 otherwise.
16144 */
16145static int
16146xmlSchemaHasElemContent(xmlNodePtr node)
16147{
16148 if (node == NULL)
16149 return (0);
16150 node = node->children;
16151 while (node != NULL) {
16152 if (node->type == XML_ELEMENT_NODE)
16153 return (1);
16154 node = node->next;
16155 }
16156 return (0);
16157}
16158/**
16159 * xmlSchemaHasElemOrCharContent:
16160 * @node: the node
16161 *
16162 * Scours the content of the given node for element
16163 * and character nodes.
16164 *
16165 * Returns 1 if an element or character node is found,
16166 * 0 otherwise.
16167 */
16168static int
16169xmlSchemaHasElemOrCharContent(xmlNodePtr node)
16170{
16171 if (node == NULL)
16172 return (0);
16173 node = node->children;
16174 while (node != NULL) {
16175 switch (node->type) {
16176 case XML_ELEMENT_NODE:
16177 /*
16178 * TODO: Ask Daniel if these are all character nodes.
16179 */
16180 case XML_TEXT_NODE:
16181 case XML_CDATA_SECTION_NODE:
16182 /*
16183 * TODO: How XML_ENTITY_NODEs evaluated?
16184 */
16185 case XML_ENTITY_REF_NODE:
16186 case XML_ENTITY_NODE:
16187 return (1);
16188 break;
16189 default:
16190 break;
16191 }
16192 node = node->next;
16193 }
16194 return (0);
16195}
16196
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016197/************************************************************************
16198 * *
16199 * Identity-constraints (IDC) *
16200 * *
16201 ************************************************************************/
16202
16203#ifdef IDC_ENABLED
16204
16205/**
16206 * xmlSchemaIDCNewBinding:
16207 * @idcDef: the IDC definition of this binding
16208 *
16209 * Creates a new IDC binding.
16210 *
16211 * Returns the new binding in case of succeeded, NULL on internal errors.
16212 */
16213static xmlSchemaPSVIIDCBindingPtr
16214xmlSchemaIDCNewBinding(xmlSchemaIDCPtr idcDef)
16215{
16216 xmlSchemaPSVIIDCBindingPtr ret;
16217
16218 ret = (xmlSchemaPSVIIDCBindingPtr) xmlMalloc(
16219 sizeof(xmlSchemaPSVIIDCBinding));
16220 if (ret == NULL) {
16221 xmlSchemaVErrMemory(NULL,
16222 "allocating a PSVI IDC binding item", NULL);
16223 return (NULL);
16224 }
16225 memset(ret, 0, sizeof(xmlSchemaPSVIIDCBinding));
16226 ret->definition = idcDef;
16227 return (ret);
16228}
16229
16230/**
16231 * xmlSchemaIDCStoreNodeTableItem:
16232 * @vctxt: the WXS validation context
16233 * @item: the IDC node table item
16234 *
16235 * The validation context is used to store an IDC node table items.
16236 * They are stored to avoid copying them if IDC node-tables are merged
16237 * with corresponding parent IDC node-tables (bubbling).
16238 *
16239 * Returns 0 if succeeded, -1 on internal errors.
16240 */
16241static int
16242xmlSchemaIDCStoreNodeTableItem(xmlSchemaValidCtxtPtr vctxt,
16243 xmlSchemaPSVIIDCNodePtr item)
16244{
16245 /*
16246 * Add to gobal list.
16247 */
16248 if (vctxt->idcNodes == NULL) {
16249 vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
16250 xmlMalloc(20 * sizeof(xmlSchemaPSVIIDCNodePtr));
16251 if (vctxt->idcNodes == NULL) {
16252 xmlSchemaVErrMemory(vctxt,
16253 "allocating the IDC node table item list", NULL);
16254 return (-1);
16255 }
16256 vctxt->sizeIdcNodes = 20;
16257 } else if (vctxt->sizeIdcNodes <= vctxt->nbIdcNodes) {
16258 vctxt->sizeIdcNodes *= 2;
16259 vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
16260 xmlRealloc(vctxt->idcNodes, vctxt->sizeIdcNodes *
16261 sizeof(xmlSchemaPSVIIDCNodePtr));
16262 if (vctxt->idcNodes == NULL) {
16263 xmlSchemaVErrMemory(vctxt,
16264 "re-allocating the IDC node table item list", NULL);
16265 return (-1);
16266 }
16267 }
16268 vctxt->idcNodes[vctxt->nbIdcNodes++] = item;
16269
16270 return (0);
16271}
16272
16273/**
16274 * xmlSchemaIDCStoreKey:
16275 * @vctxt: the WXS validation context
16276 * @item: the IDC key
16277 *
16278 * The validation context is used to store an IDC key.
16279 *
16280 * Returns 0 if succeeded, -1 on internal errors.
16281 */
16282static int
16283xmlSchemaIDCStoreKey(xmlSchemaValidCtxtPtr vctxt,
16284 xmlSchemaPSVIIDCKeyPtr key)
16285{
16286 /*
16287 * Add to gobal list.
16288 */
16289 if (vctxt->idcKeys == NULL) {
16290 vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
16291 xmlMalloc(40 * sizeof(xmlSchemaPSVIIDCKeyPtr));
16292 if (vctxt->idcKeys == NULL) {
16293 xmlSchemaVErrMemory(vctxt,
16294 "allocating the IDC key storage list", NULL);
16295 return (-1);
16296 }
16297 vctxt->sizeIdcKeys = 40;
16298 } else if (vctxt->sizeIdcKeys <= vctxt->nbIdcKeys) {
16299 vctxt->sizeIdcKeys *= 2;
16300 vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
16301 xmlRealloc(vctxt->idcKeys, vctxt->sizeIdcKeys *
16302 sizeof(xmlSchemaPSVIIDCKeyPtr));
16303 if (vctxt->idcKeys == NULL) {
16304 xmlSchemaVErrMemory(vctxt,
16305 "re-allocating the IDC key storage list", NULL);
16306 return (-1);
16307 }
16308 }
16309 vctxt->idcKeys[vctxt->nbIdcKeys++] = key;
16310
16311 return (0);
16312}
16313
16314/**
16315 * xmlSchemaIDCAppendNodeTableItem:
16316 * @bind: the IDC binding
16317 * @ntItem: the node-table item
16318 *
16319 * Appends the IDC node-table item to the binding.
16320 *
16321 * Returns 0 on success and -1 on internal errors.
16322 */
16323static int
16324xmlSchemaIDCAppendNodeTableItem(xmlSchemaPSVIIDCBindingPtr bind,
16325 xmlSchemaPSVIIDCNodePtr ntItem)
16326{
16327 if (bind->nodeTable == NULL) {
16328 bind->sizeNodes = 10;
16329 bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
16330 xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr));
16331 if (bind->nodeTable == NULL) {
16332 xmlSchemaVErrMemory(NULL,
16333 "allocating an array of IDC node-table items", NULL);
16334 return(-1);
16335 }
16336 } else if (bind->sizeNodes <= bind->nbNodes) {
16337 bind->sizeNodes *= 2;
16338 bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
16339 xmlRealloc(bind->nodeTable, bind->sizeNodes *
16340 sizeof(xmlSchemaPSVIIDCNodePtr));
16341 if (bind->nodeTable == NULL) {
16342 xmlSchemaVErrMemory(NULL,
16343 "re-allocating an array of IDC node-table items", NULL);
16344 return(-1);
16345 }
16346 }
16347 bind->nodeTable[bind->nbNodes++] = ntItem;
16348 return(0);
16349}
16350
16351/**
16352 * xmlSchemaIDCAquireBinding:
16353 * @vctxt: the WXS validation context
16354 * @matcher: the IDC matcher
16355 *
16356 * Looks up an PSVI IDC binding, for the IDC definition and
16357 * of the given matcher. If none found, a new one is created
16358 * and added to the IDC table.
16359 *
16360 * Returns an IDC binding or NULL on internal errors.
16361 */
16362static xmlSchemaPSVIIDCBindingPtr
16363xmlSchemaIDCAquireBinding(xmlSchemaValidCtxtPtr vctxt,
16364 xmlSchemaIDCMatcherPtr matcher)
16365{
16366 xmlSchemaElemInfoPtr info;
16367
16368 info = vctxt->elemInfos[matcher->depth];
16369
16370 if (info->idcTable == NULL) {
16371 info->idcTable = xmlSchemaIDCNewBinding(matcher->aidc->def);
16372 if (info->idcTable == NULL)
16373 return (NULL);
16374 return(info->idcTable);
16375 } else {
16376 xmlSchemaPSVIIDCBindingPtr bind = NULL;
16377
16378 bind = info->idcTable;
16379 do {
16380 if (bind->definition == matcher->aidc->def)
16381 return(bind);
16382 if (bind->next == NULL) {
16383 bind->next = xmlSchemaIDCNewBinding(matcher->aidc->def);
16384 if (bind->next == NULL)
16385 return (NULL);
16386 return(bind->next);
16387 }
16388 bind = bind->next;
16389 } while (bind != NULL);
16390 }
16391 return (NULL);
16392}
16393
16394/**
16395 * xmlSchemaIDCFreeKey:
16396 * @key: the IDC key
16397 *
16398 * Frees an IDC key together with its compiled value.
16399 */
16400static void
16401xmlSchemaIDCFreeKey(xmlSchemaPSVIIDCKeyPtr key)
16402{
16403 if (key->compValue != NULL)
16404 xmlSchemaFreeValue(key->compValue);
16405 xmlFree(key);
16406}
16407
16408/**
16409 * xmlSchemaIDCFreeBinding:
16410 *
16411 * Frees an IDC binding. Note that the node table-items
16412 * are not freed.
16413 */
16414xmlSchemaIDCFreeBinding(xmlSchemaPSVIIDCBindingPtr bind)
16415{
16416 if (bind->nodeTable != NULL) {
16417 xmlFree(bind->nodeTable);
16418 }
16419 xmlFree(bind);
16420}
16421
16422/**
16423 * xmlSchemaIDCFreeIDCTable:
16424 * @bind: the first IDC binding in the list
16425 *
16426 * Frees an IDC table, i.e. all the IDC bindings in the list.
16427 */
16428static void
16429xmlSchemaIDCFreeIDCTable(xmlSchemaPSVIIDCBindingPtr bind)
16430{
16431 xmlSchemaPSVIIDCBindingPtr prev;
16432
16433 while (bind != NULL) {
16434 prev = bind;
16435 bind = bind->next;
16436 xmlSchemaIDCFreeBinding(prev);
16437 }
16438}
16439
16440/**
16441 * xmlSchemaIDCFreeMatcherList:
16442 * @matcher: the first IDC matcher in the list
16443 *
16444 * Frees a list of IDC matchers.
16445 */
16446static void
16447xmlSchemaIDCFreeMatcherList(xmlSchemaIDCMatcherPtr matcher)
16448{
16449 xmlSchemaIDCMatcherPtr next;
16450
16451 while (matcher != NULL) {
16452 next = matcher->next;
16453 if (matcher->keySeqs != NULL) {
16454 int i;
16455 for (i = 0; i < matcher->sizeKeySeqs; i++)
16456 if (matcher->keySeqs[i] != NULL)
16457 xmlFree(matcher->keySeqs[i]);
16458 xmlFree(matcher->keySeqs);
16459 }
16460 xmlFree(matcher);
16461 matcher = next;
16462 }
16463}
16464
16465/**
16466 * xmlSchemaAreValuesEqual:
16467 * @ta: the first type
16468 * @a: the first value
16469 * @tb: the second type
16470 * @b: the second value
16471 *
16472 * Compares two values.
16473 *
16474 * Returns 1 if they are equal, 0 if not and -1 on internal errors.
16475 */
16476static int
16477xmlSchemaAreValuesEqual(xmlSchemaTypePtr ta,
16478 xmlSchemaValPtr a,
16479 xmlSchemaTypePtr tb,
16480 xmlSchemaValPtr b)
16481{
16482 int typeEqual = 0;
16483
16484 /* Same user derived/built-in derived/built-in primitive types. */
16485 if (ta == tb)
16486 goto compareValue;
16487
16488 /*
16489 * Comparison with anySimpleTypes is not supported by this implemention.
16490 */
16491 if ((ta->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) ||
16492 (tb->builtInType == XML_SCHEMAS_ANYSIMPLETYPE))
16493 return(0);
16494
16495 /*
16496 * 4.2.1 equal (data-types)
16497 *
16498 * the ·value space·s of all ·primitive· datatypes are disjoint
16499 * (they do not share any values)
16500 */
16501 if ((ta->builtInType != 0) && (tb->builtInType != 0) &&
16502 (ta->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE) &&
16503 (tb->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE))
16504 return(0);
16505
16506 if ((ta->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) ||
16507 (ta->flags & XML_SCHEMAS_TYPE_VARIETY_UNION) ||
16508 (tb->flags & XML_SCHEMAS_TYPE_VARIETY_LIST) ||
16509 (tb->flags & XML_SCHEMAS_TYPE_VARIETY_UNION)) {
16510 TODO
16511 return(0);
16512 }
16513 /*
16514 * (1) if a datatype T' is ·derived· by ·restriction· from an atomic datatype
16515 * T then the ·value space· of T' is a subset of the ·value space· of T.
16516 */
16517 /*
16518 * (2) if datatypes T' and T'' are ·derived· by ·restriction· from a common
16519 * atomic ancestor T then the ·value space·s of T' and T'' may overlap.
16520 */
16521
16522 {
16523 xmlSchemaTypePtr pta = ta, ptb = tb;
16524
16525 /* Note that we will compare the primitives here. */
16526 while ((pta->builtInType == 0) ||
16527 ((pta->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE) == 0))
16528 pta = pta->baseType;
16529 while ((ptb->builtInType == 0) ||
16530 ((ptb->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE) == 0))
16531 ptb = ptb->baseType;
16532 if (pta == ptb)
16533 goto compareValue;
16534 return(0);
16535 }
16536compareValue:
16537 {
16538#ifdef IDC_VALUE_SUPPORT
16539 int ret;
16540 ret = xmlSchemaCompareValuesOpt(a, b,
16541 XML_SCHEMA_VALUECOMP_STRISNORM);
16542 if (ret == 0)
16543 return(1);
16544 else if (ret == -2)
16545 return(-1);
16546 else
16547 return(0);
16548#else
16549 return (1);
16550#endif
16551 }
16552}
16553
16554/**
16555 * xmlSchemaXPathChangeState:
16556 * @vctxt: the WXS validation context
16557 * @sto: the state object
16558 * @newState: the state index to be added to the history
16559 *
16560 * Adds an entry (vctxt->depth and newState) to the history of the
16561 * state object.
16562 *
16563 * Returns 1 if they are equal, 0 if not and -1 on internal errors.
16564 */
16565static int
16566xmlSchemaXPathChangeState(xmlSchemaValidCtxtPtr vctxt,
16567 xmlSchemaIDCStateObjPtr sto,
16568 int newState)
16569
16570{
16571 int *change = NULL;
16572 /*
16573 * Create/grow the array of history items.
16574 */
16575 if (sto->history == NULL) {
16576 sto->history = (int **) xmlMalloc(5 * sizeof(int *));
16577 if (sto->history == NULL) {
16578 xmlSchemaVErrMemory(NULL,
16579 "allocating an array of state change informations", NULL);
16580 xmlFree(sto);
16581 return(-1);
16582 }
16583 memset(sto->history, 0, 5 * sizeof(int *));
16584 sto->sizeHistory = 10;
16585 } else if (sto->sizeHistory > sto->nbHistory) {
16586 /*
16587 * Reuse a history item.
16588 */
16589 change = sto->history[sto->nbHistory];
16590 } else {
16591 int i = sto->sizeHistory;
16592
16593 sto->sizeHistory *= 2;
16594 sto->history = (int **) xmlRealloc(sto->history,
16595 sto->sizeHistory * sizeof(int *));
16596 if (sto->history == NULL) {
16597 xmlSchemaVErrMemory(NULL,
16598 "re-allocating an array of state change informations", NULL);
16599 return(-1);
16600 }
16601 /*
16602 * The new memory needs to be NULLed.
16603 * TODO: Use memset instead?
16604 */
16605 for (; i < sto->sizeHistory; i++)
16606 sto->history[i] = NULL;
16607 }
16608 /*
16609 * Create the history item.
16610 */
16611 if (change == NULL) {
16612 change = (int *) xmlMalloc(2 * sizeof(int));
16613 if (change == NULL) {
16614 xmlSchemaVErrMemory(NULL,
16615 "allocating a state change information", NULL);
16616 return(-1);
16617 }
16618 sto->history[sto->nbHistory] = change;
16619 }
16620 sto->nbHistory++;
16621 /*
16622 * Init the history item.
16623 */
16624 change[0] = vctxt->depth;
16625 change[1] = newState;
16626#ifdef DEBUG_IDC
16627 xmlGenericError(xmlGenericErrorContext, "IDC: push state '%d'\n",
16628 newState);
16629#endif
16630 return(0);
16631}
16632
16633/**
16634 * xmlSchemaIDCAddStateObject:
16635 * @vctxt: the WXS validation context
16636 * @matcher: the IDC matcher
16637 * @sel: the XPath information
16638 * @parent: the parent "selector" state object if any
16639 * @type: "selector" or "field"
16640 *
16641 * Creates/reuses and activates state objects for the given
16642 * XPath information; if the XPath expression consists of unions,
16643 * multiple state objects are created for every unioned expression.
16644 *
16645 * Returns 0 on success and -1 on internal errors.
16646 */
16647static int
16648xmlSchemaIDCAddStateObject(xmlSchemaValidCtxtPtr vctxt,
16649 xmlSchemaIDCMatcherPtr matcher,
16650 xmlSchemaIDCSelectPtr sel,
16651 xmlSchemaIDCStateObjPtr parent,
16652 int type)
16653{
16654 xmlSchemaIDCStateObjPtr sto;
16655 int i = 0, stateId, reversed;
16656
16657 /*
16658 * Create a state object for every location path in the XPath expression.
16659 */
16660 while (1) {
16661#ifdef IDC_XPATH_SUPPORT
16662 stateId = xmlXPathWXSIDCGetLocationPath(sel->xpathComp, i, &reversed);
16663#else
16664 break;
16665#endif
16666 if (stateId < 0)
16667 break;
16668 /*
16669 * Reuse the state objects from the pool.
16670 */
16671 if (vctxt->xpathStatePool != NULL) {
16672 sto = vctxt->xpathStatePool;
16673 vctxt->xpathStatePool = sto->next;
16674 sto->next = NULL;
16675 } else {
16676 /*
16677 * Create a new state object.
16678 */
16679 sto = (xmlSchemaIDCStateObjPtr) xmlMalloc(sizeof(xmlSchemaIDCStateObj));
16680 if (sto == NULL) {
16681 xmlSchemaVErrMemory(NULL,
16682 "allocating an IDC state object", NULL);
16683 return (-1);
16684 }
16685 memset(sto, 0, sizeof(xmlSchemaIDCStateObj));
16686 }
16687 sto->type = type;
16688 sto->parent = parent;
16689 sto->matcher = matcher;
16690 sto->sel = sel;
16691 sto->nbHistory = 0;
16692 /*
16693 * Add to global list.
16694 */
16695 if (vctxt->xpathStates != NULL)
16696 sto->next = vctxt->xpathStates;
16697 vctxt->xpathStates = sto;
16698#if DEBUG_IDC
16699 xmlGenericError(xmlGenericErrorContext, "IDC: STO push '%s'\n",
16700 sto->sel->xpath);
16701#endif
16702 xmlSchemaXPathChangeState(vctxt, sto, stateId);
16703 /*
16704 * Set if the state object should be processed as a push
16705 * down transducer (topDown == 1) or upwards the ancestor axis of
16706 * the tree.
16707 */
16708 if (reversed)
16709 sto->topDown = 1;
16710 i++;
16711 };
16712
16713 return (0);
16714}
16715
16716/**
16717 * xmlSchemaXPathEvaluate:
16718 * @vctxt: the WXS validation context
16719 * @nodeType: the nodeType of the current node
16720 *
16721 * Evaluates all active XPath state objects.
16722 *
16723 * Returns the number of IC "field" state objects which resolved to
16724 * this node, 0 if none resolved and -1 on internal errors.
16725 */
16726static int
16727xmlSchemaXPathEvaluate(xmlSchemaValidCtxtPtr vctxt,
16728 const xmlChar *namespaceName,
16729 const xmlChar *localName,
16730 xmlElementType nodeType)
16731{
16732 xmlSchemaIDCStateObjPtr sto, head = NULL, first;
16733 int retState, *change;
16734 int res, resolved = 0;
16735
16736 if (vctxt->xpathStates == NULL)
16737 return (0);
16738#if DEBUG_IDC
16739 {
16740 xmlChar *str = NULL;
16741 xmlGenericError(xmlGenericErrorContext,
16742 "IDC: EVAL on %s, depth %d, type %d\n",
16743 xmlSchemaFormatNsUriLocal(&str, namespaceName,
16744 localName), vctxt->depth, nodeType);
16745 FREE_AND_NULL(str)
16746 }
16747#endif
16748 /*
16749 * Process all active XPath state objects.
16750 */
16751 first = vctxt->xpathStates;
16752 sto = first;
16753 while (sto != head) {
16754 /*
16755 * Evaluate:
16756 * 1. all bottom-up state objs.
16757 * 2. top-down state objs. which are not marked as
16758 * matching or blocking.
16759 * Note: sto->history[0][0] will hold the depth of creation.
16760 */
16761 if (sto->topDown == 0) {
16762 /*
16763 * Always start from the beginning with bottom-up
16764 * evaluation.
16765 */
16766 change = sto->history[0];
16767 } else {
16768 change = sto->history[sto->nbHistory -1];
16769 if (change[1] < 0)
16770 goto next_sto;
16771 }
16772 /*
16773 * change[0] holds the depth of change.
16774 * change[1] holds the state index or the "match" or "blocked"
16775 * indicator.
16776 */
16777 retState = -1;
16778#if DEBUG_IDC
16779 if (sto->type == XPATH_STATE_OBJ_IDC_SELECTOR)
16780 xmlGenericError(xmlGenericErrorContext, "IDC: ['%s'] selector '%s'\n",
16781 sto->matcher->aidc->def->name, sto->sel->xpath);
16782 else
16783 xmlGenericError(xmlGenericErrorContext, "IDC: ['%s'] field '%s'\n",
16784 sto->matcher->aidc->def->name, sto->sel->xpath);
16785#endif
16786 if (sto->topDown == 0) {
16787 /*
16788 * The XPath will be evaluated using the
16789 * ancestor-or-self axis.
16790 */
16791#ifdef IDC_XPATH_SUPPORT
16792 res = xmlXPathWXSIDCEvalOneNode(sto->sel->xpathComp,
16793 change[1], &retState, nodeType,
16794 localName, namespaceName);
16795#else
16796 res = 0;
16797#endif
16798 if (res == 1) {
16799 int i;
16800
16801 if (nodeType == XML_ELEMENT_NODE)
16802 i = vctxt->depth -1;
16803 else
16804 i = vctxt->depth;
16805 while ((res == 1) && (i >= 0)) {
16806 /*
16807 * If we get a partial match, evaluate the
16808 * ancestor axis.
16809 */
16810#ifdef IDC_XPATH_SUPPORT
16811 res = xmlXPathWXSIDCEvalOneNode(sto->sel->xpathComp,
16812 retState, &retState, XML_ELEMENT_NODE,
16813 vctxt->elemInfos[i]->localName,
16814 vctxt->elemInfos[i]->namespaceName);
16815#endif
16816 i--;
16817 }
16818 }
16819 if (res == -1) {
16820 xmlSchemaVErr(vctxt, vctxt->node,
16821 XML_SCHEMAV_INTERNAL,
16822 "Internal error: xmlSchemaXPathEvaluate, "
16823 "failed to evaluate a node.\n",
16824 NULL, NULL);
16825 return (-1);
16826 } else if (res != 2) {
16827 /*
16828 * We will record matches only.
16829 */
16830#if DEBUG_IDC
16831 xmlGenericError(xmlGenericErrorContext, "IDC: "
16832 "no match\n");
16833#endif
16834 goto next_sto;
16835 }
16836 } else {
16837 /*
16838 * Push-down.
16839 */
16840#ifdef IDC_XPATH_SUPPORT
16841 res = xmlXPathWXSIDCEvalOneNode(sto->sel->xpathComp,
16842 change[1], &retState, nodeType,
16843 localName, namespaceName);
16844#else
16845 res = 0;
16846#endif
16847 if (res == -1) {
16848 xmlSchemaVErr(vctxt, vctxt->node,
16849 XML_SCHEMAV_INTERNAL,
16850 "Internal error: xmlSchemaXPathEvaluate, "
16851 "failed to evaluate a node.\n",
16852 NULL, NULL);
16853 return (-1);
16854 } else if (res == 0) {
16855 /*
16856 * No Match.
16857 */
16858#if DEBUG_IDC
16859 xmlGenericError(xmlGenericErrorContext,
16860 "IDC: no match, blocked\n");
16861#endif
16862 if (xmlSchemaXPathChangeState(vctxt, sto, -3) == -1)
16863 return (-1);
16864 } else if (res == 1) {
16865 /*
16866 * Partial match.
16867 */
16868#if DEBUG_IDC
16869 xmlGenericError(xmlGenericErrorContext,
16870 "IDC: partial match\n");
16871#endif
16872 if (xmlSchemaXPathChangeState(vctxt, sto, retState) == -1)
16873 return (-1);
16874 }
16875 }
16876 if (res != 2)
16877 goto next_sto;
16878 /*
16879 * Full match.
16880 */
16881#if DEBUG_IDC
16882 xmlGenericError(xmlGenericErrorContext, "IDC: "
16883 "final match\n");
16884#endif
16885 /*
16886 * Register a state-change.
16887 */
16888 if (xmlSchemaXPathChangeState(vctxt, sto, -2) == -1)
16889 return (-1);
16890 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
16891 xmlSchemaIDCSelectPtr sel;
16892 /*
16893 * Activate state objects for the IDC fields of
16894 * the IDC selector.
16895 */
16896#if DEBUG_IDC
16897 xmlGenericError(xmlGenericErrorContext, "IDC: "
16898 "activating field states\n");
16899#endif
16900 sel = sto->matcher->aidc->def->fields;
16901 while (sel != NULL) {
16902 if (xmlSchemaIDCAddStateObject(vctxt, sto->matcher,
16903 sel, sto, XPATH_STATE_OBJ_TYPE_IDC_FIELD) == -1)
16904 return (-1);
16905 sel = sel->next;
16906 }
16907 } else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
16908 /*
16909 * An IDC key node was found.
16910 */
16911#if DEBUG_IDC
16912 xmlGenericError(xmlGenericErrorContext,
16913 "IDC: key found\n");
16914#endif
16915 /*
16916 * Notify that the character value of this node is
16917 * needed.
16918 */
16919 if (resolved == 0)
16920 vctxt->elemInfo->flags |= XML_SCHEMA_ELEM_INFO_VALUE_NEEDED;
16921 resolved++;
16922 }
16923next_sto:
16924 if (sto->next == NULL) {
16925 /*
16926 * Evaluate field state objects created on this node.
16927 */
16928 head = first;
16929 sto = vctxt->xpathStates;
16930 } else
16931 sto = sto->next;
16932 }
16933 return (resolved);
16934}
16935
16936/**
16937 * xmlSchemaXPathProcessChanges:
16938 * @vctxt: the WXS validation context
16939 * @type: the simple/complex type of the current node if any at all
16940 *
16941 * Processes and pops the history items of the IDC state objects.
16942 * IDC key-sequences are validated/created on IDC bindings.
16943 *
16944 * Returns 0 on success and -1 on internal errors.
16945 */
16946static int
16947xmlSchemaXPathProcessChanges(xmlSchemaValidCtxtPtr vctxt,
16948 xmlSchemaTypePtr type)
16949{
16950 xmlSchemaIDCStateObjPtr sto, nextsto;
16951 int res, *change;
16952 xmlSchemaPSVIIDCKeyPtr key = NULL;
16953
16954 if (vctxt->xpathStates == NULL)
16955 return (0);
16956 sto = vctxt->xpathStates;
16957
16958#if DEBUG_IDC
16959 {
16960 xmlChar *str = NULL;
16961 xmlGenericError(xmlGenericErrorContext,
16962 "IDC: BACK on %s, depth %d\n",
16963 xmlSchemaFormatNsUriLocal(&str, vctxt->elemInfo->namespaceName,
16964 vctxt->elemInfo->localName), vctxt->depth);
16965 FREE_AND_NULL(str)
16966 }
16967#endif
16968
16969 /*
16970 * Evaluate the state objects.
16971 */
16972 while (sto != NULL) {
16973 /*
16974 * If (nbHistory == 1) then there are no history left
16975 * (only the initial one), so deregister the state object.
16976 */
16977 if (sto->nbHistory == 1)
16978 goto deregister_check;
16979
16980 change = sto->history[sto->nbHistory -1];
16981
16982 /*
16983 * Ony history at the current depth are of interest.
16984 */
16985 if (change[0] != vctxt->depth) {
16986 sto = sto->next;
16987 continue;
16988 }
16989
16990 if (change[1] == -2) {
16991 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
16992 if (! IS_SIMPLE_TYPE(type)) {
16993 /*
16994 * Not qualified if the field resolves to a node of non
16995 * simple type.
16996 */
16997 xmlSchemaVCustomErr(vctxt,
16998 XML_SCHEMAV_CVC_IDC,
16999 vctxt->node,
17000 (xmlSchemaTypePtr) sto->matcher->aidc->def,
17001 "The field '%s' does evaluate to a node of "
17002 "non-simple type", sto->sel->xpath);
17003
17004 sto->nbHistory--;
17005 sto = sto->next;
17006 continue;
17007 }
17008 if (vctxt->value == NULL) {
17009 /*
17010 * Failed to provide the normalized value; maby
17011 * the value was invalid.
17012 */
17013 xmlSchemaVErr(vctxt, NULL,
17014 XML_SCHEMAV_INTERNAL,
17015 "Internal error: xmlSchemaIDCEvaluateMatches, "
17016 "normalized node value not available.\n",
17017 NULL, NULL);
17018 sto->nbHistory--;
17019 sto = sto->next;
17020 continue;
17021 } else {
17022 xmlSchemaIDCMatcherPtr matcher = sto->matcher;
17023 xmlSchemaPSVIIDCKeyPtr *keySeq;
17024 int pos, sizeNeeded, index;
17025
17026 /*
17027 * The key will be anchored on the matcher's list of
17028 * key-sequences. The position in this list is determined
17029 * by the target node's depth relative to the matcher's
17030 * depth of creation (i.e. the depth of the scope element).
17031 * Note that sto->parent will be the selector state object,
17032 * which resolved to a target node. Since this match was
17033 * recorded in the last change entry, we can obtain the
17034 * depth of the target node from there.
17035 */
17036 pos = sto->parent->history[sto->parent->nbHistory -1][0] -
17037 matcher->depth;
17038 sizeNeeded = pos;
17039 index = sto->sel->index;
17040
17041 /*
17042 * Create/grow the array of key-sequences.
17043 */
17044 if (matcher->keySeqs == NULL) {
17045 if (pos > 9)
17046 matcher->sizeKeySeqs = pos * 2;
17047 else
17048 matcher->sizeKeySeqs = 10;
17049 matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
17050 xmlMalloc(matcher->sizeKeySeqs *
17051 sizeof(xmlSchemaPSVIIDCKeyPtr *));
17052 if (matcher->keySeqs == NULL) {
17053 xmlSchemaVErrMemory(NULL,
17054 "allocating an array of key-sequences",
17055 NULL);
17056 return(-1);
17057 }
17058 memset(matcher->keySeqs, 0,
17059 matcher->sizeKeySeqs *
17060 sizeof(xmlSchemaPSVIIDCKeyPtr *));
17061 } else if (pos >= matcher->sizeKeySeqs) {
17062 int i = matcher->sizeKeySeqs;
17063
17064 matcher->sizeKeySeqs *= 2;
17065 matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
17066 xmlRealloc(matcher->keySeqs,
17067 matcher->sizeKeySeqs *
17068 sizeof(xmlSchemaPSVIIDCKeyPtr *));
17069 if (matcher->keySeqs == NULL) {
17070 xmlSchemaVErrMemory(NULL,
17071 "reallocating an array of key-sequences",
17072 NULL);
17073 return (-1);
17074 }
17075 /*
17076 * The array needs to be NULLed.
17077 * TODO: Use memset?
17078 */
17079 for (; i < matcher->sizeKeySeqs; i++)
17080 matcher->keySeqs[i] = NULL;
17081 }
17082
17083 /*
17084 * Get/create the key-sequence.
17085 */
17086 keySeq = matcher->keySeqs[pos];
17087 if (keySeq == NULL) {
17088 goto create_sequence;
17089 } else {
17090 if (keySeq[index] != NULL) {
17091 /*
17092 * cvc-identity-constraint:
17093 * 3 For each node in the ·target node set· all
17094 * of the {fields}, with that node as the context
17095 * node, evaluate to either an empty node-set or
17096 * a node-set with exactly one member, which must
17097 * have a simple type.
17098 *
17099 * The key was already set; report an error.
17100 */
17101 xmlSchemaVCustomErr(vctxt,
17102 XML_SCHEMAV_CVC_IDC,
17103 vctxt->node, (xmlSchemaTypePtr) matcher->aidc->def,
17104 "The field '%s' evaluates to a node-set "
17105 "with more than one member", sto->sel->xpath);
17106 return (1);
17107 } else {
17108 goto create_key;
17109 }
17110 }
17111
17112create_sequence:
17113 /*
17114 * Create a key-sequence.
17115 */
17116 keySeq = (xmlSchemaPSVIIDCKeyPtr *) xmlMalloc(
17117 matcher->aidc->def->nbFields *
17118 sizeof(xmlSchemaPSVIIDCKeyPtr));
17119 if (keySeq == NULL) {
17120 xmlSchemaVErrMemory(NULL,
17121 "allocating an IDC key-sequence", NULL);
17122 return(-1);
17123 }
17124 memset(keySeq, 0, matcher->aidc->def->nbFields *
17125 sizeof(xmlSchemaPSVIIDCKeyPtr));
17126 matcher->keySeqs[pos] = keySeq;
17127create_key:
17128 /*
17129 * Created a key once per node only.
17130 */
17131 if (key == NULL) {
17132 key = (xmlSchemaPSVIIDCKeyPtr) xmlMalloc(
17133 sizeof(xmlSchemaPSVIIDCKey));
17134 if (key == NULL) {
17135 xmlSchemaVErrMemory(NULL,
17136 "allocating a IDC key", NULL);
17137 xmlFree(keySeq);
17138 matcher->keySeqs[pos] = NULL;
17139 return(-1);
17140 }
17141 /*
17142 * Consume the compiled value.
17143 */
17144 key->type = type;
17145 key->compValue = vctxt->value;
17146 vctxt->value = NULL;
17147 /*
17148 * Store the key in a global list.
17149 */
17150 if (xmlSchemaIDCStoreKey(vctxt, key) == -1) {
17151 xmlSchemaIDCFreeKey(key);
17152 return (-1);
17153 }
17154 }
17155 keySeq[index] = key;
17156 }
17157 } else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
17158
17159 xmlSchemaPSVIIDCKeyPtr **keySeq = NULL;
17160 xmlSchemaPSVIIDCBindingPtr bind;
17161 xmlSchemaPSVIIDCNodePtr ntItem;
17162 xmlSchemaIDCMatcherPtr matcher;
17163 xmlSchemaIDCPtr idc;
17164 int pos, i, j, nbKeys;
17165 /*
17166 * Here we have the following scenario:
17167 * An IDC 'selector' state object resolved to a target node,
17168 * during the time this target node was in the
17169 * ancestor-or-self axis, the 'field' state object(s) looked
17170 * out for matching nodes to create a key-sequence for this
17171 * target node. Now we are back to this target node and need
17172 * to put the key-sequence, together with the target node
17173 * itself, into the node-table of the corresponding IDC
17174 * binding.
17175 */
17176 matcher = sto->matcher;
17177 idc = matcher->aidc->def;
17178 nbKeys = idc->nbFields;
17179 pos = vctxt->depth - matcher->depth;
17180 /*
17181 * Check if the matcher has any key-sequences at all, plus
17182 * if it has a key-sequence for the current target node.
17183 */
17184 if ((matcher->keySeqs == NULL) ||
17185 (matcher->sizeKeySeqs <= pos)) {
17186 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
17187 goto selector_key_error;
17188 else
17189 goto selector_leave;
17190 }
17191
17192 keySeq = &(matcher->keySeqs[pos]);
17193 if (*keySeq == NULL) {
17194 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
17195 goto selector_key_error;
17196 else
17197 goto selector_leave;
17198 }
17199
17200 for (i = 0; i < nbKeys; i++) {
17201 if (*keySeq[i] == NULL) {
17202 /*
17203 * Not qualified, if not all fields did resolve.
17204 */
17205 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY) {
17206 /*
17207 * All fields of a "key" IDC must resolve.
17208 */
17209 goto selector_key_error;
17210 }
17211 goto selector_leave;
17212 }
17213 }
17214 /*
17215 * All fields did resolve.
17216 */
17217
17218 /*
17219 * 4.1 If the {identity-constraint category} is unique(/key),
17220 * then no two members of the ·qualified node set· have
17221 * ·key-sequences· whose members are pairwise equal, as
17222 * defined by Equal in [XML Schemas: Datatypes].
17223 *
17224 * Get the IDC binding from the matcher and check for
17225 * duplicate key-sequences.
17226 */
17227 bind = xmlSchemaIDCAquireBinding(vctxt, matcher);
17228 if ((idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) &&
17229 (bind->nbNodes != 0)) {
17230 xmlSchemaPSVIIDCKeyPtr key, bkey, *bkeySeq;
17231
17232 i = 0;
17233 /*
17234 * Compare the key-sequences, key by key.
17235 */
17236 do {
17237 bkeySeq = bind->nodeTable[i]->keys;
17238 for (j = 0; j < nbKeys; j++) {
17239 key = *keySeq[j];
17240 bkey = bkeySeq[j];
17241 res = xmlSchemaAreValuesEqual(key->type,
17242 key->compValue, bkey->type, bkey->compValue);
17243 if (res == -1) {
17244 return (-1);
17245 } else if (res == 0)
17246 break;
17247 }
17248 if (res == 1) {
17249 /*
17250 * Duplicate found.
17251 */
17252 break;
17253 }
17254 i++;
17255 } while (i < bind->nbNodes);
17256 if (i != bind->nbNodes) {
17257 /*
17258 * TODO: Try to report the key-sequence.
17259 */
17260 xmlSchemaVCustomErr(vctxt,
17261 XML_SCHEMAV_CVC_IDC,
17262 vctxt->node,
17263 (xmlSchemaTypePtr) idc,
17264 "Duplicate key-sequence found", NULL);
17265
17266 goto selector_leave;
17267 }
17268 }
17269 /*
17270 * Add a node-table item to the IDC binding.
17271 */
17272 ntItem = (xmlSchemaPSVIIDCNodePtr) xmlMalloc(
17273 sizeof(xmlSchemaPSVIIDCNode));
17274 if (ntItem == NULL) {
17275 xmlSchemaVErrMemory(NULL,
17276 "allocating an IDC node-table item", NULL);
17277 xmlFree(*keySeq);
17278 *keySeq = NULL;
17279 return(-1);
17280 }
17281 memset(ntItem, 0, sizeof(xmlSchemaPSVIIDCNode));
17282
17283 /*
17284 * Store the node-table item on global list.
17285 */
17286 if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) {
17287 if (xmlSchemaIDCStoreNodeTableItem(vctxt, ntItem) == -1) {
17288 xmlFree(ntItem);
17289 xmlFree(*keySeq);
17290 *keySeq = NULL;
17291 return (-1);
17292 }
17293 }
17294 /*
17295 * Init the node-table item. Consume the key-sequence.
17296 */
17297 ntItem->node = vctxt->node;
17298 ntItem->keys = *keySeq;
17299 *keySeq = NULL;
17300 if (xmlSchemaIDCAppendNodeTableItem(bind, ntItem) == -1) {
17301 if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
17302 /*
17303 * Free the item, since keyref items won't be
17304 * put on a global list.
17305 */
17306 xmlFree(ntItem->keys);
17307 xmlFree(ntItem);
17308 }
17309 return (-1);
17310 }
17311
17312 goto selector_leave;
17313selector_key_error:
17314 /*
17315 * 4.2.1 (KEY) The ·target node set· and the
17316 * ·qualified node set· are equal, that is, every
17317 * member of the ·target node set· is also a member
17318 * of the ·qualified node set· and vice versa.
17319 */
17320 xmlSchemaVCustomErr(vctxt,
17321 XML_SCHEMAV_CVC_IDC,
17322 vctxt->node,
17323 (xmlSchemaTypePtr) idc,
17324 "All 'key' fields must evaluate to a node",
17325 NULL);
17326selector_leave:
17327 /*
17328 * Free the key-sequence if not added to the IDC table.
17329 */
17330 if (*keySeq != NULL) {
17331 xmlFree(*keySeq);
17332 *keySeq = NULL;
17333 }
17334 } /* if selector */
17335 } /* if matched */
17336
17337 sto->nbHistory--;
17338
17339deregister_check:
17340 /*
17341 * Deregister state objects if they reach the depth of creation.
17342 * Note that this has to be checked before and after processing
17343 * any history if the state object resolved to partially/fully
17344 * to a node on which it was created as well, since this scenario
17345 * created two entries in the list of history for the same node.
17346 */
17347 if ((sto->nbHistory == 1) && (sto->history[0][0] == vctxt->depth)) {
17348#if DEBUG_IDC
17349 xmlGenericError(xmlGenericErrorContext, "IDC: STO pop '%s'\n",
17350 sto->sel->xpath);
17351#endif
17352 if (vctxt->xpathStates != sto) {
17353 xmlSchemaVErr(vctxt, vctxt->node,
17354 XML_SCHEMAV_INTERNAL,
17355 "Internal error: xmlSchemaXPathProcessChanges, "
17356 "The state object to be removed is not the first "
17357 "in the list.\n",
17358 NULL, NULL);
17359 }
17360 sto->nbHistory = 0;
17361 nextsto = sto->next;
17362 /*
17363 * Unlink from the list of active XPath state objects.
17364 */
17365 vctxt->xpathStates = sto->next;
17366 sto->next = vctxt->xpathStatePool;
17367 /*
17368 * Link it to the pool of reusable state objects.
17369 */
17370 vctxt->xpathStatePool = sto;
17371 sto = nextsto;
17372 } else
17373 sto = sto->next;
17374 } /* while (sto != NULL) */
17375 return (0);
17376}
17377
17378/**
17379 * xmlSchemaIDCRegisterMatchers:
17380 * @vctxt: the WXS validation context
17381 * @elemDecl: the element declaration
17382 *
17383 * Creates helper objects to evaluate IDC selectors/fields
17384 * successively.
17385 *
17386 * Returns 0 if OK and -1 on internal errors.
17387 */
17388static int
17389xmlSchemaIDCRegisterMatchers(xmlSchemaValidCtxtPtr vctxt,
17390 xmlSchemaElementPtr elemDecl)
17391{
17392 xmlSchemaIDCMatcherPtr matcher, last = NULL;
17393 xmlSchemaIDCPtr idc, refIdc;
17394 xmlSchemaIDCAugPtr aidc;
17395
17396 idc = (xmlSchemaIDCPtr) elemDecl->idcs;
17397 if (idc == NULL)
17398 return (0);
17399
17400#if DEBUG_IDC
17401 {
17402 xmlChar *str = NULL;
17403 xmlGenericError(xmlGenericErrorContext,
17404 "IDC: MATCHERS on %s, depth %d\n",
17405 xmlSchemaFormatNsUriLocal(&str, vctxt->elemInfo->namespaceName,
17406 vctxt->elemInfo->localName), vctxt->depth);
17407 FREE_AND_NULL(str)
17408 }
17409#endif
17410 if (vctxt->elemInfo->idcMatchers != NULL) {
17411 xmlSchemaVErr(vctxt, vctxt->node,
17412 XML_SCHEMAV_INTERNAL,
17413 "Internal error: xmlSchemaIDCRegisterMatchers: "
17414 "The chain of IDC matchers is expected to be empty.\n",
17415 NULL, NULL);
17416 return (-1);
17417 }
17418 do {
17419 if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
17420 /*
17421 * Since IDCs bubbles are expensive we need to know the
17422 * depth at which the bubbles should stop; this will be
17423 * the depth of the top-most keyref IDC. If no keyref
17424 * references a key/unique IDC, the bubbleDepth will
17425 * be -1, indicating that no bubbles are needed.
17426 */
17427 refIdc = (xmlSchemaIDCPtr) idc->ref->item;
17428 if (refIdc != NULL) {
17429 /*
17430 * Lookup the augmented IDC.
17431 */
17432 aidc = vctxt->aidcs;
17433 while (aidc != NULL) {
17434 if (aidc->def == refIdc)
17435 break;
17436 aidc = aidc->next;
17437 }
17438 if (aidc == NULL) {
17439 xmlSchemaVErr(vctxt, vctxt->node,
17440 XML_SCHEMAV_INTERNAL,
17441 "Internal error: xmlSchemaIDCRegisterMatchers: "
17442 "Could not find an augmented IDC item for an IDC "
17443 "definition.\n",
17444 NULL, NULL);
17445 return (-1);
17446 }
17447 if ((aidc->bubbleDepth == -1) ||
17448 (vctxt->depth < aidc->bubbleDepth))
17449 aidc->bubbleDepth = vctxt->depth;
17450 }
17451 }
17452 /*
17453 * Lookup the augmented IDC item for the IDC definition.
17454 */
17455 aidc = vctxt->aidcs;
17456 while (aidc != NULL) {
17457 if (aidc->def == idc)
17458 break;
17459 aidc = aidc->next;
17460 }
17461 if (aidc == NULL) {
17462 xmlSchemaVErr(vctxt, vctxt->node,
17463 XML_SCHEMAV_INTERNAL,
17464 "Internal error: xmlSchemaIDCRegisterMatchers: "
17465 "Could not find an augmented IDC item for an IDC definition.\n",
17466 NULL, NULL);
17467 return (-1);
17468 }
17469 /*
17470 * Create an IDC matcher for every IDC definition.
17471 */
17472 matcher = (xmlSchemaIDCMatcherPtr)
17473 xmlMalloc(sizeof(xmlSchemaIDCMatcher));
17474 if (matcher == NULL) {
17475 xmlSchemaVErrMemory(vctxt,
17476 "allocating an IDC matcher", NULL);
17477 return (-1);
17478 }
17479 memset(matcher, 0, sizeof(xmlSchemaIDCMatcher));
17480 if (last == NULL)
17481 vctxt->elemInfo->idcMatchers = matcher;
17482 else
17483 last->next = matcher;
17484 last = matcher;
17485
17486 matcher->type = IDC_MATCHER;
17487 matcher->depth = vctxt->depth;
17488 matcher->aidc = aidc;
17489#if DEBUG_IDC
17490 xmlGenericError(xmlGenericErrorContext, "IDC: register matcher\n");
17491#endif
17492 /*
17493 * Init the automaton state object.
17494 */
17495 if (xmlSchemaIDCAddStateObject(vctxt, matcher,
17496 idc->selector, NULL, XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) == -1)
17497 return (-1);
17498
17499 idc = idc->next;
17500 } while (idc != NULL);
17501 return (0);
17502}
17503
17504/**
17505 * xmlSchemaBubbleIDCNodeTables:
17506 * @depth: the current tree depth
17507 *
17508 * Merges IDC bindings of an element at @depth into the corresponding IDC
17509 * bindings of its parent element. If a duplicate note-table entry is found,
17510 * both, the parent node-table entry and child entry are discarded from the
17511 * node-table of the parent.
17512 *
17513 * Returns 0 if OK and -1 on internal errors.
17514 */
17515static int
17516xmlSchemaBubbleIDCNodeTables(xmlSchemaValidCtxtPtr vctxt)
17517{
17518 xmlSchemaPSVIIDCBindingPtr bind; /* IDC bindings of the current node. */
17519 xmlSchemaPSVIIDCBindingPtr *parTable, parBind, lastParBind; /* parent IDC bindings. */
17520 xmlSchemaPSVIIDCNodePtr node, parNode; /* node-table entries. */
17521 xmlSchemaPSVIIDCKeyPtr key, parKey; /* keys of in a key-sequence. */
17522 xmlSchemaIDCAugPtr aidc;
17523 int i, j, k, ret, oldNum, newDupls = 0;
17524 int duplTop;
17525
17526 /*
17527 * The node table has the following sections:
17528 *
17529 * O --> old node-table entries (first)
17530 * O
17531 * + --> new node-table entries
17532 * +
17533 * % --> new duplicate node-table entries
17534 * %
17535 * # --> old duplicate node-table entries
17536 * # (last)
17537 *
17538 */
17539 bind = vctxt->elemInfo->idcTable;
17540 if (bind == NULL) {
17541 /* Fine, no table, no bubbles. */
17542 return (0);
17543 }
17544
17545 parTable = &(vctxt->elemInfos[vctxt->depth -1]->idcTable);
17546 /*
17547 * Walk all bindings; create new or add to existing bindings.
17548 * Remove duplicate key-sequences.
17549 */
17550start_binding:
17551 while (bind != NULL) {
17552 /*
17553 * Skip keyref IDCs.
17554 */
17555 if (bind->definition->type == XML_SCHEMA_TYPE_IDC_KEYREF)
17556 continue;
17557 /*
17558 * Check if the key/unique IDC table needs to be bubbled.
17559 */
17560 aidc = vctxt->aidcs;
17561 do {
17562 if (aidc->def == bind->definition) {
17563 if (aidc->bubbleDepth == vctxt->depth) {
17564 bind = bind->next;
17565 goto start_binding;
17566 }
17567 break;
17568 }
17569 aidc = aidc->next;
17570 } while (aidc != NULL);
17571 if (parTable != NULL)
17572 parBind = *parTable;
17573 while (parBind != NULL) {
17574 /*
17575 * Search a matching parent binding for the
17576 * IDC definition.
17577 */
17578 if (parBind->definition == bind->definition) {
17579
17580 /*
17581 * Compare every node-table entry of the child node,
17582 * i.e. the key-sequence within, ...
17583 */
17584 oldNum = parBind->nbNodes; /* Skip newly added items. */
17585 duplTop = oldNum + parBind->nbDupls;
17586
17587 for (i = 0; i < bind->nbNodes; i++) {
17588 node = bind->nodeTable[i];
17589 if (node == NULL)
17590 continue;
17591 /*
17592 * ...with every key-sequence of the parent node, already
17593 * evaluated to be a duplicate key-sequence.
17594 */
17595 if (parBind->nbDupls != 0) {
17596 j = bind->nbNodes + newDupls;
17597 while (j < duplTop) {
17598 parNode = parBind->nodeTable[j];
17599 for (k = 0; k < bind->definition->nbFields; k++) {
17600 key = node->keys[k];
17601 parKey = parNode->keys[k];
17602 ret = xmlSchemaAreValuesEqual(key->type,
17603 key->compValue,
17604 parKey->type, parKey->compValue);
17605 if (ret == -1) {
17606 /* TODO: Internal error */
17607 return(-1);
17608 } else if (ret == 0)
17609 break;
17610
17611 }
17612 if (ret == 1)
17613 /* Duplicate found. */
17614 break;
17615 j++;
17616 }
17617 if (j != duplTop) {
17618 /* Duplicate found. */
17619 continue;
17620 }
17621 }
17622 /*
17623 * ... and with every key-sequence of the parent node.
17624 */
17625 j = 0;
17626 while (j < oldNum) {
17627 parNode = parBind->nodeTable[j];
17628 /*
17629 * Compare key by key.
17630 */
17631 for (k = 0; k < parBind->definition->nbFields; k++) {
17632 key = node->keys[k];
17633 parKey = parNode->keys[k];
17634
17635 ret = xmlSchemaAreValuesEqual(key->type,
17636 key->compValue,
17637 parKey->type, parKey->compValue);
17638 if (ret == -1) {
17639 /* TODO: Internal error */
17640 } else if (ret == 0)
17641 break;
17642
17643 }
17644 if (ret == 1)
17645 /*
17646 * The key-sequences are equal.
17647 */
17648 break;
17649 j++;
17650 }
17651 if (j != oldNum) {
17652 /*
17653 * Handle duplicates.
17654 */
17655 newDupls++;
17656 oldNum--;
17657 parBind->nbNodes--;
17658 /*
17659 * Move last old item to pos of duplicate.
17660 */
17661 parBind->nodeTable[j] =
17662 parBind->nodeTable[oldNum];
17663
17664 if (parBind->nbNodes != oldNum) {
17665 /*
17666 * If new items exist, move last new item to
17667 * last of old items.
17668 */
17669 parBind->nodeTable[oldNum] =
17670 parBind->nodeTable[parBind->nbNodes];
17671 }
17672 /*
17673 * Move duplicate to last pos of new/old items.
17674 */
17675 parBind->nodeTable[parBind->nbNodes] = parNode;
17676
17677 } else {
17678 /*
17679 * Add the node-table entry (node and key-sequence) of
17680 * the child node to the node table of the parent node.
17681 */
17682 if (parBind->nodeTable == NULL) {
17683 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
17684 xmlMalloc(1 * sizeof(xmlSchemaPSVIIDCNodePtr));
17685 if (parBind->nodeTable == NULL) {
17686 xmlSchemaVErrMemory(NULL,
17687 "allocating IDC list of node-table items", NULL);
17688 return(-1);
17689 }
17690 parBind->sizeNodes = 1;
17691 } else if (duplTop >= parBind->sizeNodes) {
17692 parBind->sizeNodes++;
17693 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
17694 xmlRealloc(parBind->nodeTable, parBind->sizeNodes *
17695 sizeof(xmlSchemaPSVIIDCNodePtr));
17696 if (parBind->nodeTable == NULL) {
17697 xmlSchemaVErrMemory(NULL,
17698 "re-allocating IDC list of node-table items", NULL);
17699 return(-1);
17700 }
17701 }
17702
17703 /*
17704 * Move first old duplicate to last position
17705 * of old duplicates +1.
17706 */
17707 if (parBind->nbDupls != 0) {
17708 parBind->nodeTable[duplTop] =
17709 parBind->nodeTable[parBind->nbNodes + newDupls];
17710 }
17711 /*
17712 * Move first new duplicate to last position of
17713 * new duplicates +1.
17714 */
17715 if (newDupls != 0) {
17716 parBind->nodeTable[parBind->nbNodes + newDupls] =
17717 parBind->nodeTable[parBind->nbNodes];
17718 }
17719 /*
17720 * Append the new node-table entry to the 'new node-table
17721 * entries' section.
17722 */
17723 parBind->nodeTable[parBind->nbNodes] = node;
17724 parBind->nbNodes++;
17725 duplTop++;
17726 }
17727 }
17728 parBind->nbDupls += newDupls;
17729 break;
17730 }
17731 if (parBind->next == NULL)
17732 lastParBind = parBind;
17733 parBind = parBind->next;
17734 }
17735 if (parBind == NULL) {
17736 /*
17737 * No binding for the IDC was found: create a new one and
17738 * copy all node-tables.
17739 */
17740 parBind = xmlSchemaIDCNewBinding(bind->definition);
17741 if (parBind == NULL)
17742 return(-1);
17743
17744 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
17745 xmlMalloc(bind->nbNodes * sizeof(xmlSchemaPSVIIDCNodePtr));
17746 if (parBind->nodeTable == NULL) {
17747 xmlSchemaVErrMemory(NULL,
17748 "allocating an array of IDC node-table items", NULL);
17749 xmlSchemaIDCFreeBinding(parBind);
17750 return(-1);
17751 }
17752 parBind->sizeNodes = bind->nbNodes;
17753 memcpy(parBind->nodeTable, bind->nodeTable,
17754 bind->nbNodes * sizeof(xmlSchemaPSVIIDCNodePtr));
17755 /*
17756 for (i = 1; i < bind->nbNodes; i++)
17757 parBind->nodeTable[i] = bind->nodeTable[i];
17758 */
17759 if (*parTable == NULL)
17760 *parTable = parBind;
17761 else
17762 lastParBind->next = parBind;
17763 }
17764 bind = bind->next;
17765 }
17766 return (0);
17767}
17768
17769/**
17770 * xmlSchemaCheckCVCIDCKeyRef:
17771 * @vctxt: the WXS validation context
17772 * @elemDecl: the element declaration
17773 *
17774 * Check the cvc-idc-keyref constraints.
17775 */
17776static int
17777xmlSchemaCheckCVCIDCKeyRef(xmlSchemaValidCtxtPtr vctxt)
17778{
17779 xmlSchemaPSVIIDCBindingPtr refbind, bind;
17780
17781 refbind = vctxt->elemInfo->idcTable;
17782 /*
17783 * Find a keyref.
17784 */
17785 while (refbind != NULL) {
17786 if (refbind->definition->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
17787 int i, j, k, res;
17788 xmlSchemaPSVIIDCKeyPtr *refKeys, *keys;
17789 xmlSchemaPSVIIDCKeyPtr refKey, key;
17790
17791 /*
17792 * Find the referred key/unique.
17793 */
17794 bind = vctxt->elemInfo->idcTable;
17795 do {
17796 if ((xmlSchemaIDCPtr) refbind->definition->ref->item ==
17797 bind->definition)
17798 break;
17799 bind = bind->next;
17800 } while (bind != NULL);
17801
17802 /*
17803 * Search for a matching key-sequences.
17804 */
17805 for (i = 0; i < refbind->nbNodes; i++) {
17806 res = 0;
17807 if (bind != NULL) {
17808 refKeys = refbind->nodeTable[i]->keys;
17809 for (j = 0; j < bind->nbNodes; j++) {
17810 keys = bind->nodeTable[j]->keys;
17811 for (k = 0; k < bind->definition->nbFields; k++) {
17812 refKey = refKeys[k];
17813 key = keys[k];
17814 res = xmlSchemaAreValuesEqual(key->type, key->compValue,
17815 refKey->type, refKey->compValue);
17816 if (res == 0)
17817 break;
17818 else if (res == -1) {
17819 return (-1);
17820 }
17821 }
17822 if (res == 1) {
17823 /*
17824 * Match found.
17825 */
17826 break;
17827 }
17828 }
17829 }
17830 if (res == 0) {
17831 /* TODO: Report the key-sequence. */
17832 xmlSchemaVCustomErr(vctxt,
17833 XML_SCHEMAV_CVC_IDC,
17834 refbind->nodeTable[i]->node,
17835 (xmlSchemaTypePtr) refbind->definition,
17836 "No matching key-sequence found", NULL);
17837 }
17838 }
17839 }
17840 refbind = refbind->next;
17841 }
17842 return (0);
17843}
17844#endif /* IDC_ENABLED */
17845
17846#ifdef ELEM_INFO_ENABLED
17847/**
17848 * xmlSchemaBeginElement:
17849 * @vctxt: the WXS validation context
17850 *
17851 * Just a temporary workaround to simulate streaming validation
17852 * a bit.
17853 */
17854static void
17855xmlSchemaBeginElement(xmlSchemaValidCtxtPtr vctxt)
17856{
17857 vctxt->depth++;
17858 vctxt->elemInfo = xmlSchemaGetFreshElemInfo(vctxt);
17859 vctxt->elemInfo->node = vctxt->node;
17860 vctxt->elemInfo->localName = vctxt->node->name;
17861 if (vctxt->node->ns != NULL)
17862 vctxt->elemInfo->namespaceName = vctxt->node->ns->href;
17863 else
17864 vctxt->elemInfo->namespaceName = NULL;
17865}
17866
17867/**
17868 * xmlSchemaEndElement:
17869 * @vctxt: the WXS validation context
17870 *
17871 * Just a temporary workaround to simulate streaming validation
17872 * a bit.
17873 */
17874static void
17875xmlSchemaEndElement(xmlSchemaValidCtxtPtr vctxt)
17876{
17877 if (vctxt->depth < 0) {
17878 /* TODO: raise error? */
17879 vctxt->depth--;
17880 return;
17881 }
17882#ifdef IDC_ENABLED
17883 /*
17884 * Evaluate the history of changes of active state objects.
17885 */
17886 xmlSchemaXPathProcessChanges(vctxt, vctxt->elemInfo->typeDef);
17887
17888 if (vctxt->elemInfo->value != NULL) {
17889 xmlSchemaFreeValue(vctxt->elemInfo->value);
17890 vctxt->elemInfo->value = NULL;
17891 }
17892 /*
17893 * TODO: 6 The element information item must be ·valid· with respect to each of
17894 * the {identity-constraint definitions} as per Identity-constraint
17895 * Satisfied (§3.11.4).
17896 */
17897 /*
17898 * Validate IDC keyrefs.
17899 */
17900 xmlSchemaCheckCVCIDCKeyRef(vctxt);
17901#endif
17902
17903 /*
17904 * Merge/free the IDC table.
17905 */
17906 if (vctxt->elemInfo->idcTable != NULL) {
17907#ifdef DEBUG_IDC
17908 xmlSchemaDebugDumpIDCTable(stdout,
17909 vctxt->elemInfo->namespaceName,
17910 vctxt->elemInfo->localName,
17911 vctxt->elemInfo->idcTable);
17912#endif
17913#ifdef IDC_ENABLED
17914 if (vctxt->depth > 0) {
17915 /*
17916 * Merge the IDC node table with the table of the parent node.
17917 */
17918 xmlSchemaBubbleIDCNodeTables(vctxt);
17919 }
17920 /*
17921 * TODO: Don't free the PSVI IDC tables if they are
17922 * requested for the PSVI.
17923 */
17924 xmlSchemaIDCFreeIDCTable(vctxt->elemInfo->idcTable);
17925#endif
17926 vctxt->elemInfo->idcTable = NULL;
17927 }
17928
17929 /*
17930 * Cleanup IDC matchers.
17931 */
17932#ifdef IDC_ENABLED
17933 if (vctxt->elemInfo->idcMatchers != NULL) {
17934 xmlSchemaIDCFreeMatcherList(vctxt->elemInfo->idcMatchers);
17935 vctxt->elemInfo->idcMatchers = NULL;
17936 }
17937#endif
17938
17939 /*
17940 * Skip further processing if we are on the validation root.
17941 */
17942 if (vctxt->depth == 0) {
17943 vctxt->depth--;
17944 return;
17945 }
17946
17947 /*
17948 * Reset the bubbleDepth if needed.
17949 */
17950#ifdef IDC_ENABLED
17951 if (vctxt->aidcs != NULL) {
17952 xmlSchemaIDCAugPtr aidc = vctxt->aidcs;
17953 do {
17954 if (aidc->bubbleDepth == vctxt->depth) {
17955 /*
17956 * A bubbleDepth of a key/unique IDC matches the current
17957 * depth, this means that we are leaving the scope of the
17958 * top-most keyref IDC.
17959 */
17960 aidc->bubbleDepth = -1;
17961 }
17962 aidc = aidc->next;
17963 } while (aidc != NULL);
17964 }
17965#endif
17966 vctxt->depth--;
17967 vctxt->elemInfo = vctxt->elemInfos[vctxt->depth];
17968 vctxt->node = vctxt->elemInfo->node;
17969}
17970
17971#endif /* ELEM_INFO_ENABLED */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017972
17973/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017974 * xmlSchemaValidateElementByDeclaration:
Daniel Veillard4255d502002-04-16 15:50:10 +000017975 * @ctxt: a schema validation context
17976 * @node: the top node.
17977 *
17978 * Validate the content of an element type.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017979 * Validation Rule: Element Locally Valid (Element)
Daniel Veillard4255d502002-04-16 15:50:10 +000017980 *
17981 * Returns 0 if the element is schemas valid, a positive error code
17982 * number otherwise and -1 in case of internal or API error.
17983 */
17984static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017985xmlSchemaValidateElementByDeclaration(xmlSchemaValidCtxtPtr ctxt,
17986 xmlSchemaElementPtr elemDecl)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017987{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017988 xmlNodePtr elem;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017989 int ret = 0;
17990 xmlSchemaTypePtr actualType = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017991 xmlAttrPtr attr;
17992 xmlChar *attrValue;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017993 int nilled = 0, elemHasContent = -1;
Daniel Veillard3646d642004-06-02 19:19:14 +000017994
17995 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017996 * This one is called by xmlSchemaValidateElementByWildcardInternal,
17997 * xmlSchemaValidateElementByAnyType and xmlSchemaValidateElement.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017998 * Note that @elemDecl will be the declaration and never the
17999 * reference to a declaration.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018000 */
Daniel Veillard3646d642004-06-02 19:19:14 +000018001
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018002 if (ctxt == NULL) {
18003 xmlSchemaVErr(ctxt, NULL, XML_SCHEMAV_INTERNAL,
18004 "Internal error: xmlSchemaValidateElementByDeclaration, "
18005 "bad arguments.\n",
18006 NULL, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018007 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000018008 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018009
18010 elem = ctxt->node;
18011
18012 /*
18013 * cvc-elt (3.3.4) : 1
18014 */
18015 if (elemDecl == NULL) {
18016 xmlSchemaVCustomErr(ctxt,
18017 XML_SCHEMAV_CVC_ELT_1,
18018 elem, NULL,
18019 "No matching declaration available", NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018020 /*
18021 * Evaluate IDCs even if an error occured.
18022 */
18023#ifdef IDC_ENABLED
18024 if (xmlSchemaXPathEvaluate(ctxt, ctxt->elemInfo->namespaceName,
18025 ctxt->elemInfo->localName, XML_ELEMENT_NODE) == -1)
18026 return (-1);
18027#endif
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018028 return (ctxt->err);
18029 }
18030 /*
18031 * cvc-elt (3.3.4) : 2
18032 */
18033 if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT) {
18034 xmlSchemaVCustomErr(ctxt,
18035 XML_SCHEMAV_CVC_ELT_2,
18036 elem, NULL,
18037 "The element declaration is abstract", NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018038 /*
18039 * Evaluate IDCs even if an error occured.
18040 */
18041#ifdef IDC_ENABLED
18042 if (xmlSchemaXPathEvaluate(ctxt, ctxt->elemInfo->namespaceName,
18043 ctxt->elemInfo->localName, XML_ELEMENT_NODE) == -1)
18044 return (-1);
18045#endif
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018046 return (ctxt->err);
18047 }
18048
18049 /*
18050 * cvc-elt (3.3.4) : 3
18051 * Handle 'xsi:nil'.
18052 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018053
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018054 attr = xmlHasNsProp(elem, BAD_CAST "nil", xmlSchemaInstanceNs);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018055 if (attr != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018056 attrValue = xmlNodeGetContent((xmlNodePtr) attr);
18057 ctxt->node = (xmlNodePtr) attr;
18058 ctxt->cur = attr->children;
18059 ret = xmlSchemaValidateSimpleTypeValue(ctxt,
18060 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
18061 BAD_CAST attrValue, 1, 1, 1, 1);
18062 ctxt->node = elem;
18063 ctxt->type = (xmlSchemaTypePtr) elemDecl;
18064 if (ret < 0) {
18065 xmlSchemaVCustomErr(ctxt,
18066 XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018067 (xmlNodePtr) attr, (xmlSchemaTypePtr) elemDecl,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018068 "Internal error: xmlSchemaValidateElementByDeclaration, "
18069 "validating the attribute 'xsi:nil'", NULL);
18070 if (attrValue != NULL)
18071 xmlFree(attrValue);
18072 return (-1);
18073 }
18074 if ((elemDecl->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018075 /*
18076 * cvc-elt (3.3.4) : 3.1
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018077 */
18078 xmlSchemaVCustomErr(ctxt,
18079 XML_SCHEMAV_CVC_ELT_3_1,
18080 elem, NULL,
18081 "The element is not 'nillable'", NULL);
18082 } else {
18083 if (xmlStrEqual(BAD_CAST attrValue, BAD_CAST "true") ||
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018084 xmlStrEqual(BAD_CAST attrValue, BAD_CAST "1")) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018085 ret = 0;
18086 /*
18087 * cvc-elt (3.3.4) : 3.2.1
18088 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018089 elemHasContent = xmlSchemaHasElemOrCharContent(elem);
18090 if (elemHasContent == 1) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018091 xmlSchemaVCustomErr(ctxt,
18092 XML_SCHEMAV_CVC_ELT_3_2_1,
18093 /* XML_SCHEMAS_ERR_NOTEMPTY, */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018094 elem, (xmlSchemaTypePtr) elemDecl,
18095 "The 'nilled' element must have no character or "
18096 "element content", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018097 ret = XML_SCHEMAV_CVC_ELT_3_2_1;
18098 }
18099 /*
18100 * cvc-elt (3.3.4) : 3.2.2
18101 */
18102 if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) &&
18103 (elemDecl->value != NULL)) {
18104 xmlSchemaVCustomErr(ctxt, XML_SCHEMAV_CVC_ELT_3_2_2,
18105 /* XML_SCHEMAS_ERR_HAVEDEFAULT, */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018106 elem, (xmlSchemaTypePtr) elemDecl,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018107 "There is a fixed value constraint defined for "
18108 "the 'nilled' element", NULL);
18109 ret = XML_SCHEMAV_CVC_ELT_3_2_2;
18110 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018111 if (ret == 0)
18112 nilled = 1;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018113 }
18114 }
18115 if (attrValue != NULL)
18116 xmlFree(attrValue);
18117 }
18118
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018119
18120 actualType = elemDecl->subtypes;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018121 /*
18122 * cvc-elt (3.3.4) : 4
18123 * Handle 'xsi:type'.
18124 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018125
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018126 attr = xmlHasNsProp(elem, BAD_CAST "type", xmlSchemaInstanceNs);
18127 if (attr != NULL) {
18128 xmlChar *nsName = NULL, *local = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018129
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018130 /*
18131 * TODO: We should report a *warning* that the type was overriden
18132 * by the instance.
18133 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018134
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018135 /*
18136 * cvc-elt (3.3.4) : 4.1
18137 */
18138 attrValue = xmlNodeGetContent((xmlNodePtr) attr);
18139 ret = xmlSchemaValQNameAcquire(attrValue, attr->parent,
18140 &nsName, &local);
18141 if (ret < 0) {
18142 xmlSchemaVCustomErr(ctxt,
18143 XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018144 (xmlNodePtr) attr, (xmlSchemaTypePtr) elemDecl,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018145 "Internal error: xmlSchemaValidateElementByDeclaration, "
18146 "validating the attribute 'xsi:type'", NULL);;
18147 FREE_AND_NULL(attrValue)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018148 FREE_AND_NULL(nsName)
18149 FREE_AND_NULL(local)
18150 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018151 } else if (ret == 1) {
18152 xmlSchemaVSimpleTypeErr(ctxt,
18153 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1,
18154 (xmlNodePtr) attr, attrValue,
18155 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME));
18156 } else if (ret == 2) {
18157 xmlSchemaVCustomErr(ctxt,
18158 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1,
18159 (xmlNodePtr) attr,
18160 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
18161 "The QName value '%s' has no "
18162 "corresponding namespace declaration in scope",
18163 attrValue);
18164 } else {
18165 /*
18166 * cvc-elt (3.3.4) : 4.2
18167 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018168 actualType = xmlSchemaGetType(ctxt->schema, local, nsName);
18169 if (actualType == NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018170 xmlChar *strA = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018171
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018172 xmlSchemaVCustomErr(ctxt,
18173 XML_SCHEMAV_CVC_ELT_4_2,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018174 (xmlNodePtr) attr,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018175 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
18176 "The value %s does not resolve to a type "
18177 "definition",
18178 xmlSchemaFormatNsUriLocal(&strA, nsName, local));
18179 FREE_AND_NULL(strA);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018180 } else {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018181 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018182 * URGENT TODO: cvc-elt (3.3.4) : 4.3 (Type Derivation OK)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018183 */
18184 }
18185 }
18186 FREE_AND_NULL(attrValue)
18187 FREE_AND_NULL(nsName)
18188 FREE_AND_NULL(local)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018189 }
18190 /* TODO: Change the handling of missing types according to
18191 * the spec.
18192 */
18193 if (actualType == NULL) {
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000018194 xmlSchemaVCustomErr(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018195 XML_SCHEMAV_CVC_TYPE_1,
18196 elem, (xmlSchemaTypePtr) elemDecl,
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000018197 "The type definition is absent", NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018198 /*
18199 * Evaluate IDCs even if an error occured.
18200 */
18201#ifdef IDC_ENABLED
18202 if (xmlSchemaXPathEvaluate(ctxt, ctxt->elemInfo->namespaceName,
18203 ctxt->elemInfo->localName, XML_ELEMENT_NODE) == -1)
18204 return (-1);
18205#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018206 return (XML_SCHEMAV_CVC_TYPE_1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018207 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018208
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018209 /*
18210 * TODO: Since this should be already checked by the content model automaton,
18211 * and we want to get rid of the XML_SCHEMAS_ERR... types, the error code
18212 * has been changed to XML_SCHEMAV_INTERNAL.
18213 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018214 /*
Daniel Veillard4255d502002-04-16 15:50:10 +000018215 if (child == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000018216 if (decl->minOccurs > 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018217 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018218 XML_SCHEMAS_ERR_MISSING,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018219 "Element %s: missing child %s\n",
18220 node->name, decl->name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018221 }
18222 return (ctxt->err);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018223 }
18224 */
Daniel Veillard4255d502002-04-16 15:50:10 +000018225 /*
18226 * Verify the element matches
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018227 * TODO, FIXME: Can this still happen here? Isn't this already checked
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018228 * by the content model automaton?
Daniel Veillardc0826a72004-08-10 14:17:33 +000018229 if (!xmlStrEqual(child->name, decl->name)) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018230 xmlSchemaVErr3(ctxt, node, XML_SCHEMAV_INTERNAL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018231 XML_SCHEMAS_ERR_WRONGELEM,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018232 "Element %s: missing child %s found %s\n",
18233 node->name, decl->name, child->name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018234 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000018235 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018236 */
18237 if (elemHasContent == -1)
18238 elemHasContent = xmlSchemaHasElemOrCharContent(elem);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018239
18240 /*
18241 * IDC: Register identity-constraint XPath matchers.
18242 */
18243#ifdef IDC_ENABLED
18244 if (elemDecl->idcs != NULL)
18245 xmlSchemaIDCRegisterMatchers(ctxt, elemDecl);
18246 /*
18247 * Evaluate IDCs.
18248 */
18249 if (xmlSchemaXPathEvaluate(ctxt, ctxt->elemInfo->namespaceName,
18250 ctxt->elemInfo->localName, XML_ELEMENT_NODE) == -1)
18251 return (-1);
18252#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018253 /*
18254 * cvc-elt (3.3.4) : 5
18255 * The appropriate case among the following must be true:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018256 */
Daniel Veillard4255d502002-04-16 15:50:10 +000018257 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018258 * cvc-elt (3.3.4) : 5.1
18259 * If the declaration has a {value constraint},
18260 * the item has neither element nor character [children] and
18261 * clause 3.2 has not applied, then all of the following must be true:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018262 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018263 if ((elemHasContent == 0) && (nilled == 0) && (elemDecl->value != NULL)) {
18264 /*
18265 * cvc-elt (3.3.4) : 5.1.1
18266 * If the ·actual type definition· is a ·local type definition·
18267 * then the canonical lexical representation of the {value constraint}
18268 * value must be a valid default for the ·actual type definition· as
18269 * defined in Element Default Valid (Immediate) (§3.3.6).
18270 */
18271 /*
18272 * NOTE: 'local' above means types aquired by xsi:type.
18273 */
18274 ret = 0;
18275 if (actualType != elemDecl->subtypes) {
18276 xmlSchemaCreatePCtxtOnVCtxt(ctxt);
18277 ret = xmlSchemaCheckCOSValidDefault(ctxt->pctxt, ctxt, actualType,
18278 elemDecl->value, NULL);
18279 if (ret < 0) {
18280 xmlSchemaVCustomErr(ctxt,
18281 XML_SCHEMAV_INTERNAL,
18282 elem, actualType,
18283 "Internal error: xmlSchemaValidateElementByDeclaration, "
18284 "validating a default value", NULL);
18285 return (-1);
18286 }
18287 }
18288 /*
18289 * cvc-elt (3.3.4) : 5.1.2
18290 * The element information item with the canonical lexical
18291 * representation of the {value constraint} value used as its
18292 * ·normalized value· must be ·valid· with respect to the
18293 * ·actual type definition· as defined by Element Locally Valid (Type)
18294 * (§3.3.4).
18295 */
18296 /*
18297 * Disable validation of the simple content, since it was already
18298 * done above.
18299 */
18300 if (ret == 0) {
18301 if (actualType != elemDecl->subtypes)
18302 ret = xmlSchemaValidateElementByType(ctxt, actualType, 0);
18303 else
18304 ret = xmlSchemaValidateElementByType(ctxt, actualType, 0);
18305 ctxt->node = elem;
18306 if (ret < 0) {
18307 xmlSchemaVCustomErr(ctxt,
18308 XML_SCHEMAV_INTERNAL,
18309 elem, actualType,
18310 "Internal error: xmlSchemaValidateElementByDeclaration, "
18311 "validating against the type", NULL);
18312 return (-1);
18313 }
18314 /*
18315 * PSVI: Create a text node on the instance element.
18316 */
18317 if (ctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) {
18318 xmlNodePtr textChild;
18319
18320 textChild = xmlNewText(elemDecl->value);
18321 if (textChild == NULL) {
18322 xmlSchemaVCustomErr(ctxt,
18323 XML_SCHEMAV_INTERNAL,
18324 elem, actualType,
18325 "Internal error: xmlSchemaValidateElementByDeclaration, "
18326 "could not create a default text node for the instance",
18327 NULL);
18328 } else
18329 xmlAddChild(elem, textChild);
18330 }
18331 }
18332
18333 } else {
18334 /*
18335 * 5.2.1 The element information item must be ·valid· with respect
18336 * to the ·actual type definition· as defined by Element Locally
18337 * Valid (Type) (§3.3.4).
18338 */
18339 ret = xmlSchemaValidateElementByType(ctxt, actualType, 1);
18340 ctxt->node = elem;
18341 if (ret < 0) {
18342 xmlSchemaVCustomErr(ctxt,
18343 XML_SCHEMAV_INTERNAL,
18344 elem, actualType,
18345 "Internal error: xmlSchemaValidateElementByDeclaration, "
18346 "validating a default value", NULL);
18347 return (-1);
18348 }
18349 /*
18350 * 5.2.2 If there is a fixed {value constraint} and clause 3.2 has
18351 * not applied, all of the following must be true:
18352 */
18353
18354 if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) && (nilled == 0)) {
18355 /*
18356 * 5.2.2.1 The element information item must have no element
18357 * information item [children].
18358 *
18359 * TODO REDUNDANT: If the actual type exists, the above call to
18360 * xmlSchemaValidateElementByType will already check for element
18361 * nodes.
18362 */
18363 if (xmlSchemaHasElemContent(elem)) {
18364 xmlSchemaVCustomErr(ctxt,
18365 XML_SCHEMAV_CVC_ELT_5_2_2_1,
18366 elem, (xmlSchemaTypePtr) elemDecl,
18367 "Elements in the content are not allowed if it is "
18368 "constrained by a fixed value", NULL);
18369 } else {
18370 /*
18371 * 5.2.2.2 The appropriate case among the following must
18372 * be true:
18373 */
18374
18375 if (actualType->contentType == XML_SCHEMA_CONTENT_MIXED) {
18376 xmlChar *value;
18377 /*
18378 * 5.2.2.2.1 If the {content type} of the ·actual type
18379 * definition· is mixed, then the *initial value* of the
18380 * item must match the canonical lexical representation
18381 * of the {value constraint} value.
18382 *
18383 * ... the *initial value* of an element information
18384 * item is the string composed of, in order, the
18385 * [character code] of each character information item in
18386 * the [children] of that element information item.
18387 */
18388 value = xmlNodeListGetString(elem->doc, elem->children, 1);
18389 if (! xmlStrEqual(BAD_CAST value, elemDecl->value)) {
18390 /*
18391 * TODO: Report invalid & expected values as well.
18392 * TODO: Implement the cononical stuff.
18393 */
18394 xmlSchemaVCustomErr(ctxt,
18395 XML_SCHEMAV_CVC_ELT_5_2_2_2_1,
18396 elem, (xmlSchemaTypePtr) elemDecl,
18397 "The value does not match the cononical "
18398 "lexical representation of the fixed constraint",
18399 NULL);
18400 }
18401 if (value != NULL)
18402 xmlFree(value);
18403 } else if ((actualType->contentType ==
18404 XML_SCHEMA_CONTENT_SIMPLE) ||
18405 (actualType->contentType == XML_SCHEMA_CONTENT_BASIC)) {
18406 xmlChar *value;
18407
18408 /*
18409 * 5.2.2.2.2 If the {content type} of the ·actual type
18410 * definition· is a simple type definition, then the
18411 * *actual value* of the item must match the canonical
18412 * lexical representation of the {value constraint} value.
18413 */
18414 /*
18415 * TODO: *actual value* is the normalized value, impl. this.
18416 * TODO: Report invalid & expected values as well.
18417 * TODO: Implement the cononical stuff.
18418 *
18419 */
18420 value = xmlNodeListGetString(elem->doc, elem->children, 1);
18421 if (! xmlStrEqual(BAD_CAST value, elemDecl->value)) {
18422 xmlSchemaVCustomErr(ctxt,
18423 XML_SCHEMAV_CVC_ELT_5_2_2_2_2,
18424 elem, (xmlSchemaTypePtr) elemDecl,
18425 "The normalized value does not match the cononical "
18426 "lexical representation of the fixed constraint",
18427 NULL);
18428 }
18429 if (value != NULL)
18430 xmlFree(value);
18431
18432 }
18433 /*
18434 * TODO: What if the content type is not 'mixed' or simple?
18435 */
18436
18437 }
18438
18439 }
18440 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018441 /*
18442 * TODO: 7 If the element information item is the ·validation root·, it must be
18443 * ·valid· per Validation Root Valid (ID/IDREF) (§3.3.4).
18444 */
18445
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018446 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000018447}
18448
Daniel Veillard4255d502002-04-16 15:50:10 +000018449/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018450 * xmlSchemaValidateElementByWildcardInternal:
Daniel Veillardc0826a72004-08-10 14:17:33 +000018451 * @ctxt: a schema validation context
18452 * @node: the top node.
18453 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018454 * Represents the recursive portion of xmlSchemaValidateElementByWildcard.
18455 * Not intended to be used by other functions.
Daniel Veillardc0826a72004-08-10 14:17:33 +000018456 *
18457 * Returns 0 if the element is valid, a positive error code
18458 * number otherwise and -1 in case of an internal error.
18459 */
18460static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018461xmlSchemaValidateElementByWildcardInternal(xmlSchemaValidCtxtPtr ctxt,
18462 xmlSchemaWildcardPtr wild,
18463 xmlNodePtr node)
Daniel Veillardc0826a72004-08-10 14:17:33 +000018464{
18465 const xmlChar *uri;
18466 int ret = 0;
18467 xmlNodePtr child;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018468
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018469 if (ctxt->xsiAssemble) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018470 ret = xmlSchemaAssembleByXSIElem(ctxt, ctxt->node);
18471 if (ret == -1) {
18472 xmlSchemaVCustomErr(ctxt,
18473 XML_SCHEMAV_INTERNAL,
18474 ctxt->node, NULL,
18475 "Internal error: xmlSchemaValidateElement, "
18476 "assembling schema by xsi", NULL);
18477 return (-1);
18478 }
18479 /*
18480 * NOTE: We won't react on schema parser errors here.
18481 * TODO: But a warning would be nice.
18482 */
18483 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000018484 if (wild->processContents != XML_SCHEMAS_ANY_SKIP) {
18485 xmlSchemaElementPtr decl = NULL;
18486
18487 if (node->ns != NULL)
18488 decl = xmlHashLookup3(ctxt->schema->elemDecl,
18489 node->name, node->ns->href, NULL);
18490 else
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018491 decl = xmlHashLookup3(ctxt->schema->elemDecl, node->name,
18492 NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +000018493 if (decl != NULL) {
18494 ctxt->node = node;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018495 ret = xmlSchemaValidateElementByDeclaration(ctxt, decl);
Daniel Veillardc0826a72004-08-10 14:17:33 +000018496 if (ret < 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018497 xmlSchemaVErr(ctxt, node, XML_SCHEMAV_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000018498 "Internal error: xmlSchemaValidateAnyInternal, "
18499 "validating an element in the context of a wildcard.",
18500 NULL, NULL);
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +000018501 }
18502 return (ret);
Daniel Veillardc0826a72004-08-10 14:17:33 +000018503 } else if (wild->processContents == XML_SCHEMAS_ANY_STRICT) {
18504 /* TODO: Change to proper error code. */
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018505 xmlSchemaVWildcardErr(ctxt, XML_SCHEMAV_CVC_ELT_1,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018506 node, wild, "No matching global declaration available");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018507 /*
18508 * Evaluate IDCs even if a validation error occured.
18509 */
18510#ifdef IDC_ENABLED
18511 if (xmlSchemaXPathEvaluate(ctxt, ctxt->elemInfo->namespaceName,
18512 ctxt->elemInfo->localName, XML_ELEMENT_NODE) == -1)
18513 return(-1);
18514#endif
Daniel Veillardc0826a72004-08-10 14:17:33 +000018515 return (ctxt->err);
18516 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018517 /*
18518 * Evaluate IDCs; we need to know if an IDC field resolves to
18519 * such a node. This node has no type definition and will
18520 * definitely result in an IDC validation error if an IDC field
18521 * resolves.
18522 */
18523#ifdef IDC_ENABLED
18524 if (xmlSchemaXPathEvaluate(ctxt, ctxt->elemInfo->namespaceName,
18525 ctxt->elemInfo->localName, XML_ELEMENT_NODE) == -1)
18526 return(-1);
18527#endif
Daniel Veillardc0826a72004-08-10 14:17:33 +000018528 }
18529 if (node->children != NULL) {
18530 child = node->children;
18531 do {
18532 if (child->type == XML_ELEMENT_NODE) {
18533 if (child->ns != NULL)
18534 uri = child->ns->href;
18535 else
18536 uri = NULL;
18537 if (xmlSchemaMatchesWildcardNs(wild, uri) == 0) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000018538 /* TODO: error code. */
18539 xmlSchemaVWildcardErr(ctxt, XML_SCHEMAV_ELEMENT_CONTENT,
Daniel Veillardc0826a72004-08-10 14:17:33 +000018540 child, wild,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018541 "The namespace of the element is not allowed");
Daniel Veillardc0826a72004-08-10 14:17:33 +000018542 return (ctxt->err);
18543 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018544#ifdef ELEM_INFO_ENABLED
18545 ctxt->node = child;
18546 xmlSchemaBeginElement(ctxt);
18547#endif
18548 /*
18549 * Recurse over the children.
18550 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018551 ret = xmlSchemaValidateElementByWildcardInternal(ctxt,
18552 wild, child);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018553#ifdef ELEM_INFO_ENABLED
18554 xmlSchemaEndElement(ctxt);
18555#endif
Daniel Veillardc0826a72004-08-10 14:17:33 +000018556 if (ret != 0)
18557 return (ret);
18558 }
18559 child = child->next;
18560 } while (child != NULL);
18561 }
18562 return (0);
18563}
18564
18565/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018566 * xmlSchemaValidateElementContByWildcard:
Daniel Veillardc0826a72004-08-10 14:17:33 +000018567 * @ctxt: a schema validation context
18568 *
18569 * Returns 0 if the element is valid, a positive error code
18570 * number otherwise and -1 in case of an internal or API error.
18571 */
18572static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018573xmlSchemaValidateElementByWildcard(xmlSchemaValidCtxtPtr ctxt,
18574 xmlSchemaTypePtr type)
Daniel Veillardc0826a72004-08-10 14:17:33 +000018575{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018576 if ((type == NULL) || (type->type != XML_SCHEMA_TYPE_ANY) ||
18577 (ctxt->node == NULL)) {
18578 xmlSchemaVCustomErr(ctxt,
18579 XML_SCHEMAV_INTERNAL, ctxt->node, NULL,
18580 "Internal error: xmlSchemaValidateElementByWildcard, "
18581 "bad arguments", NULL);
18582 return (-1);
18583 }
18584 return(xmlSchemaValidateElementByWildcardInternal(ctxt,
18585 type->attributeWildcard, ctxt->node));
Daniel Veillardc0826a72004-08-10 14:17:33 +000018586}
18587
18588/**
William M. Brack2f2a6632004-08-20 23:09:47 +000018589 * xmlSchemaValidateAnyTypeContent:
18590 * @ctxt: a schema validation context
18591 * @node: the current element
18592 *
18593 * This one validates the content of an element of the type
18594 * 'anyType'. The process contents of the wildcard of 'anyType' is "lax",
18595 * thus elements in the subtree will be validated, if a corresponding
18596 * declaration in the schema exists.
18597 *
18598 * Returns 0 if the element and its subtree is valid, a positive error code
18599 * otherwise and -1 in case of an internal or API error.
18600 */
18601static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018602xmlSchemaValidateElementByAnyType(xmlSchemaValidCtxtPtr ctxt,
18603 xmlSchemaTypePtr type)
William M. Brack2f2a6632004-08-20 23:09:47 +000018604{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018605 xmlSchemaTypePtr oldtype;
18606 xmlNodePtr top, cur;
18607 xmlSchemaElementPtr decl;
William M. Brack2f2a6632004-08-20 23:09:47 +000018608 int skipContent, ret;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018609
18610 if ((type == NULL) || (ctxt->node == NULL))
18611 return (-1);
18612
18613 if (ctxt->node->children == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +000018614 return (0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018615
18616 oldtype = ctxt->type;
18617 top = ctxt->node;
18618 /*
18619 * STREAM: Child nodes are processed.
18620 */
18621 cur = ctxt->node->children;
18622 while (cur != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +000018623 skipContent = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018624 if (cur->type == XML_ELEMENT_NODE) {
William M. Brack2f2a6632004-08-20 23:09:47 +000018625 /*
18626 * The process contents of the wildcard is "lax", thus
18627 * we need to validate the element if a declaration
18628 * exists.
18629 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018630 if (cur->ns != NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +000018631 decl = xmlHashLookup3(ctxt->schema->elemDecl,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018632 cur->name, cur->ns->href, NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +000018633 else
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018634 decl = xmlHashLookup3(ctxt->schema->elemDecl, cur->name, NULL, NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +000018635 if (decl != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018636 ctxt->node = cur;
18637 ret = xmlSchemaValidateElementByDeclaration(ctxt, decl);
18638 ctxt->node = top;
William M. Brack2f2a6632004-08-20 23:09:47 +000018639 if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018640 xmlSchemaVErr(ctxt, cur, XML_SCHEMAV_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +000018641 "Internal error: xmlSchemaValidateAnyTypeContent, "
18642 "validating an element in the context of a wildcard.",
18643 NULL, NULL);
18644 return (ret);
18645 } else if (ret > 0)
18646 return (ret);
18647 skipContent = 1;
18648 }
18649 }
18650 /*
18651 * Browse the full subtree, deep first.
18652 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018653 if ((skipContent == 0) && (cur->children != NULL)) {
William M. Brack2f2a6632004-08-20 23:09:47 +000018654 /* deep first */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018655 cur = cur->children;
18656 } else if ((cur != top) && (cur->next != NULL)) {
William M. Brack2f2a6632004-08-20 23:09:47 +000018657 /* then siblings */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018658 cur = cur->next;
18659 } else if (cur != top) {
William M. Brack2f2a6632004-08-20 23:09:47 +000018660 /* go up to parents->next if needed */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018661 while (cur != top) {
18662 if (cur->parent != NULL)
18663 cur = cur->parent;
18664 if ((cur != top) && (cur->next != NULL)) {
18665 cur = cur->next;
William M. Brack2f2a6632004-08-20 23:09:47 +000018666 break;
18667 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018668 if (cur->parent == NULL) {
18669 cur = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +000018670 break;
18671 }
18672 }
18673 /* exit condition */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018674 if (cur == top)
18675 cur = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +000018676 } else
18677 break;
18678 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018679 ctxt->type = oldtype;
William M. Brack2f2a6632004-08-20 23:09:47 +000018680 return (0);
18681}
18682
18683/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018684 * xmlSchemaValidateElementByComplexType:
Daniel Veillard4255d502002-04-16 15:50:10 +000018685 * @ctxt: a schema validation context
18686 * @node: the top node.
18687 *
18688 * Validate the content of an element expected to be a complex type type
18689 * xmlschema-1.html#cvc-complex-type
18690 * Validation Rule: Element Locally Valid (Complex Type)
18691 *
18692 * Returns 0 if the element is schemas valid, a positive error code
Daniel Veillard01fa6152004-06-29 17:04:39 +000018693 * number otherwise and -1 in case of internal or API error.
18694 * Note on reported errors: Although it might be nice to report
18695 * the name of the simple/complex type, used to validate the content
18696 * of a node, it is quite unnecessary: for global defined types
18697 * the local name of the element is equal to the NCName of the type,
18698 * for local defined types it makes no sense to output the internal
18699 * computed name of the type. TODO: Instead, one should attach the
18700 * struct of the type involved to the error handler - this allows
18701 * the report of any additional information by the user.
Daniel Veillard4255d502002-04-16 15:50:10 +000018702 */
18703static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018704xmlSchemaValidateElementByComplexType(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018705 xmlSchemaTypePtr type,
18706 int valSimpleContent)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018707{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018708 xmlSchemaTypePtr oldtype;
18709 xmlNodePtr elem, child;
Daniel Veillard01fa6152004-06-29 17:04:39 +000018710 int ret = 0;
William M. Brack2f2a6632004-08-20 23:09:47 +000018711 const xmlChar *nsUri;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018712 xmlSchemaAttrStatePtr attrs = NULL, attrTop = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000018713
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018714 if ((ctxt == NULL) || (type->type != XML_SCHEMA_TYPE_COMPLEX))
18715 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000018716
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018717 oldtype = ctxt->type;
18718 ctxt->type = type;
18719 elem = ctxt->node;
18720
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018721 /*
18722 * Verify the attributes
18723 */
18724 /*
18725 * TODO: This "attrTop" thing is not needed any more.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018726 */
18727 /* NOTE: removed, since a check for abstract is
18728 * done in the cvc-type constraint.
18729 *
18730 *
18731 * if (type->flags & XML_SCHEMAS_TYPE_ABSTRACT) {
18732 * xmlSchemaVComplexTypeErr(ctxt,
18733 * XML_SCHEMAV_CVC_COMPLEX_TYPE_1,
18734 * elem, type,
18735 * "The type definition is abstract");
18736 * return (XML_SCHEMAV_CVC_COMPLEX_TYPE_1);
18737 *}
18738 */
18739
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018740 attrs = ctxt->attr;
18741 attrTop = ctxt->attrTop;
18742 /*
18743 * STREAM: Attribute nodes are processed.
18744 */
18745 xmlSchemaRegisterAttributes(ctxt, elem->properties);
18746 xmlSchemaValidateAttributes(ctxt, elem, type);
18747 if (ctxt->attr != NULL)
18748 xmlSchemaFreeAttributeStates(ctxt->attr);
18749 ctxt->attr = attrs;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018750 ctxt->attrTop = attrTop;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018751
18752 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018753 * TODO: This one creates a regexp even if no content
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018754 * model was defined. Somehow ->contModel is always not NULL
18755 * for complex types, even if they are empty.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018756 * TODO: Check if the obove still occurs.
18757 */
Daniel Veillard4255d502002-04-16 15:50:10 +000018758 switch (type->contentType) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000018759 case XML_SCHEMA_CONTENT_EMPTY: {
18760 /*
18761 * 1 If the {content type} is empty, then the element information
18762 * item has no character or element information item [children].
Daniel Veillard3646d642004-06-02 19:19:14 +000018763 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000018764 /*
18765 * TODO: Is the entity stuff correct?
18766 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018767 if (xmlSchemaHasElemOrCharContent(elem) == 1) {
William M. Brack2f2a6632004-08-20 23:09:47 +000018768 xmlSchemaVComplexTypeErr(ctxt,
18769 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018770 elem, type,
William M. Brack2f2a6632004-08-20 23:09:47 +000018771 "Character or element content is not allowed, "
18772 "because the content type is empty");
Daniel Veillard01fa6152004-06-29 17:04:39 +000018773 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018774 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +000018775 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018776 case XML_SCHEMA_CONTENT_MIXED:
18777 if ((type->subtypes == NULL) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018778 (type->baseType->builtInType == XML_SCHEMAS_ANYTYPE)) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018779 /*
18780 * The type has 'anyType' as its base and no content model
18781 * is defined -> use 'anyType' as the type to validate
18782 * against.
18783 */
18784 ret = xmlSchemaValidateElementByAnyType(ctxt, type->baseType);
18785 /* TODO: Handle -1. */
18786 break;
18787 }
18788 /* No break on purpose. */
Daniel Veillard01fa6152004-06-29 17:04:39 +000018789 case XML_SCHEMA_CONTENT_ELEMENTS:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018790 {
18791 xmlRegExecCtxtPtr oldregexp = NULL;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000018792 xmlChar *values[10];
18793 int terminal, nbval = 10, nbneg;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018794
18795 /*
18796 * Content model check initialization.
18797 */
18798 if (type->contModel != NULL) {
18799 oldregexp = ctxt->regexp;
18800 ctxt->regexp = xmlRegNewExecCtxt(type->contModel,
18801 (xmlRegExecCallbacks)
18802 xmlSchemaValidateCallback, ctxt);
18803#ifdef DEBUG_AUTOMATA
18804 xmlGenericError(xmlGenericErrorContext, "====> %s\n", elem->name);
18805#endif
18806 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018807 /*
18808 * STREAM: Children are processed.
18809 */
18810 child = elem->children;
Daniel Veillard01fa6152004-06-29 17:04:39 +000018811 while (child != NULL) {
18812 if (child->type == XML_ELEMENT_NODE) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000018813 if (child->ns != NULL)
18814 nsUri = child->ns->href;
18815 else
18816 nsUri = NULL;
18817 ret = xmlRegExecPushString2(ctxt->regexp,
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000018818 child->name, nsUri, child);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018819 /*
18820 * URGENT TODO: Could we anchor an error report
18821 * here to notify of invalid elements?
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000018822 * TODO: Perhaps it would be better to report
18823 * only the first erroneous element and then break.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018824 */
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000018825#ifdef DEBUG_AUTOMATA
Daniel Veillard01fa6152004-06-29 17:04:39 +000018826 if (ret < 0)
18827 xmlGenericError(xmlGenericErrorContext,
18828 " --> %s Error\n", child->name);
William M. Bracke7091952004-05-11 15:09:58 +000018829 else
18830 xmlGenericError(xmlGenericErrorContext,
Daniel Veillard01fa6152004-06-29 17:04:39 +000018831 " --> %s\n", child->name);
18832#endif
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000018833 if (ret < 0) {
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000018834 xmlRegExecErrInfo(ctxt->regexp, NULL, &nbval, &nbneg,
18835 &values[0], &terminal);
18836 xmlSchemaVComplexTypeElemErr(ctxt,
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000018837 XML_SCHEMAV_ELEMENT_CONTENT,
18838 child, NULL/* type */,
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000018839 "This element is not expected",
18840 nbval, nbneg, values);
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000018841 ret = 1;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000018842 /*
18843 * Note that this will skip further validation of the
18844 * content.
18845 */
18846 break;
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000018847 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000018848 } else if ((type->contentType == XML_SCHEMA_CONTENT_ELEMENTS) &&
18849 /*
18850 * TODO: Ask Daniel if this are all character nodes.
18851 */
18852 (((child->type == XML_TEXT_NODE) && (!IS_BLANK_NODE(child))) ||
18853 (child->type == XML_ENTITY_NODE) ||
18854 (child->type == XML_ENTITY_REF_NODE) ||
18855 (child->type == XML_CDATA_SECTION_NODE))) {
18856 /*
18857 * 2.3 If the {content type} is element-only, then the
18858 * element information item has no character information
18859 * item [children] other than those whose [character
18860 * code] is defined as a white space in [XML 1.0 (Second
18861 * Edition)].
18862 */
William M. Brack2f2a6632004-08-20 23:09:47 +000018863 xmlSchemaVComplexTypeErr(ctxt,
18864 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_3,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018865 elem, type,
William M. Brack2f2a6632004-08-20 23:09:47 +000018866 "Character content is not allowed, "
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000018867 "because the content type is element-only");
18868 ret = 1;
Daniel Veillard01fa6152004-06-29 17:04:39 +000018869 break;
18870 }
18871 child = child->next;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018872 }
18873 /*
18874 * Content model check finalization.
18875 */
18876 if (type->contModel != NULL) {
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000018877 if (ret == 0) {
18878 xmlRegExecNextValues(ctxt->regexp, &nbval, &nbneg,
18879 &values[0], &terminal);
18880 if (nbval + nbneg != 0) {
18881 /*
18882 * If a next value still exists, I does not have to
18883 * mean that there's an element missing, since it
18884 * might be an optional element. So double check it.
18885 */
18886 ret = xmlRegExecPushString(ctxt->regexp,
18887 NULL, NULL);
18888 if (ret <= 0) {
18889 ret = 1;
18890 xmlSchemaVComplexTypeElemErr(ctxt,
18891 XML_SCHEMAV_ELEMENT_CONTENT,
18892 elem, type, "Missing child element(s)",
18893 nbval, nbneg, values);
18894 } else
18895 ret = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018896#ifdef DEBUG_AUTOMATA
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000018897 xmlGenericError(xmlGenericErrorContext,
18898 "====> %s : %d\n", elem->name, ret);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018899#endif
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000018900 }
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000018901#ifdef DEBUG_CONTENT
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000018902 if (ret == 0)
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000018903 xmlGenericError(xmlGenericErrorContext,
18904 "Element %s content check succeeded\n",
18905 elem->name);
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000018906#endif
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018907 }
18908 xmlRegFreeExecCtxt(ctxt->regexp);
18909 ctxt->regexp = oldregexp;
18910 }
18911 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000018912 break;
18913 case XML_SCHEMA_CONTENT_SIMPLE:
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018914 case XML_SCHEMA_CONTENT_BASIC:
18915 /*
18916 * If the simple content was already validated
18917 * (e.g. a default value), the content need not
18918 * to be validated again.
18919 */
18920 if (valSimpleContent == 1) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000018921 xmlChar *value = NULL;
18922 /*
18923 * We hit a complexType with a simpleContent resolving
18924 * to a user derived or built-in simple type.
William M. Brack2f2a6632004-08-20 23:09:47 +000018925 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000018926 /*
18927 * 2.2 If the {content type} is a simple type definition,
18928 * then the element information item has no element
18929 * information item [children], and the ·normalized value·
18930 * of the element information item is ·valid· with respect
18931 * to that simple type definition as defined by String
18932 * Valid (§3.14.4).
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018933 */
18934 /*
18935 * STREAM: Children are processed.
18936 */
18937 child = elem->children;
Daniel Veillard01fa6152004-06-29 17:04:39 +000018938 while (child != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018939 /*
18940 * TODO: Could the entity stuff produce elements
18941 * as well?
18942 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000018943 if (child->type == XML_ELEMENT_NODE) {
William M. Brack2f2a6632004-08-20 23:09:47 +000018944 xmlSchemaVComplexTypeErr(ctxt,
18945 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018946 elem, type,
William M. Brack2f2a6632004-08-20 23:09:47 +000018947 "Element content is not allowed, because "
18948 "the content type is a simple type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000018949 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
18950 break;
18951 }
18952 child = child->next;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018953 }
18954 ctxt->node = elem;
18955 ctxt->cur = elem->children;
Daniel Veillard01fa6152004-06-29 17:04:39 +000018956 if (ret == 0) {
18957 /*
18958 * Validate the character content against a simple type.
Daniel Veillard3646d642004-06-02 19:19:14 +000018959 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018960 /*
18961 * STREAM: Children are processed.
18962 */
18963 if (elem->children == NULL)
Daniel Veillard01fa6152004-06-29 17:04:39 +000018964 value = NULL;
18965 else
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018966 value = xmlNodeGetContent(elem);
18967 /*
18968 * URGENT TODO: Should facets for the simple type validation be
18969 * disabled, if the derivation of facets for complex types
18970 * is implemented?
18971 */
18972 /*
18973 * NOTE: This call won't check the correct types of the
18974 * content nodes, since this should be done here.
18975 */
18976 ret = xmlSchemaValidateSimpleTypeValue(ctxt, type, value, 1, 1, 1, 0);
William M. Brack2f2a6632004-08-20 23:09:47 +000018977 if (ret > 0) {
18978 /*
18979 * NOTE: Although an error will be reported by
18980 * xmlSchemaValidateSimpleTypeValue, the spec wants
18981 * a specific complex type error to be reported
18982 * additionally.
18983 */
18984 xmlSchemaVComplexTypeErr(ctxt,
18985 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018986 elem, type,
William M. Brack2f2a6632004-08-20 23:09:47 +000018987 "The character content is not valid");
Daniel Veillard01fa6152004-06-29 17:04:39 +000018988 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
18989 } else if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018990 xmlSchemaVErr(ctxt, elem, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000018991 "Internal error: xmlSchemaValidateComplexType, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000018992 "Element '%s': Error while validating character "
18993 "content against complex type '%s'.\n",
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018994 elem->name, type->name);
18995 if (value != NULL)
18996 xmlFree(value);
18997 ctxt->type = oldtype;
Daniel Veillard01fa6152004-06-29 17:04:39 +000018998 return (-1);
18999 }
William M. Brack2f2a6632004-08-20 23:09:47 +000019000 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000019001 if (ret == 0) {
19002 /*
19003 * Apply facets of the complexType. Be sure to pass the
19004 * built-in type to xmlSchemaValidateFacetsInternal.
19005 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019006 /* URGENT TODO: I don't know yet if the facets of the simple type
Daniel Veillard01fa6152004-06-29 17:04:39 +000019007 * are used, or if the facets, defined by this complex type,
19008 * are to be used only. This here applies both facet sets.
19009 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000019010
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019011 ret = xmlSchemaValidateFacetsInternal(ctxt,
19012 type, value, 0, 1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000019013 if (ret > 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +000019014 xmlSchemaVComplexTypeErr(ctxt,
19015 XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019016 elem, type,
William M. Brack2f2a6632004-08-20 23:09:47 +000019017 "The character content is not valid");
Daniel Veillard01fa6152004-06-29 17:04:39 +000019018 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
19019 } else if (ret < 0) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019020 xmlSchemaVErr(ctxt, elem, XML_SCHEMAV_INTERNAL,
Daniel Veillard01fa6152004-06-29 17:04:39 +000019021 "Internal error: xmlSchemaValidateComplexType, "
Daniel Veillardc0826a72004-08-10 14:17:33 +000019022 "Element '%s': Error while validating character "
19023 "content against complex type '%s'; failed to "
Daniel Veillard01fa6152004-06-29 17:04:39 +000019024 "apply facets.\n",
19025 type->name, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019026 if (value != NULL)
19027 xmlFree(value);
19028 ctxt->type = oldtype;
19029 return (-1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000019030 }
19031 }
19032 if (value != NULL)
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000019033 xmlFree(value);
19034
Daniel Veillard01fa6152004-06-29 17:04:39 +000019035 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019036 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019037 default:
19038 TODO xmlGenericError(xmlGenericErrorContext,
19039 "unimplemented content type %d\n",
19040 type->contentType);
Daniel Veillard4255d502002-04-16 15:50:10 +000019041 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019042 ctxt->type = oldtype;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019043 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000019044}
19045
19046/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019047 * xmlSchemaValidateElementByType:
Daniel Veillard4255d502002-04-16 15:50:10 +000019048 * @ctxt: a schema validation context
19049 * @elem: an element
19050 * @type: the list of type declarations
19051 *
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019052 * Validation Rule: Element Locally Valid (Type).
Daniel Veillard4255d502002-04-16 15:50:10 +000019053 *
19054 * Returns 0 if the element is schemas valid, a positive error code
19055 * number otherwise and -1 in case of internal or API error.
19056 */
19057static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019058xmlSchemaValidateElementByType(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019059 xmlSchemaTypePtr type,
19060 int valSimpleContent)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019061{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019062 int ret;
Daniel Veillard4255d502002-04-16 15:50:10 +000019063
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019064
19065 if ((ctxt == NULL) || (type == NULL)) {
19066 xmlSchemaVCustomErr(ctxt, XML_SCHEMAV_INTERNAL, NULL, NULL,
19067 "Internal error: xmlSchemaValidateElementByType, "
19068 "bad arguments", NULL);
19069 return (-1);
19070 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019071 /*
19072 * This one is called by "xmlSchemaValidateElementByDeclaration".
19073 * It will forward to the proper validation
19074 * procedures for the given type.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019075 */
19076 if (type == NULL) {
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000019077 xmlSchemaVCustomErr(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019078 XML_SCHEMAV_CVC_TYPE_1,
19079 ctxt->node, NULL,
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000019080 "The type definition is absent", NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019081 return (XML_SCHEMAV_CVC_TYPE_1);
19082 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019083
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019084 if (type->flags & XML_SCHEMAS_TYPE_ABSTRACT) {
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000019085 xmlSchemaVCustomErr(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019086 XML_SCHEMAV_CVC_TYPE_2,
19087 ctxt->node, type,
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +000019088 "The type definition is abstract", NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019089 return (XML_SCHEMAV_CVC_TYPE_2);
19090 }
19091
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019092#ifdef ELEM_INFO_ENABLED
19093 ctxt->elemInfo->typeDef = type;
19094#endif
19095
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019096 switch (type->type) {
19097 case XML_SCHEMA_TYPE_COMPLEX:
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019098 ret = xmlSchemaValidateElementByComplexType(ctxt, type,
19099 valSimpleContent);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019100 break;
19101 case XML_SCHEMA_TYPE_SIMPLE:
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019102 ret = xmlSchemaValidateElementBySimpleType(ctxt, type,
19103 valSimpleContent);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019104 break;
19105 case XML_SCHEMA_TYPE_BASIC:
19106 if (type->builtInType == XML_SCHEMAS_ANYTYPE)
19107 ret = xmlSchemaValidateElementByAnyType(ctxt, type);
19108 else
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019109 ret = xmlSchemaValidateElementBySimpleType(ctxt, type,
19110 valSimpleContent);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019111 break;
19112 default:
19113 ret = -1;
19114 break;
19115 }
19116 if (ret == -1)
19117 return (-1);
19118 else
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019119 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000019120}
19121
19122
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019123static int
19124xmlSchemaCheckAttrLocallyValid(xmlSchemaValidCtxtPtr ctxt,
19125 xmlSchemaAttributePtr decl,
19126 xmlSchemaAttrStatePtr state,
19127 xmlAttrPtr attr)
19128{
19129 xmlChar *value;
19130 const xmlChar *defValue;
19131 xmlSchemaValPtr defVal;
19132 int fixed;
19133 int ret;
19134
19135 if (decl->subtypes == NULL) {
19136 state->state = XML_SCHEMAS_ATTR_TYPE_NOT_RESOLVED;
19137 return (XML_SCHEMAS_ATTR_TYPE_NOT_RESOLVED);
19138 }
19139 value = xmlNodeListGetString(attr->doc, attr->children, 1);
19140 ctxt->node = (xmlNodePtr) attr;
19141 ctxt->cur = attr->children;
19142 /*
19143 * NOTE: This call also checks the content nodes for correct type.
19144 */
19145 ret = xmlSchemaValidateSimpleTypeValue(ctxt, decl->subtypes,
19146 value, 1, 1, 1, 1);
19147
19148 /*
19149 * Handle 'fixed' attributes.
19150 */
19151 if (ret > 0) {
19152 state->state = XML_SCHEMAS_ATTR_INVALID_VALUE;
19153 /*
19154 * NOTE: Fixed value constraints will be not
19155 * applied if the value was invalid, because:
19156 * 1. The validation process does not return a precomputed
19157 * value.
19158 * 2. An invalid value implies a violation of a fixed
19159 * value constraint.
19160 */
19161 } else if (ret == 0) {
19162 state->state = XML_SCHEMAS_ATTR_CHECKED;
19163 if (xmlSchemaGetEffectiveValueConstraint(decl,
19164 &fixed, &defValue, &defVal) && (fixed == 1)) {
19165 /*
19166 * cvc-au : Attribute Locally Valid (Use)
19167 * For an attribute information item to be·valid·
19168 * with respect to an attribute use its ·normalized
19169 * value· must match the canonical lexical representation
19170 * of the attribute use's {value constraint} value, if it
19171 * is present and fixed.
19172 */
19173 /*
19174 * NOTE: the validation context holds in ctxt->value the
19175 * precomputed value of the attribute; well for some types,
19176 * fallback to string comparison if no computed value
19177 * exists.
19178 */
19179 if (((ctxt->value != NULL) &&
19180 (xmlSchemaCompareValues(ctxt->value, defVal) != 0)) ||
19181 ((ctxt->value == NULL) &&
19182 (! xmlStrEqual(defValue, BAD_CAST value)))) {
19183 state->state =
19184 XML_SCHEMAS_ATTR_INVALID_FIXED_VALUE;
19185 }
19186 }
19187 }
19188 if (value != NULL) {
19189 xmlFree(value);
19190 }
19191 return (ret);
19192}
19193
Daniel Veillard4255d502002-04-16 15:50:10 +000019194/**
19195 * xmlSchemaValidateAttributes:
19196 * @ctxt: a schema validation context
19197 * @elem: an element
Daniel Veillard3646d642004-06-02 19:19:14 +000019198 * @type: the complexType holding the attribute uses
Daniel Veillard4255d502002-04-16 15:50:10 +000019199 *
19200 * Validate the attributes of an element.
19201 *
Daniel Veillardc0826a72004-08-10 14:17:33 +000019202 * 1. Existent, invalid attributes are reported in the form
19203 * "prefix:localName".
19204 * Reason: readability - it is easier to find the actual XML
19205 * representation of the attributes QName.
19206 * 2. Missing attributes are reported in the form
19207 * {"URI", "localName"}.
19208 * This is necessary, since the the prefix need not to be declared
19209 * at all, and thus is not computable.
19210 *
Daniel Veillard4255d502002-04-16 15:50:10 +000019211 * Returns 0 if the element is schemas valid, a positive error code
19212 * number otherwise and -1 in case of internal or API error.
19213 */
19214static int
Daniel Veillard3646d642004-06-02 19:19:14 +000019215xmlSchemaValidateAttributes(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem, xmlSchemaTypePtr type)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019216{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019217 const xmlChar *nsURI;
Daniel Veillard3646d642004-06-02 19:19:14 +000019218 int ret;
19219 xmlAttrPtr attr; /* An attribute on the element. */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019220 const xmlChar *defValue;
19221 xmlSchemaValPtr defVal;
19222 int fixed;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019223 xmlSchemaAttributeLinkPtr attrUse = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000019224 xmlSchemaAttributePtr attrDecl;
Daniel Veillardc85d0fe2004-04-16 16:46:51 +000019225 int found;
William M. Brack803812b2004-06-03 02:11:24 +000019226 xmlSchemaAttrStatePtr curState, reqAttrStates = NULL, reqAttrStatesTop = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019227 xmlSchemaAttrStatePtr defAttrStates = NULL, defAttrStatesTop = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019228 xmlNodePtr oldnode;
Daniel Veillard3646d642004-06-02 19:19:14 +000019229#ifdef DEBUG_ATTR_VALIDATION
19230 int redundant = 0;
19231#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000019232
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019233
Daniel Veillardc0826a72004-08-10 14:17:33 +000019234 /*
19235 * Allow all attributes if the type is anyType.
19236 */
19237 if (type == xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE))
19238 return (0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019239
19240 oldnode = ctxt->node;
19241 if (type != NULL)
19242 attrUse = type->attributeUses;
Daniel Veillard3646d642004-06-02 19:19:14 +000019243 while (attrUse != NULL) {
Daniel Veillardc85d0fe2004-04-16 16:46:51 +000019244 found = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000019245 attrDecl = attrUse->attr;
19246#ifdef DEBUG_ATTR_VALIDATION
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019247 printf("attr use - name: %s\n", xmlSchemaGetAttrName(attrDecl));
Daniel Veillard3646d642004-06-02 19:19:14 +000019248 printf("attr use - use: %d\n", attrDecl->occurs);
19249#endif
19250 for (curState = ctxt->attr; curState != NULL; curState = curState->next) {
19251
19252 if (curState->decl == attrUse->attr) {
19253#ifdef DEBUG_ATTR_VALIDATION
19254 redundant = 1;
19255#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019256 }
Daniel Veillard3646d642004-06-02 19:19:14 +000019257 attr = curState->attr;
19258#ifdef DEBUG_ATTR_VALIDATION
19259 printf("attr - name: %s\n", attr->name);
19260 if (attr->ns != NULL)
19261 printf("attr - ns: %s\n", attr->ns->href);
19262 else
19263 printf("attr - ns: none\n");
19264#endif
19265 /* TODO: Can this ever happen? */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019266 if (attr == NULL)
19267 continue;
Daniel Veillard3646d642004-06-02 19:19:14 +000019268 if (attrDecl->ref != NULL) {
19269 if (!xmlStrEqual(attr->name, attrDecl->ref))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019270 continue;
19271 if (attr->ns != NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +000019272 if ((attrDecl->refNs == NULL) ||
19273 (!xmlStrEqual(attr->ns->href, attrDecl->refNs)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019274 continue;
Daniel Veillard3646d642004-06-02 19:19:14 +000019275 } else if (attrDecl->refNs != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019276 continue;
19277 }
19278 } else {
Daniel Veillard3646d642004-06-02 19:19:14 +000019279 if (!xmlStrEqual(attr->name, attrDecl->name))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019280 continue;
19281 /*
Daniel Veillardbe9c6322003-11-22 20:37:51 +000019282 * handle the namespaces checks here
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019283 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +000019284 if (attr->ns == NULL) {
19285 /*
William M. Bracke7091952004-05-11 15:09:58 +000019286 * accept an unqualified attribute only if the target
19287 * namespace of the declaration is absent.
Daniel Veillardbe9c6322003-11-22 20:37:51 +000019288 */
Daniel Veillard3646d642004-06-02 19:19:14 +000019289 if (attrDecl->targetNamespace != NULL)
William M. Bracke7091952004-05-11 15:09:58 +000019290 /*
19291 * This check was removed, since the target namespace
19292 * was evaluated during parsing and already took
19293 * "attributeFormDefault" into account.
19294 */
19295 /* ((attributes->flags & XML_SCHEMAS_ATTR_NSDEFAULT) == 0)) */
Daniel Veillardbe9c6322003-11-22 20:37:51 +000019296 continue;
19297 } else {
Daniel Veillard3646d642004-06-02 19:19:14 +000019298 if (attrDecl->targetNamespace == NULL)
Daniel Veillardbe9c6322003-11-22 20:37:51 +000019299 continue;
Daniel Veillard3646d642004-06-02 19:19:14 +000019300 if (!xmlStrEqual(attrDecl->targetNamespace,
Daniel Veillardbe9c6322003-11-22 20:37:51 +000019301 attr->ns->href))
19302 continue;
19303 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019304 }
Daniel Veillard3646d642004-06-02 19:19:14 +000019305#ifdef DEBUG_ATTR_VALIDATION
19306 printf("found\n");
19307#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019308 found = 1;
Daniel Veillard3646d642004-06-02 19:19:14 +000019309 curState->decl = attrDecl;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019310 ret = xmlSchemaCheckAttrLocallyValid(ctxt, attrDecl, curState, attr);
Daniel Veillard3646d642004-06-02 19:19:14 +000019311 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019312 if (!found) {
19313 if (attrDecl->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED) {
19314 xmlSchemaAttrStatePtr tmp;
19315
Daniel Veillard3646d642004-06-02 19:19:14 +000019316#ifdef DEBUG_ATTR_VALIDATION
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019317 printf("required attr not found\n");
Daniel Veillard3646d642004-06-02 19:19:14 +000019318#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019319 /*
19320 * Add a new dummy attribute state.
19321 */
19322 tmp = (xmlSchemaAttrStatePtr) xmlMalloc(sizeof(xmlSchemaAttrState));
19323 if (tmp == NULL) {
19324 xmlSchemaVErrMemory(ctxt, "registering required attributes", NULL);
19325 ctxt->node = oldnode;
19326 return (-1);
19327 }
19328 tmp->attr = NULL;
19329 tmp->state = XML_SCHEMAS_ATTR_MISSING;
19330 tmp->decl = attrDecl;
19331 tmp->next = NULL;
19332
19333 if (reqAttrStates == NULL) {
19334 reqAttrStates = tmp;
19335 reqAttrStatesTop = tmp;
19336 } else {
19337 reqAttrStatesTop->next = tmp;
19338 reqAttrStatesTop = tmp;
19339 }
19340 } else if ((attrDecl->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
19341 (xmlSchemaGetEffectiveValueConstraint(attrDecl,
19342 &fixed, &defValue, &defVal))) {
19343 xmlSchemaAttrStatePtr tmp;
19344 /*
19345 * Handle non existent default/fixed attributes.
19346 */
19347 tmp = (xmlSchemaAttrStatePtr)
19348 xmlMalloc(sizeof(xmlSchemaAttrState));
19349 if (tmp == NULL) {
19350 xmlSchemaVErrMemory(ctxt,
19351 "registering schema specified attributes", NULL);
19352 ctxt->node = oldnode;
19353 return (-1);
19354 }
19355 tmp->attr = NULL;
19356 tmp->state = XML_SCHEMAS_ATTR_DEFAULT;
19357 tmp->decl = attrDecl;
19358 tmp->value = defValue;
19359 tmp->next = NULL;
19360
19361 if (defAttrStates == NULL) {
19362 defAttrStates = tmp;
19363 defAttrStates = tmp;
19364 } else {
19365 defAttrStates->next = tmp;
19366 defAttrStatesTop = tmp;
19367 }
19368 }
Daniel Veillard3646d642004-06-02 19:19:14 +000019369 }
19370 attrUse = attrUse->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000019371 }
Daniel Veillard3646d642004-06-02 19:19:14 +000019372 /*
19373 * Add required attributes to the attribute states of the context.
19374 */
19375 if (reqAttrStates != NULL) {
19376 if (ctxt->attr == NULL) {
19377 ctxt->attr = reqAttrStates;
19378 } else {
19379 ctxt->attrTop->next = reqAttrStates;
19380 }
19381 ctxt->attrTop = reqAttrStatesTop;
Daniel Veillardc0826a72004-08-10 14:17:33 +000019382 }
Daniel Veillard3646d642004-06-02 19:19:14 +000019383 /*
19384 * Process wildcards.
19385 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019386
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019387 if ((type != NULL) && (type->attributeWildcard != NULL)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000019388#ifdef DEBUG_ATTR_VALIDATION
19389 xmlSchemaWildcardNsPtr ns;
19390 printf("matching wildcard: [%d] of complexType: %s\n", type->attributeWildcard, type->name);
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000019391 if (type->attributeWildcard->processContents ==
19392 XML_SCHEMAS_ANY_LAX)
19393 printf("processContents: lax\n");
19394 else if (type->attributeWildcard->processContents ==
19395 XML_SCHEMAS_ANY_STRICT)
19396 printf("processContents: strict\n");
19397 else
19398 printf("processContents: skip\n");
Daniel Veillard3646d642004-06-02 19:19:14 +000019399 if (type->attributeWildcard->any)
19400 printf("type: any\n");
19401 else if (type->attributeWildcard->negNsSet != NULL) {
19402 printf("type: negated\n");
19403 if (type->attributeWildcard->negNsSet->value == NULL)
19404 printf("ns: (absent)\n");
19405 else
19406 printf("ns: %s\n", type->attributeWildcard->negNsSet->value);
19407 } else if (type->attributeWildcard->nsSet != NULL) {
19408 printf("type: set\n");
19409 ns = type->attributeWildcard->nsSet;
19410 while (ns != NULL) {
19411 if (ns->value == NULL)
19412 printf("ns: (absent)\n");
19413 else
19414 printf("ns: %s\n", ns->value);
19415 ns = ns->next;
19416 }
19417 } else
19418 printf("empty\n");
19419
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000019420
19421#endif
Daniel Veillard3646d642004-06-02 19:19:14 +000019422 curState = ctxt->attr;
19423 while (curState != NULL) {
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000019424 if (curState->state == XML_SCHEMAS_ATTR_UNKNOWN) {
19425 if (curState->attr->ns != NULL)
19426 nsURI = curState->attr->ns->href;
19427 else
19428 nsURI = NULL;
19429 if (xmlSchemaMatchesWildcardNs(type->attributeWildcard,
19430 nsURI)) {
19431 /*
19432 * Handle processContents.
19433 */
19434 if ((type->attributeWildcard->processContents ==
19435 XML_SCHEMAS_ANY_LAX) ||
19436 (type->attributeWildcard->processContents ==
19437 XML_SCHEMAS_ANY_STRICT)) {
19438
19439 attr = curState->attr;
19440 attrDecl = xmlSchemaGetAttribute(ctxt->schema,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019441 attr->name, nsURI);
19442 curState->decl = attrDecl;
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000019443 if (attrDecl != NULL) {
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000019444 curState->decl = attrDecl;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019445 ret = xmlSchemaCheckAttrLocallyValid(ctxt, attrDecl, curState, attr);
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000019446 } else if (type->attributeWildcard->processContents ==
19447 XML_SCHEMAS_ANY_LAX) {
19448 curState->state = XML_SCHEMAS_ATTR_CHECKED;
19449 }
19450 } else
Daniel Veillard3646d642004-06-02 19:19:14 +000019451 curState->state = XML_SCHEMAS_ATTR_CHECKED;
Daniel Veillard8acdfbf2004-06-03 16:00:59 +000019452 }
19453 }
Daniel Veillard3646d642004-06-02 19:19:14 +000019454 curState = curState->next;
19455 }
19456 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019457
Daniel Veillardc0826a72004-08-10 14:17:33 +000019458 /*
19459 * Report missing and illegal attributes.
19460 */
19461 if (ctxt->attr != NULL) {
19462 curState = ctxt->attr;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019463 while ((curState != NULL) && (curState != ctxt->attrTop->next)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000019464 if (curState->state != XML_SCHEMAS_ATTR_CHECKED) {
19465 attr = curState->attr;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019466 if (curState->decl != NULL) {
19467 if (curState->decl->ref != NULL)
19468 attrDecl = curState->decl->refDecl;
19469 else
19470 attrDecl = curState->decl;
19471 } else
19472 attrDecl = NULL;
19473 if (curState->state == XML_SCHEMAS_ATTR_MISSING) {
19474 xmlSchemaVMissingAttrErr(ctxt, elem, attrDecl);
19475 } else if (curState->state ==
19476 XML_SCHEMAS_ATTR_TYPE_NOT_RESOLVED) {
19477 xmlSchemaVCustomErr(ctxt,
19478 XML_SCHEMAV_CVC_ATTRIBUTE_2,
19479 (xmlNodePtr) attr,
19480 (xmlSchemaTypePtr) attrDecl,
19481 "The type definition is absent",
19482 NULL);
19483 } else if (curState->state ==
19484 XML_SCHEMAS_ATTR_INVALID_FIXED_VALUE) {
19485 xmlSchemaVCustomErr(ctxt,
19486 XML_SCHEMAV_CVC_AU,
19487 (xmlNodePtr) attr, (xmlSchemaTypePtr) attrDecl,
19488 "The value does not match the fixed value "
19489 "constraint", NULL);
19490 } else if (curState->state == XML_SCHEMAS_ATTR_UNKNOWN) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000019491 /* TODO: "prohibited" won't ever be touched here!.
19492 (curState->state == XML_SCHEMAS_ATTR_PROHIBITED))
19493 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019494 /*
19495 * TODO: One might report different error messages
19496 * for the following errors.
19497 */
19498 if ((type == NULL) || (type->attributeWildcard == NULL)) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000019499 xmlSchemaVIllegalAttrErr(ctxt,
19500 XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_1, attr);
19501 } else {
19502 xmlSchemaVIllegalAttrErr(ctxt,
19503 XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_2, attr);
19504 }
19505 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000019506 }
19507 curState = curState->next;
19508 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019509 }
19510
19511 /*
19512 * Add missing default/fixed attributes.
19513 */
19514 if (ctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) {
19515 curState = defAttrStates;
19516 while (curState != NULL) {
19517 attrDecl = curState->decl;
19518 if (attrDecl->ref != NULL)
19519 attrDecl = attrDecl->refDecl;
19520 /*
19521 * PSVI: Add a new attribute node to the current element.
19522 */
19523 if (attrDecl->targetNamespace == NULL) {
19524 xmlNewProp(elem, attrDecl->name, curState->value);
19525 } else {
19526 xmlNsPtr ns;
19527
19528 ns = xmlSearchNsByHref(elem->doc, elem,
19529 attrDecl->targetNamespace);
19530 if (ns == NULL) {
19531 xmlChar prefix[12];
19532 int counter = 1;
19533
19534 attr = curState->attr;
19535 /*
19536 * Create a namespace declaration on the validation
19537 * root node if no namespace declaration is in scope.
19538 */
19539 snprintf((char *) prefix, sizeof(prefix), "p");
19540 /*
19541 * This is somehow not performant, since the ancestor
19542 * axis beyond @elem will be searched as well.
19543 */
19544 ns = xmlSearchNs(elem->doc, elem, BAD_CAST prefix);
19545 while (ns != NULL) {
19546 if (counter > 1000) {
19547 xmlSchemaVErr(ctxt, (xmlNodePtr) attr,
19548 XML_SCHEMAV_INTERNAL,
19549 "Internal error: xmlSchemaValidateAttributes, "
19550 "could not compute a ns prefix for "
19551 "default/fixed attribute '%s'.\n",
19552 attrDecl->name, NULL);
19553
19554 break;
19555 }
19556 snprintf((char *) prefix,
19557 sizeof(prefix), "p%d", counter++);
19558 ns = xmlSearchNs(elem->doc, elem,
19559 BAD_CAST prefix);
19560 }
19561 if (ns == NULL) {
19562 ns = xmlNewNs(ctxt->validationRoot,
19563 attrDecl->targetNamespace, BAD_CAST prefix);
19564 xmlNewNsProp(elem, ns, attrDecl->name,
19565 curState->value);
19566 }
19567 } else {
19568 xmlNewNsProp(elem, ns, attrDecl->name,
19569 curState->value);
19570 }
19571 }
19572 curState = curState->next;
19573 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000019574 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019575 if (defAttrStates != NULL)
19576 xmlSchemaFreeAttributeStates(defAttrStates);
19577
Daniel Veillard3646d642004-06-02 19:19:14 +000019578#ifdef DEBUG_ATTR_VALIDATION
19579 if (redundant)
19580 xmlGenericError(xmlGenericErrorContext,
19581 "xmlSchemaValidateAttributes: redundant call by type: %s\n",
19582 type->name);
19583#endif
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019584 ctxt->node = oldnode;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019585 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000019586}
19587
19588/**
19589 * xmlSchemaValidateElement:
19590 * @ctxt: a schema validation context
19591 * @elem: an element
19592 *
19593 * Validate an element in a tree
19594 *
19595 * Returns 0 if the element is schemas valid, a positive error code
19596 * number otherwise and -1 in case of internal or API error.
19597 */
19598static int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019599xmlSchemaValidateElement(xmlSchemaValidCtxtPtr ctxt)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019600{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019601 xmlSchemaElementPtr elemDecl;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019602 int ret = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000019603
Daniel Veillardc0826a72004-08-10 14:17:33 +000019604 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019605 * This one is called by xmlSchemaValidateDocument and
19606 * xmlSchemaValidateOneElement.
19607 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019608 if (ctxt->schema == NULL) {
19609 /*
19610 * No schema was specified at time of creation of the validation
19611 * context. Use xsi:schemaLocation and xsi:noNamespaceSchemaLocation
19612 * of the instance to build a schema.
19613 */
19614 if (ctxt->pctxt == NULL)
19615 ctxt->pctxt = xmlSchemaNewParserCtxt("*");
19616 if (ctxt->pctxt == NULL)
19617 return (-1);
19618 ctxt->schema = xmlSchemaNewSchema(ctxt->pctxt);
19619 if (ctxt->schema == NULL)
19620 return (-1);
19621 /* TODO: assign user data. */
19622 ctxt->pctxt->error = ctxt->error;
19623 ctxt->pctxt->warning = ctxt->warning;
19624 ctxt->xsiAssemble = 1;
19625 } else
19626 ctxt->xsiAssemble = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019627 /*
19628 * Assemble new schemata using xsi.
Daniel Veillardc0826a72004-08-10 14:17:33 +000019629 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019630 if (ctxt->xsiAssemble) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019631 ret = xmlSchemaAssembleByXSIElem(ctxt, ctxt->node);
19632 if (ret == -1) {
19633 xmlSchemaVCustomErr(ctxt,
19634 XML_SCHEMAV_INTERNAL,
19635 ctxt->node, NULL,
19636 "Internal error: xmlSchemaValidateElement, "
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019637 "assembling schema by xsi", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019638 }
19639 /*
19640 * NOTE: We won't react on schema parser errors here.
19641 * TODO: But a warning would be nice.
19642 */
19643 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019644 if (ret != -1) {
19645 if (ctxt->node->ns != NULL)
19646 elemDecl = xmlSchemaGetElem(ctxt->schema, ctxt->node->name,
19647 ctxt->node->ns->href);
19648 else
19649 elemDecl = xmlSchemaGetElem(ctxt->schema, ctxt->node->name, NULL);
19650
19651 if (elemDecl == NULL) {
19652 xmlSchemaVCustomErr(ctxt,
19653 XML_SCHEMAV_CVC_ELT_1,
19654 ctxt->node, NULL,
19655 "No matching global declaration available", NULL);
19656 ret = XML_SCHEMAV_CVC_ELT_1;
19657 } else {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019658#ifdef ELEM_INFO_ENABLED
19659 ctxt->depth = -1;
19660 xmlSchemaBeginElement(ctxt);
19661#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019662 ret = xmlSchemaValidateElementByDeclaration(ctxt, elemDecl);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019663#ifdef ELEM_INFO_ENABLED
19664 xmlSchemaEndElement(ctxt);
19665#endif
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019666 if (ret < 0) {
19667 xmlSchemaVCustomErr(ctxt,
19668 XML_SCHEMAV_INTERNAL, ctxt->node, NULL,
19669 "Internal error: xmlSchemaValidateElement, "
19670 "calling validation by declaration", NULL);
19671 }
19672 }
19673 }
19674 /* ctxt->xsiAssemble = 0; */
19675 if (ctxt->xsiAssemble) {
19676 if (ctxt->schema != NULL) {
19677 xmlSchemaFree(ctxt->schema);
19678 ctxt->schema = NULL;
19679 }
Daniel Veillard4255d502002-04-16 15:50:10 +000019680 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019681 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000019682}
19683
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019684
Daniel Veillard4255d502002-04-16 15:50:10 +000019685/**
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000019686 * xmlSchemaValidateOneElement:
19687 * @ctxt: a schema validation context
19688 * @elem: an element node
19689 *
19690 * Validate a branch of a tree, starting with the given @elem.
19691 *
19692 * Returns 0 if the element and its subtree is valid, a positive error
19693 * code number otherwise and -1 in case of an internal or API error.
19694 */
19695int
19696xmlSchemaValidateOneElement(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem)
19697{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019698 if ((ctxt == NULL) || (elem == NULL) || (elem->type != XML_ELEMENT_NODE))
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000019699 return (-1);
19700
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019701 if (ctxt->schema == NULL) {
19702 xmlSchemaVErr(ctxt, NULL,
19703 XML_SCHEMAV_INTERNAL,
19704 "API error: xmlSchemaValidateOneElement, "
19705 "no schema specified.\n", NULL, NULL);
19706 return (-1);
19707 }
19708
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000019709 ctxt->doc = elem->doc;
19710 ctxt->err = 0;
19711 ctxt->nberrors = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019712 ctxt->node = elem;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019713 ctxt->validationRoot = elem;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019714 return (xmlSchemaValidateElement(ctxt));
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000019715}
19716
19717/**
Daniel Veillard4255d502002-04-16 15:50:10 +000019718 * xmlSchemaValidateDocument:
19719 * @ctxt: a schema validation context
19720 * @doc: a parsed document tree
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019721 * @xsiAssemble: should schemata be added if requested by the instance?
Daniel Veillard4255d502002-04-16 15:50:10 +000019722 *
19723 * Validate a document tree in memory.
19724 *
19725 * Returns 0 if the document is schemas valid, a positive error code
19726 * number otherwise and -1 in case of internal or API error.
19727 */
19728static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019729xmlSchemaValidateDocument(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
19730{
Daniel Veillard4255d502002-04-16 15:50:10 +000019731 xmlNodePtr root;
Daniel Veillard01fa6152004-06-29 17:04:39 +000019732
Daniel Veillard4255d502002-04-16 15:50:10 +000019733 root = xmlDocGetRootElement(doc);
19734 if (root == NULL) {
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000019735 xmlSchemaVCustomErr(ctxt,
19736 XML_SCHEMAV_DOCUMENT_ELEMENT_MISSING,
19737 (xmlNodePtr) doc, NULL,
19738 "The document has no document element", NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019739 return (ctxt->err);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019740 }
Daniel Veillard4255d502002-04-16 15:50:10 +000019741 /*
19742 * Okay, start the recursive validation
19743 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019744 ctxt->node = root;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019745 ctxt->validationRoot = root;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019746 xmlSchemaValidateElement(ctxt);
Daniel Veillard4255d502002-04-16 15:50:10 +000019747
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019748 return (ctxt->err);
Daniel Veillard4255d502002-04-16 15:50:10 +000019749}
19750
19751/************************************************************************
19752 * *
19753 * SAX Validation code *
19754 * *
19755 ************************************************************************/
19756
19757/************************************************************************
19758 * *
19759 * Validation interfaces *
19760 * *
19761 ************************************************************************/
19762
19763/**
19764 * xmlSchemaNewValidCtxt:
19765 * @schema: a precompiled XML Schemas
19766 *
19767 * Create an XML Schemas validation context based on the given schema
19768 *
19769 * Returns the validation context or NULL in case of error
19770 */
19771xmlSchemaValidCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019772xmlSchemaNewValidCtxt(xmlSchemaPtr schema)
19773{
Daniel Veillard4255d502002-04-16 15:50:10 +000019774 xmlSchemaValidCtxtPtr ret;
19775
19776 ret = (xmlSchemaValidCtxtPtr) xmlMalloc(sizeof(xmlSchemaValidCtxt));
19777 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019778 xmlSchemaVErrMemory(NULL, "allocating validation context", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000019779 return (NULL);
19780 }
19781 memset(ret, 0, sizeof(xmlSchemaValidCtxt));
Daniel Veillardc0826a72004-08-10 14:17:33 +000019782 ret->schema = schema;
Daniel Veillard3646d642004-06-02 19:19:14 +000019783 ret->attrTop = NULL;
19784 ret->attr = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000019785 return (ret);
19786}
19787
19788/**
19789 * xmlSchemaFreeValidCtxt:
19790 * @ctxt: the schema validation context
19791 *
19792 * Free the resources associated to the schema validation context
19793 */
19794void
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019795xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt)
19796{
Daniel Veillard4255d502002-04-16 15:50:10 +000019797 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019798 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000019799 if (ctxt->attr != NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000019800 xmlSchemaFreeAttributeStates(ctxt->attr);
Daniel Veillard88c58912002-04-23 07:12:20 +000019801 if (ctxt->value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019802 xmlSchemaFreeValue(ctxt->value);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019803 if (ctxt->pctxt != NULL) {
19804 xmlSchemaFreeParserCtxt(ctxt->pctxt);
19805 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019806
19807#ifdef IDC_ENABLED
19808 if (ctxt->idcNodes != NULL) {
19809 int i;
19810 xmlSchemaPSVIIDCNodePtr item;
19811
19812 for (i = 0; i < ctxt->nbIdcNodes; i++) {
19813 item = ctxt->idcNodes[i];
19814 xmlFree(item->keys);
19815 xmlFree(item);
19816 }
19817 xmlFree(ctxt->idcNodes);
19818 }
19819
19820 if (ctxt->idcKeys != NULL) {
19821 int i;
19822 for (i = 0; i < ctxt->nbIdcKeys; i++)
19823 xmlSchemaIDCFreeKey(ctxt->idcKeys[i]);
19824 xmlFree(ctxt->idcKeys);
19825 }
19826
19827 if (ctxt->xpathStates != NULL)
19828 xmlSchemaFreeIDCStateObjList(ctxt->xpathStates);
19829 if (ctxt->xpathStatePool != NULL)
19830 xmlSchemaFreeIDCStateObjList(ctxt->xpathStatePool);
19831
19832 /*
19833 * Augmented IDC information.
19834 */
19835 if (ctxt->aidcs != NULL) {
19836 xmlSchemaIDCAugPtr cur = ctxt->aidcs, next;
19837 do {
19838 next = cur->next;
19839 xmlFree(cur);
19840 cur = next;
19841 } while (cur != NULL);
19842 }
19843#endif /* IDC_ENABLED */
19844#ifdef ELEM_INFO_ENABLED
19845 if (ctxt->elemInfos != NULL) {
19846 int i;
19847 xmlSchemaElemInfoPtr info;
19848
19849 for (i = 0; i < ctxt->sizeElemInfos; i++) {
19850 info = ctxt->elemInfos[i];
19851 if (info == NULL)
19852 continue;
19853 if (info->value != NULL)
19854 xmlSchemaFreeValue(info->value);
19855#ifdef IDC_ENABLED
19856 if (info->idcMatchers != NULL)
19857 xmlSchemaIDCFreeMatcherList(info->idcMatchers);
19858#endif
19859 /*
19860 * TODO: Free the IDC table if still existent.
19861 */
19862
19863 /*
19864 xmlFree(info->localName);
19865 if (info->namespaceName != NULL)
19866 xmlFree(info->namespaceName);
19867 */
19868 xmlFree(info);
19869 }
19870 xmlFree(ctxt->elemInfos);
19871 }
19872#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000019873 xmlFree(ctxt);
19874}
19875
19876/**
19877 * xmlSchemaSetValidErrors:
19878 * @ctxt: a schema validation context
19879 * @err: the error function
19880 * @warn: the warning function
Daniel Veillarda9b66d02002-12-11 14:23:49 +000019881 * @ctx: the functions context
Daniel Veillard4255d502002-04-16 15:50:10 +000019882 *
William M. Brack2f2a6632004-08-20 23:09:47 +000019883 * Set the error and warning callback informations
Daniel Veillard4255d502002-04-16 15:50:10 +000019884 */
19885void
19886xmlSchemaSetValidErrors(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019887 xmlSchemaValidityErrorFunc err,
19888 xmlSchemaValidityWarningFunc warn, void *ctx)
19889{
Daniel Veillard4255d502002-04-16 15:50:10 +000019890 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019891 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000019892 ctxt->error = err;
19893 ctxt->warning = warn;
19894 ctxt->userData = ctx;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019895 if (ctxt->pctxt != NULL)
19896 xmlSchemaSetParserErrors(ctxt->pctxt, err, warn, ctx);
Daniel Veillard4255d502002-04-16 15:50:10 +000019897}
19898
19899/**
Daniel Veillard259f0df2004-08-18 09:13:18 +000019900 * xmlSchemaGetValidErrors:
19901 * @ctxt: a XML-Schema validation context
19902 * @err: the error function result
19903 * @warn: the warning function result
19904 * @ctx: the functions context result
19905 *
19906 * Get the error and warning callback informations
19907 *
19908 * Returns -1 in case of error and 0 otherwise
19909 */
19910int
19911xmlSchemaGetValidErrors(xmlSchemaValidCtxtPtr ctxt,
19912 xmlSchemaValidityErrorFunc * err,
19913 xmlSchemaValidityWarningFunc * warn, void **ctx)
19914{
19915 if (ctxt == NULL)
19916 return (-1);
19917 if (err != NULL)
19918 *err = ctxt->error;
19919 if (warn != NULL)
19920 *warn = ctxt->warning;
19921 if (ctx != NULL)
19922 *ctx = ctxt->userData;
19923 return (0);
19924}
19925
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019926
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019927/**
Daniel Veillard6927b102004-10-27 17:29:04 +000019928 * xmlSchemaSetValidOptions:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019929 * @ctxt: a schema validation context
19930 * @options: a combination of xmlSchemaValidOption
19931 *
19932 * Sets the options to be used during the validation.
19933 *
19934 * Returns 0 in case of success, -1 in case of an
19935 * API error.
19936 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019937int
19938xmlSchemaSetValidOptions(xmlSchemaValidCtxtPtr ctxt,
19939 int options)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019940
19941{
19942 int i;
19943
19944 if (ctxt == NULL)
19945 return (-1);
19946 /*
19947 * WARNING: Change the start value if adding to the
19948 * xmlSchemaValidOption.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019949 * TODO: Is there an other, more easy to maintain,
19950 * way?
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019951 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019952 for (i = 1; i < (int) sizeof(int) * 8; i++) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019953 if (options & 1<<i) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019954 xmlSchemaVErr(ctxt, NULL,
19955 XML_SCHEMAV_INTERNAL,
19956 "Internal error: xmlSchemaSetValidOptions, "
19957 "invalid option argument.\n", NULL, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019958 return (-1);
19959 }
19960 }
19961 ctxt->options = options;
19962 return (0);
19963}
19964
19965/**
Daniel Veillard6927b102004-10-27 17:29:04 +000019966 * xmlSchemaValidCtxtGetOptions:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019967 * @ctxt: a schema validation context
19968 *
William M. Brack21e4ef22005-01-02 09:53:13 +000019969 * Get the validation context options.
19970 *
19971 * Returns the option combination or -1 on error.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019972 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019973int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019974xmlSchemaValidCtxtGetOptions(xmlSchemaValidCtxtPtr ctxt)
19975
19976{
19977 if (ctxt == NULL)
19978 return (-1);
19979 else
19980 return (ctxt->options);
19981}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019982
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000019983
Daniel Veillard259f0df2004-08-18 09:13:18 +000019984/**
Daniel Veillard4255d502002-04-16 15:50:10 +000019985 * xmlSchemaValidateDoc:
19986 * @ctxt: a schema validation context
19987 * @doc: a parsed document tree
19988 *
19989 * Validate a document tree in memory.
19990 *
19991 * Returns 0 if the document is schemas valid, a positive error code
19992 * number otherwise and -1 in case of internal or API error.
19993 */
19994int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000019995xmlSchemaValidateDoc(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
19996{
Daniel Veillard4255d502002-04-16 15:50:10 +000019997 int ret;
19998
19999 if ((ctxt == NULL) || (doc == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020000 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000020001
20002 ctxt->doc = doc;
William M. Brack2f2a6632004-08-20 23:09:47 +000020003 ctxt->err = 0;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000020004 ctxt->nberrors = 0;
20005
20006 /*
20007 if (ctxt->schema == NULL) {
20008 xmlSchemaVErr(ctxt, NULL,
20009 XML_SCHEMAV_INTERNAL,
20010 "API error: xmlSchemaValidateDoc, "
20011 "no schema specified and assembling of schemata "
20012 "using xsi:schemaLocation and xsi:noNamespaceSchemaLocation "
20013 "is not enabled.\n", NULL, NULL);
20014 return (-1);
20015 }
20016 */
Daniel Veillard4255d502002-04-16 15:50:10 +000020017 ret = xmlSchemaValidateDocument(ctxt, doc);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020018 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000020019}
20020
20021/**
20022 * xmlSchemaValidateStream:
20023 * @ctxt: a schema validation context
20024 * @input: the input to use for reading the data
20025 * @enc: an optional encoding information
20026 * @sax: a SAX handler for the resulting events
20027 * @user_data: the context to provide to the SAX handler.
20028 *
20029 * Validate a document tree in memory.
20030 *
20031 * Returns 0 if the document is schemas valid, a positive error code
20032 * number otherwise and -1 in case of internal or API error.
20033 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020034int
Daniel Veillard4255d502002-04-16 15:50:10 +000020035xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020036 xmlParserInputBufferPtr input, xmlCharEncoding enc,
20037 xmlSAXHandlerPtr sax, void *user_data)
20038{
Daniel Veillard4255d502002-04-16 15:50:10 +000020039 if ((ctxt == NULL) || (input == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020040 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000020041 ctxt->input = input;
20042 ctxt->enc = enc;
20043 ctxt->sax = sax;
20044 ctxt->user_data = user_data;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000020045 TODO return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000020046}
20047
20048#endif /* LIBXML_SCHEMAS_ENABLED */