blob: 76bf3fdb908e1550152198087eeb4b259d6675b1 [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
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010/*
Daniel Veillardb0f397e2003-12-23 23:30:53 +000011 * 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.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015 * - if we don't intend to use the schema for schemas, we
Daniel Veillard01fa6152004-06-29 17:04:39 +000016 * need to validate all schema attributes (ref, type, name)
17 * against their types.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018 * - Eliminate item creation for: ??
19 *
20 * NOTES:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021 * - Elimated item creation for: <restriction>, <extension>,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000022 * <simpleContent>, <complexContent>, <list>, <union>
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023 *
Daniel Veillardb0f397e2003-12-23 23:30:53 +000024 */
Daniel Veillard4255d502002-04-16 15:50:10 +000025#define IN_LIBXML
26#include "libxml.h"
27
28#ifdef LIBXML_SCHEMAS_ENABLED
29
30#include <string.h>
31#include <libxml/xmlmemory.h>
32#include <libxml/parser.h>
33#include <libxml/parserInternals.h>
34#include <libxml/hash.h>
Daniel Veillard5a872412002-05-22 06:40:27 +000035#include <libxml/uri.h>
Daniel Veillard4255d502002-04-16 15:50:10 +000036#include <libxml/xmlschemas.h>
37#include <libxml/schemasInternals.h>
38#include <libxml/xmlschemastypes.h>
39#include <libxml/xmlautomata.h>
40#include <libxml/xmlregexp.h>
Daniel Veillardbe9c6322003-11-22 20:37:51 +000041#include <libxml/dict.h>
Kasimier T. Buchcik72d3adc2005-07-08 16:43:37 +000042#include <libxml/encoding.h>
43#include <libxml/xmlIO.h>
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000044#ifdef LIBXML_PATTERN_ENABLED
45#include <libxml/pattern.h>
46#endif
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000047#ifdef LIBXML_READER_ENABLED
48#include <libxml/xmlreader.h>
49#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000050
Daniel Veillarda84c0b32003-06-02 16:58:46 +000051/* #define DEBUG 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000052
Daniel Veillard82bbbd42003-05-11 20:16:09 +000053/* #define DEBUG_CONTENT 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000054
Daniel Veillard82bbbd42003-05-11 20:16:09 +000055/* #define DEBUG_TYPE 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000056
Daniel Veillard118aed72002-09-24 14:13:13 +000057/* #define DEBUG_CONTENT_REGEXP 1 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000058
Daniel Veillard4255d502002-04-16 15:50:10 +000059/* #define DEBUG_AUTOMATA 1 */
60
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000061#define DEBUG_ATTR_VALIDATION 0
Daniel Veillardc0826a72004-08-10 14:17:33 +000062
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000063/* #define DEBUG_IDC 1 */
64
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +000065/* #define DEBUG_INCLUDES 1 */
66
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000067/* #define ENABLE_PARTICLE_RESTRICTION 1 */
68
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000069/* #define ENABLE_REDEFINE */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000070
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000071#define DUMP_CONTENT_MODEL
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000072
73#ifdef LIBXML_READER_ENABLED
74/* #define XML_SCHEMA_READER_ENABLED */
75#endif
Daniel Veillardc0826a72004-08-10 14:17:33 +000076
Daniel Veillard4255d502002-04-16 15:50:10 +000077#define UNBOUNDED (1 << 30)
78#define TODO \
79 xmlGenericError(xmlGenericErrorContext, \
80 "Unimplemented block at %s:%d\n", \
81 __FILE__, __LINE__);
82
William M. Brack2f2a6632004-08-20 23:09:47 +000083#define XML_SCHEMAS_NO_NAMESPACE (const xmlChar *) "##"
Daniel Veillardc0826a72004-08-10 14:17:33 +000084
Daniel Veillard4255d502002-04-16 15:50:10 +000085/*
86 * The XML Schemas namespaces
87 */
88static const xmlChar *xmlSchemaNs = (const xmlChar *)
89 "http://www.w3.org/2001/XMLSchema";
90
91static const xmlChar *xmlSchemaInstanceNs = (const xmlChar *)
92 "http://www.w3.org/2001/XMLSchema-instance";
93
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000094static const xmlChar *xmlNamespaceNs = (const xmlChar *)
95 "http://www.w3.org/2000/xmlns/";
96
Daniel Veillardc0826a72004-08-10 14:17:33 +000097static const xmlChar *xmlSchemaElemDesElemDecl = (const xmlChar *)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000098 "element decl.";
Daniel Veillardc0826a72004-08-10 14:17:33 +000099static const xmlChar *xmlSchemaElemDesAttrDecl = (const xmlChar *)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000100 "attribute decl.";
Daniel Veillardc0826a72004-08-10 14:17:33 +0000101static const xmlChar *xmlSchemaElemDesAttrRef = (const xmlChar *)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000102 "attribute use";
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +0000103static const xmlChar *xmlSchemaElemModelGrDef = (const xmlChar *)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000104 "model group";
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000105#if 0
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +0000106static const xmlChar *xmlSchemaElemModelGrRef = (const xmlChar *)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000107 "model group ref.";
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000108#endif
Daniel Veillardc0826a72004-08-10 14:17:33 +0000109
Daniel Veillard4255d502002-04-16 15:50:10 +0000110#define IS_SCHEMA(node, type) \
111 ((node != NULL) && (node->ns != NULL) && \
112 (xmlStrEqual(node->name, (const xmlChar *) type)) && \
113 (xmlStrEqual(node->ns->href, xmlSchemaNs)))
114
Daniel Veillardc0826a72004-08-10 14:17:33 +0000115#define FREE_AND_NULL(str) \
116 if (str != NULL) { \
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000117 xmlFree((xmlChar *) str); \
Daniel Veillardc0826a72004-08-10 14:17:33 +0000118 str = NULL; \
119 }
120
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000121#define IS_ANYTYPE(item) \
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000122 ((item->type == XML_SCHEMA_TYPE_BASIC) && \
123 (item->builtInType == XML_SCHEMAS_ANYTYPE))
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000124
125#define IS_COMPLEX_TYPE(item) \
126 ((item->type == XML_SCHEMA_TYPE_COMPLEX) || \
127 (item->builtInType == XML_SCHEMAS_ANYTYPE))
128
129#define IS_SIMPLE_TYPE(item) \
130 ((item->type == XML_SCHEMA_TYPE_SIMPLE) || \
131 ((item->type == XML_SCHEMA_TYPE_BASIC) && \
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000132 (item->builtInType != XML_SCHEMAS_ANYTYPE)))
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000133
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000134#define IS_ANY_SIMPLE_TYPE(item) \
135 ((item->type == XML_SCHEMA_TYPE_BASIC) && \
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000136 (item->builtInType == XML_SCHEMAS_ANYSIMPLETYPE))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000137
138#define IS_NOT_TYPEFIXED(item) \
139 ((item->type != XML_SCHEMA_TYPE_BASIC) && \
140 ((item->flags & XML_SCHEMAS_TYPE_INTERNAL_RESOLVED) == 0))
141
142#define HAS_COMPLEX_CONTENT(item) \
143 ((item->contentType == XML_SCHEMA_CONTENT_MIXED) || \
144 (item->contentType == XML_SCHEMA_CONTENT_EMPTY) || \
145 (item->contentType == XML_SCHEMA_CONTENT_ELEMENTS))
146
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +0000147#define HAS_SIMPLE_CONTENT(item) \
148 ((item->contentType == XML_SCHEMA_CONTENT_SIMPLE) || \
149 (item->contentType == XML_SCHEMA_CONTENT_BASIC))
150
151#define HAS_MIXED_CONTENT(item) (item->contentType == XML_SCHEMA_CONTENT_MIXED)
152
153#define IS_PARTICLE_EMPTIABLE(item) \
154 (xmlSchemaIsParticleEmptiable((xmlSchemaParticlePtr) item->subtypes))
155
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000156#define GET_NODE(item) xmlSchemaGetComponentNode((xmlSchemaBasicItemPtr) item)
157
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000158#define GET_LIST_ITEM_TYPE(item) item->subtypes
159
160#define VARIETY_ATOMIC(item) (item->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC)
161#define VARIETY_LIST(item) (item->flags & XML_SCHEMAS_TYPE_VARIETY_LIST)
162#define VARIETY_UNION(item) (item->flags & XML_SCHEMAS_TYPE_VARIETY_UNION)
163
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000164#define IS_MODEL_GROUP(item) \
165 ((item->type == XML_SCHEMA_TYPE_SEQUENCE) || \
166 (item->type == XML_SCHEMA_TYPE_CHOICE) || \
167 (item->type == XML_SCHEMA_TYPE_ALL))
168
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000169#define INODE_NILLED(item) (item->flags & XML_SCHEMA_ELEM_INFO_NILLED)
170
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +0000171#define ELEM_TYPE(item) item->subtypes
172
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +0000173#define GET_PARTICLE(item) (xmlSchemaParticlePtr) item->subtypes;
174
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +0000175#define SUBST_GROUP_AFF(item) item->refDecl
176
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000177#if 0
178#define WXS_GET_NEXT(item) xmlSchemaGetNextComponent((xmlSchemaBasicItemPtr) item)
179#endif
180
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +0000181#define SUBSET_RESTRICTION 1<<0
182#define SUBSET_EXTENSION 1<<1
183#define SUBSET_SUBSTITUTION 1<<2
184#define SUBSET_LIST 1<<3
185#define SUBSET_UNION 1<<4
186
Daniel Veillard4255d502002-04-16 15:50:10 +0000187#define XML_SCHEMAS_PARSE_ERROR 1
188
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000189#define SCHEMAS_PARSE_OPTIONS XML_PARSE_NOENT
190
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000191typedef struct _xmlSchemaNodeInfo xmlSchemaNodeInfo;
192typedef xmlSchemaNodeInfo *xmlSchemaNodeInfoPtr;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000193
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000194
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000195typedef struct _xmlSchemaItemList xmlSchemaAssemble;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000196typedef xmlSchemaAssemble *xmlSchemaAssemblePtr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000197
198typedef struct _xmlSchemaItemList xmlSchemaItemList;
199typedef xmlSchemaItemList *xmlSchemaItemListPtr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000200struct _xmlSchemaItemList {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000201 void **items; /* used for dynamic addition of schemata */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000202 int nbItems; /* used for dynamic addition of schemata */
203 int sizeItems; /* used for dynamic addition of schemata */
204};
205
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +0000206/*
207typedef struct _xmlSchemaItemListChain xmlSchemaItemListChain;
208typedef xmlSchemaItemListChain xmlSchemaItemListChainPtr;
209struct _xmlSchemaItemListChain {
210 xmlSchemaItemListChainPtr next;
211 xmlSchemaItemListPtr list;
212}
213*/
214
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +0000215/*
216typedef struct _xmlSchemaItemListChain xmlSchemaItemListChain;
217typedef xmlSchemaItemListChain xmlSchemaItemListChainPtr;
218struct _xmlSchemaItemListChain {
219 xmlSchemaItemListChainPtr next;
220 xmlSchemaItemListPtr list;
221}
222*/
223
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000224typedef struct _xmlSchemaAbstractCtxt xmlSchemaAbstractCtxt;
225typedef xmlSchemaAbstractCtxt *xmlSchemaAbstractCtxtPtr;
226struct _xmlSchemaAbstractCtxt {
227 int type;
228};
229
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +0000230/**
231 * xmlSchemaContainer:
232 */
233typedef struct _xmlSchemaContainer xmlSchemaContainer;
234typedef xmlSchemaContainer *xmlSchemaContainerPtr;
235struct _xmlSchemaContainer {
236 xmlSchemaItemListPtr typeDefs;
237 xmlSchemaItemListPtr attrDecls;
238 xmlSchemaItemListPtr elemDecls;
239 xmlSchemaItemListPtr attrGroupDefs;
240 xmlSchemaItemListPtr modelGroupDefs;
241 xmlSchemaItemListPtr notationDecls;
242 xmlSchemaItemListPtr annotations;
243 xmlSchemaItemListPtr locals;
244};
245
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000246#define XML_SCHEMA_CTXT_PARSER 1
247#define XML_SCHEMA_CTXT_VALIDATOR 2
248
Daniel Veillard4255d502002-04-16 15:50:10 +0000249struct _xmlSchemaParserCtxt {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000250 int type;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000251 void *userData; /* user specific data block */
252 xmlSchemaValidityErrorFunc error; /* the callback in case of errors */
253 xmlSchemaValidityWarningFunc warning; /* the callback in case of warning */
Daniel Veillarde19fc232002-04-22 16:01:24 +0000254 xmlSchemaValidError err;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000255 int nberrors;
Daniel Veillard659e71e2003-10-10 14:10:40 +0000256 xmlStructuredErrorFunc serror;
Daniel Veillard4255d502002-04-16 15:50:10 +0000257
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +0000258 /* xmlSchemaPtr topschema; The main schema */
259 /* xmlHashTablePtr namespaces; Hash table of namespaces to schemas */
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000260
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000261 xmlSchemaPtr schema; /* The schema in use */
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000262 const xmlChar *container; /* the current element, group, ... */
Daniel Veillard4255d502002-04-16 15:50:10 +0000263 int counter;
264
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000265 const xmlChar *URL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000266 xmlDocPtr doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +0000267 int preserve; /* Whether the doc should be freed */
Daniel Veillard4255d502002-04-16 15:50:10 +0000268
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000269 const char *buffer;
270 int size;
Daniel Veillard6045c902002-10-09 21:13:59 +0000271
Daniel Veillard4255d502002-04-16 15:50:10 +0000272 /*
273 * Used to build complex element content models
274 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000275 xmlAutomataPtr am;
Daniel Veillard4255d502002-04-16 15:50:10 +0000276 xmlAutomataStatePtr start;
277 xmlAutomataStatePtr end;
278 xmlAutomataStatePtr state;
Daniel Veillardbe9c6322003-11-22 20:37:51 +0000279
280 xmlDictPtr dict; /* dictionnary for interned string names */
Daniel Veillardb0f397e2003-12-23 23:30:53 +0000281 int includes; /* the inclusion level, 0 for root or imports */
Daniel Veillard01fa6152004-06-29 17:04:39 +0000282 xmlSchemaTypePtr ctxtType; /* The current context simple/complex type */
283 xmlSchemaTypePtr parentItem; /* The current parent schema item */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000284 xmlSchemaAssemblePtr assemble;
285 int options;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000286 xmlSchemaValidCtxtPtr vctxt;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +0000287 const xmlChar **localImports; /* list of locally imported namespaces */
288 int sizeLocalImports;
289 int nbLocalImports;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +0000290 xmlHashTablePtr substGroups;
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +0000291 int isS4S;
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +0000292 int isRedefine;
293 xmlSchemaContainerPtr compContainer;
Daniel Veillard4255d502002-04-16 15:50:10 +0000294};
295
Daniel Veillard4255d502002-04-16 15:50:10 +0000296#define XML_SCHEMAS_ATTR_UNKNOWN 1
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000297#define XML_SCHEMAS_ATTR_ASSESSED 2
Daniel Veillard3646d642004-06-02 19:19:14 +0000298#define XML_SCHEMAS_ATTR_PROHIBITED 3
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000299#define XML_SCHEMAS_ATTR_ERR_MISSING 4
Daniel Veillard3646d642004-06-02 19:19:14 +0000300#define XML_SCHEMAS_ATTR_INVALID_VALUE 5
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000301#define XML_SCHEMAS_ATTR_ERR_NO_TYPE 6
302#define XML_SCHEMAS_ATTR_ERR_FIXED_VALUE 7
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000303#define XML_SCHEMAS_ATTR_DEFAULT 8
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +0000304#define XML_SCHEMAS_ATTR_VALIDATE_VALUE 9
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000305#define XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL 10
306#define XML_SCHEMAS_ATTR_HAS_ATTR_USE 11
307#define XML_SCHEMAS_ATTR_HAS_ATTR_DECL 12
308#define XML_SCHEMAS_ATTR_WILD_SKIP 13
309#define XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL 14
310#define XML_SCHEMAS_ATTR_ERR_WILD_DUPLICATE_ID 15
311#define XML_SCHEMAS_ATTR_ERR_WILD_AND_USE_ID 16
312#define XML_SCHEMAS_ATTR_META 17
Daniel Veillard4255d502002-04-16 15:50:10 +0000313
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000314/**
315 * xmlSchemaBasicItem:
316 *
317 * The abstract base type for schema components.
318 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000319typedef struct _xmlSchemaBasicItem xmlSchemaBasicItem;
320typedef xmlSchemaBasicItem *xmlSchemaBasicItemPtr;
321struct _xmlSchemaBasicItem {
322 xmlSchemaTypeType type;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000323};
324
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +0000325#define XML_SCHEMA_SCHEMA_REF_IMPORT 1
326#define XML_SCHEMA_SCHEMA_REF_INCLUDE 2
327#define XML_SCHEMA_SCHEMA_REF_REDEFINE 3
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +0000328
329#define XML_SCHEMA_SCHEMA_REF_REL_CHILD 1
330#define XML_SCHEMA_SCHEMA_REF_REL_PARENT 2
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +0000331/**
332 * xmlSchemaSchemaRef:
333 *
334 * Used to create a graph of schema relationships.
335 */
336typedef struct _xmlSchemaSchemaRef xmlSchemaSchemaRef;
337typedef xmlSchemaSchemaRef *xmlSchemaSchemaRefPtr;
338struct _xmlSchemaSchemaRef {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +0000339 xmlSchemaSchemaRefPtr next;
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +0000340 int type; /* E.g. XML_SCHEMA_SCHEMA_REF_IMPORT */
341 int relation;
342 xmlSchemaPtr schema;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +0000343};
344
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000345/**
346 * xmlSchemaAnnotItem:
347 *
348 * The abstract base type for annotated schema components.
349 * (Extends xmlSchemaBasicItem)
350 */
351typedef struct _xmlSchemaAnnotItem xmlSchemaAnnotItem;
352typedef xmlSchemaAnnotItem *xmlSchemaAnnotItemPtr;
353struct _xmlSchemaAnnotItem {
354 xmlSchemaTypeType type;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000355 xmlSchemaAnnotPtr annot;
356};
357
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000358/**
359 * xmlSchemaTreeItem:
360 *
361 * The abstract base type for tree-like structured schema components.
362 * (Extends xmlSchemaAnnotItem)
363 */
364typedef struct _xmlSchemaTreeItem xmlSchemaTreeItem;
365typedef xmlSchemaTreeItem *xmlSchemaTreeItemPtr;
366struct _xmlSchemaTreeItem {
367 xmlSchemaTypeType type;
368 xmlSchemaAnnotPtr annot;
369 xmlSchemaTreeItemPtr next;
370 xmlSchemaTreeItemPtr children;
371};
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000372
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000373/**
374 * xmlSchemaQNameRef:
375 *
376 * A component reference item (not a schema component)
377 * (Extends xmlSchemaBasicItem)
378 */
379typedef struct _xmlSchemaQNameRef xmlSchemaQNameRef;
380typedef xmlSchemaQNameRef *xmlSchemaQNameRefPtr;
381struct _xmlSchemaQNameRef {
382 xmlSchemaTypeType type;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000383 xmlSchemaBasicItemPtr item;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000384 xmlSchemaTypeType itemType;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000385 const xmlChar *name;
386 const xmlChar *targetNamespace;
387};
388
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000389/**
390 * xmlSchemaParticle:
391 *
392 * A particle component.
393 * (Extends xmlSchemaTreeItem)
394 */
395typedef struct _xmlSchemaParticle xmlSchemaParticle;
396typedef xmlSchemaParticle *xmlSchemaParticlePtr;
397struct _xmlSchemaParticle {
398 xmlSchemaTypeType type;
399 xmlSchemaAnnotPtr annot;
400 xmlSchemaTreeItemPtr next; /* next particle (OR "element decl" OR "wildcard") */
401 xmlSchemaTreeItemPtr children; /* the "term" ("model group" OR "group definition") */
402 int minOccurs;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000403 int maxOccurs;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000404 xmlNodePtr node;
405};
406
407/**
408 * xmlSchemaModelGroup:
409 *
410 * A model group component.
411 * (Extends xmlSchemaTreeItem)
412 */
413typedef struct _xmlSchemaModelGroup xmlSchemaModelGroup;
414typedef xmlSchemaModelGroup *xmlSchemaModelGroupPtr;
415struct _xmlSchemaModelGroup {
416 xmlSchemaTypeType type; /* XML_SCHEMA_TYPE_SEQUENCE, XML_SCHEMA_TYPE_CHOICE, XML_SCHEMA_TYPE_ALL */
417 xmlSchemaAnnotPtr annot;
418 xmlSchemaTreeItemPtr next; /* not used */
419 xmlSchemaTreeItemPtr children; /* first particle (OR "element decl" OR "wildcard") */
420 xmlNodePtr node;
421};
422
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +0000423#define XML_SCHEMA_MODEL_GROUP_DEF_MARKED 1<<0
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000424/**
425 * xmlSchemaModelGroupDef:
426 *
427 * A model group definition component.
428 * (Extends xmlSchemaTreeItem)
429 */
430typedef struct _xmlSchemaModelGroupDef xmlSchemaModelGroupDef;
431typedef xmlSchemaModelGroupDef *xmlSchemaModelGroupDefPtr;
432struct _xmlSchemaModelGroupDef {
433 xmlSchemaTypeType type; /* XML_SCHEMA_TYPE_GROUP */
434 xmlSchemaAnnotPtr annot;
435 xmlSchemaTreeItemPtr next; /* not used */
436 xmlSchemaTreeItemPtr children; /* the "model group" */
437 const xmlChar *name;
438 const xmlChar *targetNamespace;
439 xmlNodePtr node;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +0000440 int flags;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000441};
442
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000443typedef struct _xmlSchemaIDC xmlSchemaIDC;
444typedef xmlSchemaIDC *xmlSchemaIDCPtr;
445
446/**
447 * xmlSchemaIDCSelect:
448 *
449 * The identity-constraint "field" and "selector" item, holding the
450 * XPath expression.
451 */
452typedef struct _xmlSchemaIDCSelect xmlSchemaIDCSelect;
453typedef xmlSchemaIDCSelect *xmlSchemaIDCSelectPtr;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000454struct _xmlSchemaIDCSelect {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000455 xmlSchemaIDCSelectPtr next;
456 xmlSchemaIDCPtr idc;
457 int index; /* an index position if significant for IDC key-sequences */
458 const xmlChar *xpath; /* the XPath expression */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +0000459 void *xpathComp; /* the compiled XPath expression */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000460};
461
462/**
463 * xmlSchemaIDC:
464 *
465 * The identity-constraint definition component.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000466 * (Extends xmlSchemaAnnotItem)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000467 */
468
469struct _xmlSchemaIDC {
470 xmlSchemaTypeType type;
471 xmlSchemaAnnotPtr annot;
472 xmlSchemaIDCPtr next;
473 xmlNodePtr node;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000474 const xmlChar *name;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000475 const xmlChar *targetNamespace;
476 xmlSchemaIDCSelectPtr selector;
477 xmlSchemaIDCSelectPtr fields;
478 int nbFields;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000479 xmlSchemaQNameRefPtr ref;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000480};
481
482/**
483 * xmlSchemaIDCAug:
484 *
485 * The augmented IDC information used for validation.
486 */
487typedef struct _xmlSchemaIDCAug xmlSchemaIDCAug;
488typedef xmlSchemaIDCAug *xmlSchemaIDCAugPtr;
489struct _xmlSchemaIDCAug {
490 xmlSchemaIDCAugPtr next; /* next in a list */
491 xmlSchemaIDCPtr def; /* the IDC definition */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000492 int bubbleDepth; /* the lowest tree level to which IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000493 tables need to be bubbled upwards */
494};
495
496/**
497 * xmlSchemaPSVIIDCKeySequence:
498 *
499 * The key sequence of a node table item.
500 */
501typedef struct _xmlSchemaPSVIIDCKey xmlSchemaPSVIIDCKey;
502typedef xmlSchemaPSVIIDCKey *xmlSchemaPSVIIDCKeyPtr;
503struct _xmlSchemaPSVIIDCKey {
504 xmlSchemaTypePtr type;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000505 xmlSchemaValPtr val;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000506};
507
508/**
509 * xmlSchemaPSVIIDCNode:
510 *
511 * The node table item of a node table.
512 */
513typedef struct _xmlSchemaPSVIIDCNode xmlSchemaPSVIIDCNode;
514typedef xmlSchemaPSVIIDCNode *xmlSchemaPSVIIDCNodePtr;
515struct _xmlSchemaPSVIIDCNode {
516 xmlNodePtr node;
517 xmlSchemaPSVIIDCKeyPtr *keys;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +0000518 int nodeLine;
519 int nodeQNameID;
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +0000520
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000521};
522
523/**
524 * xmlSchemaPSVIIDCBinding:
525 *
526 * The identity-constraint binding item of the [identity-constraint table].
527 */
528typedef struct _xmlSchemaPSVIIDCBinding xmlSchemaPSVIIDCBinding;
529typedef xmlSchemaPSVIIDCBinding *xmlSchemaPSVIIDCBindingPtr;
530struct _xmlSchemaPSVIIDCBinding {
531 xmlSchemaPSVIIDCBindingPtr next; /* next binding of a specific node */
532 xmlSchemaIDCPtr definition; /* the IDC definition */
533 xmlSchemaPSVIIDCNodePtr *nodeTable; /* array of key-sequences */
534 int nbNodes; /* number of entries in the node table */
535 int sizeNodes; /* size of the node table */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000536 int nbDupls; /* number of already identified duplicates in the node
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000537 table */
538 /* int nbKeys; number of keys in each key-sequence */
539};
540
541#define XPATH_STATE_OBJ_TYPE_IDC_SELECTOR 1
542#define XPATH_STATE_OBJ_TYPE_IDC_FIELD 2
543
544#define XPATH_STATE_OBJ_MATCHES -2
545#define XPATH_STATE_OBJ_BLOCKED -3
546
547typedef struct _xmlSchemaIDCMatcher xmlSchemaIDCMatcher;
548typedef xmlSchemaIDCMatcher *xmlSchemaIDCMatcherPtr;
549
550/**
551 * xmlSchemaIDCStateObj:
552 *
553 * The state object used to evaluate XPath expressions.
554 */
555typedef struct _xmlSchemaIDCStateObj xmlSchemaIDCStateObj;
556typedef xmlSchemaIDCStateObj *xmlSchemaIDCStateObjPtr;
557struct _xmlSchemaIDCStateObj {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000558 int type;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000559 xmlSchemaIDCStateObjPtr next; /* next if in a list */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +0000560 int depth; /* depth of creation */
561 int *history; /* list of (depth, state-id) tuples */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000562 int nbHistory;
563 int sizeHistory;
564 xmlSchemaIDCMatcherPtr matcher; /* the correspondent field/selector
565 matcher */
566 xmlSchemaIDCSelectPtr sel;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +0000567 void *xpathCtxt;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000568};
569
570#define IDC_MATCHER 0
571
572/**
573 * xmlSchemaIDCMatcher:
574 *
575 * Used to IDC selectors (and fields) successively.
576 */
577struct _xmlSchemaIDCMatcher {
578 int type;
579 int depth; /* the tree depth at creation time */
580 xmlSchemaIDCMatcherPtr next; /* next in the list */
581 xmlSchemaIDCAugPtr aidc; /* the augmented IDC item */
582 xmlSchemaPSVIIDCKeyPtr **keySeqs; /* the key-sequences of the target
583 elements */
584 int sizeKeySeqs;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000585 int targetDepth;
586};
587
588/*
589* Element info flags.
590*/
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000591#define XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES 1<<0
592#define XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES 1<<1
593#define XML_SCHEMA_ELEM_INFO_NILLED 1<<2
594#define XML_SCHEMA_ELEM_INFO_LOCAL_TYPE 1<<3
595
596#define XML_SCHEMA_NODE_INFO_VALUE_NEEDED 1<<4
597#define XML_SCHEMA_ELEM_INFO_EMPTY 1<<5
598#define XML_SCHEMA_ELEM_INFO_HAS_CONTENT 1<<6
599
600#define XML_SCHEMA_ELEM_INFO_HAS_ELEM_CONTENT 1<<7
601#define XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT 1<<8
602#define XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED 1<<9
603#define XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE 1<<10
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000604
605/**
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +0000606 * xmlSchemaNodeInfo:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000607 *
608 * Holds information of an element node.
609 */
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +0000610struct _xmlSchemaNodeInfo {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000611 int nodeType;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +0000612 xmlNodePtr node;
613 int nodeLine;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000614 const xmlChar *localName;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000615 const xmlChar *nsName;
616 const xmlChar *value;
617 xmlSchemaValPtr val; /* the pre-computed value if any */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000618 xmlSchemaTypePtr typeDef; /* the complex/simple type definition if any */
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +0000619
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +0000620 int flags; /* combination of node info flags */
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +0000621
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000622 int valNeeded;
623 int normVal;
624
625 xmlSchemaElementPtr decl; /* the element/attribute declaration */
626 int depth;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000627 xmlSchemaPSVIIDCBindingPtr idcTable; /* the table of PSVI IDC bindings
628 for the scope element*/
629 xmlSchemaIDCMatcherPtr idcMatchers; /* the IDC matchers for the scope
630 element */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000631 xmlRegExecCtxtPtr regexCtxt;
632
633 const xmlChar **nsBindings; /* Namespace bindings on this element */
634 int nbNsBindings;
635 int sizeNsBindings;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000636};
637
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000638/*
639* @metaType values of xmlSchemaAttrInfo.
640*/
641#define XML_SCHEMA_ATTR_INFO_META_XSI_TYPE 1
642#define XML_SCHEMA_ATTR_INFO_META_XSI_NIL 2
643#define XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC 3
644#define XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC 4
645#define XML_SCHEMA_ATTR_INFO_META_XMLNS 5
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000646
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000647typedef struct _xmlSchemaAttrInfo xmlSchemaAttrInfo;
648typedef xmlSchemaAttrInfo *xmlSchemaAttrInfoPtr;
649struct _xmlSchemaAttrInfo {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000650 int nodeType;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +0000651 xmlNodePtr node;
652 int nodeLine;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000653 const xmlChar *localName;
654 const xmlChar *nsName;
655 const xmlChar *value;
656 xmlSchemaValPtr val; /* the pre-computed value if any */
657 xmlSchemaTypePtr typeDef; /* the complex/simple type definition if any */
658 int flags; /* combination of node info flags */
659
660 xmlSchemaAttributePtr decl; /* the attribute declaration */
661 xmlSchemaAttributePtr use; /* the attribute use */
662 int state;
663 int metaType;
664 const xmlChar *vcValue; /* the value constraint value */
665 xmlSchemaNodeInfoPtr parent;
666};
667
668
669#define XML_SCHEMA_VALID_CTXT_FLAG_STREAM 1
Daniel Veillard4255d502002-04-16 15:50:10 +0000670/**
671 * xmlSchemaValidCtxt:
672 *
673 * A Schemas validation context
674 */
Daniel Veillard4255d502002-04-16 15:50:10 +0000675struct _xmlSchemaValidCtxt {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000676 int type;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000677 void *userData; /* user specific data block */
678 xmlSchemaValidityErrorFunc error; /* the callback in case of errors */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000679 xmlSchemaValidityWarningFunc warning; /* the callback in case of warning */
Daniel Veillard659e71e2003-10-10 14:10:40 +0000680 xmlStructuredErrorFunc serror;
Daniel Veillard4255d502002-04-16 15:50:10 +0000681
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000682 xmlSchemaPtr schema; /* The schema in use */
683 xmlDocPtr doc;
Daniel Veillard4255d502002-04-16 15:50:10 +0000684 xmlParserInputBufferPtr input;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000685 xmlCharEncoding enc;
686 xmlSAXHandlerPtr sax;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000687 xmlParserCtxtPtr parserCtxt;
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000688 void *user_data;
Daniel Veillard4255d502002-04-16 15:50:10 +0000689
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000690 int err;
691 int nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +0000692
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000693 xmlNodePtr node;
694 xmlNodePtr cur;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000695 /* xmlSchemaTypePtr type; */
Daniel Veillard4255d502002-04-16 15:50:10 +0000696
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000697 xmlRegExecCtxtPtr regexp;
698 xmlSchemaValPtr value;
Daniel Veillard4255d502002-04-16 15:50:10 +0000699
Daniel Veillardc0826a72004-08-10 14:17:33 +0000700 int valueWS;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000701 int options;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000702 xmlNodePtr validationRoot;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +0000703 xmlSchemaParserCtxtPtr pctxt;
704 int xsiAssemble;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000705
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000706 int depth;
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +0000707 xmlSchemaNodeInfoPtr *elemInfos; /* array of element informations */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000708 int sizeElemInfos;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000709 xmlSchemaNodeInfoPtr inode; /* the current element information */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000710
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000711 xmlSchemaIDCAugPtr aidcs; /* a list of augmented IDC informations */
712
713 xmlSchemaIDCStateObjPtr xpathStates; /* first active state object. */
714 xmlSchemaIDCStateObjPtr xpathStatePool; /* first stored state object. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000715
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +0000716 xmlSchemaPSVIIDCNodePtr *idcNodes; /* list of all IDC node-table entries*/
717 int nbIdcNodes;
718 int sizeIdcNodes;
719
720 xmlSchemaPSVIIDCKeyPtr *idcKeys; /* list of all IDC node-table entries */
721 int nbIdcKeys;
722 int sizeIdcKeys;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000723
724 int flags;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000725
726 xmlDictPtr dict;
727
Daniel Veillard39e5c892005-07-03 22:48:50 +0000728#ifdef LIBXML_READER_ENABLED
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000729 xmlTextReaderPtr reader;
Daniel Veillard39e5c892005-07-03 22:48:50 +0000730#endif
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000731
732 xmlSchemaAttrInfoPtr *attrInfos;
733 int nbAttrInfos;
734 int sizeAttrInfos;
735
736 int skipDepth;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +0000737 xmlSchemaItemListPtr nodeQNames;
Daniel Veillard4255d502002-04-16 15:50:10 +0000738};
739
Daniel Veillard1d913862003-11-21 00:28:39 +0000740/*
741 * These are the entries in the schemas importSchemas hash table
742 */
743typedef struct _xmlSchemaImport xmlSchemaImport;
744typedef xmlSchemaImport *xmlSchemaImportPtr;
745struct _xmlSchemaImport {
746 const xmlChar *schemaLocation;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000747 xmlSchemaPtr schema; /* not used any more */
William M. Brack2f2a6632004-08-20 23:09:47 +0000748 xmlDocPtr doc;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +0000749 int isMain;
Daniel Veillard1d913862003-11-21 00:28:39 +0000750};
Daniel Veillard4255d502002-04-16 15:50:10 +0000751
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000752/*
753 * These are the entries associated to includes in a schemas
754 */
755typedef struct _xmlSchemaInclude xmlSchemaInclude;
756typedef xmlSchemaInclude *xmlSchemaIncludePtr;
757struct _xmlSchemaInclude {
758 xmlSchemaIncludePtr next;
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000759 const xmlChar *schemaLocation;
760 xmlDocPtr doc;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +0000761 const xmlChar *origTargetNamespace;
762 const xmlChar *targetNamespace;
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000763};
764
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +0000765/**
766 * xmlSchemaSubstGroup:
767 *
768 *
769 */
770typedef struct _xmlSchemaSubstGroup xmlSchemaSubstGroup;
771typedef xmlSchemaSubstGroup *xmlSchemaSubstGroupPtr;
772struct _xmlSchemaSubstGroup {
773 xmlSchemaElementPtr head;
774 xmlSchemaItemListPtr members;
775};
776
Daniel Veillard4255d502002-04-16 15:50:10 +0000777/************************************************************************
778 * *
779 * Some predeclarations *
780 * *
781 ************************************************************************/
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000782
Daniel Veillardbd2904b2003-11-25 15:38:59 +0000783static int xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt,
784 xmlSchemaPtr schema,
785 xmlNodePtr node);
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +0000786#ifdef ENABLE_REDEFINE
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +0000787static int xmlSchemaParseRedefine(xmlSchemaParserCtxtPtr ctxt,
788 xmlSchemaPtr schema,
789 xmlNodePtr node);
790#endif
Daniel Veillard01fa6152004-06-29 17:04:39 +0000791static void
792xmlSchemaTypeFixup(xmlSchemaTypePtr typeDecl,
793 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +0000794static const xmlChar *
Daniel Veillard01fa6152004-06-29 17:04:39 +0000795xmlSchemaFacetTypeToString(xmlSchemaTypeType type);
796static int
William M. Brack2f2a6632004-08-20 23:09:47 +0000797xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
798 xmlNodePtr node);
Kasimier T. Buchcikb8841242004-11-15 12:11:56 +0000799static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000800xmlSchemaCheckFacetValues(xmlSchemaTypePtr typeDecl,
801 xmlSchemaParserCtxtPtr ctxt);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +0000802static void
803xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000804static xmlSchemaWhitespaceValueType
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +0000805xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +0000806static xmlSchemaTreeItemPtr
807xmlSchemaParseModelGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
808 xmlNodePtr node, xmlSchemaTypeType type,
809 int withParticle);
810static const xmlChar *
811xmlSchemaCompTypeToString(xmlSchemaTypeType type);
812static xmlSchemaTypeLinkPtr
813xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000814static void
815xmlSchemaInternalErr(xmlSchemaAbstractCtxtPtr actxt,
816 const char *funcName,
817 const char *message);
818static int
819xmlSchemaCheckCOSSTDerivedOK(xmlSchemaTypePtr type,
820 xmlSchemaTypePtr baseType,
821 int subset);
822static void
823xmlSchemaCheckElementDeclComponent(xmlSchemaElementPtr elemDecl,
824 xmlSchemaParserCtxtPtr ctxt,
825 const xmlChar * name ATTRIBUTE_UNUSED);
William M. Brack87640d52004-04-17 14:58:15 +0000826
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000827/************************************************************************
828 * *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000829 * Helper functions *
Daniel Veillardd0c9c322003-10-10 00:49:42 +0000830 * *
831 ************************************************************************/
832
833/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000834 * xmlSchemaCompTypeToString:
835 * @type: the type of the schema item
836 *
837 * Returns the component name of a schema item.
838 */
839static const xmlChar *
840xmlSchemaCompTypeToString(xmlSchemaTypeType type)
841{
842 switch (type) {
843 case XML_SCHEMA_TYPE_SIMPLE:
844 return(BAD_CAST "simple type definition");
845 case XML_SCHEMA_TYPE_COMPLEX:
846 return(BAD_CAST "complex type definition");
847 case XML_SCHEMA_TYPE_ELEMENT:
848 return(BAD_CAST "element declaration");
849 case XML_SCHEMA_TYPE_ATTRIBUTE:
850 return(BAD_CAST "attribute declaration");
851 case XML_SCHEMA_TYPE_GROUP:
852 return(BAD_CAST "model group definition");
853 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
854 return(BAD_CAST "attribute group definition");
855 case XML_SCHEMA_TYPE_NOTATION:
856 return(BAD_CAST "notation declaration");
857 case XML_SCHEMA_TYPE_SEQUENCE:
858 return(BAD_CAST "model group (sequence)");
859 case XML_SCHEMA_TYPE_CHOICE:
860 return(BAD_CAST "model group (choice)");
861 case XML_SCHEMA_TYPE_ALL:
862 return(BAD_CAST "model group (all)");
863 case XML_SCHEMA_TYPE_PARTICLE:
864 return(BAD_CAST "particle");
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +0000865 case XML_SCHEMA_TYPE_IDC_UNIQUE:
866 return(BAD_CAST "IDC (unique)");
867 case XML_SCHEMA_TYPE_IDC_KEY:
868 return(BAD_CAST "IDC (key)");
869 case XML_SCHEMA_TYPE_IDC_KEYREF:
870 return(BAD_CAST "IDC (keyref)");
Kasimier T. Buchcik11162b72005-07-28 00:50:22 +0000871 case XML_SCHEMA_TYPE_ANY:
872 return(BAD_CAST "wildcard (any)");
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +0000873 case XML_SCHEMA_EXTRA_QNAMEREF:
874 return(BAD_CAST "[helper component] QName reference");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +0000875 default:
876 return(BAD_CAST "Not a schema component");
877 }
878}
879
880/**
881 * xmlSchemaGetComponentNode:
882 * @item: a schema component
883 *
884 * Returns node associated with the schema component.
885 * NOTE that such a node need not be available; plus, a component's
886 * node need not to reflect the component directly, since there is no
887 * one-to-one relationship between the XML Schema representation and
888 * the component representation.
889 */
890static xmlNodePtr
891xmlSchemaGetComponentNode(xmlSchemaBasicItemPtr item)
892{
893 switch (item->type) {
894 case XML_SCHEMA_TYPE_ELEMENT:
895 return (((xmlSchemaElementPtr) item)->node);
896 case XML_SCHEMA_TYPE_ATTRIBUTE:
897 return (((xmlSchemaAttributePtr) item)->node);
898 case XML_SCHEMA_TYPE_COMPLEX:
899 case XML_SCHEMA_TYPE_SIMPLE:
900 return (((xmlSchemaTypePtr) item)->node);
901 case XML_SCHEMA_TYPE_ANY:
902 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
903 return (((xmlSchemaWildcardPtr) item)->node);
904 case XML_SCHEMA_TYPE_PARTICLE:
905 return (((xmlSchemaParticlePtr) item)->node);
906 case XML_SCHEMA_TYPE_SEQUENCE:
907 case XML_SCHEMA_TYPE_CHOICE:
908 case XML_SCHEMA_TYPE_ALL:
909 return (((xmlSchemaModelGroupPtr) item)->node);
910 case XML_SCHEMA_TYPE_GROUP:
911 return (((xmlSchemaModelGroupDefPtr) item)->node);
912 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
913 return (((xmlSchemaAttributeGroupPtr) item)->node);
914 case XML_SCHEMA_TYPE_IDC_UNIQUE:
915 case XML_SCHEMA_TYPE_IDC_KEY:
916 case XML_SCHEMA_TYPE_IDC_KEYREF:
917 return (((xmlSchemaIDCPtr) item)->node);
918 default:
919 return (NULL);
920 }
921}
922
923#if 0
924/**
925 * xmlSchemaGetNextComponent:
926 * @item: a schema component
927 *
928 * Returns the next sibling of the schema component.
929 */
930static xmlSchemaBasicItemPtr
931xmlSchemaGetNextComponent(xmlSchemaBasicItemPtr item)
932{
933 switch (item->type) {
934 case XML_SCHEMA_TYPE_ELEMENT:
935 return ((xmlSchemaBasicItemPtr) ((xmlSchemaElementPtr) item)->next);
936 case XML_SCHEMA_TYPE_ATTRIBUTE:
937 return ((xmlSchemaBasicItemPtr) ((xmlSchemaAttributePtr) item)->next);
938 case XML_SCHEMA_TYPE_COMPLEX:
939 case XML_SCHEMA_TYPE_SIMPLE:
940 return ((xmlSchemaBasicItemPtr) ((xmlSchemaTypePtr) item)->next);
941 case XML_SCHEMA_TYPE_ANY:
942 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
943 return (NULL);
944 case XML_SCHEMA_TYPE_PARTICLE:
945 return ((xmlSchemaBasicItemPtr) ((xmlSchemaParticlePtr) item)->next);
946 case XML_SCHEMA_TYPE_SEQUENCE:
947 case XML_SCHEMA_TYPE_CHOICE:
948 case XML_SCHEMA_TYPE_ALL:
949 return (NULL);
950 case XML_SCHEMA_TYPE_GROUP:
951 return (NULL);
952 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
953 return ((xmlSchemaBasicItemPtr) ((xmlSchemaAttributeGroupPtr) item)->next);
954 case XML_SCHEMA_TYPE_IDC_UNIQUE:
955 case XML_SCHEMA_TYPE_IDC_KEY:
956 case XML_SCHEMA_TYPE_IDC_KEYREF:
957 return ((xmlSchemaBasicItemPtr) ((xmlSchemaIDCPtr) item)->next);
958 default:
959 return (NULL);
960 }
961}
962#endif
963
964/**
965 * xmlSchemaGetAttrName:
966 * @attr: the attribute declaration/use
967 *
968 * Returns the name of the attribute; if the attribute
969 * is a reference, the name of the referenced global type will be returned.
970 */
971static const xmlChar *
972xmlSchemaGetAttrName(xmlSchemaAttributePtr attr)
973{
974 if (attr->ref != NULL)
975 return(attr->ref);
976 else
977 return(attr->name);
978}
979
980/**
981 * xmlSchemaGetAttrTargetNsURI:
982 * @type: the type (element or attribute)
983 *
984 * Returns the target namespace URI of the type; if the type is a reference,
985 * the target namespace of the referenced type will be returned.
986 */
987static const xmlChar *
988xmlSchemaGetAttrTargetNsURI(xmlSchemaAttributePtr attr)
989{
990 if (attr->ref != NULL)
991 return (attr->refNs);
992 else
993 return(attr->targetNamespace);
994}
995
996/**
997 * xmlSchemaFormatQName:
998 * @buf: the string buffer
999 * @namespaceName: the namespace name
1000 * @localName: the local name
1001 *
1002 * Returns the given QName in the format "{namespaceName}localName" or
1003 * just "localName" if @namespaceName is NULL.
1004 *
1005 * Returns the localName if @namespaceName is NULL, a formatted
1006 * string otherwise.
1007 */
1008static const xmlChar*
1009xmlSchemaFormatQName(xmlChar **buf,
1010 const xmlChar *namespaceName,
1011 const xmlChar *localName)
1012{
1013 FREE_AND_NULL(*buf)
1014 if (namespaceName == NULL)
1015 return(localName);
1016
1017 *buf = xmlStrdup(BAD_CAST "{");
1018 *buf = xmlStrcat(*buf, namespaceName);
1019 *buf = xmlStrcat(*buf, BAD_CAST "}");
1020 *buf = xmlStrcat(*buf, localName);
1021
1022 return ((const xmlChar *) *buf);
1023}
1024
1025static const xmlChar*
1026xmlSchemaFormatQNameNs(xmlChar **buf, xmlNsPtr ns, const xmlChar *localName)
1027{
1028 if (ns != NULL)
1029 return (xmlSchemaFormatQName(buf, ns->href, localName));
1030 else
1031 return (xmlSchemaFormatQName(buf, NULL, localName));
1032}
1033
1034static const xmlChar *
1035xmlSchemaGetComponentName(xmlSchemaBasicItemPtr item)
1036{
1037 switch (item->type) {
1038 case XML_SCHEMA_TYPE_ELEMENT:
1039 return (((xmlSchemaElementPtr) item)->name);
1040 case XML_SCHEMA_TYPE_ATTRIBUTE:
1041 return (((xmlSchemaAttributePtr) item)->name);
1042 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1043 return (((xmlSchemaAttributeGroupPtr) item)->name);
1044 case XML_SCHEMA_TYPE_BASIC:
1045 case XML_SCHEMA_TYPE_SIMPLE:
1046 case XML_SCHEMA_TYPE_COMPLEX:
1047 return (((xmlSchemaTypePtr) item)->name);
1048 case XML_SCHEMA_TYPE_GROUP:
1049 return (((xmlSchemaModelGroupDefPtr) item)->name);
1050 case XML_SCHEMA_TYPE_IDC_KEY:
1051 case XML_SCHEMA_TYPE_IDC_UNIQUE:
1052 case XML_SCHEMA_TYPE_IDC_KEYREF:
1053 return (((xmlSchemaIDCPtr) item)->name);
1054 default:
1055 /*
1056 * Other components cannot have names.
1057 */
1058 break;
1059 }
1060 return (NULL);
1061}
1062
1063static const xmlChar *
1064xmlSchemaGetComponentTargetNs(xmlSchemaBasicItemPtr item)
1065{
1066 switch (item->type) {
1067 case XML_SCHEMA_TYPE_ELEMENT:
1068 return (((xmlSchemaElementPtr) item)->targetNamespace);
1069 case XML_SCHEMA_TYPE_ATTRIBUTE:
1070 return (((xmlSchemaAttributePtr) item)->targetNamespace);
1071 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1072 return (((xmlSchemaAttributeGroupPtr) item)->targetNamespace);
1073 case XML_SCHEMA_TYPE_BASIC:
1074 return (BAD_CAST "http://www.w3.org/2001/XMLSchema");
1075 case XML_SCHEMA_TYPE_SIMPLE:
1076 case XML_SCHEMA_TYPE_COMPLEX:
1077 return (((xmlSchemaTypePtr) item)->targetNamespace);
1078 case XML_SCHEMA_TYPE_GROUP:
1079 return (((xmlSchemaModelGroupDefPtr) item)->targetNamespace);
1080 case XML_SCHEMA_TYPE_IDC_KEY:
1081 case XML_SCHEMA_TYPE_IDC_UNIQUE:
1082 case XML_SCHEMA_TYPE_IDC_KEYREF:
1083 return (((xmlSchemaIDCPtr) item)->targetNamespace);
1084 default:
1085 /*
1086 * Other components cannot have names.
1087 */
1088 break;
1089 }
1090 return (NULL);
1091}
1092
1093static const xmlChar*
1094xmlSchemaGetComponentQName(xmlChar **buf,
1095 void *item)
1096{
1097 return (xmlSchemaFormatQName(buf,
1098 xmlSchemaGetComponentTargetNs((xmlSchemaBasicItemPtr) item),
1099 xmlSchemaGetComponentName((xmlSchemaBasicItemPtr) item)));
1100}
1101
1102/**
1103 * xmlSchemaWildcardPCToString:
1104 * @pc: the type of processContents
1105 *
1106 * Returns a string representation of the type of
1107 * processContents.
1108 */
1109static const xmlChar *
1110xmlSchemaWildcardPCToString(int pc)
1111{
1112 switch (pc) {
1113 case XML_SCHEMAS_ANY_SKIP:
1114 return (BAD_CAST "skip");
1115 case XML_SCHEMAS_ANY_LAX:
1116 return (BAD_CAST "lax");
1117 case XML_SCHEMAS_ANY_STRICT:
1118 return (BAD_CAST "strict");
1119 default:
1120 return (BAD_CAST "invalid process contents");
1121 }
1122}
1123
1124/**
1125 * xmlSchemaGetCanonValueWhtspExt:
1126 * @val: the precomputed value
1127 * @retValue: the returned value
1128 * @ws: the whitespace type of the value
1129 *
1130 * Get a the cononical representation of the value.
1131 * The caller has to free the returned retValue.
1132 *
1133 * Returns 0 if the value could be built and -1 in case of
1134 * API errors or if the value type is not supported yet.
1135 */
1136static int
1137xmlSchemaGetCanonValueWhtspExt(xmlSchemaValPtr val,
1138 xmlSchemaWhitespaceValueType ws,
1139 xmlChar **retValue)
1140{
1141 int list;
1142 xmlSchemaValType valType;
1143 const xmlChar *value, *value2 = NULL;
1144
1145
1146 if ((retValue == NULL) || (val == NULL))
1147 return (-1);
1148 list = xmlSchemaValueGetNext(val) ? 1 : 0;
1149 *retValue = NULL;
1150 do {
1151 value = NULL;
1152 valType = xmlSchemaGetValType(val);
1153 switch (valType) {
1154 case XML_SCHEMAS_STRING:
1155 case XML_SCHEMAS_NORMSTRING:
1156 case XML_SCHEMAS_ANYSIMPLETYPE:
1157 value = xmlSchemaValueGetAsString(val);
1158 if (value != NULL) {
1159 if (ws == XML_SCHEMA_WHITESPACE_COLLAPSE)
1160 value2 = xmlSchemaCollapseString(value);
1161 else if (ws == XML_SCHEMA_WHITESPACE_REPLACE)
1162 value2 = xmlSchemaWhiteSpaceReplace(value);
1163 if (value2 != NULL)
1164 value = value2;
1165 }
1166 break;
1167 default:
1168 if (xmlSchemaGetCanonValue(val, &value2) == -1) {
1169 if (value2 != NULL)
1170 xmlFree((xmlChar *) value2);
1171 goto internal_error;
1172 }
1173 value = value2;
1174 }
1175 if (*retValue == NULL)
1176 if (value == NULL) {
1177 if (! list)
1178 *retValue = xmlStrdup(BAD_CAST "");
1179 } else
1180 *retValue = xmlStrdup(value);
1181 else if (value != NULL) {
1182 /* List. */
1183 *retValue = xmlStrcat((xmlChar *) *retValue, BAD_CAST " ");
1184 *retValue = xmlStrcat((xmlChar *) *retValue, value);
1185 }
1186 FREE_AND_NULL(value2)
1187 val = xmlSchemaValueGetNext(val);
1188 } while (val != NULL);
1189
1190 return (0);
1191internal_error:
1192 if (*retValue != NULL)
1193 xmlFree((xmlChar *) (*retValue));
1194 if (value2 != NULL)
1195 xmlFree((xmlChar *) value2);
1196 return (-1);
1197}
1198
1199/**
1200 * xmlSchemaFormatItemForReport:
1201 * @buf: the string buffer
1202 * @itemDes: the designation of the item
1203 * @itemName: the name of the item
1204 * @item: the item as an object
1205 * @itemNode: the node of the item
1206 * @local: the local name
1207 * @parsing: if the function is used during the parse
1208 *
1209 * Returns a representation of the given item used
1210 * for error reports.
1211 *
1212 * The following order is used to build the resulting
1213 * designation if the arguments are not NULL:
1214 * 1a. If itemDes not NULL -> itemDes
1215 * 1b. If (itemDes not NULL) and (itemName not NULL)
1216 * -> itemDes + itemName
1217 * 2. If the preceding was NULL and (item not NULL) -> item
1218 * 3. If the preceding was NULL and (itemNode not NULL) -> itemNode
1219 *
1220 * If the itemNode is an attribute node, the name of the attribute
1221 * will be appended to the result.
1222 *
1223 * Returns the formatted string and sets @buf to the resulting value.
1224 */
1225static xmlChar*
1226xmlSchemaFormatItemForReport(xmlChar **buf,
1227 const xmlChar *itemDes,
1228 xmlSchemaTypePtr item,
1229 xmlNodePtr itemNode)
1230{
1231 xmlChar *str = NULL;
1232 int named = 1;
1233
1234 if (*buf != NULL) {
1235 xmlFree(*buf);
1236 *buf = NULL;
1237 }
1238
1239 if (itemDes != NULL) {
1240 *buf = xmlStrdup(itemDes);
1241 } else if (item != NULL) {
1242 switch (item->type) {
1243 case XML_SCHEMA_TYPE_BASIC:
1244 if (VARIETY_ATOMIC(item))
1245 *buf = xmlStrdup(BAD_CAST "atomic type 'xs:");
1246 else if (VARIETY_LIST(item))
1247 *buf = xmlStrdup(BAD_CAST "list type 'xs:");
1248 else if (VARIETY_UNION(item))
1249 *buf = xmlStrdup(BAD_CAST "union type 'xs:");
1250 else
1251 *buf = xmlStrdup(BAD_CAST "simple type 'xs:");
1252 *buf = xmlStrcat(*buf, item->name);
1253 *buf = xmlStrcat(*buf, BAD_CAST "'");
1254 break;
1255 case XML_SCHEMA_TYPE_SIMPLE:
1256 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL) {
1257 *buf = xmlStrdup(BAD_CAST"");
1258 } else {
1259 *buf = xmlStrdup(BAD_CAST "local ");
1260 }
1261 if (VARIETY_ATOMIC(item))
1262 *buf = xmlStrcat(*buf, BAD_CAST "atomic type");
1263 else if (VARIETY_LIST(item))
1264 *buf = xmlStrcat(*buf, BAD_CAST "list type");
1265 else if (VARIETY_UNION(item))
1266 *buf = xmlStrcat(*buf, BAD_CAST "union type");
1267 else
1268 *buf = xmlStrcat(*buf, BAD_CAST "simple type");
1269 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL) {
1270 *buf = xmlStrcat(*buf, BAD_CAST " '");
1271 *buf = xmlStrcat(*buf, item->name);
1272 *buf = xmlStrcat(*buf, BAD_CAST "'");
1273 }
1274 break;
1275 case XML_SCHEMA_TYPE_COMPLEX:
1276 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL)
1277 *buf = xmlStrdup(BAD_CAST "");
1278 else
1279 *buf = xmlStrdup(BAD_CAST "local ");
1280 *buf = xmlStrcat(*buf, BAD_CAST "complex type");
1281 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL) {
1282 *buf = xmlStrcat(*buf, BAD_CAST " '");
1283 *buf = xmlStrcat(*buf, item->name);
1284 *buf = xmlStrcat(*buf, BAD_CAST "'");
1285 }
1286 break;
1287 case XML_SCHEMA_TYPE_ATTRIBUTE: {
1288 xmlSchemaAttributePtr attr;
1289
1290 attr = (xmlSchemaAttributePtr) item;
1291 if ((attr->flags & XML_SCHEMAS_ATTR_GLOBAL) ||
1292 (attr->ref == NULL)) {
1293 *buf = xmlStrdup(xmlSchemaElemDesAttrDecl);
1294 *buf = xmlStrcat(*buf, BAD_CAST " '");
1295 *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1296 attr->targetNamespace, attr->name));
1297 FREE_AND_NULL(str)
1298 *buf = xmlStrcat(*buf, BAD_CAST "'");
1299 } else {
1300 *buf = xmlStrdup(xmlSchemaElemDesAttrRef);
1301 *buf = xmlStrcat(*buf, BAD_CAST " '");
1302 *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1303 attr->refNs, attr->ref));
1304 FREE_AND_NULL(str)
1305 *buf = xmlStrcat(*buf, BAD_CAST "'");
1306 }
1307 }
1308 break;
1309 case XML_SCHEMA_TYPE_ELEMENT: {
1310 xmlSchemaElementPtr elem;
1311
1312 elem = (xmlSchemaElementPtr) item;
1313 if ((elem->flags & XML_SCHEMAS_ELEM_GLOBAL) ||
1314 (elem->ref == NULL)) {
1315 *buf = xmlStrdup(xmlSchemaElemDesElemDecl);
1316 *buf = xmlStrcat(*buf, BAD_CAST " '");
1317 *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1318 elem->targetNamespace, elem->name));
1319 *buf = xmlStrcat(*buf, BAD_CAST "'");
1320 }
1321 }
1322 break;
1323 case XML_SCHEMA_TYPE_IDC_UNIQUE:
1324 case XML_SCHEMA_TYPE_IDC_KEY:
1325 case XML_SCHEMA_TYPE_IDC_KEYREF:
1326 if (item->type == XML_SCHEMA_TYPE_IDC_UNIQUE)
1327 *buf = xmlStrdup(BAD_CAST "unique '");
1328 else if (item->type == XML_SCHEMA_TYPE_IDC_KEY)
1329 *buf = xmlStrdup(BAD_CAST "key '");
1330 else
1331 *buf = xmlStrdup(BAD_CAST "keyRef '");
1332 *buf = xmlStrcat(*buf, ((xmlSchemaIDCPtr) item)->name);
1333 *buf = xmlStrcat(*buf, BAD_CAST "'");
1334 break;
1335 case XML_SCHEMA_TYPE_ANY:
1336 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
1337 *buf = xmlStrdup(xmlSchemaWildcardPCToString(
1338 ((xmlSchemaWildcardPtr) item)->processContents));
1339 *buf = xmlStrcat(*buf, BAD_CAST " wildcard");
1340 break;
1341 case XML_SCHEMA_FACET_MININCLUSIVE:
1342 case XML_SCHEMA_FACET_MINEXCLUSIVE:
1343 case XML_SCHEMA_FACET_MAXINCLUSIVE:
1344 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
1345 case XML_SCHEMA_FACET_TOTALDIGITS:
1346 case XML_SCHEMA_FACET_FRACTIONDIGITS:
1347 case XML_SCHEMA_FACET_PATTERN:
1348 case XML_SCHEMA_FACET_ENUMERATION:
1349 case XML_SCHEMA_FACET_WHITESPACE:
1350 case XML_SCHEMA_FACET_LENGTH:
1351 case XML_SCHEMA_FACET_MAXLENGTH:
1352 case XML_SCHEMA_FACET_MINLENGTH:
1353 *buf = xmlStrdup(BAD_CAST "facet '");
1354 *buf = xmlStrcat(*buf, xmlSchemaFacetTypeToString(item->type));
1355 *buf = xmlStrcat(*buf, BAD_CAST "'");
1356 break;
1357 case XML_SCHEMA_TYPE_NOTATION:
1358 *buf = xmlStrdup(BAD_CAST "notation");
1359 break;
1360 case XML_SCHEMA_TYPE_GROUP: {
1361 *buf = xmlStrdup(xmlSchemaElemModelGrDef);
1362 *buf = xmlStrcat(*buf, BAD_CAST " '");
1363 *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1364 ((xmlSchemaModelGroupDefPtr) item)->targetNamespace,
1365 ((xmlSchemaModelGroupDefPtr) item)->name));
1366 *buf = xmlStrcat(*buf, BAD_CAST "'");
1367 FREE_AND_NULL(str)
1368 }
1369 break;
1370 case XML_SCHEMA_TYPE_SEQUENCE:
1371 case XML_SCHEMA_TYPE_CHOICE:
1372 case XML_SCHEMA_TYPE_ALL:
1373 case XML_SCHEMA_TYPE_PARTICLE:
1374 *buf = xmlStrdup(xmlSchemaCompTypeToString(item->type));
1375 break;
1376 default:
1377 named = 0;
1378 }
1379 } else
1380 named = 0;
1381
1382 if ((named == 0) && (itemNode != NULL)) {
1383 xmlNodePtr elem;
1384
1385 if (itemNode->type == XML_ATTRIBUTE_NODE)
1386 elem = itemNode->parent;
1387 else
1388 elem = itemNode;
1389 *buf = xmlStrdup(BAD_CAST "Element '");
1390 if (elem->ns != NULL) {
1391 *buf = xmlStrcat(*buf,
1392 xmlSchemaFormatQName(&str, elem->ns->href, elem->name));
1393 FREE_AND_NULL(str)
1394 } else
1395 *buf = xmlStrcat(*buf, elem->name);
1396 *buf = xmlStrcat(*buf, BAD_CAST "'");
1397
1398 }
1399 if ((itemNode != NULL) && (itemNode->type == XML_ATTRIBUTE_NODE)) {
1400 *buf = xmlStrcat(*buf, BAD_CAST ", attribute '");
1401 if (itemNode->ns != NULL) {
1402 *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1403 itemNode->ns->href, itemNode->name));
1404 FREE_AND_NULL(str)
1405 } else
1406 *buf = xmlStrcat(*buf, itemNode->name);
1407 *buf = xmlStrcat(*buf, BAD_CAST "'");
1408 }
1409 FREE_AND_NULL(str)
1410
1411 return (*buf);
1412}
1413
1414/**
1415 * xmlSchemaFormatFacetEnumSet:
1416 * @buf: the string buffer
1417 * @type: the type holding the enumeration facets
1418 *
1419 * Builds a string consisting of all enumeration elements.
1420 *
1421 * Returns a string of all enumeration elements.
1422 */
1423static const xmlChar *
1424xmlSchemaFormatFacetEnumSet(xmlSchemaAbstractCtxtPtr actxt,
1425 xmlChar **buf, xmlSchemaTypePtr type)
1426{
1427 xmlSchemaFacetPtr facet;
1428 xmlSchemaWhitespaceValueType ws;
1429 xmlChar *value = NULL;
1430 int res;
1431
1432 if (*buf != NULL)
1433 xmlFree(*buf);
1434 *buf = NULL;
1435
1436 do {
1437 /*
1438 * Use the whitespace type of the base type.
1439 */
1440 ws = xmlSchemaGetWhiteSpaceFacetValue(type->baseType);
1441 for (facet = type->facets; facet != NULL; facet = facet->next) {
1442 if (facet->type != XML_SCHEMA_FACET_ENUMERATION)
1443 continue;
1444 res = xmlSchemaGetCanonValueWhtspExt(facet->val,
1445 ws, &value);
1446 if (res == -1) {
1447 xmlSchemaInternalErr(actxt,
1448 "xmlSchemaFormatFacetEnumSet",
1449 "compute the canonical lexical representation");
1450 if (*buf != NULL)
1451 xmlFree(*buf);
1452 *buf = NULL;
1453 return (NULL);
1454 }
1455 if (*buf == NULL)
1456 *buf = xmlStrdup(BAD_CAST "'");
1457 else
1458 *buf = xmlStrcat(*buf, BAD_CAST ", '");
1459 *buf = xmlStrcat(*buf, BAD_CAST value);
1460 *buf = xmlStrcat(*buf, BAD_CAST "'");
1461 if (value != NULL) {
1462 xmlFree((xmlChar *)value);
1463 value = NULL;
1464 }
1465 }
1466 type = type->baseType;
1467 } while ((type != NULL) && (type->type != XML_SCHEMA_TYPE_BASIC));
1468
1469 return ((const xmlChar *) *buf);
1470}
1471
1472/************************************************************************
1473 * *
1474 * Error functions *
1475 * *
1476 ************************************************************************/
1477
1478#if 0
1479static void
1480xmlSchemaErrMemory(const char *msg)
1481{
1482 __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, NULL, NULL,
1483 msg);
1484}
1485#endif
1486
1487/**
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001488 * xmlSchemaPErrMemory:
1489 * @node: a context node
1490 * @extra: extra informations
1491 *
1492 * Handle an out of memory condition
1493 */
1494static void
1495xmlSchemaPErrMemory(xmlSchemaParserCtxtPtr ctxt,
1496 const char *extra, xmlNodePtr node)
1497{
1498 if (ctxt != NULL)
1499 ctxt->nberrors++;
1500 __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, node, NULL,
1501 extra);
1502}
1503
1504/**
1505 * xmlSchemaPErr:
1506 * @ctxt: the parsing context
1507 * @node: the context node
1508 * @error: the error code
1509 * @msg: the error message
1510 * @str1: extra data
1511 * @str2: extra data
1512 *
1513 * Handle a parser error
1514 */
1515static void
1516xmlSchemaPErr(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
1517 const char *msg, const xmlChar * str1, const xmlChar * str2)
1518{
1519 xmlGenericErrorFunc channel = NULL;
Daniel Veillard659e71e2003-10-10 14:10:40 +00001520 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001521 void *data = NULL;
1522
1523 if (ctxt != NULL) {
1524 ctxt->nberrors++;
1525 channel = ctxt->error;
1526 data = ctxt->userData;
Daniel Veillard659e71e2003-10-10 14:10:40 +00001527 schannel = ctxt->serror;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001528 }
Daniel Veillard659e71e2003-10-10 14:10:40 +00001529 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001530 error, XML_ERR_ERROR, NULL, 0,
1531 (const char *) str1, (const char *) str2, NULL, 0, 0,
1532 msg, str1, str2);
1533}
1534
1535/**
1536 * xmlSchemaPErr2:
1537 * @ctxt: the parsing context
1538 * @node: the context node
1539 * @node: the current child
1540 * @error: the error code
1541 * @msg: the error message
1542 * @str1: extra data
1543 * @str2: extra data
1544 *
1545 * Handle a parser error
1546 */
1547static void
1548xmlSchemaPErr2(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
1549 xmlNodePtr child, int error,
1550 const char *msg, const xmlChar * str1, const xmlChar * str2)
1551{
1552 if (child != NULL)
1553 xmlSchemaPErr(ctxt, child, error, msg, str1, str2);
1554 else
1555 xmlSchemaPErr(ctxt, node, error, msg, str1, str2);
1556}
1557
Daniel Veillard01fa6152004-06-29 17:04:39 +00001558
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001559/**
Daniel Veillard3646d642004-06-02 19:19:14 +00001560 * xmlSchemaPErrExt:
1561 * @ctxt: the parsing context
1562 * @node: the context node
1563 * @error: the error code
1564 * @strData1: extra data
1565 * @strData2: extra data
1566 * @strData3: extra data
1567 * @msg: the message
1568 * @str1: extra parameter for the message display
1569 * @str2: extra parameter for the message display
1570 * @str3: extra parameter for the message display
1571 * @str4: extra parameter for the message display
1572 * @str5: extra parameter for the message display
1573 *
1574 * Handle a parser error
1575 */
1576static void
1577xmlSchemaPErrExt(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
1578 const xmlChar * strData1, const xmlChar * strData2,
1579 const xmlChar * strData3, const char *msg, const xmlChar * str1,
1580 const xmlChar * str2, const xmlChar * str3, const xmlChar * str4,
1581 const xmlChar * str5)
1582{
1583
1584 xmlGenericErrorFunc channel = NULL;
1585 xmlStructuredErrorFunc schannel = NULL;
1586 void *data = NULL;
1587
1588 if (ctxt != NULL) {
1589 ctxt->nberrors++;
1590 channel = ctxt->error;
1591 data = ctxt->userData;
1592 schannel = ctxt->serror;
1593 }
1594 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
1595 error, XML_ERR_ERROR, NULL, 0,
1596 (const char *) strData1, (const char *) strData2,
William M. Brack803812b2004-06-03 02:11:24 +00001597 (const char *) strData3, 0, 0, msg, str1, str2,
1598 str3, str4, str5);
Daniel Veillard3646d642004-06-02 19:19:14 +00001599}
Daniel Veillard01fa6152004-06-29 17:04:39 +00001600
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001601/************************************************************************
1602 * *
1603 * Allround error functions *
1604 * *
1605 ************************************************************************/
Daniel Veillard3646d642004-06-02 19:19:14 +00001606
1607/**
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001608 * xmlSchemaVTypeErrMemory:
1609 * @node: a context node
1610 * @extra: extra informations
1611 *
1612 * Handle an out of memory condition
1613 */
1614static void
1615xmlSchemaVErrMemory(xmlSchemaValidCtxtPtr ctxt,
1616 const char *extra, xmlNodePtr node)
1617{
1618 if (ctxt != NULL) {
1619 ctxt->nberrors++;
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00001620 ctxt->err = XML_SCHEMAV_INTERNAL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001621 }
1622 __xmlSimpleError(XML_FROM_SCHEMASV, XML_ERR_NO_MEMORY, node, NULL,
1623 extra);
1624}
1625
1626/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001627 * xmlSchemaErr3:
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001628 * @ctxt: the validation context
1629 * @node: the context node
1630 * @error: the error code
1631 * @msg: the error message
1632 * @str1: extra data
1633 * @str2: extra data
1634 * @str3: extra data
1635 *
1636 * Handle a validation error
1637 */
1638static void
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00001639xmlSchemaErr3Line(xmlSchemaAbstractCtxtPtr ctxt,
1640 int error, xmlNodePtr node, int line, const char *msg,
1641 const xmlChar *str1, const xmlChar *str2,
1642 const xmlChar *str3)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001643{
Daniel Veillard659e71e2003-10-10 14:10:40 +00001644 xmlStructuredErrorFunc schannel = NULL;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00001645 xmlGenericErrorFunc channel = NULL;
1646 void *data = NULL;
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00001647
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001648 if (ctxt != NULL) {
1649 if (ctxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
1650 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctxt;
Daniel Veillard971771e2005-07-09 17:32:57 +00001651 const char *file = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001652
1653 vctxt->nberrors++;
1654 vctxt->err = error;
1655 channel = vctxt->error;
1656 schannel = vctxt->serror;
1657 data = vctxt->userData;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00001658
1659 /*
1660 * Error node. If we specify a line number, then
1661 * do not channel any node to the error function.
1662 */
1663 if (line == 0) {
1664 if ((node == NULL) &&
1665 (vctxt->depth >= 0) &&
1666 (vctxt->inode != NULL)) {
1667 node = vctxt->inode->node;
1668 }
1669 /*
1670 * Get filename and line if no node-tree.
1671 */
1672 if ((node == NULL) &&
1673 (vctxt->parserCtxt != NULL) &&
1674 (vctxt->parserCtxt->input != NULL)) {
1675 file = vctxt->parserCtxt->input->filename;
1676 line = vctxt->parserCtxt->input->line;
1677 }
1678 } else {
1679 /*
1680 * Override the given node's (if any) position
1681 * and channel only the given line number.
1682 */
1683 node = NULL;
1684 /*
1685 * Get filename.
1686 */
1687 if (vctxt->doc != NULL)
1688 file = (const char *) vctxt->doc->URL;
1689 else if ((vctxt->parserCtxt != NULL) &&
1690 (vctxt->parserCtxt->input != NULL))
1691 file = vctxt->parserCtxt->input->filename;
1692 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001693 __xmlRaiseError(schannel, channel, data, ctxt,
1694 node, XML_FROM_SCHEMASV,
Daniel Veillard971771e2005-07-09 17:32:57 +00001695 error, XML_ERR_ERROR, file, line,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001696 (const char *) str1, (const char *) str2,
1697 (const char *) str3, 0, 0, msg, str1, str2, str3);
1698
1699 } else if (ctxt->type == XML_SCHEMA_CTXT_PARSER) {
1700 xmlSchemaParserCtxtPtr pctxt = (xmlSchemaParserCtxtPtr) ctxt;
1701
1702 pctxt->nberrors++;
1703 pctxt->err = error;
1704 channel = pctxt->error;
1705 schannel = pctxt->serror;
1706 data = pctxt->userData;
1707 __xmlRaiseError(schannel, channel, data, ctxt,
1708 node, XML_FROM_SCHEMASP,
1709 error, XML_ERR_ERROR, NULL, 0,
1710 (const char *) str1, (const char *) str2,
1711 (const char *) str3, 0, 0, msg, str1, str2, str3);
1712 } else {
1713 TODO
1714 }
1715 }
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00001716}
1717
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00001718/**
1719 * xmlSchemaErr3:
1720 * @ctxt: the validation context
1721 * @node: the context node
1722 * @error: the error code
1723 * @msg: the error message
1724 * @str1: extra data
1725 * @str2: extra data
1726 * @str3: extra data
1727 *
1728 * Handle a validation error
1729 */
1730static void
1731xmlSchemaErr3(xmlSchemaAbstractCtxtPtr actxt,
1732 int error, xmlNodePtr node, const char *msg,
1733 const xmlChar *str1, const xmlChar *str2, const xmlChar *str3)
1734{
1735 xmlSchemaErr3Line(actxt, error, node, 0, msg, str1, str2, str3);
1736}
1737
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001738static void
1739xmlSchemaErr(xmlSchemaAbstractCtxtPtr actxt,
1740 int error, xmlNodePtr node, const char *msg,
1741 const xmlChar *str1, const xmlChar *str2)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001742{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001743 xmlSchemaErr3(actxt, error, node, msg, str1, str2, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00001744}
1745
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001746static xmlChar *
1747xmlSchemaFormatNodeForError(xmlChar ** msg,
1748 xmlSchemaAbstractCtxtPtr actxt,
1749 xmlNodePtr node)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001750{
1751 xmlChar *str = NULL;
1752
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001753 if (node != NULL) {
1754 /*
1755 * Work on tree nodes.
1756 */
1757 if (node->type == XML_ATTRIBUTE_NODE) {
1758 xmlNodePtr elem = node->parent;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001759
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001760 *msg = xmlStrdup(BAD_CAST "Element '");
1761 if (elem->ns != NULL)
1762 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
1763 elem->ns->href, elem->name));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001764 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001765 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
1766 NULL, elem->name));
1767 FREE_AND_NULL(str);
1768 *msg = xmlStrcat(*msg, BAD_CAST "', ");
1769 *msg = xmlStrcat(*msg, BAD_CAST "attribute '");
1770 } else {
1771 *msg = xmlStrdup(BAD_CAST "Element '");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00001772 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001773 if (node->ns != NULL)
1774 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
1775 node->ns->href, node->name));
Daniel Veillardc0826a72004-08-10 14:17:33 +00001776 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001777 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
1778 NULL, node->name));
1779 FREE_AND_NULL(str);
1780 *msg = xmlStrcat(*msg, BAD_CAST "': ");
1781 } else if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
1782 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) actxt;
1783 /*
1784 * Work on node infos.
1785 */
1786 if (vctxt->inode->nodeType == XML_ATTRIBUTE_NODE) {
1787 xmlSchemaNodeInfoPtr ielem =
1788 vctxt->elemInfos[vctxt->depth];
1789
1790 *msg = xmlStrdup(BAD_CAST "Element '");
1791 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
1792 ielem->nsName, ielem->localName));
1793 FREE_AND_NULL(str);
1794 *msg = xmlStrcat(*msg, BAD_CAST "', ");
1795 *msg = xmlStrcat(*msg, BAD_CAST "attribute '");
1796 } else {
1797 *msg = xmlStrdup(BAD_CAST "Element '");
1798 }
1799 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
1800 vctxt->inode->nsName, vctxt->inode->localName));
1801 FREE_AND_NULL(str);
1802 *msg = xmlStrcat(*msg, BAD_CAST "': ");
1803 } else {
1804 TODO
1805 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00001806 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001807 /*
1808 * VAL TODO: The output of the given schema component is currently
1809 * disabled.
1810 */
1811#if 0
1812 if ((type != NULL) && (xmlSchemaIsGlobalItem(type))) {
1813 *msg = xmlStrcat(*msg, BAD_CAST " [");
1814 *msg = xmlStrcat(*msg, xmlSchemaFormatItemForReport(&str,
1815 NULL, type, NULL, 0));
1816 FREE_AND_NULL(str)
1817 *msg = xmlStrcat(*msg, BAD_CAST "]");
Daniel Veillardc0826a72004-08-10 14:17:33 +00001818 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001819#endif
1820 return (*msg);
Daniel Veillardc0826a72004-08-10 14:17:33 +00001821}
1822
Daniel Veillardc0826a72004-08-10 14:17:33 +00001823static void
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00001824xmlSchemaInternalErr2(xmlSchemaAbstractCtxtPtr actxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001825 const char *funcName,
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00001826 const char *message,
1827 const xmlChar *str1,
1828 const xmlChar *str2)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001829{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001830 xmlChar *msg = NULL;
1831
1832 msg = xmlStrdup(BAD_CAST "Internal error: ");
1833 msg = xmlStrcat(msg, BAD_CAST funcName);
1834 msg = xmlStrcat(msg, BAD_CAST ", ");
1835 msg = xmlStrcat(msg, BAD_CAST message);
1836 msg = xmlStrcat(msg, BAD_CAST ".\n");
1837
1838 if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR)
1839 xmlSchemaErr(actxt, XML_SCHEMAV_INTERNAL, NULL,
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00001840 (const char *) msg, str1, str2);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001841
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00001842 else if (actxt->type == XML_SCHEMA_CTXT_PARSER)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001843 xmlSchemaErr(actxt, XML_SCHEMAP_INTERNAL, NULL,
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00001844 (const char *) msg, str1, str2);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001845
1846 FREE_AND_NULL(msg)
Daniel Veillardc0826a72004-08-10 14:17:33 +00001847}
1848
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001849static void
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +00001850xmlSchemaInternalErr(xmlSchemaAbstractCtxtPtr actxt,
1851 const char *funcName,
1852 const char *message)
1853{
1854 xmlSchemaInternalErr2(actxt, funcName, message, NULL, NULL);
1855}
1856
1857static void
1858xmlSchemaPInternalErr(xmlSchemaParserCtxtPtr pctxt,
1859 const char *funcName,
1860 const char *message,
1861 const xmlChar *str1,
1862 const xmlChar *str2)
1863{
1864 xmlSchemaInternalErr2((xmlSchemaAbstractCtxtPtr) pctxt, funcName, message,
1865 str1, str2);
1866}
1867
1868static void
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001869xmlSchemaCustomErr(xmlSchemaAbstractCtxtPtr actxt,
1870 xmlParserErrors error,
1871 xmlNodePtr node,
1872 xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
1873 const char *message,
1874 const xmlChar *str1,
1875 const xmlChar *str2)
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00001876{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001877 xmlChar *msg = NULL;
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00001878
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001879 xmlSchemaFormatNodeForError(&msg, actxt, node);
1880 msg = xmlStrcat(msg, (const xmlChar *) message);
1881 msg = xmlStrcat(msg, BAD_CAST ".\n");
1882 xmlSchemaErr(actxt, error, node,
1883 (const char *) msg, str1, str2);
1884 FREE_AND_NULL(msg)
1885}
1886
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00001887static void
1888xmlSchemaKeyrefErr(xmlSchemaValidCtxtPtr vctxt,
1889 xmlParserErrors error,
1890 xmlSchemaPSVIIDCNodePtr idcNode,
1891 xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
1892 const char *message,
1893 const xmlChar *str1,
1894 const xmlChar *str2)
1895{
1896 xmlChar *msg = NULL, *qname = NULL;
1897
1898 msg = xmlStrdup(BAD_CAST "Element '%s': ");
1899 msg = xmlStrcat(msg, (const xmlChar *) message);
1900 msg = xmlStrcat(msg, BAD_CAST ".\n");
1901 xmlSchemaErr3Line((xmlSchemaAbstractCtxtPtr) vctxt,
1902 error, NULL, idcNode->nodeLine, (const char *) msg,
1903 xmlSchemaFormatQName(&qname,
1904 vctxt->nodeQNames->items[idcNode->nodeQNameID +1],
1905 vctxt->nodeQNames->items[idcNode->nodeQNameID]),
1906 str1, str2);
1907 FREE_AND_NULL(qname);
1908 FREE_AND_NULL(msg);
1909}
1910
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001911static int
1912xmlSchemaEvalErrorNodeType(xmlSchemaAbstractCtxtPtr actxt,
1913 xmlNodePtr node)
1914{
1915 if (node != NULL)
1916 return (node->type);
1917 if ((actxt->type == XML_SCHEMA_CTXT_VALIDATOR) &&
1918 (((xmlSchemaValidCtxtPtr) actxt)->inode != NULL))
1919 return ( ((xmlSchemaValidCtxtPtr) actxt)->inode->nodeType);
1920 return (-1);
1921}
1922
1923static int
1924xmlSchemaIsGlobalItem(xmlSchemaTypePtr item)
1925{
1926 switch (item->type) {
1927 case XML_SCHEMA_TYPE_COMPLEX:
1928 case XML_SCHEMA_TYPE_SIMPLE:
1929 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL)
1930 return(1);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00001931 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001932 case XML_SCHEMA_TYPE_GROUP:
1933 return (1);
1934 case XML_SCHEMA_TYPE_ELEMENT:
1935 if ( ((xmlSchemaElementPtr) item)->flags &
1936 XML_SCHEMAS_ELEM_GLOBAL)
1937 return(1);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00001938 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001939 case XML_SCHEMA_TYPE_ATTRIBUTE:
1940 if ( ((xmlSchemaAttributePtr) item)->flags &
1941 XML_SCHEMAS_ATTR_GLOBAL)
1942 return(1);
1943 break;
1944 /* Note that attribute groups are always global. */
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00001945 default:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001946 return(1);
1947 }
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +00001948 return (0);
1949}
1950
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00001951static void
1952xmlSchemaSimpleTypeErr(xmlSchemaAbstractCtxtPtr actxt,
1953 xmlParserErrors error,
1954 xmlNodePtr node,
1955 const xmlChar *value,
1956 xmlSchemaTypePtr type,
1957 int displayValue)
1958{
1959 xmlChar *msg = NULL;
1960
1961 xmlSchemaFormatNodeForError(&msg, actxt, node);
1962
1963 if (displayValue || (xmlSchemaEvalErrorNodeType(actxt, node) ==
1964 XML_ATTRIBUTE_NODE))
1965 msg = xmlStrcat(msg, BAD_CAST "'%s' is not a valid value of ");
1966 else
1967 msg = xmlStrcat(msg, BAD_CAST "The character content is not a valid "
1968 "value of ");
1969
1970 if (! xmlSchemaIsGlobalItem(type))
1971 msg = xmlStrcat(msg, BAD_CAST "the local ");
1972 else
1973 msg = xmlStrcat(msg, BAD_CAST "the ");
1974
1975 if (VARIETY_ATOMIC(type))
1976 msg = xmlStrcat(msg, BAD_CAST "atomic type");
1977 else if (VARIETY_LIST(type))
1978 msg = xmlStrcat(msg, BAD_CAST "list type");
1979 else if (VARIETY_UNION(type))
1980 msg = xmlStrcat(msg, BAD_CAST "union type");
1981
1982 if (xmlSchemaIsGlobalItem(type)) {
1983 xmlChar *str = NULL;
1984 msg = xmlStrcat(msg, BAD_CAST " '");
1985 if (type->builtInType != 0) {
1986 msg = xmlStrcat(msg, BAD_CAST "xs:");
1987 msg = xmlStrcat(msg, type->name);
1988 } else
1989 msg = xmlStrcat(msg,
1990 xmlSchemaFormatQName(&str,
1991 type->targetNamespace, type->name));
1992 msg = xmlStrcat(msg, BAD_CAST "'");
1993 FREE_AND_NULL(str);
1994 }
1995 msg = xmlStrcat(msg, BAD_CAST ".\n");
1996 if (displayValue || (xmlSchemaEvalErrorNodeType(actxt, node) ==
1997 XML_ATTRIBUTE_NODE))
1998 xmlSchemaErr(actxt, error, node, (const char *) msg, value, NULL);
1999 else
2000 xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
2001 FREE_AND_NULL(msg)
2002}
2003
Daniel Veillardc0826a72004-08-10 14:17:33 +00002004static const xmlChar *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002005xmlSchemaFormatErrorNodeQName(xmlChar ** str,
2006 xmlSchemaNodeInfoPtr ni,
2007 xmlNodePtr node)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002008{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002009 if (node != NULL) {
2010 if (node->ns != NULL)
2011 return (xmlSchemaFormatQName(str, node->ns->href, node->name));
2012 else
2013 return (xmlSchemaFormatQName(str, NULL, node->name));
2014 } else if (ni != NULL)
2015 return (xmlSchemaFormatQName(str, ni->nsName, ni->localName));
2016 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002017}
2018
Daniel Veillardc0826a72004-08-10 14:17:33 +00002019static void
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002020xmlSchemaIllegalAttrErr(xmlSchemaAbstractCtxtPtr actxt,
2021 xmlParserErrors error,
2022 xmlSchemaAttrInfoPtr ni,
2023 xmlNodePtr node)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002024{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002025 xmlChar *msg = NULL, *str = NULL;
2026
2027 xmlSchemaFormatNodeForError(&msg, actxt, node);
2028 msg = xmlStrcat(msg, BAD_CAST "The attribute '%s' is not allowed.\n");
2029 xmlSchemaErr(actxt, error, node, (const char *) msg,
2030 xmlSchemaFormatErrorNodeQName(&str, (xmlSchemaNodeInfoPtr) ni, node),
2031 NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002032 FREE_AND_NULL(str)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002033 FREE_AND_NULL(msg)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002034}
2035
Daniel Veillardc0826a72004-08-10 14:17:33 +00002036static void
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002037xmlSchemaComplexTypeErr(xmlSchemaAbstractCtxtPtr actxt,
2038 xmlParserErrors error,
2039 xmlNodePtr node,
2040 xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002041 const char *message,
2042 int nbval,
2043 int nbneg,
2044 xmlChar **values)
2045{
2046 xmlChar *str = NULL, *msg = NULL;
2047 xmlChar *localName, *nsName;
2048 const xmlChar *cur, *end;
Daniel Veillard77005e62005-07-19 16:26:18 +00002049 int i, is_not;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002050
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002051 xmlSchemaFormatNodeForError(&msg, actxt, node);
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002052 msg = xmlStrcat(msg, (const xmlChar *) message);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002053 msg = xmlStrcat(msg, BAD_CAST ".");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002054 /*
2055 * Note that is does not make sense to report that we have a
2056 * wildcard here, since the wildcard might be unfolded into
2057 * multiple transitions.
2058 */
2059 if (nbval + nbneg > 0) {
2060 if (nbval + nbneg > 1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002061 str = xmlStrdup(BAD_CAST " Expected is one of ( ");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002062 } else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002063 str = xmlStrdup(BAD_CAST " Expected is ( ");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002064 nsName = NULL;
2065
2066 for (i = 0; i < nbval + nbneg; i++) {
2067 cur = values[i];
Daniel Veillard77005e62005-07-19 16:26:18 +00002068 if (cur == NULL)
2069 continue;
2070 if ((cur[0] == 'n') && (cur[1] == 'o') && (cur[2] == 't') &&
2071 (cur[3] == ' ')) {
2072 is_not = 1;
2073 cur += 4;
Daniel Veillard6e65e152005-08-09 11:09:52 +00002074 str = xmlStrcat(str, BAD_CAST "##other");
Daniel Veillard77005e62005-07-19 16:26:18 +00002075 } else {
2076 is_not = 0;
2077 }
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002078 /*
2079 * Get the local name.
2080 */
2081 localName = NULL;
2082
2083 end = cur;
2084 if (*end == '*') {
2085 localName = xmlStrdup(BAD_CAST "*");
Kasimier T. Buchcikc0e833f2005-04-19 15:02:20 +00002086 end++;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002087 } else {
2088 while ((*end != 0) && (*end != '|'))
2089 end++;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002090 localName = xmlStrncat(localName, BAD_CAST cur, end - cur);
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002091 }
2092 if (*end != 0) {
Kasimier T. Buchcikc0e833f2005-04-19 15:02:20 +00002093 end++;
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002094 /*
2095 * Skip "*|*" if they come with negated expressions, since
2096 * they represent the same negated wildcard.
2097 */
2098 if ((nbneg == 0) || (*end != '*') || (*localName != '*')) {
2099 /*
2100 * Get the namespace name.
2101 */
2102 cur = end;
2103 if (*end == '*') {
2104 nsName = xmlStrdup(BAD_CAST "{*}");
2105 } else {
2106 while (*end != 0)
2107 end++;
2108
2109 if (i >= nbval)
2110 nsName = xmlStrdup(BAD_CAST "{##other:");
2111 else
2112 nsName = xmlStrdup(BAD_CAST "{");
2113
2114 nsName = xmlStrncat(nsName, BAD_CAST cur, end - cur);
2115 nsName = xmlStrcat(nsName, BAD_CAST "}");
2116 }
2117 str = xmlStrcat(str, BAD_CAST nsName);
2118 FREE_AND_NULL(nsName)
2119 } else {
2120 FREE_AND_NULL(localName);
2121 continue;
2122 }
2123 }
2124 str = xmlStrcat(str, BAD_CAST localName);
2125 FREE_AND_NULL(localName);
2126
2127 if (i < nbval + nbneg -1)
2128 str = xmlStrcat(str, BAD_CAST ", ");
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00002129 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002130 str = xmlStrcat(str, BAD_CAST " ).\n");
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002131 msg = xmlStrcat(msg, BAD_CAST str);
2132 FREE_AND_NULL(str)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002133 } else
2134 msg = xmlStrcat(msg, BAD_CAST "\n");
2135 xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002136 xmlFree(msg);
2137}
2138
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002139static void
2140xmlSchemaFacetErr(xmlSchemaAbstractCtxtPtr actxt,
2141 xmlParserErrors error,
2142 xmlNodePtr node,
2143 const xmlChar *value,
2144 unsigned long length,
2145 xmlSchemaTypePtr type,
2146 xmlSchemaFacetPtr facet,
2147 const char *message,
2148 const xmlChar *str1,
2149 const xmlChar *str2)
2150{
2151 xmlChar *str = NULL, *msg = NULL;
2152 xmlSchemaTypeType facetType;
2153 int nodeType = xmlSchemaEvalErrorNodeType(actxt, node);
2154
2155 xmlSchemaFormatNodeForError(&msg, actxt, node);
2156 if (error == XML_SCHEMAV_CVC_ENUMERATION_VALID) {
2157 facetType = XML_SCHEMA_FACET_ENUMERATION;
2158 /*
2159 * If enumerations are validated, one must not expect the
2160 * facet to be given.
2161 */
2162 } else
2163 facetType = facet->type;
2164 msg = xmlStrcat(msg, BAD_CAST "[");
2165 msg = xmlStrcat(msg, BAD_CAST "facet '");
2166 msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facetType));
2167 msg = xmlStrcat(msg, BAD_CAST "'] ");
2168 if (message == NULL) {
2169 /*
2170 * Use a default message.
2171 */
2172 if ((facetType == XML_SCHEMA_FACET_LENGTH) ||
2173 (facetType == XML_SCHEMA_FACET_MINLENGTH) ||
2174 (facetType == XML_SCHEMA_FACET_MAXLENGTH)) {
2175
2176 char len[25], actLen[25];
2177
2178 /* FIXME, TODO: What is the max expected string length of the
2179 * this value?
2180 */
2181 if (nodeType == XML_ATTRIBUTE_NODE)
2182 msg = xmlStrcat(msg, BAD_CAST "The value '%s' has a length of '%s'; ");
2183 else
2184 msg = xmlStrcat(msg, BAD_CAST "The value has a length of '%s'; ");
2185
2186 snprintf(len, 24, "%lu", xmlSchemaGetFacetValueAsULong(facet));
2187 snprintf(actLen, 24, "%lu", length);
2188
2189 if (facetType == XML_SCHEMA_FACET_LENGTH)
2190 msg = xmlStrcat(msg,
2191 BAD_CAST "this differs from the allowed length of '%s'.\n");
2192 else if (facetType == XML_SCHEMA_FACET_MAXLENGTH)
2193 msg = xmlStrcat(msg,
2194 BAD_CAST "this exceeds the allowed maximum length of '%s'.\n");
2195 else if (facetType == XML_SCHEMA_FACET_MINLENGTH)
2196 msg = xmlStrcat(msg,
2197 BAD_CAST "this underruns the allowed minimum length of '%s'.\n");
2198
2199 if (nodeType == XML_ATTRIBUTE_NODE)
2200 xmlSchemaErr3(actxt, error, node, (const char *) msg,
2201 value, (const xmlChar *) actLen, (const xmlChar *) len);
2202 else
2203 xmlSchemaErr(actxt, error, node, (const char *) msg,
2204 (const xmlChar *) actLen, (const xmlChar *) len);
2205
2206 } else if (facetType == XML_SCHEMA_FACET_ENUMERATION) {
2207 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not an element "
2208 "of the set {%s}.\n");
2209 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2210 xmlSchemaFormatFacetEnumSet(actxt, &str, type));
2211 } else if (facetType == XML_SCHEMA_FACET_PATTERN) {
2212 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not accepted "
2213 "by the pattern '%s'.\n");
2214 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2215 facet->value);
2216 } else if (facetType == XML_SCHEMA_FACET_MININCLUSIVE) {
2217 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is less than the "
2218 "minimum value allowed ('%s').\n");
2219 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2220 facet->value);
2221 } else if (facetType == XML_SCHEMA_FACET_MAXINCLUSIVE) {
2222 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is greater than the "
2223 "maximum value allowed ('%s').\n");
2224 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2225 facet->value);
2226 } else if (facetType == XML_SCHEMA_FACET_MINEXCLUSIVE) {
2227 msg = xmlStrcat(msg, BAD_CAST "The value '%s' must be less than "
2228 "'%s'.\n");
2229 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2230 facet->value);
2231 } else if (facetType == XML_SCHEMA_FACET_MAXEXCLUSIVE) {
2232 msg = xmlStrcat(msg, BAD_CAST "The value '%s' must be more than "
2233 "'%s'.\n");
2234 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2235 facet->value);
2236 } else if (facetType == XML_SCHEMA_FACET_TOTALDIGITS) {
2237 msg = xmlStrcat(msg, BAD_CAST "The value '%s' has more "
2238 "digits than are allowed ('%s').\n");
2239 xmlSchemaErr(actxt, error, node, (const char*) msg, value,
2240 facet->value);
2241 } else if (facetType == XML_SCHEMA_FACET_FRACTIONDIGITS) {
2242 msg = xmlStrcat(msg, BAD_CAST "The value '%s' has more fractional "
2243 "digits than are allowed ('%s').\n");
2244 xmlSchemaErr(actxt, error, node, (const char*) msg, value,
2245 facet->value);
2246 } else if (nodeType == XML_ATTRIBUTE_NODE) {
2247 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not facet-valid.\n");
2248 xmlSchemaErr(actxt, error, node, (const char *) msg, value, NULL);
2249 } else {
2250 msg = xmlStrcat(msg, BAD_CAST "The value is not facet-valid.\n");
2251 xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
2252 }
2253 } else {
2254 msg = xmlStrcat(msg, (const xmlChar *) message);
2255 msg = xmlStrcat(msg, BAD_CAST ".\n");
2256 xmlSchemaErr(actxt, error, node, (const char *) msg, str1, str2);
2257 }
2258 FREE_AND_NULL(str)
2259 xmlFree(msg);
2260}
2261
2262#define VERROR(err, type, msg) \
2263 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt, err, NULL, type, msg, NULL, NULL);
2264
2265#define VERROR_INT(func, msg) xmlSchemaInternalErr((xmlSchemaAbstractCtxtPtr) vctxt, func, msg);
2266
2267#define PERROR_INT(func, msg) xmlSchemaInternalErr((xmlSchemaAbstractCtxtPtr) pctxt, func, msg);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00002268#define PERROR_INT2(func, msg) xmlSchemaInternalErr((xmlSchemaAbstractCtxtPtr) ctxt, func, msg);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002269
2270#define AERROR_INT(func, msg) xmlSchemaInternalErr(actxt, func, msg);
2271
2272
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +00002273/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00002274 * xmlSchemaPMissingAttrErr:
2275 * @ctxt: the schema validation context
2276 * @ownerDes: the designation of the owner
2277 * @ownerName: the name of the owner
2278 * @ownerItem: the owner as a schema object
2279 * @ownerElem: the owner as an element node
2280 * @node: the parent element node of the missing attribute node
2281 * @type: the corresponding type of the attribute node
2282 *
2283 * Reports an illegal attribute.
2284 */
2285static void
2286xmlSchemaPMissingAttrErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002287 xmlParserErrors error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002288 xmlSchemaTypePtr ownerItem,
2289 xmlNodePtr ownerElem,
2290 const char *name,
2291 const char *message)
2292{
2293 xmlChar *des = NULL;
2294
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002295 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
2296
Daniel Veillardc0826a72004-08-10 14:17:33 +00002297 if (message != NULL)
2298 xmlSchemaPErr(ctxt, ownerElem, error, "%s: %s.\n", BAD_CAST des, BAD_CAST message);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002299 else
2300 xmlSchemaPErr(ctxt, ownerElem, error,
2301 "%s: The attribute '%s' is required but missing.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00002302 BAD_CAST des, BAD_CAST name);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002303 FREE_AND_NULL(des);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002304}
2305
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002306
Daniel Veillardc0826a72004-08-10 14:17:33 +00002307/**
2308 * xmlSchemaPResCompAttrErr:
2309 * @ctxt: the schema validation context
2310 * @error: the error code
2311 * @ownerDes: the designation of the owner
2312 * @ownerItem: the owner as a schema object
2313 * @ownerElem: the owner as an element node
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002314 * @name: the name of the attribute holding the QName
Daniel Veillardc0826a72004-08-10 14:17:33 +00002315 * @refName: the referenced local name
2316 * @refURI: the referenced namespace URI
2317 * @message: optional message
2318 *
2319 * Used to report QName attribute values that failed to resolve
2320 * to schema components.
2321 */
2322static void
2323xmlSchemaPResCompAttrErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002324 xmlParserErrors error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002325 xmlSchemaTypePtr ownerItem,
2326 xmlNodePtr ownerElem,
2327 const char *name,
2328 const xmlChar *refName,
2329 const xmlChar *refURI,
2330 xmlSchemaTypeType refType,
2331 const char *refTypeStr)
2332{
2333 xmlChar *des = NULL, *strA = NULL;
2334
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002335 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002336 if (refTypeStr == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002337 refTypeStr = (const char *) xmlSchemaCompTypeToString(refType);
2338 xmlSchemaPErrExt(ctxt, ownerElem, error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002339 NULL, NULL, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002340 "%s, attribute '%s': The QName value '%s' does not resolve to a(n) "
2341 "%s.\n", BAD_CAST des, BAD_CAST name,
2342 xmlSchemaFormatQName(&strA, refURI, refName),
Daniel Veillardc0826a72004-08-10 14:17:33 +00002343 BAD_CAST refTypeStr, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002344 FREE_AND_NULL(des)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002345 FREE_AND_NULL(strA)
2346}
2347
William M. Brack2f2a6632004-08-20 23:09:47 +00002348/**
2349 * xmlSchemaPCustomAttrErr:
2350 * @ctxt: the schema parser context
2351 * @error: the error code
2352 * @ownerDes: the designation of the owner
2353 * @ownerItem: the owner as a schema object
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002354 * @attr: the illegal attribute node
William M. Brack2f2a6632004-08-20 23:09:47 +00002355 *
2356 * Reports an illegal attribute during the parse.
2357 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002358static void
2359xmlSchemaPCustomAttrErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002360 xmlParserErrors error,
William M. Brack2f2a6632004-08-20 23:09:47 +00002361 xmlChar **ownerDes,
2362 xmlSchemaTypePtr ownerItem,
2363 xmlAttrPtr attr,
2364 const char *msg)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002365{
2366 xmlChar *des = NULL;
2367
2368 if (ownerDes == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002369 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002370 else if (*ownerDes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002371 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002372 des = *ownerDes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002373 } else
2374 des = *ownerDes;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002375 xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002376 "%s, attribute '%s': %s.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00002377 BAD_CAST des, attr->name, (const xmlChar *) msg, NULL, NULL);
2378 if (ownerDes == NULL)
2379 FREE_AND_NULL(des);
2380}
2381
2382/**
2383 * xmlSchemaPIllegalAttrErr:
William M. Brack2f2a6632004-08-20 23:09:47 +00002384 * @ctxt: the schema parser context
Daniel Veillardc0826a72004-08-10 14:17:33 +00002385 * @error: the error code
William M. Brack2f2a6632004-08-20 23:09:47 +00002386 * @ownerDes: the designation of the attribute's owner
2387 * @ownerItem: the attribute's owner item
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002388 * @attr: the illegal attribute node
Daniel Veillardc0826a72004-08-10 14:17:33 +00002389 *
William M. Brack2f2a6632004-08-20 23:09:47 +00002390 * Reports an illegal attribute during the parse.
Daniel Veillardc0826a72004-08-10 14:17:33 +00002391 */
2392static void
2393xmlSchemaPIllegalAttrErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002394 xmlParserErrors error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002395 xmlChar **ownerDes,
2396 xmlSchemaTypePtr ownerItem,
2397 xmlAttrPtr attr)
2398{
2399 xmlChar *des = NULL, *strA = NULL;
2400
2401 if (ownerDes == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002402 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002403 else if (*ownerDes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002404 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002405 des = *ownerDes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002406 } else
2407 des = *ownerDes;
2408 xmlSchemaPErr(ctxt, (xmlNodePtr) attr, error,
2409 "%s: The attribute '%s' is not allowed.\n", BAD_CAST des,
2410 xmlSchemaFormatQNameNs(&strA, attr->ns, attr->name));
Daniel Veillardc0826a72004-08-10 14:17:33 +00002411 if (ownerDes == NULL)
2412 FREE_AND_NULL(des);
2413 FREE_AND_NULL(strA);
2414}
2415
William M. Brack2f2a6632004-08-20 23:09:47 +00002416/**
2417 * xmlSchemaPAquireDes:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002418 * @des: the first designation
William M. Brack2f2a6632004-08-20 23:09:47 +00002419 * @itemDes: the second designation
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002420 * @item: the schema item
William M. Brack2f2a6632004-08-20 23:09:47 +00002421 * @itemElem: the node of the schema item
2422 *
2423 * Creates a designation for an item.
2424 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002425static void
2426xmlSchemaPAquireDes(xmlChar **des,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002427 xmlChar **itemDes,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002428 xmlSchemaTypePtr item,
2429 xmlNodePtr itemElem)
2430{
2431 if (itemDes == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002432 xmlSchemaFormatItemForReport(des, NULL, item, itemElem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002433 else if (*itemDes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002434 xmlSchemaFormatItemForReport(itemDes, NULL, item, itemElem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002435 *des = *itemDes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002436 } else
2437 *des = *itemDes;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002438}
2439
William M. Brack2f2a6632004-08-20 23:09:47 +00002440/**
2441 * xmlSchemaPCustomErr:
2442 * @ctxt: the schema parser context
2443 * @error: the error code
2444 * @itemDes: the designation of the schema item
2445 * @item: the schema item
2446 * @itemElem: the node of the schema item
2447 * @message: the error message
2448 * @str1: an optional param for the error message
2449 * @str2: an optional param for the error message
2450 * @str3: an optional param for the error message
2451 *
2452 * Reports an error during parsing.
2453 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002454static void
2455xmlSchemaPCustomErrExt(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002456 xmlParserErrors error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002457 xmlChar **itemDes,
2458 xmlSchemaTypePtr item,
2459 xmlNodePtr itemElem,
2460 const char *message,
2461 const xmlChar *str1,
2462 const xmlChar *str2,
2463 const xmlChar *str3)
2464{
2465 xmlChar *des = NULL, *msg = NULL;
2466
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002467 xmlSchemaPAquireDes(&des, itemDes, item, itemElem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002468 msg = xmlStrdup(BAD_CAST "%s: ");
2469 msg = xmlStrcat(msg, (const xmlChar *) message);
2470 msg = xmlStrcat(msg, BAD_CAST ".\n");
2471 if ((itemElem == NULL) && (item != NULL))
2472 itemElem = item->node;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002473 xmlSchemaPErrExt(ctxt, itemElem, error, NULL, NULL, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002474 (const char *) msg, BAD_CAST des, str1, str2, str3, NULL);
2475 if (itemDes == NULL)
2476 FREE_AND_NULL(des);
2477 FREE_AND_NULL(msg);
2478}
2479
William M. Brack2f2a6632004-08-20 23:09:47 +00002480/**
2481 * xmlSchemaPCustomErr:
2482 * @ctxt: the schema parser context
2483 * @error: the error code
2484 * @itemDes: the designation of the schema item
2485 * @item: the schema item
2486 * @itemElem: the node of the schema item
2487 * @message: the error message
2488 * @str1: the optional param for the error message
2489 *
2490 * Reports an error during parsing.
2491 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002492static void
2493xmlSchemaPCustomErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002494 xmlParserErrors error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002495 xmlChar **itemDes,
2496 xmlSchemaTypePtr item,
2497 xmlNodePtr itemElem,
2498 const char *message,
2499 const xmlChar *str1)
2500{
2501 xmlSchemaPCustomErrExt(ctxt, error, itemDes, item, itemElem, message,
2502 str1, NULL, NULL);
2503}
2504
William M. Brack2f2a6632004-08-20 23:09:47 +00002505/**
2506 * xmlSchemaPAttrUseErr:
2507 * @ctxt: the schema parser context
2508 * @error: the error code
2509 * @itemDes: the designation of the schema type
2510 * @item: the schema type
2511 * @itemElem: the node of the schema type
2512 * @attr: the invalid schema attribute
2513 * @message: the error message
2514 * @str1: the optional param for the error message
2515 *
2516 * Reports an attribute use error during parsing.
2517 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002518static void
2519xmlSchemaPAttrUseErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002520 xmlParserErrors error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002521 xmlSchemaTypePtr item,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002522 const xmlSchemaAttributePtr attr,
2523 const char *message,
2524 const xmlChar *str1)
2525{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002526 xmlChar *str = NULL, *msg = NULL;
2527 xmlSchemaFormatItemForReport(&msg, NULL, item, NULL);
2528 msg = xmlStrcat(msg, BAD_CAST ", ");
2529 msg = xmlStrcat(msg,
2530 BAD_CAST xmlSchemaFormatItemForReport(&str, NULL,
2531 (xmlSchemaTypePtr) attr, NULL));
2532 FREE_AND_NULL(str);
2533 msg = xmlStrcat(msg, BAD_CAST ": ");
Daniel Veillardc0826a72004-08-10 14:17:33 +00002534 msg = xmlStrcat(msg, (const xmlChar *) message);
2535 msg = xmlStrcat(msg, BAD_CAST ".\n");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002536 xmlSchemaPErr(ctxt, attr->node, error,
2537 (const char *) msg, str1, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002538 xmlFree(msg);
2539}
2540
William M. Brack2f2a6632004-08-20 23:09:47 +00002541/**
2542 * xmlSchemaPIllegalFacetAtomicErr:
2543 * @ctxt: the schema parser context
2544 * @error: the error code
2545 * @itemDes: the designation of the type
2546 * @item: the schema type
2547 * @baseItem: the base type of type
2548 * @facet: the illegal facet
2549 *
2550 * Reports an illegal facet for atomic simple types.
2551 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002552static void
2553xmlSchemaPIllegalFacetAtomicErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002554 xmlParserErrors error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002555 xmlChar **itemDes,
2556 xmlSchemaTypePtr item,
2557 xmlSchemaTypePtr baseItem,
2558 xmlSchemaFacetPtr facet)
2559{
2560 xmlChar *des = NULL, *strT = NULL;
2561
2562 xmlSchemaPAquireDes(&des, itemDes, item, item->node);
2563 xmlSchemaPErrExt(ctxt, item->node, error, NULL, NULL, NULL,
2564 "%s: The facet '%s' is not allowed on types derived from the "
2565 "type %s.\n",
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00002566 BAD_CAST des, xmlSchemaFacetTypeToString(facet->type),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002567 xmlSchemaFormatItemForReport(&strT, NULL, baseItem, NULL),
Daniel Veillardc0826a72004-08-10 14:17:33 +00002568 NULL, NULL);
2569 if (itemDes == NULL)
2570 FREE_AND_NULL(des);
2571 FREE_AND_NULL(strT);
2572}
2573
William M. Brack2f2a6632004-08-20 23:09:47 +00002574/**
2575 * xmlSchemaPIllegalFacetListUnionErr:
2576 * @ctxt: the schema parser context
2577 * @error: the error code
2578 * @itemDes: the designation of the schema item involved
2579 * @item: the schema item involved
2580 * @facet: the illegal facet
2581 *
2582 * Reports an illegal facet for <list> and <union>.
2583 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002584static void
2585xmlSchemaPIllegalFacetListUnionErr(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002586 xmlParserErrors error,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002587 xmlChar **itemDes,
2588 xmlSchemaTypePtr item,
2589 xmlSchemaFacetPtr facet)
2590{
2591 xmlChar *des = NULL, *strT = NULL;
2592
2593 xmlSchemaPAquireDes(&des, itemDes, item, item->node);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002594 xmlSchemaPErr(ctxt, item->node, error,
2595 "%s: The facet '%s' is not allowed.\n",
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00002596 BAD_CAST des, xmlSchemaFacetTypeToString(facet->type));
Daniel Veillardc0826a72004-08-10 14:17:33 +00002597 if (itemDes == NULL)
2598 FREE_AND_NULL(des);
2599 FREE_AND_NULL(strT);
2600}
2601
2602/**
2603 * xmlSchemaPMutualExclAttrErr:
2604 * @ctxt: the schema validation context
2605 * @error: the error code
2606 * @elemDes: the designation of the parent element node
2607 * @attr: the bad attribute node
2608 * @type: the corresponding type of the attribute node
2609 *
2610 * Reports an illegal attribute.
2611 */
2612static void
2613xmlSchemaPMutualExclAttrErr(xmlSchemaParserCtxtPtr ctxt,
2614 xmlParserErrors error,
2615 xmlChar **ownerDes,
2616 xmlSchemaTypePtr ownerItem,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002617 xmlAttrPtr attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002618 const char *name1,
2619 const char *name2)
2620{
2621 xmlChar *des = NULL;
2622
2623 if (ownerDes == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002624 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002625 else if (*ownerDes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002626 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002627 des = *ownerDes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002628 } else
2629 des = *ownerDes;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002630 xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002631 "%s: The attributes '%s' and '%s' are mutually exclusive.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00002632 BAD_CAST des, BAD_CAST name1, BAD_CAST name2, NULL, NULL);
2633 if (ownerDes == NULL)
2634 FREE_AND_NULL(des)
2635}
2636
2637/**
2638 * xmlSchemaPSimpleTypeErr:
2639 * @ctxt: the schema validation context
2640 * @error: the error code
William M. Brack2f2a6632004-08-20 23:09:47 +00002641 * @type: the type specifier
Daniel Veillardc0826a72004-08-10 14:17:33 +00002642 * @ownerDes: the designation of the owner
2643 * @ownerItem: the schema object if existent
2644 * @node: the validated node
2645 * @value: the validated value
2646 *
2647 * Reports a simple type validation error.
2648 * TODO: Should this report the value of an element as well?
2649 */
2650static void
2651xmlSchemaPSimpleTypeErr(xmlSchemaParserCtxtPtr ctxt,
2652 xmlParserErrors error,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002653 xmlSchemaTypePtr ownerItem ATTRIBUTE_UNUSED,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002654 xmlNodePtr node,
William M. Brack2f2a6632004-08-20 23:09:47 +00002655 xmlSchemaTypePtr type,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002656 const char *expected,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002657 const xmlChar *value,
2658 const char *message,
2659 const xmlChar *str1,
2660 const xmlChar *str2)
2661{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002662 xmlChar *msg = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002663
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002664 xmlSchemaFormatNodeForError(&msg, (xmlSchemaAbstractCtxtPtr) ctxt, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002665 if (message == NULL) {
2666 /*
2667 * Use default messages.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002668 */
2669 if (type != NULL) {
2670 if (node->type == XML_ATTRIBUTE_NODE)
2671 msg = xmlStrcat(msg, BAD_CAST "'%s' is not a valid value of ");
2672 else
2673 msg = xmlStrcat(msg, BAD_CAST "The character content is not a "
2674 "valid value of ");
2675 if (! xmlSchemaIsGlobalItem(type))
2676 msg = xmlStrcat(msg, BAD_CAST "the local ");
2677 else
2678 msg = xmlStrcat(msg, BAD_CAST "the ");
2679
2680 if (VARIETY_ATOMIC(type))
2681 msg = xmlStrcat(msg, BAD_CAST "atomic type");
2682 else if (VARIETY_LIST(type))
2683 msg = xmlStrcat(msg, BAD_CAST "list type");
2684 else if (VARIETY_UNION(type))
2685 msg = xmlStrcat(msg, BAD_CAST "union type");
2686
2687 if (xmlSchemaIsGlobalItem(type)) {
2688 xmlChar *str = NULL;
2689 msg = xmlStrcat(msg, BAD_CAST " '");
2690 if (type->builtInType != 0) {
2691 msg = xmlStrcat(msg, BAD_CAST "xs:");
2692 msg = xmlStrcat(msg, type->name);
2693 } else
2694 msg = xmlStrcat(msg,
2695 xmlSchemaFormatQName(&str,
2696 type->targetNamespace, type->name));
2697 msg = xmlStrcat(msg, BAD_CAST "'.");
2698 FREE_AND_NULL(str);
2699 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00002700 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002701 if (node->type == XML_ATTRIBUTE_NODE)
2702 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not valid.");
2703 else
2704 msg = xmlStrcat(msg, BAD_CAST "The character content is not "
2705 "valid.");
2706 }
2707 if (expected) {
2708 msg = xmlStrcat(msg, BAD_CAST " Expected is '");
2709 msg = xmlStrcat(msg, BAD_CAST expected);
2710 msg = xmlStrcat(msg, BAD_CAST "'.\n");
2711 } else
2712 msg = xmlStrcat(msg, BAD_CAST "\n");
Daniel Veillardc0826a72004-08-10 14:17:33 +00002713 if (node->type == XML_ATTRIBUTE_NODE)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002714 xmlSchemaPErr(ctxt, node, error, (const char *) msg, value, NULL);
2715 else
2716 xmlSchemaPErr(ctxt, node, error, (const char *) msg, NULL, NULL);
2717 } else {
Kasimier T. Buchcik2c9aac02005-07-21 22:14:12 +00002718 msg = xmlStrcat(msg, BAD_CAST message);
Kasimier T. Buchcik11162b72005-07-28 00:50:22 +00002719 msg = xmlStrcat(msg, BAD_CAST ".\n");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002720 xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL,
Kasimier T. Buchcik2c9aac02005-07-21 22:14:12 +00002721 (const char*) msg, str1, str2, NULL, NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002722 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002723 /* Cleanup. */
2724 FREE_AND_NULL(msg)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002725}
2726
William M. Brack2f2a6632004-08-20 23:09:47 +00002727/**
2728 * xmlSchemaPContentErr:
2729 * @ctxt: the schema parser context
2730 * @error: the error code
2731 * @onwerDes: the designation of the holder of the content
2732 * @ownerItem: the owner item of the holder of the content
2733 * @ownerElem: the node of the holder of the content
2734 * @child: the invalid child node
2735 * @message: the optional error message
2736 * @content: the optional string describing the correct content
2737 *
2738 * Reports an error concerning the content of a schema element.
2739 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00002740static void
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002741xmlSchemaPContentErr(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002742 xmlParserErrors error,
2743 xmlChar **ownerDes,
2744 xmlSchemaTypePtr ownerItem,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002745 xmlNodePtr ownerElem,
Daniel Veillardc0826a72004-08-10 14:17:33 +00002746 xmlNodePtr child,
2747 const char *message,
2748 const char *content)
2749{
2750 xmlChar *des = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002751
Daniel Veillardc0826a72004-08-10 14:17:33 +00002752 if (ownerDes == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002753 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002754 else if (*ownerDes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002755 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, ownerElem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00002756 des = *ownerDes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002757 } else
2758 des = *ownerDes;
Daniel Veillardc0826a72004-08-10 14:17:33 +00002759 if (message != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002760 xmlSchemaPErr2(ctxt, ownerElem, child, error,
2761 "%s: %s.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00002762 BAD_CAST des, BAD_CAST message);
2763 else {
2764 if (content != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002765 xmlSchemaPErr2(ctxt, ownerElem, child, error,
2766 "%s: The content is not valid. Expected is %s.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00002767 BAD_CAST des, BAD_CAST content);
2768 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002769 xmlSchemaPErr2(ctxt, ownerElem, child, error,
2770 "%s: The content is not valid.\n",
Daniel Veillardc0826a72004-08-10 14:17:33 +00002771 BAD_CAST des, NULL);
2772 }
2773 }
2774 if (ownerDes == NULL)
2775 FREE_AND_NULL(des)
Daniel Veillardc0826a72004-08-10 14:17:33 +00002776}
2777
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002778/************************************************************************
2779 * *
2780 * Streamable error functions *
2781 * *
2782 ************************************************************************/
Kasimier T. Buchcik8b418172004-11-17 13:14:27 +00002783
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00002784
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00002785
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00002786
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002787/************************************************************************
2788 * *
2789 * Validation helper functions *
2790 * *
2791 ************************************************************************/
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +00002792
Daniel Veillardc0826a72004-08-10 14:17:33 +00002793
Daniel Veillard4255d502002-04-16 15:50:10 +00002794/************************************************************************
2795 * *
2796 * Allocation functions *
2797 * *
2798 ************************************************************************/
2799
2800/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00002801 * xmlSchemaNewSchemaForParserCtxt:
William M. Brack08171912003-12-29 02:52:11 +00002802 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00002803 *
2804 * Allocate a new Schema structure.
2805 *
2806 * Returns the newly allocated structure or NULL in case or error
2807 */
2808static xmlSchemaPtr
2809xmlSchemaNewSchema(xmlSchemaParserCtxtPtr ctxt)
2810{
2811 xmlSchemaPtr ret;
2812
2813 ret = (xmlSchemaPtr) xmlMalloc(sizeof(xmlSchema));
2814 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002815 xmlSchemaPErrMemory(ctxt, "allocating schema", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00002816 return (NULL);
2817 }
2818 memset(ret, 0, sizeof(xmlSchema));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00002819 ret->dict = ctxt->dict;
Daniel Veillard500a1de2004-03-22 15:22:58 +00002820 xmlDictReference(ret->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00002821
2822 return (ret);
2823}
2824
2825/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00002826 * xmlSchemaNewSchema:
2827 * @ctxt: a schema validation context
2828 *
2829 * Allocate a new Schema structure.
2830 *
2831 * Returns the newly allocated structure or NULL in case or error
2832 */
2833static xmlSchemaAssemblePtr
2834xmlSchemaNewAssemble(void)
2835{
2836 xmlSchemaAssemblePtr ret;
2837
2838 ret = (xmlSchemaAssemblePtr) xmlMalloc(sizeof(xmlSchemaAssemble));
2839 if (ret == NULL) {
2840 /* xmlSchemaPErrMemory(ctxt, "allocating assemble info", NULL); */
2841 return (NULL);
2842 }
2843 memset(ret, 0, sizeof(xmlSchemaAssemble));
2844 ret->items = NULL;
2845 return (ret);
2846}
2847
2848/**
Daniel Veillard4255d502002-04-16 15:50:10 +00002849 * xmlSchemaNewFacet:
Daniel Veillard4255d502002-04-16 15:50:10 +00002850 *
2851 * Allocate a new Facet structure.
2852 *
2853 * Returns the newly allocated structure or NULL in case or error
2854 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00002855xmlSchemaFacetPtr
2856xmlSchemaNewFacet(void)
Daniel Veillard4255d502002-04-16 15:50:10 +00002857{
2858 xmlSchemaFacetPtr ret;
2859
2860 ret = (xmlSchemaFacetPtr) xmlMalloc(sizeof(xmlSchemaFacet));
2861 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00002862 return (NULL);
2863 }
2864 memset(ret, 0, sizeof(xmlSchemaFacet));
2865
2866 return (ret);
2867}
2868
2869/**
2870 * xmlSchemaNewAnnot:
William M. Brack08171912003-12-29 02:52:11 +00002871 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +00002872 * @node: a node
2873 *
2874 * Allocate a new annotation structure.
2875 *
2876 * Returns the newly allocated structure or NULL in case or error
2877 */
2878static xmlSchemaAnnotPtr
2879xmlSchemaNewAnnot(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
2880{
2881 xmlSchemaAnnotPtr ret;
2882
2883 ret = (xmlSchemaAnnotPtr) xmlMalloc(sizeof(xmlSchemaAnnot));
2884 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00002885 xmlSchemaPErrMemory(ctxt, "allocating annotation", node);
Daniel Veillard4255d502002-04-16 15:50:10 +00002886 return (NULL);
2887 }
2888 memset(ret, 0, sizeof(xmlSchemaAnnot));
2889 ret->content = node;
2890 return (ret);
2891}
2892
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00002893static xmlSchemaItemListPtr
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +00002894xmlSchemaItemListCreate(void)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00002895{
2896 xmlSchemaItemListPtr ret;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00002897
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00002898 ret = xmlMalloc(sizeof(xmlSchemaItemList));
2899 if (ret == NULL) {
2900 xmlSchemaPErrMemory(NULL,
2901 "allocating an item list structure", NULL);
2902 return (NULL);
2903 }
2904 memset(ret, 0, sizeof(xmlSchemaItemList));
2905 return (ret);
2906}
2907
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00002908static void
2909xmlSchemaItemListClear(xmlSchemaItemListPtr list)
2910{
2911 if (list->items != NULL) {
2912 xmlFree(list->items);
2913 list->items = NULL;
2914 }
2915 list->nbItems = 0;
2916 list->sizeItems = 0;
2917}
2918
2919static int
2920xmlSchemaItemListAdd(xmlSchemaItemListPtr list, void *item)
2921{
2922 if (list->items == NULL) {
2923 list->items = (void **) xmlMalloc(
2924 20 * sizeof(void *));
2925 if (list->items == NULL) {
2926 xmlSchemaPErrMemory(NULL, "allocating new item list", NULL);
2927 return(-1);
2928 }
2929 list->sizeItems = 20;
2930 } else if (list->sizeItems <= list->nbItems) {
2931 list->sizeItems *= 2;
2932 list->items = (void **) xmlRealloc(list->items,
2933 list->sizeItems * sizeof(void *));
2934 if (list->items == NULL) {
2935 xmlSchemaPErrMemory(NULL, "growing item list", NULL);
2936 list->sizeItems = 0;
2937 return(-1);
2938 }
2939 }
2940 /* ((xmlSchemaBasicItemPtr *) list->items)[list->nbItems++] = (void *) item; */
2941 list->items[list->nbItems++] = item;
2942 return(0);
2943}
2944
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00002945/**
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +00002946 * xmlSchemaItemListFree:
2947 * @annot: a schema type structure
2948 *
2949 * Deallocate a annotation structure
2950 */
2951static void
2952xmlSchemaItemListFree(xmlSchemaItemListPtr list)
2953{
2954 if (list == NULL)
2955 return;
2956 if (list->items != NULL)
2957 xmlFree(list->items);
2958 xmlFree(list);
2959}
2960
2961static xmlSchemaContainerPtr
2962xmlSchemaContainerCreate(void)
2963{
2964 xmlSchemaContainerPtr ret;
2965
2966 ret = (xmlSchemaContainerPtr) xmlMalloc(sizeof(xmlSchemaContainer));
2967 if (ret == NULL) {
2968 xmlSchemaPErrMemory(NULL, "allocating component container",
2969 NULL);
2970 return(NULL);
2971 }
2972 memset(ret, 0, sizeof(xmlSchemaContainer));
2973 return(ret);
2974}
2975
2976static void
2977xmlSchemaContainerFree(xmlSchemaContainerPtr cont)
2978{
2979 if (cont == NULL)
2980 return;
2981 if (cont->typeDefs != NULL)
2982 xmlSchemaItemListFree(cont->typeDefs);
2983 if (cont->attrDecls != NULL)
2984 xmlSchemaItemListFree(cont->attrDecls);
2985 if (cont->elemDecls != NULL)
2986 xmlSchemaItemListFree(cont->elemDecls);
2987 if (cont->attrGroupDefs != NULL)
2988 xmlSchemaItemListFree(cont->attrGroupDefs);
2989 if (cont->modelGroupDefs != NULL)
2990 xmlSchemaItemListFree(cont->modelGroupDefs);
2991 if (cont->notationDecls != NULL)
2992 xmlSchemaItemListFree(cont->notationDecls);
2993 if (cont->annotations != NULL)
2994 xmlSchemaItemListFree(cont->annotations);
2995 if (cont->locals != NULL)
2996 xmlSchemaItemListFree(cont->locals);
2997 xmlFree(cont);
2998}
2999
3000/**
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003001 * xmlSchemaAddElementSubstitutionMember:
3002 * @pctxt: a schema parser context
3003 * @head: the head of the substitution group
3004 * @member: the new member of the substitution group
3005 *
3006 * Allocate a new annotation structure.
3007 *
3008 * Returns the newly allocated structure or NULL in case or error
3009 */
3010static int
3011xmlSchemaAddElementSubstitutionMember(xmlSchemaParserCtxtPtr pctxt,
3012 xmlSchemaElementPtr head,
3013 xmlSchemaElementPtr member)
3014{
3015 xmlSchemaSubstGroupPtr substGroup;
3016
3017 if (pctxt == NULL)
3018 return (-1);
3019
3020 if (pctxt->substGroups == NULL) {
3021 pctxt->substGroups = xmlHashCreateDict(10, pctxt->dict);
3022 if (pctxt->substGroups == NULL)
3023 return (-1);
3024 }
3025 substGroup = xmlHashLookup2(pctxt->substGroups, head->name,
3026 head->targetNamespace);
3027 if (substGroup == NULL) {
3028 int res;
3029
3030 substGroup = (xmlSchemaSubstGroupPtr) xmlMalloc(sizeof(xmlSchemaSubstGroup));
3031 if (substGroup == NULL) {
3032 xmlSchemaPErrMemory(NULL,
3033 "xmlSchemaAddElementSubstitution, allocating a substitution "
3034 "group container",
3035 NULL);
3036 return (-1);
3037 }
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +00003038 substGroup->members = xmlSchemaItemListCreate();
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003039 if (substGroup->members == NULL) {
3040 xmlFree(substGroup);
3041 return (-1);
3042 }
3043 substGroup->head = head;
3044
3045 res = xmlHashAddEntry2(pctxt->substGroups,
3046 head->name, head->targetNamespace, substGroup);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003047 if (res != 0) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003048 xmlFree(substGroup->members);
3049 xmlFree(substGroup);
3050 xmlSchemaPErr(pctxt, member->node,
3051 XML_SCHEMAP_INTERNAL,
3052 "Internal error: xmlSchemaAddElementSubstitution, "
3053 "failed to add a new substitution group container for "
3054 "'%s'.\n", head->name, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003055 return (-1);
3056 }
3057 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003058 if (substGroup->members->items == NULL) {
3059 substGroup->members->items = (void **) xmlMalloc(
3060 5 * sizeof(xmlSchemaElementPtr));
3061 if (substGroup->members->items == NULL) {
3062 xmlSchemaPErrMemory(NULL,
3063 "allocating list of substitution group members", NULL);
3064 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003065 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003066 substGroup->members->sizeItems = 5;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003067 } else if (substGroup->members->sizeItems <=
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003068 substGroup->members->nbItems) {
3069 substGroup->members->sizeItems *= 2;
3070 substGroup->members->items = (void **) xmlRealloc(
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003071 substGroup->members->items,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003072 substGroup->members->sizeItems * sizeof(xmlSchemaElementPtr));
3073 if (substGroup->members->items == NULL) {
3074 xmlSchemaPErrMemory(NULL,
3075 "re-allocating list of substitution group members", NULL);
3076 substGroup->members->sizeItems = 0;
3077 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003078 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003079 }
3080 ((xmlSchemaElementPtr *) substGroup->members->items)
3081 [substGroup->members->nbItems++] = (void *) member;
3082 return (0);
3083}
3084
3085/**
3086 * xmlSchemaGetElementSubstitutionGroup:
3087 * @pctxt: a schema parser context
3088 * @head: the head of the substitution group
3089 * @member: the new member of the substitution group
3090 *
3091 * Allocate a new annotation structure.
3092 *
3093 * Returns the newly allocated structure or NULL in case or error
3094 */
3095static xmlSchemaSubstGroupPtr
3096xmlSchemaGetElementSubstitutionGroup(xmlSchemaParserCtxtPtr pctxt,
3097 xmlSchemaElementPtr head)
3098{
3099 if (pctxt == NULL)
3100 return (NULL);
3101
3102 if (pctxt->substGroups == NULL)
3103 return (NULL);
3104
3105 return ((xmlSchemaSubstGroupPtr) xmlHashLookup2(pctxt->substGroups,
3106 head->name, head->targetNamespace));
3107}
3108
3109/**
Daniel Veillardfdc91562002-07-01 21:52:03 +00003110 * xmlSchemaFreeAnnot:
3111 * @annot: a schema type structure
3112 *
3113 * Deallocate a annotation structure
3114 */
3115static void
3116xmlSchemaFreeAnnot(xmlSchemaAnnotPtr annot)
3117{
3118 if (annot == NULL)
3119 return;
Kasimier T. Buchcik004b5462005-08-08 12:43:09 +00003120 if (annot->next == NULL) {
3121 xmlFree(annot);
3122 } else {
3123 xmlSchemaAnnotPtr prev;
3124
3125 do {
3126 prev = annot;
3127 annot = annot->next;
3128 xmlFree(prev);
3129 } while (annot != NULL);
3130 }
Daniel Veillardfdc91562002-07-01 21:52:03 +00003131}
3132
3133/**
Daniel Veillard1d913862003-11-21 00:28:39 +00003134 * xmlSchemaFreeImport:
3135 * @import: a schema import structure
3136 *
3137 * Deallocate an import structure
3138 */
3139static void
3140xmlSchemaFreeImport(xmlSchemaImportPtr import)
3141{
3142 if (import == NULL)
3143 return;
3144
3145 xmlSchemaFree(import->schema);
William M. Brack2f2a6632004-08-20 23:09:47 +00003146 xmlFreeDoc(import->doc);
Daniel Veillard1d913862003-11-21 00:28:39 +00003147 xmlFree(import);
3148}
3149
3150/**
Daniel Veillardbd2904b2003-11-25 15:38:59 +00003151 * xmlSchemaFreeInclude:
3152 * @include: a schema include structure
3153 *
3154 * Deallocate an include structure
3155 */
3156static void
3157xmlSchemaFreeInclude(xmlSchemaIncludePtr include)
3158{
3159 if (include == NULL)
3160 return;
3161
3162 xmlFreeDoc(include->doc);
3163 xmlFree(include);
3164}
3165
3166/**
3167 * xmlSchemaFreeIncludeList:
3168 * @includes: a schema include list
3169 *
3170 * Deallocate an include structure
3171 */
3172static void
3173xmlSchemaFreeIncludeList(xmlSchemaIncludePtr includes)
3174{
3175 xmlSchemaIncludePtr next;
3176
3177 while (includes != NULL) {
3178 next = includes->next;
3179 xmlSchemaFreeInclude(includes);
3180 includes = next;
3181 }
3182}
3183
3184/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003185 * xmlSchemaFreeNotation:
3186 * @schema: a schema notation structure
3187 *
3188 * Deallocate a Schema Notation structure.
3189 */
3190static void
3191xmlSchemaFreeNotation(xmlSchemaNotationPtr nota)
3192{
3193 if (nota == NULL)
3194 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00003195 xmlFree(nota);
3196}
3197
3198/**
3199 * xmlSchemaFreeAttribute:
3200 * @schema: a schema attribute structure
3201 *
3202 * Deallocate a Schema Attribute structure.
3203 */
3204static void
3205xmlSchemaFreeAttribute(xmlSchemaAttributePtr attr)
3206{
3207 if (attr == NULL)
3208 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003209 if (attr->annot != NULL)
Daniel Veillardc0826a72004-08-10 14:17:33 +00003210 xmlSchemaFreeAnnot(attr->annot);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00003211 if (attr->defVal != NULL)
3212 xmlSchemaFreeValue(attr->defVal);
Daniel Veillard4255d502002-04-16 15:50:10 +00003213 xmlFree(attr);
3214}
3215
3216/**
Daniel Veillard3646d642004-06-02 19:19:14 +00003217 * xmlSchemaFreeWildcardNsSet:
3218 * set: a schema wildcard namespace
3219 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00003220 * Deallocates a list of wildcard constraint structures.
Daniel Veillard3646d642004-06-02 19:19:14 +00003221 */
3222static void
3223xmlSchemaFreeWildcardNsSet(xmlSchemaWildcardNsPtr set)
3224{
3225 xmlSchemaWildcardNsPtr next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003226
Daniel Veillard3646d642004-06-02 19:19:14 +00003227 while (set != NULL) {
3228 next = set->next;
3229 xmlFree(set);
3230 set = next;
3231 }
3232}
3233
3234/**
3235 * xmlSchemaFreeWildcard:
Daniel Veillard01fa6152004-06-29 17:04:39 +00003236 * @wildcard: a wildcard structure
Daniel Veillard3646d642004-06-02 19:19:14 +00003237 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00003238 * Deallocates a wildcard structure.
Daniel Veillard3646d642004-06-02 19:19:14 +00003239 */
Daniel Veillard01fa6152004-06-29 17:04:39 +00003240void
Daniel Veillard3646d642004-06-02 19:19:14 +00003241xmlSchemaFreeWildcard(xmlSchemaWildcardPtr wildcard)
3242{
3243 if (wildcard == NULL)
3244 return;
3245 if (wildcard->annot != NULL)
3246 xmlSchemaFreeAnnot(wildcard->annot);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003247 if (wildcard->nsSet != NULL)
3248 xmlSchemaFreeWildcardNsSet(wildcard->nsSet);
3249 if (wildcard->negNsSet != NULL)
3250 xmlFree(wildcard->negNsSet);
Daniel Veillard3646d642004-06-02 19:19:14 +00003251 xmlFree(wildcard);
3252}
3253
3254/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003255 * xmlSchemaFreeAttributeGroup:
3256 * @schema: a schema attribute group structure
3257 *
3258 * Deallocate a Schema Attribute Group structure.
3259 */
3260static void
3261xmlSchemaFreeAttributeGroup(xmlSchemaAttributeGroupPtr attr)
3262{
3263 if (attr == NULL)
3264 return;
Daniel Veillard3646d642004-06-02 19:19:14 +00003265 if (attr->annot != NULL)
3266 xmlSchemaFreeAnnot(attr->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00003267 xmlFree(attr);
3268}
3269
3270/**
Daniel Veillard3646d642004-06-02 19:19:14 +00003271 * xmlSchemaFreeAttributeUseList:
Daniel Veillard01fa6152004-06-29 17:04:39 +00003272 * @attrUse: an attribute link
Daniel Veillard3646d642004-06-02 19:19:14 +00003273 *
3274 * Deallocate a list of schema attribute uses.
3275 */
3276static void
3277xmlSchemaFreeAttributeUseList(xmlSchemaAttributeLinkPtr attrUse)
3278{
3279 xmlSchemaAttributeLinkPtr next;
3280
3281 while (attrUse != NULL) {
3282 next = attrUse->next;
3283 xmlFree(attrUse);
3284 attrUse = next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003285 }
Daniel Veillard3646d642004-06-02 19:19:14 +00003286}
3287
3288/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003289 * xmlSchemaFreeQNameRef:
3290 * @item: a QName reference structure
3291 *
3292 * Deallocatea a QName reference structure.
3293 */
3294static void
3295xmlSchemaFreeQNameRef(xmlSchemaQNameRefPtr item)
3296{
3297 xmlFree(item);
3298}
3299
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003300/**
3301 * xmlSchemaFreeQNameRef:
3302 * @item: a QName reference structure
3303 *
3304 * Deallocatea a QName reference structure.
3305 */
3306static void
3307xmlSchemaFreeSubstGroup(xmlSchemaSubstGroupPtr item)
3308{
3309 if (item == NULL)
3310 return;
3311 if (item->members != NULL)
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +00003312 xmlSchemaItemListFree(item->members);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00003313 xmlFree(item);
3314}
3315
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003316static int
3317xmlSchemaAddVolatile(xmlSchemaPtr schema,
3318 xmlSchemaBasicItemPtr item)
3319{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003320 if (schema->volatiles == NULL) {
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +00003321 schema->volatiles = (void *) xmlSchemaItemListCreate();
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003322 if (schema->volatiles == NULL) {
3323 xmlSchemaPErrMemory(NULL,
3324 "allocating list of volatiles", NULL);
3325 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003326 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003327 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00003328 return(xmlSchemaItemListAdd((xmlSchemaItemListPtr) schema->volatiles, item));
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003329}
3330
3331/**
Daniel Veillard01fa6152004-06-29 17:04:39 +00003332 * xmlSchemaFreeTypeLinkList:
3333 * @alink: a type link
3334 *
3335 * Deallocate a list of types.
3336 */
3337static void
3338xmlSchemaFreeTypeLinkList(xmlSchemaTypeLinkPtr link)
3339{
3340 xmlSchemaTypeLinkPtr next;
3341
3342 while (link != NULL) {
3343 next = link->next;
3344 xmlFree(link);
3345 link = next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003346 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00003347}
3348
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003349static void
3350xmlSchemaFreeIDCStateObjList(xmlSchemaIDCStateObjPtr sto)
3351{
3352 xmlSchemaIDCStateObjPtr next;
3353 while (sto != NULL) {
3354 next = sto->next;
3355 if (sto->history != NULL)
3356 xmlFree(sto->history);
3357 if (sto->xpathCtxt != NULL)
3358 xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
3359 xmlFree(sto);
3360 sto = next;
3361 }
3362}
3363
3364/**
3365 * xmlSchemaFreeIDC:
3366 * @idc: a identity-constraint definition
3367 *
3368 * Deallocates an identity-constraint definition.
3369 */
3370static void
3371xmlSchemaFreeIDC(xmlSchemaIDCPtr idcDef)
3372{
3373 xmlSchemaIDCSelectPtr cur, prev;
3374
3375 if (idcDef == NULL)
3376 return;
3377 if (idcDef->annot != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003378 xmlSchemaFreeAnnot(idcDef->annot);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003379 /* Selector */
3380 if (idcDef->selector != NULL) {
3381 if (idcDef->selector->xpathComp != NULL)
3382 xmlFreePattern((xmlPatternPtr) idcDef->selector->xpathComp);
3383 xmlFree(idcDef->selector);
3384 }
3385 /* Fields */
3386 if (idcDef->fields != NULL) {
3387 cur = idcDef->fields;
3388 do {
3389 prev = cur;
3390 cur = cur->next;
3391 if (prev->xpathComp != NULL)
3392 xmlFreePattern((xmlPatternPtr) prev->xpathComp);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003393 xmlFree(prev);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003394 } while (cur != NULL);
3395 }
3396 xmlFree(idcDef);
3397}
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003398
Daniel Veillard01fa6152004-06-29 17:04:39 +00003399/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003400 * xmlSchemaFreeElement:
3401 * @schema: a schema element structure
3402 *
3403 * Deallocate a Schema Element structure.
3404 */
3405static void
3406xmlSchemaFreeElement(xmlSchemaElementPtr elem)
3407{
3408 if (elem == NULL)
3409 return;
Daniel Veillard32370232002-10-16 14:08:14 +00003410 if (elem->annot != NULL)
3411 xmlSchemaFreeAnnot(elem->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00003412 if (elem->contModel != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003413 xmlRegFreeRegexp(elem->contModel);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00003414 if (elem->defVal != NULL)
3415 xmlSchemaFreeValue(elem->defVal);
Daniel Veillard4255d502002-04-16 15:50:10 +00003416 xmlFree(elem);
3417}
3418
3419/**
3420 * xmlSchemaFreeFacet:
3421 * @facet: a schema facet structure
3422 *
3423 * Deallocate a Schema Facet structure.
3424 */
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00003425void
Daniel Veillard4255d502002-04-16 15:50:10 +00003426xmlSchemaFreeFacet(xmlSchemaFacetPtr facet)
3427{
3428 if (facet == NULL)
3429 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00003430 if (facet->val != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003431 xmlSchemaFreeValue(facet->val);
Daniel Veillard4255d502002-04-16 15:50:10 +00003432 if (facet->regexp != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003433 xmlRegFreeRegexp(facet->regexp);
Daniel Veillardfdc91562002-07-01 21:52:03 +00003434 if (facet->annot != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003435 xmlSchemaFreeAnnot(facet->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00003436 xmlFree(facet);
3437}
3438
3439/**
3440 * xmlSchemaFreeType:
3441 * @type: a schema type structure
3442 *
3443 * Deallocate a Schema Type structure.
3444 */
3445void
3446xmlSchemaFreeType(xmlSchemaTypePtr type)
3447{
3448 if (type == NULL)
3449 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00003450 if (type->annot != NULL)
Daniel Veillard32370232002-10-16 14:08:14 +00003451 xmlSchemaFreeAnnot(type->annot);
Daniel Veillard4255d502002-04-16 15:50:10 +00003452 if (type->facets != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003453 xmlSchemaFacetPtr facet, next;
Daniel Veillard4255d502002-04-16 15:50:10 +00003454
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003455 facet = type->facets;
3456 while (facet != NULL) {
3457 next = facet->next;
3458 xmlSchemaFreeFacet(facet);
3459 facet = next;
3460 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003461 }
Daniel Veillard3646d642004-06-02 19:19:14 +00003462 if (type->type != XML_SCHEMA_TYPE_BASIC) {
Kasimier T. Buchcik11162b72005-07-28 00:50:22 +00003463 /*
3464 * TODO: Why is this restricted to non built-in types?
3465 */
Daniel Veillard3646d642004-06-02 19:19:14 +00003466 if (type->attributeUses != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003467 xmlSchemaFreeAttributeUseList(type->attributeUses);
Daniel Veillard3646d642004-06-02 19:19:14 +00003468 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00003469 if (type->memberTypes != NULL)
3470 xmlSchemaFreeTypeLinkList(type->memberTypes);
3471 if (type->facetSet != NULL) {
3472 xmlSchemaFacetLinkPtr next, link;
3473
3474 link = type->facetSet;
3475 do {
3476 next = link->next;
3477 xmlFree(link);
3478 link = next;
3479 } while (link != NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003480 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00003481 if (type->contModel != NULL)
3482 xmlRegFreeRegexp(type->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +00003483 xmlFree(type);
3484}
3485
3486/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003487 * xmlSchemaFreeModelGroupDef:
3488 * @item: a schema model group definition
3489 *
3490 * Deallocates a schema model group definition.
3491 */
3492static void
3493xmlSchemaFreeModelGroupDef(xmlSchemaModelGroupDefPtr item)
3494{
3495 if (item->annot != NULL)
3496 xmlSchemaFreeAnnot(item->annot);
3497 xmlFree(item);
3498}
3499
3500/**
3501 * xmlSchemaFreeModelGroup:
3502 * @item: a schema model group
3503 *
3504 * Deallocates a schema model group structure.
3505 */
3506static void
3507xmlSchemaFreeModelGroup(xmlSchemaModelGroupPtr item)
3508{
3509 if (item->annot != NULL)
3510 xmlSchemaFreeAnnot(item->annot);
3511 xmlFree(item);
3512}
3513
3514/**
3515 * xmlSchemaFreeParticle:
3516 * @type: a schema type structure
3517 *
3518 * Deallocate a Schema Type structure.
3519 */
3520static void
3521xmlSchemaFreeParticle(xmlSchemaParticlePtr item)
3522{
3523 if (item->annot != NULL)
3524 xmlSchemaFreeAnnot(item->annot);
3525 xmlFree(item);
3526}
3527
3528/**
3529 * xmlSchemaFreeMiscComponents:
3530 * @item: a schema component
3531 *
3532 * Deallocates misc. schema component structures.
3533 */
3534static void
3535xmlSchemaFreeMiscComponents(xmlSchemaTreeItemPtr item)
3536{
3537 if (item == NULL)
3538 return;
3539 switch (item->type) {
3540 case XML_SCHEMA_TYPE_PARTICLE:
3541 xmlSchemaFreeParticle((xmlSchemaParticlePtr) item);
3542 return;
3543 case XML_SCHEMA_TYPE_SEQUENCE:
3544 case XML_SCHEMA_TYPE_CHOICE:
3545 case XML_SCHEMA_TYPE_ALL:
3546 xmlSchemaFreeModelGroup((xmlSchemaModelGroupPtr) item);
3547 return;
3548 case XML_SCHEMA_TYPE_ANY:
3549 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
3550 xmlSchemaFreeWildcard((xmlSchemaWildcardPtr) item);
3551 break;
3552 default:
3553 /* TODO: This should never be hit. */
3554 TODO
3555 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003556 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003557}
3558
3559static void
3560xmlSchemaFreeVolatiles(xmlSchemaPtr schema)
3561{
3562 if (schema->volatiles == NULL)
3563 return;
3564 {
3565 xmlSchemaItemListPtr list = (xmlSchemaItemListPtr) schema->volatiles;
3566 xmlSchemaTreeItemPtr item;
3567 int i;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003568
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003569 for (i = 0; i < list->nbItems; i++) {
3570 if (list->items[i] != NULL) {
3571 item = (xmlSchemaTreeItemPtr) list->items[i];
3572 switch (item->type) {
3573 case XML_SCHEMA_EXTRA_QNAMEREF:
3574 xmlSchemaFreeQNameRef((xmlSchemaQNameRefPtr) item);
3575 break;
3576 default:
3577 xmlSchemaFreeMiscComponents(item);
3578 }
3579 }
3580 }
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +00003581 xmlSchemaItemListFree(list);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003582 }
3583}
3584/**
Daniel Veillardb0f397e2003-12-23 23:30:53 +00003585 * xmlSchemaFreeTypeList:
3586 * @type: a schema type structure
3587 *
3588 * Deallocate a Schema Type structure.
3589 */
3590static void
3591xmlSchemaFreeTypeList(xmlSchemaTypePtr type)
3592{
3593 xmlSchemaTypePtr next;
3594
3595 while (type != NULL) {
3596 next = type->redef;
3597 xmlSchemaFreeType(type);
3598 type = next;
3599 }
3600}
3601
3602/**
Daniel Veillard4255d502002-04-16 15:50:10 +00003603 * xmlSchemaFree:
3604 * @schema: a schema structure
3605 *
3606 * Deallocate a Schema structure.
3607 */
3608void
3609xmlSchemaFree(xmlSchemaPtr schema)
3610{
3611 if (schema == NULL)
3612 return;
3613
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003614 if (schema->volatiles != NULL)
3615 xmlSchemaFreeVolatiles(schema);
Daniel Veillard4255d502002-04-16 15:50:10 +00003616 if (schema->notaDecl != NULL)
3617 xmlHashFree(schema->notaDecl,
3618 (xmlHashDeallocator) xmlSchemaFreeNotation);
3619 if (schema->attrDecl != NULL)
3620 xmlHashFree(schema->attrDecl,
3621 (xmlHashDeallocator) xmlSchemaFreeAttribute);
3622 if (schema->attrgrpDecl != NULL)
3623 xmlHashFree(schema->attrgrpDecl,
3624 (xmlHashDeallocator) xmlSchemaFreeAttributeGroup);
3625 if (schema->elemDecl != NULL)
3626 xmlHashFree(schema->elemDecl,
3627 (xmlHashDeallocator) xmlSchemaFreeElement);
3628 if (schema->typeDecl != NULL)
3629 xmlHashFree(schema->typeDecl,
Daniel Veillardb0f397e2003-12-23 23:30:53 +00003630 (xmlHashDeallocator) xmlSchemaFreeTypeList);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00003631 if (schema->groupDecl != NULL)
3632 xmlHashFree(schema->groupDecl,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003633 (xmlHashDeallocator) xmlSchemaFreeModelGroupDef);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00003634 if (schema->idcDef != NULL)
3635 xmlHashFree(schema->idcDef,
3636 (xmlHashDeallocator) xmlSchemaFreeIDC);
Daniel Veillard1d913862003-11-21 00:28:39 +00003637 if (schema->schemasImports != NULL)
3638 xmlHashFree(schema->schemasImports,
3639 (xmlHashDeallocator) xmlSchemaFreeImport);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00003640 if (schema->includes != NULL) {
3641 xmlSchemaFreeIncludeList((xmlSchemaIncludePtr) schema->includes);
3642 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003643 if (schema->annot != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003644 xmlSchemaFreeAnnot(schema->annot);
Daniel Veillarddda22c12004-01-24 08:31:30 +00003645 if (schema->doc != NULL && !schema->preserve)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003646 xmlFreeDoc(schema->doc);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003647 xmlDictFree(schema->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00003648 xmlFree(schema);
3649}
3650
3651/************************************************************************
3652 * *
Daniel Veillard4255d502002-04-16 15:50:10 +00003653 * Debug functions *
3654 * *
3655 ************************************************************************/
3656
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00003657#ifdef LIBXML_OUTPUT_ENABLED
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003658
Daniel Veillard4255d502002-04-16 15:50:10 +00003659/**
3660 * xmlSchemaElementDump:
3661 * @elem: an element
3662 * @output: the file output
3663 *
3664 * Dump the element
3665 */
3666static void
3667xmlSchemaElementDump(xmlSchemaElementPtr elem, FILE * output,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003668 const xmlChar * name ATTRIBUTE_UNUSED,
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003669 const xmlChar * namespace ATTRIBUTE_UNUSED,
3670 const xmlChar * context ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +00003671{
3672 if (elem == NULL)
3673 return;
3674
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003675 if (elem->flags & XML_SCHEMAS_ELEM_REF) {
3676 fprintf(output, "Particle: %s", name);
3677 fprintf(output, ", term element: %s", elem->ref);
3678 if (elem->refNs != NULL)
3679 fprintf(output, " ns %s", elem->refNs);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003680 } else {
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003681 fprintf(output, "Element");
3682 if (elem->flags & XML_SCHEMAS_ELEM_GLOBAL)
3683 fprintf(output, " (global)");
3684 fprintf(output, ": %s ", elem->name);
3685 if (namespace != NULL)
3686 fprintf(output, "ns %s", namespace);
3687 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003688 fprintf(output, "\n");
3689 if ((elem->minOccurs != 1) || (elem->maxOccurs != 1)) {
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003690 fprintf(output, " min %d ", elem->minOccurs);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003691 if (elem->maxOccurs >= UNBOUNDED)
3692 fprintf(output, "max: unbounded\n");
3693 else if (elem->maxOccurs != 1)
3694 fprintf(output, "max: %d\n", elem->maxOccurs);
3695 else
3696 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00003697 }
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003698 /*
3699 * Misc other properties.
3700 */
3701 if ((elem->flags & XML_SCHEMAS_ELEM_NILLABLE) ||
3702 (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT) ||
3703 (elem->flags & XML_SCHEMAS_ELEM_FIXED) ||
3704 (elem->flags & XML_SCHEMAS_ELEM_DEFAULT) ||
3705 (elem->id != NULL)) {
3706 fprintf(output, " props: ");
3707 if (elem->flags & XML_SCHEMAS_ELEM_FIXED)
3708 fprintf(output, "[fixed] ");
3709 if (elem->flags & XML_SCHEMAS_ELEM_DEFAULT)
3710 fprintf(output, "[default] ");
3711 if (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT)
3712 fprintf(output, "[abstract] ");
3713 if (elem->flags & XML_SCHEMAS_ELEM_NILLABLE)
3714 fprintf(output, "[nillable] ");
3715 if (elem->id != NULL)
3716 fprintf(output, "[id: '%s'] ", elem->id);
3717 fprintf(output, "\n");
Daniel Veillard4255d502002-04-16 15:50:10 +00003718 }
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003719 /*
3720 * Default/fixed value.
3721 */
Daniel Veillard4255d502002-04-16 15:50:10 +00003722 if (elem->value != NULL)
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003723 fprintf(output, " value: '%s'\n", elem->value);
3724 /*
3725 * Type.
3726 */
3727 if (elem->namedType != NULL) {
3728 fprintf(output, " type: %s ", elem->namedType);
3729 if (elem->namedTypeNs != NULL)
3730 fprintf(output, "ns %s\n", elem->namedTypeNs);
3731 else
3732 fprintf(output, "\n");
3733 }
3734 /*
3735 * Substitution group.
3736 */
3737 if (elem->substGroup != NULL) {
3738 fprintf(output, " substitutionGroup: %s ", elem->substGroup);
3739 if (elem->substGroupNs != NULL)
3740 fprintf(output, "ns %s\n", elem->substGroupNs);
3741 else
3742 fprintf(output, "\n");
3743 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003744}
3745
3746/**
3747 * xmlSchemaAnnotDump:
3748 * @output: the file output
3749 * @annot: a annotation
3750 *
3751 * Dump the annotation
3752 */
3753static void
3754xmlSchemaAnnotDump(FILE * output, xmlSchemaAnnotPtr annot)
3755{
3756 xmlChar *content;
3757
3758 if (annot == NULL)
3759 return;
3760
3761 content = xmlNodeGetContent(annot->content);
3762 if (content != NULL) {
3763 fprintf(output, " Annot: %s\n", content);
3764 xmlFree(content);
3765 } else
3766 fprintf(output, " Annot: empty\n");
3767}
3768
3769/**
3770 * xmlSchemaTypeDump:
3771 * @output: the file output
3772 * @type: a type structure
3773 *
3774 * Dump a SchemaType structure
3775 */
3776static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003777xmlSchemaContentModelDump(xmlSchemaParticlePtr particle, FILE * output, int depth)
3778{
3779 xmlChar *str = NULL;
3780 xmlSchemaTreeItemPtr term;
3781 char shift[100];
3782 int i;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003783
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003784 if (particle == NULL)
3785 return;
3786 for (i = 0;((i < depth) && (i < 25));i++)
3787 shift[2 * i] = shift[2 * i + 1] = ' ';
3788 shift[2 * i] = shift[2 * i + 1] = 0;
3789 fprintf(output, shift);
3790 if (particle->children == NULL) {
3791 fprintf(output, "MISSING particle term\n");
3792 return;
3793 }
3794 term = particle->children;
3795 switch (term->type) {
3796 case XML_SCHEMA_TYPE_ELEMENT:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003797 fprintf(output, "ELEM '%s'", xmlSchemaFormatQName(&str,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003798 ((xmlSchemaElementPtr)term)->targetNamespace,
3799 ((xmlSchemaElementPtr)term)->name));
3800 break;
3801 case XML_SCHEMA_TYPE_SEQUENCE:
3802 fprintf(output, "SEQUENCE");
3803 break;
3804 case XML_SCHEMA_TYPE_CHOICE:
3805 fprintf(output, "CHOICE");
3806 break;
3807 case XML_SCHEMA_TYPE_ALL:
3808 fprintf(output, "ALL");
3809 break;
3810 case XML_SCHEMA_TYPE_ANY:
3811 fprintf(output, "ANY");
3812 break;
3813 default:
3814 fprintf(output, "UNKNOWN\n");
3815 return;
3816 }
3817 if (particle->minOccurs != 1)
3818 fprintf(output, " min: %d", particle->minOccurs);
3819 if (particle->maxOccurs >= UNBOUNDED)
3820 fprintf(output, " max: unbounded");
3821 else if (particle->maxOccurs != 1)
3822 fprintf(output, " max: %d", particle->maxOccurs);
3823 fprintf(output, "\n");
3824 if (((term->type == XML_SCHEMA_TYPE_SEQUENCE) ||
3825 (term->type == XML_SCHEMA_TYPE_CHOICE) ||
3826 (term->type == XML_SCHEMA_TYPE_ALL)) &&
3827 (term->children != NULL)) {
3828 xmlSchemaContentModelDump((xmlSchemaParticlePtr) term->children,
3829 output, depth +1);
3830 }
3831 if (particle->next != NULL)
3832 xmlSchemaContentModelDump((xmlSchemaParticlePtr) particle->next,
3833 output, depth);
3834}
3835/**
3836 * xmlSchemaTypeDump:
3837 * @output: the file output
3838 * @type: a type structure
3839 *
3840 * Dump a SchemaType structure
3841 */
3842static void
Daniel Veillard4255d502002-04-16 15:50:10 +00003843xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output)
3844{
3845 if (type == NULL) {
3846 fprintf(output, "Type: NULL\n");
3847 return;
3848 }
3849 fprintf(output, "Type: ");
3850 if (type->name != NULL)
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003851 fprintf(output, "%s ", type->name);
Daniel Veillard4255d502002-04-16 15:50:10 +00003852 else
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003853 fprintf(output, "no name ");
3854 if (type->targetNamespace != NULL)
3855 fprintf(output, "ns %s ", type->targetNamespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00003856 switch (type->type) {
3857 case XML_SCHEMA_TYPE_BASIC:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003858 fprintf(output, "[basic] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003859 break;
3860 case XML_SCHEMA_TYPE_SIMPLE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003861 fprintf(output, "[simple] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003862 break;
3863 case XML_SCHEMA_TYPE_COMPLEX:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003864 fprintf(output, "[complex] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003865 break;
3866 case XML_SCHEMA_TYPE_SEQUENCE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003867 fprintf(output, "[sequence] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003868 break;
3869 case XML_SCHEMA_TYPE_CHOICE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003870 fprintf(output, "[choice] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003871 break;
3872 case XML_SCHEMA_TYPE_ALL:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003873 fprintf(output, "[all] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003874 break;
3875 case XML_SCHEMA_TYPE_UR:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003876 fprintf(output, "[ur] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003877 break;
3878 case XML_SCHEMA_TYPE_RESTRICTION:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003879 fprintf(output, "[restriction] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003880 break;
3881 case XML_SCHEMA_TYPE_EXTENSION:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003882 fprintf(output, "[extension] ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003883 break;
3884 default:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003885 fprintf(output, "[unknown type %d] ", type->type);
Daniel Veillard4255d502002-04-16 15:50:10 +00003886 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003887 }
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003888 fprintf(output, "content: ");
Daniel Veillard4255d502002-04-16 15:50:10 +00003889 switch (type->contentType) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003890 case XML_SCHEMA_CONTENT_UNKNOWN:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003891 fprintf(output, "[unknown] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003892 break;
3893 case XML_SCHEMA_CONTENT_EMPTY:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003894 fprintf(output, "[empty] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003895 break;
3896 case XML_SCHEMA_CONTENT_ELEMENTS:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003897 fprintf(output, "[element] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003898 break;
3899 case XML_SCHEMA_CONTENT_MIXED:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003900 fprintf(output, "[mixed] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003901 break;
3902 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00003903 /* not used. */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003904 break;
3905 case XML_SCHEMA_CONTENT_BASIC:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003906 fprintf(output, "[basic] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003907 break;
3908 case XML_SCHEMA_CONTENT_SIMPLE:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003909 fprintf(output, "[simple] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003910 break;
3911 case XML_SCHEMA_CONTENT_ANY:
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003912 fprintf(output, "[any] ");
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003913 break;
Daniel Veillard4255d502002-04-16 15:50:10 +00003914 }
3915 fprintf(output, "\n");
Kasimier T. Buchcikf500aec2005-01-19 16:30:24 +00003916 if (type->base != NULL) {
3917 fprintf(output, " base type: %s", type->base);
3918 if (type->baseNs != NULL)
3919 fprintf(output, " ns %s\n", type->baseNs);
3920 else
3921 fprintf(output, "\n");
3922 }
Daniel Veillard4255d502002-04-16 15:50:10 +00003923 if (type->annot != NULL)
3924 xmlSchemaAnnotDump(output, type->annot);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003925#ifdef DUMP_CONTENT_MODEL
3926 if ((type->type == XML_SCHEMA_TYPE_COMPLEX) &&
3927 (type->subtypes != NULL)) {
3928 xmlSchemaContentModelDump((xmlSchemaParticlePtr) type->subtypes,
3929 output, 1);
Daniel Veillard4255d502002-04-16 15:50:10 +00003930 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00003931#endif
Daniel Veillard4255d502002-04-16 15:50:10 +00003932}
3933
3934/**
3935 * xmlSchemaDump:
3936 * @output: the file output
3937 * @schema: a schema structure
3938 *
3939 * Dump a Schema structure.
3940 */
3941void
3942xmlSchemaDump(FILE * output, xmlSchemaPtr schema)
3943{
Daniel Veillardce682bc2004-11-05 17:22:25 +00003944 if (output == NULL)
3945 return;
Daniel Veillard4255d502002-04-16 15:50:10 +00003946 if (schema == NULL) {
3947 fprintf(output, "Schemas: NULL\n");
3948 return;
3949 }
3950 fprintf(output, "Schemas: ");
3951 if (schema->name != NULL)
3952 fprintf(output, "%s, ", schema->name);
3953 else
3954 fprintf(output, "no name, ");
3955 if (schema->targetNamespace != NULL)
Daniel Veillard580ced82003-03-21 21:22:48 +00003956 fprintf(output, "%s", (const char *) schema->targetNamespace);
Daniel Veillard4255d502002-04-16 15:50:10 +00003957 else
3958 fprintf(output, "no target namespace");
3959 fprintf(output, "\n");
3960 if (schema->annot != NULL)
3961 xmlSchemaAnnotDump(output, schema->annot);
3962
3963 xmlHashScan(schema->typeDecl, (xmlHashScanner) xmlSchemaTypeDump,
3964 output);
3965 xmlHashScanFull(schema->elemDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00003966 (xmlHashScannerFull) xmlSchemaElementDump, output);
Daniel Veillard4255d502002-04-16 15:50:10 +00003967}
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003968
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00003969#ifdef DEBUG_IDC
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003970/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003971 * xmlSchemaDebugDumpIDCTable:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003972 * @vctxt: the WXS validation context
3973 *
3974 * Displays the current IDC table for debug purposes.
3975 */
3976static void
3977xmlSchemaDebugDumpIDCTable(FILE * output,
3978 const xmlChar *namespaceName,
3979 const xmlChar *localName,
3980 xmlSchemaPSVIIDCBindingPtr bind)
3981{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003982 xmlChar *str = NULL, *value;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003983 xmlSchemaPSVIIDCNodePtr tab;
3984 xmlSchemaPSVIIDCKeyPtr key;
3985 int i, j, res;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003986
3987 fprintf(output, "IDC: TABLES on %s\n",
3988 xmlSchemaFormatQName(&str, namespaceName, localName));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003989 FREE_AND_NULL(str)
3990
3991 if (bind == NULL)
3992 return;
3993 do {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003994 fprintf(output, "IDC: BINDING %s\n",
3995 xmlSchemaFormatQName(&str, bind->definition->targetNamespace,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003996 bind->definition->name));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00003997 FREE_AND_NULL(str)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00003998 for (i = 0; i < bind->nbNodes; i++) {
3999 tab = bind->nodeTable[i];
4000 fprintf(output, " ( ");
4001 for (j = 0; j < bind->definition->nbFields; j++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004002 key = tab->keys[j];
4003 if ((key != NULL) && (key->val != NULL)) {
4004 res = xmlSchemaGetCanonValue(key->val, &value);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004005 if (res >= 0)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00004006 fprintf(output, "\"%s\" ", value);
4007 else
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004008 fprintf(output, "CANON-VALUE-FAILED ");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004009 if (res == 0)
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004010 FREE_AND_NULL(value)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00004011 } else if (key != NULL)
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004012 fprintf(output, "(no val), ");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00004013 else
4014 fprintf(output, "(key missing), ");
4015 }
4016 fprintf(output, ")\n");
4017 }
4018 bind = bind->next;
4019 } while (bind != NULL);
4020}
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00004021#endif /* DEBUG_IDC */
Daniel Veillarda9cce9c2003-09-29 13:20:24 +00004022#endif /* LIBXML_OUTPUT_ENABLED */
Daniel Veillard4255d502002-04-16 15:50:10 +00004023
4024/************************************************************************
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004025 * *
4026 * Utilities *
4027 * *
4028 ************************************************************************/
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004029
Daniel Veillardc0826a72004-08-10 14:17:33 +00004030/**
4031 * xmlSchemaGetPropNode:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004032 * @node: the element node
Daniel Veillardc0826a72004-08-10 14:17:33 +00004033 * @name: the name of the attribute
4034 *
4035 * Seeks an attribute with a name of @name in
4036 * no namespace.
4037 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004038 * Returns the attribute or NULL if not present.
Daniel Veillardc0826a72004-08-10 14:17:33 +00004039 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +00004040static xmlAttrPtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004041xmlSchemaGetPropNode(xmlNodePtr node, const char *name)
Daniel Veillard01fa6152004-06-29 17:04:39 +00004042{
4043 xmlAttrPtr prop;
4044
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004045 if ((node == NULL) || (name == NULL))
Daniel Veillardc0826a72004-08-10 14:17:33 +00004046 return(NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +00004047 prop = node->properties;
4048 while (prop != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004049 if ((prop->ns == NULL) && xmlStrEqual(prop->name, BAD_CAST name))
Daniel Veillardc0826a72004-08-10 14:17:33 +00004050 return(prop);
4051 prop = prop->next;
4052 }
4053 return (NULL);
4054}
4055
4056/**
4057 * xmlSchemaGetPropNodeNs:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004058 * @node: the element node
Daniel Veillardc0826a72004-08-10 14:17:33 +00004059 * @uri: the uri
4060 * @name: the name of the attribute
4061 *
4062 * Seeks an attribute with a local name of @name and
4063 * a namespace URI of @uri.
4064 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004065 * Returns the attribute or NULL if not present.
Daniel Veillardc0826a72004-08-10 14:17:33 +00004066 */
4067static xmlAttrPtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004068xmlSchemaGetPropNodeNs(xmlNodePtr node, const char *uri, const char *name)
Daniel Veillardc0826a72004-08-10 14:17:33 +00004069{
4070 xmlAttrPtr prop;
4071
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004072 if ((node == NULL) || (name == NULL))
Daniel Veillardc0826a72004-08-10 14:17:33 +00004073 return(NULL);
4074 prop = node->properties;
4075 while (prop != NULL) {
4076 if ((prop->ns != NULL) &&
4077 xmlStrEqual(prop->name, BAD_CAST name) &&
4078 xmlStrEqual(prop->ns->href, BAD_CAST uri))
Daniel Veillard01fa6152004-06-29 17:04:39 +00004079 return(prop);
4080 prop = prop->next;
4081 }
4082 return (NULL);
4083}
4084
4085static const xmlChar *
4086xmlSchemaGetNodeContent(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
4087{
4088 xmlChar *val;
4089 const xmlChar *ret;
4090
4091 val = xmlNodeGetContent(node);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004092 if (val == NULL)
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00004093 val = xmlStrdup((xmlChar *)"");
Daniel Veillard01fa6152004-06-29 17:04:39 +00004094 ret = xmlDictLookup(ctxt->dict, val, -1);
4095 xmlFree(val);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004096 return(ret);
Daniel Veillard01fa6152004-06-29 17:04:39 +00004097}
4098
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004099/**
4100 * xmlSchemaGetProp:
4101 * @ctxt: the parser context
4102 * @node: the node
4103 * @name: the property name
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004104 *
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004105 * Read a attribute value and internalize the string
4106 *
4107 * Returns the string or NULL if not present.
4108 */
4109static const xmlChar *
4110xmlSchemaGetProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
4111 const char *name)
4112{
4113 xmlChar *val;
4114 const xmlChar *ret;
4115
4116 val = xmlGetProp(node, BAD_CAST name);
4117 if (val == NULL)
4118 return(NULL);
4119 ret = xmlDictLookup(ctxt->dict, val, -1);
4120 xmlFree(val);
4121 return(ret);
4122}
4123
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004124/************************************************************************
Daniel Veillard4255d502002-04-16 15:50:10 +00004125 * *
4126 * Parsing functions *
4127 * *
4128 ************************************************************************/
4129
4130/**
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004131 * xmlSchemaGetElem:
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00004132 * @schema: the schema context
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004133 * @name: the element name
4134 * @ns: the element namespace
4135 *
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00004136 * Lookup a global element declaration in the schema.
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004137 *
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00004138 * Returns the element declaration or NULL if not found.
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004139 */
4140static xmlSchemaElementPtr
4141xmlSchemaGetElem(xmlSchemaPtr schema, const xmlChar * name,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00004142 const xmlChar * nsName)
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004143{
4144 xmlSchemaElementPtr ret;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004145
4146 if ((name == NULL) || (schema == NULL))
4147 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004148
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00004149 ret = xmlHashLookup2(schema->elemDecl, name, nsName);
Daniel Veillardf2a12832003-11-24 13:04:35 +00004150 if ((ret != NULL) &&
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00004151 (ret->flags & XML_SCHEMAS_ELEM_GLOBAL)) {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004152 return (ret);
Daniel Veillard3646d642004-06-02 19:19:14 +00004153 } else
4154 ret = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004155
William M. Brack2f2a6632004-08-20 23:09:47 +00004156 /*
4157 * Removed since imported components will be hold by the main schema only.
4158 *
Daniel Veillard3646d642004-06-02 19:19:14 +00004159 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00004160 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00004161 else
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004162 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00004163 if (import != NULL) {
Daniel Veillardf2a12832003-11-24 13:04:35 +00004164 ret = xmlSchemaGetElem(import->schema, name, namespace, level + 1);
Daniel Veillard3646d642004-06-02 19:19:14 +00004165 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ELEM_GLOBAL)) {
4166 return (ret);
4167 } else
4168 ret = NULL;
4169 }
William M. Brack2f2a6632004-08-20 23:09:47 +00004170 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004171#ifdef DEBUG
4172 if (ret == NULL) {
4173 if (namespace == NULL)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004174 fprintf(stderr, "Unable to lookup element decl. %s", name);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004175 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004176 fprintf(stderr, "Unable to lookup element decl. %s:%s", name,
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004177 namespace);
4178 }
4179#endif
4180 return (ret);
4181}
4182
4183/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004184 * xmlSchemaGetType:
4185 * @schema: the schemas context
4186 * @name: the type name
4187 * @ns: the type namespace
4188 *
4189 * Lookup a type in the schemas or the predefined types
4190 *
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004191 * Returns the group definition or NULL if not found.
Daniel Veillard4255d502002-04-16 15:50:10 +00004192 */
4193static xmlSchemaTypePtr
4194xmlSchemaGetType(xmlSchemaPtr schema, const xmlChar * name,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00004195 const xmlChar * nsName)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004196{
Daniel Veillard4255d502002-04-16 15:50:10 +00004197 xmlSchemaTypePtr ret;
4198
4199 if (name == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004200 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004201 if (schema != NULL) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00004202 ret = xmlHashLookup2(schema->typeDecl, name, nsName);
4203 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL)) {
4204 if (ret->redef != NULL) {
4205 /*
4206 * Return the last redefinition.
4207 */
4208 return(ret->redef);
4209 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004210 return (ret);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00004211 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004212 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00004213 ret = xmlSchemaGetPredefinedType(name, nsName);
Daniel Veillard1d913862003-11-21 00:28:39 +00004214 if (ret != NULL)
4215 return (ret);
William M. Brack2f2a6632004-08-20 23:09:47 +00004216 /*
4217 * Removed, since the imported components will be grafted on the
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004218 * main schema only.
Daniel Veillard3646d642004-06-02 19:19:14 +00004219 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00004220 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00004221 else
Daniel Veillard1d913862003-11-21 00:28:39 +00004222 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00004223 if (import != NULL) {
Daniel Veillard1d913862003-11-21 00:28:39 +00004224 ret = xmlSchemaGetType(import->schema, name, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00004225 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL)) {
4226 return (ret);
4227 } else
4228 ret = NULL;
4229 }
William M. Brack2f2a6632004-08-20 23:09:47 +00004230 */
Daniel Veillard4255d502002-04-16 15:50:10 +00004231#ifdef DEBUG
4232 if (ret == NULL) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00004233 if (nsName == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004234 fprintf(stderr, "Unable to lookup type %s", name);
4235 else
4236 fprintf(stderr, "Unable to lookup type %s:%s", name,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00004237 nsName);
Daniel Veillard4255d502002-04-16 15:50:10 +00004238 }
4239#endif
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00004240 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004241}
4242
Daniel Veillard3646d642004-06-02 19:19:14 +00004243/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004244 * xmlSchemaGetAttributeDecl:
4245 * @schema: the context of the schema
Daniel Veillard3646d642004-06-02 19:19:14 +00004246 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004247 * @ns: the target namespace of the attribute
Daniel Veillard3646d642004-06-02 19:19:14 +00004248 *
4249 * Lookup a an attribute in the schema or imported schemas
4250 *
4251 * Returns the attribute declaration or NULL if not found.
4252 */
4253static xmlSchemaAttributePtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004254xmlSchemaGetAttributeDecl(xmlSchemaPtr schema, const xmlChar * name,
Daniel Veillard3646d642004-06-02 19:19:14 +00004255 const xmlChar * namespace)
4256{
4257 xmlSchemaAttributePtr ret;
Daniel Veillard3646d642004-06-02 19:19:14 +00004258
4259 if ((name == NULL) || (schema == NULL))
4260 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004261
4262
Daniel Veillard3646d642004-06-02 19:19:14 +00004263 ret = xmlHashLookup2(schema->attrDecl, name, namespace);
4264 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTR_GLOBAL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004265 return (ret);
Daniel Veillard3646d642004-06-02 19:19:14 +00004266 else
4267 ret = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00004268 /*
4269 * Removed, since imported components will be hold by the main schema only.
4270 *
Daniel Veillard3646d642004-06-02 19:19:14 +00004271 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00004272 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00004273 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004274 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00004275 if (import != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004276 ret = xmlSchemaGetAttributeDecl(import->schema, name, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00004277 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTR_GLOBAL)) {
4278 return (ret);
4279 } else
4280 ret = NULL;
4281 }
William M. Brack2f2a6632004-08-20 23:09:47 +00004282 */
Daniel Veillard3646d642004-06-02 19:19:14 +00004283#ifdef DEBUG
4284 if (ret == NULL) {
4285 if (namespace == NULL)
4286 fprintf(stderr, "Unable to lookup attribute %s", name);
4287 else
4288 fprintf(stderr, "Unable to lookup attribute %s:%s", name,
4289 namespace);
4290 }
4291#endif
4292 return (ret);
4293}
4294
4295/**
4296 * xmlSchemaGetAttributeGroup:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004297 * @schema: the context of the schema
Daniel Veillard3646d642004-06-02 19:19:14 +00004298 * @name: the name of the attribute group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004299 * @ns: the target namespace of the attribute group
Daniel Veillard3646d642004-06-02 19:19:14 +00004300 *
4301 * Lookup a an attribute group in the schema or imported schemas
4302 *
4303 * Returns the attribute group definition or NULL if not found.
4304 */
4305static xmlSchemaAttributeGroupPtr
4306xmlSchemaGetAttributeGroup(xmlSchemaPtr schema, const xmlChar * name,
4307 const xmlChar * namespace)
4308{
4309 xmlSchemaAttributeGroupPtr ret;
Daniel Veillard3646d642004-06-02 19:19:14 +00004310
4311 if ((name == NULL) || (schema == NULL))
4312 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004313
4314
Daniel Veillard3646d642004-06-02 19:19:14 +00004315 ret = xmlHashLookup2(schema->attrgrpDecl, name, namespace);
4316 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004317 return (ret);
Daniel Veillard3646d642004-06-02 19:19:14 +00004318 else
4319 ret = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00004320 /*
4321 * Removed since imported components will be hold by the main schema only.
4322 *
Daniel Veillard3646d642004-06-02 19:19:14 +00004323 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00004324 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00004325 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004326 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00004327 if (import != NULL) {
4328 ret = xmlSchemaGetAttributeGroup(import->schema, name, namespace);
4329 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL))
4330 return (ret);
4331 else
4332 ret = NULL;
4333 }
William M. Brack2f2a6632004-08-20 23:09:47 +00004334 */
Daniel Veillard3646d642004-06-02 19:19:14 +00004335#ifdef DEBUG
4336 if (ret == NULL) {
4337 if (namespace == NULL)
4338 fprintf(stderr, "Unable to lookup attribute group %s", name);
4339 else
4340 fprintf(stderr, "Unable to lookup attribute group %s:%s", name,
4341 namespace);
4342 }
4343#endif
4344 return (ret);
4345}
4346
4347/**
4348 * xmlSchemaGetGroup:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004349 * @schema: the context of the schema
Daniel Veillard3646d642004-06-02 19:19:14 +00004350 * @name: the name of the group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004351 * @ns: the target namespace of the group
Daniel Veillard3646d642004-06-02 19:19:14 +00004352 *
4353 * Lookup a group in the schema or imported schemas
4354 *
4355 * Returns the group definition or NULL if not found.
4356 */
4357static xmlSchemaTypePtr
4358xmlSchemaGetGroup(xmlSchemaPtr schema, const xmlChar * name,
4359 const xmlChar * namespace)
4360{
4361 xmlSchemaTypePtr ret;
Daniel Veillard3646d642004-06-02 19:19:14 +00004362
4363 if ((name == NULL) || (schema == NULL))
4364 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004365
Daniel Veillard3646d642004-06-02 19:19:14 +00004366 ret = xmlHashLookup2(schema->groupDecl, name, namespace);
William M. Brack2f2a6632004-08-20 23:09:47 +00004367 /*
4368 * Removed since imported components will be hold by the main schema only.
4369 *
Daniel Veillard3646d642004-06-02 19:19:14 +00004370 if (namespace == NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00004371 import = xmlHashLookup(schema->schemasImports, XML_SCHEMAS_NO_NAMESPACE);
Daniel Veillard3646d642004-06-02 19:19:14 +00004372 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004373 import = xmlHashLookup(schema->schemasImports, namespace);
Daniel Veillard3646d642004-06-02 19:19:14 +00004374 if (import != NULL) {
4375 ret = xmlSchemaGetGroup(import->schema, name, namespace);
4376 if ((ret != NULL) && (ret->flags & XML_SCHEMAS_TYPE_GLOBAL))
4377 return (ret);
4378 else
4379 ret = NULL;
4380 }
William M. Brack2f2a6632004-08-20 23:09:47 +00004381 */
Daniel Veillard3646d642004-06-02 19:19:14 +00004382#ifdef DEBUG
4383 if (ret == NULL) {
4384 if (namespace == NULL)
4385 fprintf(stderr, "Unable to lookup group %s", name);
4386 else
4387 fprintf(stderr, "Unable to lookup group %s:%s", name,
4388 namespace);
4389 }
4390#endif
4391 return (ret);
4392}
4393
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004394/**
4395 * xmlSchemaGetNamedComponent:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004396 * @schema: the schema
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004397 * @name: the name of the group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004398 * @ns: the target namespace of the group
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004399 *
4400 * Lookup a group in the schema or imported schemas
4401 *
4402 * Returns the group definition or NULL if not found.
4403 */
4404static xmlSchemaTreeItemPtr
4405xmlSchemaGetNamedComponent(xmlSchemaPtr schema,
4406 xmlSchemaTypeType itemType,
4407 const xmlChar *name,
4408 const xmlChar *targetNs)
4409{
4410 switch (itemType) {
4411 case XML_SCHEMA_TYPE_GROUP:
4412 return ((xmlSchemaTreeItemPtr) xmlSchemaGetGroup(schema,
4413 name, targetNs));
4414 case XML_SCHEMA_TYPE_ELEMENT:
4415 return ((xmlSchemaTreeItemPtr) xmlSchemaGetElem(schema,
4416 name, targetNs));
4417 default:
4418 return (NULL);
4419 }
4420}
4421
Daniel Veillard4255d502002-04-16 15:50:10 +00004422/************************************************************************
4423 * *
4424 * Parsing functions *
4425 * *
4426 ************************************************************************/
4427
4428#define IS_BLANK_NODE(n) \
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004429 (((n)->type == XML_TEXT_NODE) && (xmlSchemaIsBlank((n)->content, -1)))
Daniel Veillard4255d502002-04-16 15:50:10 +00004430
4431/**
4432 * xmlSchemaIsBlank:
4433 * @str: a string
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004434 * @len: the length of the string or -1
Daniel Veillard4255d502002-04-16 15:50:10 +00004435 *
4436 * Check if a string is ignorable
4437 *
4438 * Returns 1 if the string is NULL or made of blanks chars, 0 otherwise
4439 */
4440static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004441xmlSchemaIsBlank(xmlChar * str, int len)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004442{
Daniel Veillard4255d502002-04-16 15:50:10 +00004443 if (str == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004444 return (1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004445 if (len < 0) {
4446 while (*str != 0) {
4447 if (!(IS_BLANK_CH(*str)))
4448 return (0);
4449 str++;
4450 }
4451 } else while ((*str != 0) && (len != 0)) {
4452 if (!(IS_BLANK_CH(*str)))
4453 return (0);
4454 str++;
4455 len--;
Daniel Veillard4255d502002-04-16 15:50:10 +00004456 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004457
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004458 return (1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004459}
4460
4461/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004462 * xmlSchemaAddAssembledItem:
4463 * @ctxt: a schema parser context
4464 * @schema: the schema being built
4465 * @item: the item
4466 *
4467 * Add a item to the schema's list of current items.
4468 * This is used if the schema was already constructed and
4469 * new schemata need to be added to it.
4470 * *WARNING* this interface is highly subject to change.
4471 *
4472 * Returns 0 if suceeds and -1 if an internal error occurs.
4473 */
4474static int
4475xmlSchemaAddAssembledItem(xmlSchemaParserCtxtPtr ctxt,
4476 xmlSchemaTypePtr item)
4477{
4478 static int growSize = 100;
4479 xmlSchemaAssemblePtr ass;
4480
4481 ass = ctxt->assemble;
4482 if (ass->sizeItems < 0) {
4483 /* If disabled. */
4484 return (0);
4485 }
4486 if (ass->sizeItems <= 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00004487 ass->items = (void **) xmlMalloc(growSize * sizeof(xmlSchemaTypePtr));
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004488 if (ass->items == NULL) {
4489 xmlSchemaPErrMemory(ctxt,
4490 "allocating new item buffer", NULL);
4491 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004492 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004493 ass->sizeItems = growSize;
4494 } else if (ass->sizeItems <= ass->nbItems) {
4495 ass->sizeItems *= 2;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004496 ass->items = (void **) xmlRealloc(ass->items,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004497 ass->sizeItems * sizeof(xmlSchemaTypePtr));
4498 if (ass->items == NULL) {
4499 xmlSchemaPErrMemory(ctxt,
4500 "growing item buffer", NULL);
4501 ass->sizeItems = 0;
4502 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004503 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004504 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00004505 /* ass->items[ass->nbItems++] = (void *) item; */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004506 ((xmlSchemaTypePtr *) ass->items)[ass->nbItems++] = (void *) item;
4507 return (0);
4508}
4509
4510/**
Daniel Veillard4255d502002-04-16 15:50:10 +00004511 * xmlSchemaAddNotation:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004512 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00004513 * @schema: the schema being built
4514 * @name: the item name
4515 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00004516 * Add an XML schema annotation declaration
Daniel Veillard4255d502002-04-16 15:50:10 +00004517 * *WARNING* this interface is highly subject to change
4518 *
4519 * Returns the new struture or NULL in case of error
4520 */
4521static xmlSchemaNotationPtr
4522xmlSchemaAddNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00004523 const xmlChar *name)
Daniel Veillard4255d502002-04-16 15:50:10 +00004524{
4525 xmlSchemaNotationPtr ret = NULL;
4526 int val;
4527
4528 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
4529 return (NULL);
4530
4531 if (schema->notaDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00004532 schema->notaDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00004533 if (schema->notaDecl == NULL)
4534 return (NULL);
4535
4536 ret = (xmlSchemaNotationPtr) xmlMalloc(sizeof(xmlSchemaNotation));
4537 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004538 xmlSchemaPErrMemory(ctxt, "add annotation", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004539 return (NULL);
4540 }
4541 memset(ret, 0, sizeof(xmlSchemaNotation));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004542 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004543 val = xmlHashAddEntry2(schema->notaDecl, name, schema->targetNamespace,
4544 ret);
4545 if (val != 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00004546 /*
4547 * TODO: This should never happen, since a unique name will be computed.
4548 * If it fails, then an other internal error must have occured.
4549 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004550 xmlSchemaPErr(ctxt, (xmlNodePtr) ctxt->doc,
4551 XML_SCHEMAP_REDEFINED_NOTATION,
Daniel Veillardc0826a72004-08-10 14:17:33 +00004552 "Annotation declaration '%s' is already declared.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004553 name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004554 xmlFree(ret);
4555 return (NULL);
4556 }
4557 return (ret);
4558}
4559
4560
4561/**
4562 * xmlSchemaAddAttribute:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004563 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00004564 * @schema: the schema being built
4565 * @name: the item name
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004566 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00004567 *
4568 * Add an XML schema Attrribute declaration
4569 * *WARNING* this interface is highly subject to change
4570 *
4571 * Returns the new struture or NULL in case of error
4572 */
4573static xmlSchemaAttributePtr
4574xmlSchemaAddAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00004575 const xmlChar * name, const xmlChar * namespace,
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004576 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00004577{
4578 xmlSchemaAttributePtr ret = NULL;
4579 int val;
4580
4581 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
4582 return (NULL);
4583
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004584#ifdef DEBUG
4585 fprintf(stderr, "Adding attribute %s\n", name);
4586 if (namespace != NULL)
4587 fprintf(stderr, " target namespace %s\n", namespace);
4588#endif
4589
Daniel Veillard4255d502002-04-16 15:50:10 +00004590 if (schema->attrDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00004591 schema->attrDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00004592 if (schema->attrDecl == NULL)
4593 return (NULL);
4594
4595 ret = (xmlSchemaAttributePtr) xmlMalloc(sizeof(xmlSchemaAttribute));
4596 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004597 xmlSchemaPErrMemory(ctxt, "allocating attribute", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004598 return (NULL);
4599 }
4600 memset(ret, 0, sizeof(xmlSchemaAttribute));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004601 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00004602 ret->targetNamespace = namespace;
Daniel Veillard4255d502002-04-16 15:50:10 +00004603 val = xmlHashAddEntry3(schema->attrDecl, name,
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00004604 namespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004605 if (val != 0) {
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004606 if (topLevel) {
4607 xmlSchemaPCustomErr(ctxt,
4608 XML_SCHEMAP_REDEFINED_ATTR,
4609 NULL, NULL, node,
4610 "A global attribute declaration with the name '%s' does "
4611 "already exist", name);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004612 xmlFree(ret);
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004613 return (NULL);
4614 } else {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004615 char buf[30];
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004616 /*
4617 * Using the ctxt->container for xmlHashAddEntry3 is ambigious
4618 * in the scenario:
4619 * 1. multiple top-level complex types have different target
4620 * namespaces but have the SAME NAME; this can happen if
4621 * schemata are imported
4622 * 2. those complex types contain attributes with an equal name
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004623 * 3. those attributes are in no namespace
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004624 * We will compute a new context string.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004625 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004626 snprintf(buf, 29, "#aCont%d", ctxt->counter++ + 1);
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004627 val = xmlHashAddEntry3(schema->attrDecl, name,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00004628 namespace, xmlDictLookup(ctxt->dict, BAD_CAST buf, -1), ret);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004629
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004630 if (val != 0) {
4631 xmlSchemaPCustomErr(ctxt,
4632 XML_SCHEMAP_INTERNAL,
4633 NULL, NULL, node,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004634 "Internal error: xmlSchemaAddAttribute, "
4635 "a dublicate attribute declaration with the name '%s' "
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004636 "could not be added to the hash.", name);
4637 xmlFree(ret);
4638 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004639 }
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004640 }
Daniel Veillard4255d502002-04-16 15:50:10 +00004641 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004642 if (ctxt->assemble != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004643 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004644 return (ret);
4645}
4646
4647/**
4648 * xmlSchemaAddAttributeGroup:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004649 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00004650 * @schema: the schema being built
4651 * @name: the item name
4652 *
4653 * Add an XML schema Attrribute Group declaration
4654 *
4655 * Returns the new struture or NULL in case of error
4656 */
4657static xmlSchemaAttributeGroupPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004658xmlSchemaAddAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00004659 xmlSchemaPtr schema, const xmlChar * name,
4660 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00004661{
4662 xmlSchemaAttributeGroupPtr ret = NULL;
4663 int val;
4664
4665 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
4666 return (NULL);
4667
4668 if (schema->attrgrpDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00004669 schema->attrgrpDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00004670 if (schema->attrgrpDecl == NULL)
4671 return (NULL);
4672
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004673 ret =
4674 (xmlSchemaAttributeGroupPtr)
4675 xmlMalloc(sizeof(xmlSchemaAttributeGroup));
Daniel Veillard4255d502002-04-16 15:50:10 +00004676 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004677 xmlSchemaPErrMemory(ctxt, "allocating attribute group", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004678 return (NULL);
4679 }
4680 memset(ret, 0, sizeof(xmlSchemaAttributeGroup));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004681 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004682 val = xmlHashAddEntry3(schema->attrgrpDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004683 schema->targetNamespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004684 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00004685 xmlSchemaPCustomErr(ctxt,
4686 XML_SCHEMAP_REDEFINED_ATTRGROUP,
4687 NULL, NULL, node,
4688 "A global attribute group definition with the name '%s' does already exist", name);
Daniel Veillard4255d502002-04-16 15:50:10 +00004689 xmlFree(ret);
4690 return (NULL);
4691 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004692 if (ctxt->assemble != NULL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004693 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004694 return (ret);
4695}
4696
4697/**
4698 * xmlSchemaAddElement:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004699 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00004700 * @schema: the schema being built
4701 * @name: the type name
4702 * @namespace: the type namespace
4703 *
4704 * Add an XML schema Element declaration
4705 * *WARNING* this interface is highly subject to change
4706 *
4707 * Returns the new struture or NULL in case of error
4708 */
4709static xmlSchemaElementPtr
4710xmlSchemaAddElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00004711 const xmlChar * name, const xmlChar * namespace,
4712 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00004713{
4714 xmlSchemaElementPtr ret = NULL;
4715 int val;
4716
4717 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
4718 return (NULL);
4719
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004720#ifdef DEBUG
4721 fprintf(stderr, "Adding element %s\n", name);
4722 if (namespace != NULL)
4723 fprintf(stderr, " target namespace %s\n", namespace);
4724#endif
4725
Daniel Veillard4255d502002-04-16 15:50:10 +00004726 if (schema->elemDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00004727 schema->elemDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00004728 if (schema->elemDecl == NULL)
4729 return (NULL);
4730
4731 ret = (xmlSchemaElementPtr) xmlMalloc(sizeof(xmlSchemaElement));
4732 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004733 xmlSchemaPErrMemory(ctxt, "allocating element", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004734 return (NULL);
4735 }
4736 memset(ret, 0, sizeof(xmlSchemaElement));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004737 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00004738 val = xmlHashAddEntry3(schema->elemDecl, name,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004739 namespace, ctxt->container, ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004740 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00004741 if (topLevel) {
4742 xmlSchemaPCustomErr(ctxt,
4743 XML_SCHEMAP_REDEFINED_ELEMENT,
4744 NULL, NULL, node,
4745 "A global element declaration with the name '%s' does "
4746 "already exist", name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004747 xmlFree(ret);
4748 return (NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +00004749 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004750 char buf[30];
William M. Brack2f2a6632004-08-20 23:09:47 +00004751
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00004752 snprintf(buf, 29, "#eCont%d", ctxt->counter++ + 1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004753 val = xmlHashAddEntry3(schema->elemDecl, name,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00004754 namespace, (xmlChar *) buf, ret);
William M. Brack2f2a6632004-08-20 23:09:47 +00004755 if (val != 0) {
4756 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00004757 XML_SCHEMAP_INTERNAL,
William M. Brack2f2a6632004-08-20 23:09:47 +00004758 NULL, NULL, node,
4759 "Internal error: xmlSchemaAddElement, "
4760 "a dublicate element declaration with the name '%s' "
4761 "could not be added to the hash.", name);
4762 xmlFree(ret);
4763 return (NULL);
4764 }
4765 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004766
Daniel Veillard4255d502002-04-16 15:50:10 +00004767 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004768 if (ctxt->assemble != NULL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004769 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00004770 return (ret);
4771}
4772
4773/**
4774 * xmlSchemaAddType:
Daniel Veillard01fa6152004-06-29 17:04:39 +00004775 * @ctxt: a schema parser context
Daniel Veillard4255d502002-04-16 15:50:10 +00004776 * @schema: the schema being built
4777 * @name: the item name
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004778 * @namespace: the namespace
Daniel Veillard4255d502002-04-16 15:50:10 +00004779 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00004780 * Add an XML schema item
Daniel Veillard4255d502002-04-16 15:50:10 +00004781 * *WARNING* this interface is highly subject to change
4782 *
4783 * Returns the new struture or NULL in case of error
4784 */
4785static xmlSchemaTypePtr
4786xmlSchemaAddType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00004787 const xmlChar * name, const xmlChar * nsName,
4788 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00004789{
4790 xmlSchemaTypePtr ret = NULL;
4791 int val;
4792
4793 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
4794 return (NULL);
4795
4796 if (schema->typeDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00004797 schema->typeDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +00004798 if (schema->typeDecl == NULL)
4799 return (NULL);
4800
4801 ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
4802 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00004803 xmlSchemaPErrMemory(ctxt, "allocating type", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00004804 return (NULL);
4805 }
4806 memset(ret, 0, sizeof(xmlSchemaType));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00004807 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00004808 ret->redef = NULL;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00004809 val = xmlHashAddEntry2(schema->typeDecl, name, nsName, ret);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004810 if (val != 0) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00004811 if (! ctxt->isRedefine) {
4812 xmlChar *str = NULL;
4813 if (topLevel) {
4814 xmlSchemaPCustomErr(ctxt,
4815 XML_SCHEMAP_REDEFINED_TYPE,
4816 NULL, NULL, node,
4817 "A global type definition with the name '%s' does "
4818 "already exist",
4819 xmlSchemaFormatQName(&str, nsName, name));
4820 } else {
4821 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
4822 NULL, NULL, node, "Internal error: xmlSchemaAddType, "
4823 "local type '%s' has a duplicate",
4824 xmlSchemaFormatQName(&str, nsName, name));
4825 }
Daniel Veillardb0f397e2003-12-23 23:30:53 +00004826 xmlFree(ret);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00004827 FREE_AND_NULL(str);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00004828 return (NULL);
4829 } else {
4830 xmlSchemaTypePtr prev;
4831
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00004832 /*
4833 * REDEFINE: Add a redefinition.
4834 */
4835 TODO
4836 prev = xmlHashLookup2(schema->typeDecl, name, nsName);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00004837 if (prev == NULL) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00004838 PERROR_INT2("xmlSchemaAddType", "hash list didn't return "
4839 "a type component, but should");
Daniel Veillardb0f397e2003-12-23 23:30:53 +00004840 xmlFree(ret);
4841 return (NULL);
4842 }
4843 ret->redef = prev->redef;
4844 prev->redef = ret;
4845 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004846 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004847 ret->node = node;
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004848 ret->minOccurs = 1;
4849 ret->maxOccurs = 1;
Daniel Veillard3646d642004-06-02 19:19:14 +00004850 ret->attributeUses = NULL;
4851 ret->attributeWildcard = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004852 if (ctxt->assemble != NULL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00004853 xmlSchemaAddAssembledItem(ctxt,ret);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004854 return (ret);
4855}
4856
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004857static xmlSchemaQNameRefPtr
4858xmlSchemaNewQNameRef(xmlSchemaPtr schema,
4859 xmlSchemaTypeType refType,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004860 const xmlChar *refName,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004861 const xmlChar *refNs)
4862{
4863 xmlSchemaQNameRefPtr ret;
4864
4865 ret = (xmlSchemaQNameRefPtr)
4866 xmlMalloc(sizeof(xmlSchemaQNameRef));
4867 if (ret == NULL) {
4868 xmlSchemaPErrMemory(NULL, "allocating QName reference item",
4869 NULL);
4870 return (NULL);
4871 }
4872 ret->type = XML_SCHEMA_EXTRA_QNAMEREF;
4873 ret->name = refName;
4874 ret->targetNamespace = refNs;
4875 ret->item = NULL;
4876 ret->itemType = refType;
4877 /*
4878 * Store the reference item in the schema.
4879 */
4880 xmlSchemaAddVolatile(schema, (xmlSchemaBasicItemPtr) ret);
4881 return (ret);
4882}
4883
4884/**
4885 * xmlSchemaAddModelGroup:
4886 * @ctxt: a schema parser context
4887 * @schema: the schema being built
4888 * @type: the "compositor" type of the model group
4889 * @container: the internal component name
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004890 * @node: the node in the schema doc
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004891 *
4892 * Adds a schema model group
4893 * *WARNING* this interface is highly subject to change
4894 *
4895 * Returns the new struture or NULL in case of error
4896 */
4897static xmlSchemaModelGroupPtr
4898xmlSchemaAddModelGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
4899 xmlSchemaTypeType type, const xmlChar **container,
4900 xmlNodePtr node)
4901{
4902 xmlSchemaModelGroupPtr ret = NULL;
4903 xmlChar buf[30];
4904
4905 if ((ctxt == NULL) || (schema == NULL))
4906 return (NULL);
4907
4908#ifdef DEBUG
4909 fprintf(stderr, "Adding model group component\n");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004910#endif
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004911 ret = (xmlSchemaModelGroupPtr)
4912 xmlMalloc(sizeof(xmlSchemaModelGroup));
4913 if (ret == NULL) {
4914 xmlSchemaPErrMemory(ctxt, "allocating model group component",
4915 NULL);
4916 return (NULL);
4917 }
4918 ret->type = type;
4919 ret->annot = NULL;
4920 ret->node = node;
4921 ret->children = NULL;
4922 ret->next = NULL;
4923 if (type == XML_SCHEMA_TYPE_SEQUENCE) {
4924 if (container != NULL)
4925 snprintf((char *) buf, 29, "#seq%d", ctxt->counter++ + 1);
4926 } else if (type == XML_SCHEMA_TYPE_CHOICE) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00004927 if (container != NULL)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00004928 snprintf((char *) buf, 29, "#cho%d", ctxt->counter++ + 1);
4929 } else {
4930 if (container != NULL)
4931 snprintf((char *) buf, 29, "#all%d", ctxt->counter++ + 1);
4932 }
4933 if (container != NULL)
4934 *container = xmlDictLookup(ctxt->dict, BAD_CAST buf, -1);
4935 /*
4936 * Add to volatile items.
4937 * TODO: this should be changed someday.
4938 */
4939 if (xmlSchemaAddVolatile(schema, (xmlSchemaBasicItemPtr) ret) != 0) {
4940 xmlFree(ret);
4941 return (NULL);
4942 }
4943 return (ret);
4944}
4945
4946
4947/**
4948 * xmlSchemaAddParticle:
4949 * @ctxt: a schema parser context
4950 * @schema: the schema being built
4951 * @node: the corresponding node in the schema doc
4952 * @min: the minOccurs
4953 * @max: the maxOccurs
4954 *
4955 * Adds an XML schema particle component.
4956 * *WARNING* this interface is highly subject to change
4957 *
4958 * Returns the new struture or NULL in case of error
4959 */
4960static xmlSchemaParticlePtr
4961xmlSchemaAddParticle(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
4962 xmlNodePtr node, int min, int max)
4963{
4964 xmlSchemaParticlePtr ret = NULL;
4965 if ((ctxt == NULL) || (schema == NULL))
4966 return (NULL);
4967
4968#ifdef DEBUG
4969 fprintf(stderr, "Adding particle component\n");
4970#endif
4971 ret = (xmlSchemaParticlePtr)
4972 xmlMalloc(sizeof(xmlSchemaParticle));
4973 if (ret == NULL) {
4974 xmlSchemaPErrMemory(ctxt, "allocating particle component",
4975 NULL);
4976 return (NULL);
4977 }
4978 ret->type = XML_SCHEMA_TYPE_PARTICLE;
4979 ret->annot = NULL;
4980 ret->node = node;
4981 ret->minOccurs = min;
4982 ret->maxOccurs = max;
4983 ret->next = NULL;
4984 ret->children = NULL;
4985
4986 if (xmlSchemaAddVolatile(schema, (xmlSchemaBasicItemPtr) ret) != 0) {
4987 xmlFree(ret);
4988 return (NULL);
4989 }
4990 return (ret);
4991}
4992
Daniel Veillarda84c0b32003-06-02 16:58:46 +00004993/**
4994 * xmlSchemaAddGroup:
4995 * @ctxt: a schema validation context
4996 * @schema: the schema being built
4997 * @name: the group name
4998 *
4999 * Add an XML schema Group definition
5000 *
5001 * Returns the new struture or NULL in case of error
5002 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005003static xmlSchemaModelGroupDefPtr
Daniel Veillarda84c0b32003-06-02 16:58:46 +00005004xmlSchemaAddGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00005005 const xmlChar *name, const xmlChar *namespaceName,
5006 xmlNodePtr node)
Daniel Veillarda84c0b32003-06-02 16:58:46 +00005007{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005008 xmlSchemaModelGroupDefPtr ret = NULL;
Daniel Veillarda84c0b32003-06-02 16:58:46 +00005009 int val;
5010
5011 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
5012 return (NULL);
5013
5014 if (schema->groupDecl == NULL)
Daniel Veillardb9e2f262005-01-23 23:48:34 +00005015 schema->groupDecl = xmlHashCreateDict(10, ctxt->dict);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00005016 if (schema->groupDecl == NULL)
5017 return (NULL);
5018
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005019 ret = (xmlSchemaModelGroupDefPtr) xmlMalloc(sizeof(xmlSchemaModelGroupDef));
Daniel Veillarda84c0b32003-06-02 16:58:46 +00005020 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005021 xmlSchemaPErrMemory(ctxt, "adding group", NULL);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00005022 return (NULL);
5023 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005024 memset(ret, 0, sizeof(xmlSchemaModelGroupDef));
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005025 ret->name = xmlDictLookup(ctxt->dict, name, -1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005026 ret->type = XML_SCHEMA_TYPE_GROUP;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005027 ret->node = node;
5028 ret->targetNamespace = namespaceName;
5029 val = xmlHashAddEntry2(schema->groupDecl, ret->name, namespaceName, ret);
Daniel Veillarda84c0b32003-06-02 16:58:46 +00005030 if (val != 0) {
William M. Brack2f2a6632004-08-20 23:09:47 +00005031 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00005032 XML_SCHEMAP_REDEFINED_GROUP,
5033 NULL, NULL, node,
5034 "A global model group definition with the name '%s' does already "
5035 "exist", name);
Daniel Veillard4255d502002-04-16 15:50:10 +00005036 xmlFree(ret);
5037 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005038 }
5039 if (ctxt->assemble != NULL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005040 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005041 return (ret);
5042}
5043
Daniel Veillard3646d642004-06-02 19:19:14 +00005044/**
5045 * xmlSchemaNewWildcardNs:
5046 * @ctxt: a schema validation context
5047 *
5048 * Creates a new wildcard namespace constraint.
5049 *
5050 * Returns the new struture or NULL in case of error
5051 */
5052static xmlSchemaWildcardNsPtr
5053xmlSchemaNewWildcardNsConstraint(xmlSchemaParserCtxtPtr ctxt)
5054{
5055 xmlSchemaWildcardNsPtr ret;
5056
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005057 ret = (xmlSchemaWildcardNsPtr)
Daniel Veillard3646d642004-06-02 19:19:14 +00005058 xmlMalloc(sizeof(xmlSchemaWildcardNs));
5059 if (ret == NULL) {
5060 xmlSchemaPErrMemory(ctxt, "creating wildcard namespace constraint", NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005061 return (NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +00005062 }
5063 ret->value = NULL;
5064 ret->next = NULL;
5065 return (ret);
5066}
5067
5068/**
5069 * xmlSchemaAddWildcard:
5070 * @ctxt: a schema validation context
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005071 * @schema: a schema
5072 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005073 * Adds a wildcard.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005074 * It corresponds to a xsd:anyAttribute and xsd:any.
Daniel Veillard3646d642004-06-02 19:19:14 +00005075 *
5076 * Returns the new struture or NULL in case of error
5077 */
5078static xmlSchemaWildcardPtr
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005079xmlSchemaAddWildcard(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5080 xmlSchemaTypeType type, xmlNodePtr node)
Daniel Veillard3646d642004-06-02 19:19:14 +00005081{
5082 xmlSchemaWildcardPtr ret = NULL;
5083
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005084 if ((ctxt == NULL) || (schema == NULL))
Daniel Veillard3646d642004-06-02 19:19:14 +00005085 return (NULL);
5086
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005087#ifdef DEBUG
5088 fprintf(stderr, "Adding wildcard component\n");
5089#endif
5090
Daniel Veillard3646d642004-06-02 19:19:14 +00005091 ret = (xmlSchemaWildcardPtr) xmlMalloc(sizeof(xmlSchemaWildcard));
5092 if (ret == NULL) {
5093 xmlSchemaPErrMemory(ctxt, "adding wildcard", NULL);
5094 return (NULL);
5095 }
5096 memset(ret, 0, sizeof(xmlSchemaWildcard));
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005097 ret->type = type;
Daniel Veillard3646d642004-06-02 19:19:14 +00005098 ret->minOccurs = 1;
5099 ret->maxOccurs = 1;
5100
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005101 if (xmlSchemaAddVolatile(schema, (xmlSchemaBasicItemPtr) ret) != 0) {
5102 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL, NULL, NULL, node,
5103 "Failed to add a wildcard component to the list", NULL);
5104 xmlFree(ret);
5105 return (NULL);
5106 }
Daniel Veillard3646d642004-06-02 19:19:14 +00005107 return (ret);
5108}
5109
Daniel Veillard4255d502002-04-16 15:50:10 +00005110/************************************************************************
5111 * *
5112 * Utilities for parsing *
5113 * *
5114 ************************************************************************/
5115
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00005116#if 0
Daniel Veillard4255d502002-04-16 15:50:10 +00005117/**
5118 * xmlGetQNameProp:
5119 * @ctxt: a schema validation context
5120 * @node: a subtree containing XML Schema informations
5121 * @name: the attribute name
5122 * @namespace: the result namespace if any
5123 *
5124 * Extract a QName Attribute value
5125 *
5126 * Returns the NCName or NULL if not found, and also update @namespace
5127 * with the namespace URI
5128 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005129static const xmlChar *
Daniel Veillard4255d502002-04-16 15:50:10 +00005130xmlGetQNameProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005131 const char *name, const xmlChar ** namespace)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005132{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005133 const xmlChar *val;
Daniel Veillard4255d502002-04-16 15:50:10 +00005134 xmlNsPtr ns;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005135 const xmlChar *ret, *prefix;
5136 int len;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00005137 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005138
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005139 *namespace = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00005140 attr = xmlSchemaGetPropNode(node, name);
5141 if (attr == NULL)
5142 return (NULL);
5143 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005144
Daniel Veillard4255d502002-04-16 15:50:10 +00005145 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005146 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005147
Daniel Veillardba0153a2004-04-01 10:42:31 +00005148 if (!strchr((char *) val, ':')) {
Daniel Veillardebcdebd2004-03-05 00:15:50 +00005149 ns = xmlSearchNs(node->doc, node, 0);
5150 if (ns) {
5151 *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
5152 return (val);
5153 }
5154 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005155 ret = xmlSplitQName3(val, &len);
5156 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005157 return (val);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005158 }
5159 ret = xmlDictLookup(ctxt->dict, ret, -1);
5160 prefix = xmlDictLookup(ctxt->dict, val, len);
Daniel Veillard4255d502002-04-16 15:50:10 +00005161
5162 ns = xmlSearchNs(node->doc, node, prefix);
5163 if (ns == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005164 xmlSchemaPSimpleTypeErr(ctxt, XML_SCHEMAP_PREFIX_UNDEFINED,
5165 NULL, NULL, (xmlNodePtr) attr,
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +00005166 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), NULL, val,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005167 "The QName value '%s' has no corresponding namespace "
5168 "declaration in scope", val, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005169 } else {
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005170 *namespace = xmlDictLookup(ctxt->dict, ns->href, -1);
Daniel Veillard4255d502002-04-16 15:50:10 +00005171 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005172 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005173}
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00005174#endif
Daniel Veillard4255d502002-04-16 15:50:10 +00005175
5176/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00005177 * xmlSchemaPValAttrNodeQNameValue:
5178 * @ctxt: a schema parser context
5179 * @schema: the schema context
5180 * @ownerDes: the designation of the parent element
5181 * @ownerItem: the parent as a schema object
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005182 * @value: the QName value
Daniel Veillardc0826a72004-08-10 14:17:33 +00005183 * @local: the resulting local part if found, the attribute value otherwise
5184 * @uri: the resulting namespace URI if found
5185 *
5186 * Extracts the local name and the URI of a QName value and validates it.
5187 * This one is intended to be used on attribute values that
5188 * should resolve to schema components.
5189 *
5190 * Returns 0, in case the QName is valid, a positive error code
5191 * if not valid and -1 if an internal error occurs.
5192 */
5193static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005194xmlSchemaPValAttrNodeQNameValue(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005195 xmlSchemaPtr schema,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005196 xmlChar **ownerDes ATTRIBUTE_UNUSED,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005197 xmlSchemaTypePtr ownerItem,
5198 xmlAttrPtr attr,
5199 const xmlChar *value,
5200 const xmlChar **uri,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005201 const xmlChar **local)
5202{
5203 const xmlChar *pref;
5204 xmlNsPtr ns;
5205 int len, ret;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005206
Daniel Veillardc0826a72004-08-10 14:17:33 +00005207 *uri = NULL;
5208 *local = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005209 ret = xmlValidateQName(value, 1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005210 if (ret > 0) {
5211 xmlSchemaPSimpleTypeErr(ctxt,
5212 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5213 ownerItem, (xmlNodePtr) attr,
5214 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
5215 NULL, value, NULL, NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005216 *local = value;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005217 return (ctxt->err);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005218 } else if (ret < 0)
5219 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005220
5221 if (!strchr((char *) value, ':')) {
Daniel Veillard24505b02005-07-28 23:49:35 +00005222 ns = xmlSearchNs(attr->doc, attr->parent, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005223 if (ns)
5224 *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
5225 else if (schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) {
5226 /*
5227 * This one takes care of included schemas with no
5228 * target namespace.
5229 */
5230 *uri = schema->targetNamespace;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005231 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005232 *local = xmlDictLookup(ctxt->dict, value, -1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005233 return (0);
5234 }
5235 /*
5236 * At this point xmlSplitQName3 has to return a local name.
5237 */
5238 *local = xmlSplitQName3(value, &len);
5239 *local = xmlDictLookup(ctxt->dict, *local, -1);
5240 pref = xmlDictLookup(ctxt->dict, value, len);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005241 ns = xmlSearchNs(attr->doc, attr->parent, pref);
5242 if (ns == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005243 xmlSchemaPSimpleTypeErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005244 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005245 ownerItem, (xmlNodePtr) attr,
5246 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), NULL, value,
5247 "The value '%s' of simple type 'xs:QName' has no "
5248 "corresponding namespace declaration in scope", value, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005249 return (ctxt->err);
5250 } else {
5251 *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005252 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005253 return (0);
5254}
5255
5256/**
5257 * xmlSchemaPValAttrNodeQName:
5258 * @ctxt: a schema parser context
5259 * @schema: the schema context
5260 * @ownerDes: the designation of the owner element
5261 * @ownerItem: the owner as a schema object
5262 * @attr: the attribute node
5263 * @local: the resulting local part if found, the attribute value otherwise
5264 * @uri: the resulting namespace URI if found
5265 *
5266 * Extracts and validates the QName of an attribute value.
5267 * This one is intended to be used on attribute values that
5268 * should resolve to schema components.
5269 *
5270 * Returns 0, in case the QName is valid, a positive error code
5271 * if not valid and -1 if an internal error occurs.
5272 */
5273static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005274xmlSchemaPValAttrNodeQName(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005275 xmlSchemaPtr schema,
5276 xmlChar **ownerDes,
5277 xmlSchemaTypePtr ownerItem,
5278 xmlAttrPtr attr,
5279 const xmlChar **uri,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005280 const xmlChar **local)
5281{
5282 const xmlChar *value;
5283
5284 value = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005285 return (xmlSchemaPValAttrNodeQNameValue(ctxt, schema,
5286 ownerDes, ownerItem, attr, value, uri, local));
Daniel Veillardc0826a72004-08-10 14:17:33 +00005287}
5288
5289/**
5290 * xmlSchemaPValAttrQName:
5291 * @ctxt: a schema parser context
5292 * @schema: the schema context
5293 * @ownerDes: the designation of the parent element
5294 * @ownerItem: the owner as a schema object
5295 * @ownerElem: the parent node of the attribute
5296 * @name: the name of the attribute
5297 * @local: the resulting local part if found, the attribute value otherwise
5298 * @uri: the resulting namespace URI if found
5299 *
5300 * Extracts and validates the QName of an attribute value.
5301 *
5302 * Returns 0, in case the QName is valid, a positive error code
5303 * if not valid and -1 if an internal error occurs.
5304 */
5305static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005306xmlSchemaPValAttrQName(xmlSchemaParserCtxtPtr ctxt,
5307 xmlSchemaPtr schema,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005308 xmlChar **ownerDes,
5309 xmlSchemaTypePtr ownerItem,
5310 xmlNodePtr ownerElem,
5311 const char *name,
5312 const xmlChar **uri,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005313 const xmlChar **local)
5314{
5315 xmlAttrPtr attr;
5316
5317 attr = xmlSchemaGetPropNode(ownerElem, name);
5318 if (attr == NULL) {
5319 *local = NULL;
5320 *uri = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005321 return (0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005322 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005323 return (xmlSchemaPValAttrNodeQName(ctxt, schema,
5324 ownerDes, ownerItem, attr, uri, local));
Daniel Veillardc0826a72004-08-10 14:17:33 +00005325}
5326
5327/**
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005328 * xmlSchemaPValAttrID:
5329 * @ctxt: a schema parser context
5330 * @schema: the schema context
5331 * @ownerDes: the designation of the parent element
5332 * @ownerItem: the owner as a schema object
5333 * @ownerElem: the parent node of the attribute
5334 * @name: the name of the attribute
5335 *
5336 * Extracts and validates the ID of an attribute value.
5337 *
5338 * Returns 0, in case the ID is valid, a positive error code
5339 * if not valid and -1 if an internal error occurs.
5340 */
5341static int
5342xmlSchemaPValAttrID(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005343 xmlChar **ownerDes ATTRIBUTE_UNUSED,
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005344 xmlSchemaTypePtr ownerItem,
5345 xmlNodePtr ownerElem,
5346 const xmlChar *name)
5347{
5348 int ret;
5349 xmlChar *value;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005350 xmlAttrPtr attr;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005351
5352 value = xmlGetNoNsProp(ownerElem, name);
5353 if (value == NULL)
5354 return (0);
5355
5356 attr = xmlSchemaGetPropNode(ownerElem, (const char *) name);
5357 if (attr == NULL)
5358 return (-1);
5359
5360 ret = xmlValidateNCName(BAD_CAST value, 1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005361 if (ret == 0) {
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005362 /*
5363 * NOTE: the IDness might have already be declared in the DTD
5364 */
5365 if (attr->atype != XML_ATTRIBUTE_ID) {
5366 xmlIDPtr res;
5367 xmlChar *strip;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005368
5369 /*
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005370 * TODO: Use xmlSchemaStrip here; it's not exported at this
5371 * moment.
5372 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005373 strip = xmlSchemaCollapseString(BAD_CAST value);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005374 if (strip != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005375 value = strip;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005376 res = xmlAddID(NULL, ownerElem->doc, BAD_CAST value, attr);
5377 if (res == NULL) {
5378 ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005379 xmlSchemaPSimpleTypeErr(ctxt,
5380 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5381 ownerItem, (xmlNodePtr) attr,
5382 xmlSchemaGetBuiltInType(XML_SCHEMAS_ID),
5383 NULL, NULL, "Duplicate value '%s' of simple "
5384 "type 'xs:ID'", BAD_CAST value, NULL);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005385 } else
5386 attr->atype = XML_ATTRIBUTE_ID;
5387 if (strip != NULL)
5388 xmlFree(strip);
5389 }
5390 } else if (ret > 0) {
5391 ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005392 xmlSchemaPSimpleTypeErr(ctxt,
5393 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5394 ownerItem, (xmlNodePtr) attr,
5395 xmlSchemaGetBuiltInType(XML_SCHEMAS_ID),
5396 NULL, NULL, "The value '%s' of simple type 'xs:ID' is "
5397 "not a valid 'xs:NCName'",
5398 BAD_CAST value, NULL);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005399 }
5400 xmlFree(value);
5401
5402 return (ret);
5403}
5404
5405/**
Daniel Veillard4255d502002-04-16 15:50:10 +00005406 * xmlGetMaxOccurs:
5407 * @ctxt: a schema validation context
5408 * @node: a subtree containing XML Schema informations
5409 *
5410 * Get the maxOccurs property
5411 *
5412 * Returns the default if not found, or the value
5413 */
5414static int
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005415xmlGetMaxOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
5416 int min, int max, int def, const char *expected)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005417{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005418 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00005419 int ret = 0;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005420 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005421
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005422 attr = xmlSchemaGetPropNode(node, "maxOccurs");
5423 if (attr == NULL)
5424 return (def);
5425 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Daniel Veillard4255d502002-04-16 15:50:10 +00005426
5427 if (xmlStrEqual(val, (const xmlChar *) "unbounded")) {
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005428 if (max != UNBOUNDED) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005429 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005430 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5431 /* XML_SCHEMAP_INVALID_MINOCCURS, */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005432 NULL, (xmlNodePtr) attr, NULL, expected,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005433 val, NULL, NULL, NULL);
5434 return (def);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005435 } else
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005436 return (UNBOUNDED); /* encoding it with -1 might be another option */
Daniel Veillard4255d502002-04-16 15:50:10 +00005437 }
5438
5439 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00005440 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005441 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005442 if (*cur == 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005443 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005444 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5445 /* XML_SCHEMAP_INVALID_MINOCCURS, */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005446 NULL, (xmlNodePtr) attr, NULL, expected,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005447 val, NULL, NULL, NULL);
5448 return (def);
5449 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005450 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005451 ret = ret * 10 + (*cur - '0');
5452 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00005453 }
William M. Brack76e95df2003-10-18 16:20:14 +00005454 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005455 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005456 /*
5457 * TODO: Restrict the maximal value to Integer.
5458 */
5459 if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005460 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005461 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5462 /* XML_SCHEMAP_INVALID_MINOCCURS, */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005463 NULL, (xmlNodePtr) attr, NULL, expected,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005464 val, NULL, NULL, NULL);
5465 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00005466 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005467 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005468}
5469
5470/**
5471 * xmlGetMinOccurs:
5472 * @ctxt: a schema validation context
5473 * @node: a subtree containing XML Schema informations
5474 *
5475 * Get the minOccurs property
5476 *
5477 * Returns the default if not found, or the value
5478 */
5479static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005480xmlGetMinOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005481 int min, int max, int def, const char *expected)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005482{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005483 const xmlChar *val, *cur;
Daniel Veillard4255d502002-04-16 15:50:10 +00005484 int ret = 0;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005485 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005486
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005487 attr = xmlSchemaGetPropNode(node, "minOccurs");
5488 if (attr == NULL)
5489 return (def);
5490 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Daniel Veillard4255d502002-04-16 15:50:10 +00005491 cur = val;
William M. Brack76e95df2003-10-18 16:20:14 +00005492 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005493 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005494 if (*cur == 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005495 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005496 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5497 /* XML_SCHEMAP_INVALID_MINOCCURS, */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005498 NULL, (xmlNodePtr) attr, NULL, expected,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005499 val, NULL, NULL, NULL);
5500 return (def);
5501 }
Daniel Veillard4255d502002-04-16 15:50:10 +00005502 while ((*cur >= '0') && (*cur <= '9')) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005503 ret = ret * 10 + (*cur - '0');
5504 cur++;
Daniel Veillard4255d502002-04-16 15:50:10 +00005505 }
William M. Brack76e95df2003-10-18 16:20:14 +00005506 while (IS_BLANK_CH(*cur))
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005507 cur++;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005508 /*
5509 * TODO: Restrict the maximal value to Integer.
5510 */
5511 if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005512 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005513 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5514 /* XML_SCHEMAP_INVALID_MINOCCURS, */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005515 NULL, (xmlNodePtr) attr, NULL, expected,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00005516 val, NULL, NULL, NULL);
5517 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00005518 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005519 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +00005520}
5521
5522/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005523 * xmlSchemaPGetBoolNodeValue:
5524 * @ctxt: a schema validation context
5525 * @ownerDes: owner designation
5526 * @ownerItem: the owner as a schema item
5527 * @node: the node holding the value
5528 *
5529 * Converts a boolean string value into 1 or 0.
5530 *
5531 * Returns 0 or 1.
5532 */
5533static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005534xmlSchemaPGetBoolNodeValue(xmlSchemaParserCtxtPtr ctxt,
5535 xmlChar **ownerDes ATTRIBUTE_UNUSED,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005536 xmlSchemaTypePtr ownerItem,
5537 xmlNodePtr node)
5538{
5539 xmlChar *value = NULL;
5540 int res = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005541
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005542 value = xmlNodeGetContent(node);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005543 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005544 * 3.2.2.1 Lexical representation
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005545 * An instance of a datatype that is defined as ·boolean·
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005546 * can have the following legal literals {true, false, 1, 0}.
5547 */
5548 if (xmlStrEqual(BAD_CAST value, BAD_CAST "true"))
5549 res = 1;
5550 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "false"))
5551 res = 0;
5552 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "1"))
5553 res = 1;
5554 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "0"))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005555 res = 0;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005556 else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005557 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005558 XML_SCHEMAP_INVALID_BOOLEAN,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005559 ownerItem, node,
5560 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
5561 NULL, BAD_CAST value,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00005562 NULL, NULL, NULL);
5563 }
5564 if (value != NULL)
5565 xmlFree(value);
5566 return (res);
5567}
5568
5569/**
Daniel Veillard4255d502002-04-16 15:50:10 +00005570 * xmlGetBooleanProp:
5571 * @ctxt: a schema validation context
5572 * @node: a subtree containing XML Schema informations
5573 * @name: the attribute name
5574 * @def: the default value
5575 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00005576 * Evaluate if a boolean property is set
Daniel Veillard4255d502002-04-16 15:50:10 +00005577 *
5578 * Returns the default if not found, 0 if found to be false,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005579 * 1 if found to be true
Daniel Veillard4255d502002-04-16 15:50:10 +00005580 */
5581static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005582xmlGetBooleanProp(xmlSchemaParserCtxtPtr ctxt,
5583 xmlChar **ownerDes ATTRIBUTE_UNUSED,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005584 xmlSchemaTypePtr ownerItem,
5585 xmlNodePtr node,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005586 const char *name, int def)
5587{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005588 const xmlChar *val;
Daniel Veillard4255d502002-04-16 15:50:10 +00005589
Daniel Veillardbe9c6322003-11-22 20:37:51 +00005590 val = xmlSchemaGetProp(ctxt, node, name);
Daniel Veillard4255d502002-04-16 15:50:10 +00005591 if (val == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005592 return (def);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005593 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00005594 * 3.2.2.1 Lexical representation
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005595 * An instance of a datatype that is defined as ·boolean·
Daniel Veillardc0826a72004-08-10 14:17:33 +00005596 * can have the following legal literals {true, false, 1, 0}.
5597 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005598 if (xmlStrEqual(val, BAD_CAST "true"))
5599 def = 1;
5600 else if (xmlStrEqual(val, BAD_CAST "false"))
5601 def = 0;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005602 else if (xmlStrEqual(val, BAD_CAST "1"))
5603 def = 1;
5604 else if (xmlStrEqual(val, BAD_CAST "0"))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005605 def = 0;
5606 else {
5607 xmlSchemaPSimpleTypeErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005608 XML_SCHEMAP_INVALID_BOOLEAN,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005609 ownerItem,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00005610 (xmlNodePtr) xmlSchemaGetPropNode(node, name),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005611 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
5612 NULL, val, NULL, NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00005613 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005614 return (def);
Daniel Veillard4255d502002-04-16 15:50:10 +00005615}
5616
5617/************************************************************************
5618 * *
5619 * Shema extraction from an Infoset *
5620 * *
5621 ************************************************************************/
5622static xmlSchemaTypePtr xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr
5623 ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00005624 xmlNodePtr node,
5625 int topLevel);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005626static xmlSchemaTypePtr xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr
5627 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00005628 xmlSchemaPtr schema,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005629 xmlNodePtr node,
Daniel Veillard3646d642004-06-02 19:19:14 +00005630 int topLevel);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005631static xmlSchemaTypePtr xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr
5632 ctxt,
Daniel Veillard4255d502002-04-16 15:50:10 +00005633 xmlSchemaPtr schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005634 xmlNodePtr node,
5635 xmlSchemaTypeType parentType);
Daniel Veillard4255d502002-04-16 15:50:10 +00005636static xmlSchemaAttributePtr xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr
5637 ctxt,
5638 xmlSchemaPtr schema,
William M. Bracke7091952004-05-11 15:09:58 +00005639 xmlNodePtr node,
5640 int topLevel);
Daniel Veillard4255d502002-04-16 15:50:10 +00005641static xmlSchemaAttributeGroupPtr
5642xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +00005643 xmlSchemaPtr schema, xmlNodePtr node,
5644 int topLevel);
Daniel Veillard4255d502002-04-16 15:50:10 +00005645static xmlSchemaTypePtr xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt,
5646 xmlSchemaPtr schema,
5647 xmlNodePtr node);
Daniel Veillard3646d642004-06-02 19:19:14 +00005648static xmlSchemaWildcardPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005649xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
5650 xmlSchemaPtr schema, xmlNodePtr node);
Daniel Veillard4255d502002-04-16 15:50:10 +00005651
5652/**
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00005653 * xmlSchemaPValAttrNodeValue:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005654 *
Daniel Veillard01fa6152004-06-29 17:04:39 +00005655 * @ctxt: a schema parser context
Daniel Veillardc0826a72004-08-10 14:17:33 +00005656 * @ownerDes: the designation of the parent element
5657 * @ownerItem: the schema object owner if existent
5658 * @attr: the schema attribute node being validated
5659 * @value: the value
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005660 * @type: the built-in type to be validated against
Daniel Veillard01fa6152004-06-29 17:04:39 +00005661 *
5662 * Validates a value against the given built-in type.
5663 * This one is intended to be used internally for validation
5664 * of schema attribute values during parsing of the schema.
5665 *
5666 * Returns 0 if the value is valid, a positive error code
5667 * number otherwise and -1 in case of an internal or API error.
5668 */
5669static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005670xmlSchemaPValAttrNodeValue(xmlSchemaParserCtxtPtr pctxt,
5671 xmlChar **ownerDes ATTRIBUTE_UNUSED,
5672 xmlSchemaTypePtr ownerItem,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005673 xmlAttrPtr attr,
5674 const xmlChar *value,
5675 xmlSchemaTypePtr type)
Daniel Veillard01fa6152004-06-29 17:04:39 +00005676{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005677
5678 int ret = 0;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005679
5680 /*
5681 * NOTE: Should we move this to xmlschematypes.c? Hmm, but this
5682 * one is really meant to be used internally, so better not.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005683 */
5684 if ((pctxt == NULL) || (type == NULL) || (attr == NULL))
Daniel Veillard01fa6152004-06-29 17:04:39 +00005685 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005686 if (type->type != XML_SCHEMA_TYPE_BASIC) {
5687 PERROR_INT("xmlSchemaPValAttrNodeValue",
5688 "the given type is not a built-in type");
5689 return (-1);
5690 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00005691 switch (type->builtInType) {
5692 case XML_SCHEMAS_NCNAME:
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00005693 case XML_SCHEMAS_QNAME:
5694 case XML_SCHEMAS_ANYURI:
5695 case XML_SCHEMAS_TOKEN:
5696 case XML_SCHEMAS_LANGUAGE:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005697 ret = xmlSchemaValPredefTypeNode(type, value, NULL,
5698 (xmlNodePtr) attr);
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00005699 break;
Daniel Veillard01fa6152004-06-29 17:04:39 +00005700 default: {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005701 PERROR_INT("xmlSchemaPValAttrNodeValue",
5702 "validation using the given type is not supported");
Daniel Veillard01fa6152004-06-29 17:04:39 +00005703 return (-1);
5704 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005705 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00005706 /*
5707 * TODO: Should we use the S4S error codes instead?
5708 */
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00005709 if (ret < 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005710 PERROR_INT("xmlSchemaPValAttrNodeValue",
5711 "failed to validate a schema attribute value");
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +00005712 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005713 } else if (ret > 0) {
5714 if (VARIETY_LIST(type))
5715 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
5716 else
5717 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
5718 xmlSchemaPSimpleTypeErr(pctxt,
5719 ret, ownerItem, (xmlNodePtr) attr,
5720 type, NULL, value, NULL, NULL, NULL);
5721 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00005722 return (ret);
5723}
5724
5725/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00005726 * xmlSchemaPValAttrNode:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005727 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00005728 * @ctxt: a schema parser context
5729 * @ownerDes: the designation of the parent element
5730 * @ownerItem: the schema object owner if existent
5731 * @attr: the schema attribute node being validated
5732 * @type: the built-in type to be validated against
5733 * @value: the resulting value if any
5734 *
5735 * Extracts and validates a value against the given built-in type.
5736 * This one is intended to be used internally for validation
5737 * of schema attribute values during parsing of the schema.
5738 *
5739 * Returns 0 if the value is valid, a positive error code
5740 * number otherwise and -1 in case of an internal or API error.
5741 */
5742static int
5743xmlSchemaPValAttrNode(xmlSchemaParserCtxtPtr ctxt,
5744 xmlChar **ownerDes,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005745 xmlSchemaTypePtr ownerItem,
5746 xmlAttrPtr attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005747 xmlSchemaTypePtr type,
5748 const xmlChar **value)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005749{
Daniel Veillardc0826a72004-08-10 14:17:33 +00005750 const xmlChar *val;
5751
5752 if ((ctxt == NULL) || (type == NULL) || (attr == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005753 return (-1);
5754
Daniel Veillardc0826a72004-08-10 14:17:33 +00005755 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5756 if (value != NULL)
5757 *value = val;
5758
5759 return (xmlSchemaPValAttrNodeValue(ctxt, ownerDes, ownerItem, attr,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005760 val, type));
Daniel Veillardc0826a72004-08-10 14:17:33 +00005761}
5762
5763/**
5764 * xmlSchemaPValAttr:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005765 *
Daniel Veillardc0826a72004-08-10 14:17:33 +00005766 * @ctxt: a schema parser context
5767 * @node: the element node of the attribute
5768 * @ownerDes: the designation of the parent element
5769 * @ownerItem: the schema object owner if existent
5770 * @ownerElem: the owner element node
5771 * @name: the name of the schema attribute node
5772 * @type: the built-in type to be validated against
5773 * @value: the resulting value if any
5774 *
5775 * Extracts and validates a value against the given built-in type.
5776 * This one is intended to be used internally for validation
5777 * of schema attribute values during parsing of the schema.
5778 *
5779 * Returns 0 if the value is valid, a positive error code
5780 * number otherwise and -1 in case of an internal or API error.
5781 */
5782static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005783xmlSchemaPValAttr(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005784 xmlChar **ownerDes,
5785 xmlSchemaTypePtr ownerItem,
5786 xmlNodePtr ownerElem,
5787 const char *name,
5788 xmlSchemaTypePtr type,
5789 const xmlChar **value)
5790{
5791 xmlAttrPtr attr;
5792
5793 if ((ctxt == NULL) || (type == NULL)) {
5794 if (value != NULL)
5795 *value = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005796 return (-1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005797 }
5798 if (type->type != XML_SCHEMA_TYPE_BASIC) {
5799 if (value != NULL)
5800 *value = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005801 xmlSchemaPErr(ctxt, ownerElem,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +00005802 XML_SCHEMAP_INTERNAL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005803 "Internal error: xmlSchemaPValAttr, the given "
5804 "type '%s' is not a built-in type.\n",
5805 type->name, NULL);
5806 return (-1);
5807 }
5808 attr = xmlSchemaGetPropNode(ownerElem, name);
5809 if (attr == NULL) {
5810 if (value != NULL)
5811 *value = NULL;
5812 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005813 }
5814 return (xmlSchemaPValAttrNode(ctxt, ownerDes, ownerItem, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005815 type, value));
5816}
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00005817
5818static int
5819xmlSchemaCheckReference(xmlSchemaParserCtxtPtr pctxt,
5820 xmlSchemaPtr schema,
5821 xmlNodePtr node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005822 xmlSchemaBasicItemPtr item,
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00005823 const xmlChar *namespaceName)
5824{
5825 if (xmlStrEqual(schema->targetNamespace, namespaceName))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005826 return (1);
5827 if (xmlStrEqual(xmlSchemaNs, namespaceName))
5828 return (1);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00005829 if (pctxt->localImports != NULL) {
5830 int i;
5831 for (i = 0; i < pctxt->nbLocalImports; i++)
5832 if (xmlStrEqual(namespaceName, pctxt->localImports[i]))
5833 return (1);
5834 }
5835 if (namespaceName == NULL)
5836 xmlSchemaPCustomErr(pctxt, XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005837 NULL, (xmlSchemaTypePtr) item, node,
5838 "References from this schema to components in no "
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00005839 "namespace are not valid, since not indicated by an import "
5840 "statement", NULL);
5841 else
5842 xmlSchemaPCustomErr(pctxt, XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005843 NULL, (xmlSchemaTypePtr) item, node,
5844 "References from this schema to components in the "
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00005845 "namespace '%s' are not valid, since not indicated by an import "
5846 "statement", namespaceName);
5847 return (0);
5848}
5849
Daniel Veillardc0826a72004-08-10 14:17:33 +00005850/**
Daniel Veillard4255d502002-04-16 15:50:10 +00005851 * xmlSchemaParseAttrDecls:
5852 * @ctxt: a schema validation context
5853 * @schema: the schema being built
5854 * @node: a subtree containing XML Schema informations
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005855 * @type: the hosting type where the attributes will be anchored
Daniel Veillard4255d502002-04-16 15:50:10 +00005856 *
5857 * parse a XML schema attrDecls declaration corresponding to
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005858 * <!ENTITY % attrDecls
Daniel Veillard4255d502002-04-16 15:50:10 +00005859 * '((%attribute;| %attributeGroup;)*,(%anyAttribute;)?)'>
5860 */
5861static xmlNodePtr
5862xmlSchemaParseAttrDecls(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5863 xmlNodePtr child, xmlSchemaTypePtr type)
5864{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005865 xmlSchemaAttributePtr lastattr = NULL, attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00005866
Daniel Veillard4255d502002-04-16 15:50:10 +00005867 while ((IS_SCHEMA(child, "attribute")) ||
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005868 (IS_SCHEMA(child, "attributeGroup"))) {
5869 attr = NULL;
5870 if (IS_SCHEMA(child, "attribute")) {
William M. Bracke7091952004-05-11 15:09:58 +00005871 attr = xmlSchemaParseAttribute(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005872 } else if (IS_SCHEMA(child, "attributeGroup")) {
5873 attr = (xmlSchemaAttributePtr)
Daniel Veillard3646d642004-06-02 19:19:14 +00005874 xmlSchemaParseAttributeGroup(ctxt, schema, child, 0);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005875 }
5876 if (attr != NULL) {
5877 if (lastattr == NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +00005878 if (type->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP)
5879 ((xmlSchemaAttributeGroupPtr) type)->attributes = attr;
5880 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00005881 type->attributes = attr;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005882 lastattr = attr;
5883 } else {
5884 lastattr->next = attr;
5885 lastattr = attr;
5886 }
5887 }
5888 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005889 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00005890 return (child);
Daniel Veillard4255d502002-04-16 15:50:10 +00005891}
5892
5893/**
5894 * xmlSchemaParseAnnotation:
5895 * @ctxt: a schema validation context
5896 * @schema: the schema being built
5897 * @node: a subtree containing XML Schema informations
5898 *
5899 * parse a XML schema Attrribute declaration
5900 * *WARNING* this interface is highly subject to change
5901 *
William M. Bracke7091952004-05-11 15:09:58 +00005902 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00005903 * 1 in case of success.
5904 */
5905static xmlSchemaAnnotPtr
5906xmlSchemaParseAnnotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5907 xmlNodePtr node)
5908{
5909 xmlSchemaAnnotPtr ret;
Daniel Veillardc0826a72004-08-10 14:17:33 +00005910 xmlNodePtr child = NULL;
5911 xmlAttrPtr attr;
5912 int barked = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00005913
Daniel Veillardc0826a72004-08-10 14:17:33 +00005914 /*
5915 * INFO: S4S completed.
5916 */
5917 /*
5918 * id = ID
5919 * {any attributes with non-schema namespace . . .}>
5920 * Content: (appinfo | documentation)*
5921 */
Daniel Veillard4255d502002-04-16 15:50:10 +00005922 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
5923 return (NULL);
5924 ret = xmlSchemaNewAnnot(ctxt, node);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005925 attr = node->properties;
5926 while (attr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005927 if (((attr->ns == NULL) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00005928 (!xmlStrEqual(attr->name, BAD_CAST "id"))) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005929 ((attr->ns != NULL) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00005930 xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005931
5932 xmlSchemaPIllegalAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005933 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5934 NULL, NULL, attr);
5935 }
5936 attr = attr->next;
5937 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00005938 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Daniel Veillardc0826a72004-08-10 14:17:33 +00005939 /*
5940 * And now for the children...
5941 */
5942 child = node->children;
5943 while (child != NULL) {
5944 if (IS_SCHEMA(child, "appinfo")) {
5945 /* TODO: make available the content of "appinfo". */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005946 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00005947 * source = anyURI
5948 * {any attributes with non-schema namespace . . .}>
5949 * Content: ({any})*
5950 */
5951 attr = child->properties;
5952 while (attr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005953 if (((attr->ns == NULL) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00005954 (!xmlStrEqual(attr->name, BAD_CAST "source"))) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005955 ((attr->ns != NULL) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00005956 xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
Daniel Veillard4255d502002-04-16 15:50:10 +00005957
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005958 xmlSchemaPIllegalAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005959 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5960 NULL, NULL, attr);
5961 }
5962 attr = attr->next;
5963 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005964 xmlSchemaPValAttr(ctxt, NULL, NULL, child, "source",
5965 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00005966 child = child->next;
5967 } else if (IS_SCHEMA(child, "documentation")) {
5968 /* TODO: make available the content of "documentation". */
5969 /*
5970 * source = anyURI
5971 * {any attributes with non-schema namespace . . .}>
5972 * Content: ({any})*
5973 */
5974 attr = child->properties;
5975 while (attr != NULL) {
5976 if (attr->ns == NULL) {
5977 if (!xmlStrEqual(attr->name, BAD_CAST "source")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005978 xmlSchemaPIllegalAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005979 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5980 NULL, NULL, attr);
5981 }
5982 } else {
5983 if (xmlStrEqual(attr->ns->href, xmlSchemaNs) ||
5984 (xmlStrEqual(attr->name, BAD_CAST "lang") &&
5985 (!xmlStrEqual(attr->ns->href, XML_XML_NAMESPACE)))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00005986
5987 xmlSchemaPIllegalAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00005988 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
5989 NULL, NULL, attr);
5990 }
5991 }
5992 attr = attr->next;
5993 }
5994 /*
5995 * Attribute "xml:lang".
5996 */
5997 attr = xmlSchemaGetPropNodeNs(child, (const char *) XML_XML_NAMESPACE, "lang");
5998 if (attr != NULL)
5999 xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006000 xmlSchemaGetBuiltInType(XML_SCHEMAS_LANGUAGE), NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006001 child = child->next;
6002 } else {
6003 if (!barked)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006004 xmlSchemaPContentErr(ctxt,
6005 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006006 NULL, NULL, node, child, NULL, "(appinfo | documentation)*");
6007 barked = 1;
6008 child = child->next;
6009 }
6010 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006011
Daniel Veillard4255d502002-04-16 15:50:10 +00006012 return (ret);
6013}
6014
6015/**
6016 * xmlSchemaParseFacet:
6017 * @ctxt: a schema validation context
6018 * @schema: the schema being built
6019 * @node: a subtree containing XML Schema informations
6020 *
6021 * parse a XML schema Facet declaration
6022 * *WARNING* this interface is highly subject to change
6023 *
6024 * Returns the new type structure or NULL in case of error
6025 */
6026static xmlSchemaFacetPtr
6027xmlSchemaParseFacet(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006028 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00006029{
6030 xmlSchemaFacetPtr facet;
6031 xmlNodePtr child = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006032 const xmlChar *value;
Daniel Veillard4255d502002-04-16 15:50:10 +00006033
6034 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6035 return (NULL);
6036
Daniel Veillard8bc6cf92003-02-27 17:42:22 +00006037 facet = xmlSchemaNewFacet();
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006038 if (facet == NULL) {
6039 xmlSchemaPErrMemory(ctxt, "allocating facet", node);
6040 return (NULL);
6041 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006042 facet->node = node;
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006043 value = xmlSchemaGetProp(ctxt, node, "value");
Daniel Veillard4255d502002-04-16 15:50:10 +00006044 if (value == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006045 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_FACET_NO_VALUE,
6046 "Facet %s has no value\n", node->name, NULL);
6047 xmlSchemaFreeFacet(facet);
Daniel Veillard4255d502002-04-16 15:50:10 +00006048 return (NULL);
6049 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006050 if (IS_SCHEMA(node, "minInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006051 facet->type = XML_SCHEMA_FACET_MININCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006052 } else if (IS_SCHEMA(node, "minExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006053 facet->type = XML_SCHEMA_FACET_MINEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006054 } else if (IS_SCHEMA(node, "maxInclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006055 facet->type = XML_SCHEMA_FACET_MAXINCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006056 } else if (IS_SCHEMA(node, "maxExclusive")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006057 facet->type = XML_SCHEMA_FACET_MAXEXCLUSIVE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006058 } else if (IS_SCHEMA(node, "totalDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006059 facet->type = XML_SCHEMA_FACET_TOTALDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006060 } else if (IS_SCHEMA(node, "fractionDigits")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006061 facet->type = XML_SCHEMA_FACET_FRACTIONDIGITS;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006062 } else if (IS_SCHEMA(node, "pattern")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006063 facet->type = XML_SCHEMA_FACET_PATTERN;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006064 } else if (IS_SCHEMA(node, "enumeration")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006065 facet->type = XML_SCHEMA_FACET_ENUMERATION;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006066 } else if (IS_SCHEMA(node, "whiteSpace")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006067 facet->type = XML_SCHEMA_FACET_WHITESPACE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006068 } else if (IS_SCHEMA(node, "length")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006069 facet->type = XML_SCHEMA_FACET_LENGTH;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006070 } else if (IS_SCHEMA(node, "maxLength")) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006071 facet->type = XML_SCHEMA_FACET_MAXLENGTH;
6072 } else if (IS_SCHEMA(node, "minLength")) {
6073 facet->type = XML_SCHEMA_FACET_MINLENGTH;
6074 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006075 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_TYPE,
6076 "Unknown facet type %s\n", node->name, NULL);
6077 xmlSchemaFreeFacet(facet);
6078 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006079 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00006080 xmlSchemaPValAttrID(ctxt, NULL,
6081 (xmlSchemaTypePtr) facet, node, BAD_CAST "id");
Daniel Veillard4255d502002-04-16 15:50:10 +00006082 facet->value = value;
Daniel Veillard01fa6152004-06-29 17:04:39 +00006083 if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
6084 (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
6085 const xmlChar *fixed;
6086
6087 fixed = xmlSchemaGetProp(ctxt, node, "fixed");
6088 if (fixed != NULL) {
6089 if (xmlStrEqual(fixed, BAD_CAST "true"))
6090 facet->fixed = 1;
6091 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006092 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006093 child = node->children;
6094
6095 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006096 facet->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6097 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006098 }
6099 if (child != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006100 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_CHILD,
6101 "Facet %s has unexpected child content\n",
6102 node->name, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006103 }
6104 return (facet);
6105}
6106
6107/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00006108 * xmlSchemaParseWildcardNs:
6109 * @ctxt: a schema parser context
6110 * @wildc: the wildcard, already created
6111 * @node: a subtree containing XML Schema informations
6112 *
6113 * Parses the attribute "processContents" and "namespace"
6114 * of a xsd:anyAttribute and xsd:any.
6115 * *WARNING* this interface is highly subject to change
6116 *
6117 * Returns 0 if everything goes fine, a positive error code
6118 * if something is not valid and -1 if an internal error occurs.
6119 */
6120static int
6121xmlSchemaParseWildcardNs(xmlSchemaParserCtxtPtr ctxt,
6122 xmlSchemaPtr schema,
6123 xmlSchemaWildcardPtr wildc,
6124 xmlNodePtr node)
6125{
6126 const xmlChar *pc, *ns, *dictnsItem;
6127 int ret = 0;
6128 xmlChar *nsItem;
6129 xmlSchemaWildcardNsPtr tmp, lastNs = NULL;
6130 xmlAttrPtr attr;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006131
Daniel Veillardc0826a72004-08-10 14:17:33 +00006132 pc = xmlSchemaGetProp(ctxt, node, "processContents");
6133 if ((pc == NULL)
6134 || (xmlStrEqual(pc, (const xmlChar *) "strict"))) {
6135 wildc->processContents = XML_SCHEMAS_ANY_STRICT;
6136 } else if (xmlStrEqual(pc, (const xmlChar *) "skip")) {
6137 wildc->processContents = XML_SCHEMAS_ANY_SKIP;
6138 } else if (xmlStrEqual(pc, (const xmlChar *) "lax")) {
6139 wildc->processContents = XML_SCHEMAS_ANY_LAX;
6140 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006141 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006142 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006143 NULL, node,
6144 NULL, "(strict | skip | lax)", pc,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006145 NULL, NULL, NULL);
6146 wildc->processContents = XML_SCHEMAS_ANY_STRICT;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006147 ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006148 }
6149 /*
6150 * Build the namespace constraints.
6151 */
6152 attr = xmlSchemaGetPropNode(node, "namespace");
6153 ns = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00006154 if ((attr == NULL) || (xmlStrEqual(ns, BAD_CAST "##any")))
Daniel Veillardc0826a72004-08-10 14:17:33 +00006155 wildc->any = 1;
6156 else if (xmlStrEqual(ns, BAD_CAST "##other")) {
6157 wildc->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006158 if (wildc->negNsSet == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006159 return (-1);
6160 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006161 wildc->negNsSet->value = schema->targetNamespace;
6162 } else {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006163 const xmlChar *end, *cur;
6164
6165 cur = ns;
6166 do {
6167 while (IS_BLANK_CH(*cur))
6168 cur++;
6169 end = cur;
6170 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
6171 end++;
6172 if (end == cur)
6173 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006174 nsItem = xmlStrndup(cur, end - cur);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006175 if ((xmlStrEqual(nsItem, BAD_CAST "##other")) ||
6176 (xmlStrEqual(nsItem, BAD_CAST "##any"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006177 xmlSchemaPSimpleTypeErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006178 XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006179 NULL, (xmlNodePtr) attr,
6180 NULL,
6181 "((##any | ##other) | List of (xs:anyURI | "
6182 "(##targetNamespace | ##local)))",
Daniel Veillardc0826a72004-08-10 14:17:33 +00006183 nsItem, NULL, NULL, NULL);
6184 ret = XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER;
6185 } else {
6186 if (xmlStrEqual(nsItem, BAD_CAST "##targetNamespace")) {
6187 dictnsItem = schema->targetNamespace;
6188 } else if (xmlStrEqual(nsItem, BAD_CAST "##local")) {
6189 dictnsItem = NULL;
6190 } else {
6191 /*
6192 * Validate the item (anyURI).
6193 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006194 xmlSchemaPValAttrNodeValue(ctxt, NULL, NULL, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006195 nsItem, xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI));
6196 dictnsItem = xmlDictLookup(ctxt->dict, nsItem, -1);
6197 }
6198 /*
6199 * Avoid dublicate namespaces.
6200 */
6201 tmp = wildc->nsSet;
6202 while (tmp != NULL) {
6203 if (dictnsItem == tmp->value)
6204 break;
6205 tmp = tmp->next;
6206 }
6207 if (tmp == NULL) {
6208 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
6209 if (tmp == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006210 xmlFree(nsItem);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006211 return (-1);
6212 }
6213 tmp->value = dictnsItem;
6214 tmp->next = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006215 if (wildc->nsSet == NULL)
Daniel Veillardc0826a72004-08-10 14:17:33 +00006216 wildc->nsSet = tmp;
6217 else
6218 lastNs->next = tmp;
6219 lastNs = tmp;
6220 }
6221
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006222 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006223 xmlFree(nsItem);
6224 cur = end;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006225 } while (*cur != 0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006226 }
6227 return (ret);
6228}
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006229
6230static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006231xmlSchemaPCheckParticleCorrect_2(xmlSchemaParserCtxtPtr ctxt,
6232 xmlSchemaParticlePtr item ATTRIBUTE_UNUSED,
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006233 xmlNodePtr node,
6234 int minOccurs,
6235 int maxOccurs) {
6236
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006237 if ((maxOccurs == 0) && ( minOccurs == 0))
6238 return (0);
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006239 if (maxOccurs != UNBOUNDED) {
6240 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006241 * TODO: Maybe we should better not create the particle,
6242 * if min/max is invalid, since it could confuse the build of the
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006243 * content model.
6244 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006245 /*
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006246 * 3.9.6 Schema Component Constraint: Particle Correct
6247 *
6248 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006249 if (maxOccurs < 1) {
6250 /*
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006251 * 2.2 {max occurs} must be greater than or equal to 1.
6252 */
6253 xmlSchemaPCustomAttrErr(ctxt,
6254 XML_SCHEMAP_P_PROPS_CORRECT_2_2,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006255 NULL, NULL,
6256 xmlSchemaGetPropNode(node, "maxOccurs"),
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006257 "The value must be greater than or equal to 1");
6258 return (XML_SCHEMAP_P_PROPS_CORRECT_2_2);
6259 } else if (minOccurs > maxOccurs) {
6260 /*
6261 * 2.1 {min occurs} must not be greater than {max occurs}.
6262 */
6263 xmlSchemaPCustomAttrErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006264 XML_SCHEMAP_P_PROPS_CORRECT_2_1,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006265 NULL, NULL,
6266 xmlSchemaGetPropNode(node, "minOccurs"),
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006267 "The value must not be greater than the value of 'maxOccurs'");
6268 return (XML_SCHEMAP_P_PROPS_CORRECT_2_1);
6269 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006270 }
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006271 return (0);
6272}
6273
Daniel Veillardc0826a72004-08-10 14:17:33 +00006274/**
Daniel Veillard4255d502002-04-16 15:50:10 +00006275 * xmlSchemaParseAny:
6276 * @ctxt: a schema validation context
6277 * @schema: the schema being built
6278 * @node: a subtree containing XML Schema informations
6279 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006280 * Parsea a XML schema <any> element. A particle and wildcard
6281 * will be created (except if minOccurs==maxOccurs==0, in this case
6282 * nothing will be created).
Daniel Veillard4255d502002-04-16 15:50:10 +00006283 * *WARNING* this interface is highly subject to change
6284 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006285 * Returns the particle or NULL in case of error or if minOccurs==maxOccurs==0
Daniel Veillard4255d502002-04-16 15:50:10 +00006286 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006287static xmlSchemaParticlePtr
Daniel Veillard4255d502002-04-16 15:50:10 +00006288xmlSchemaParseAny(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6289 xmlNodePtr node)
6290{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006291 xmlSchemaParticlePtr particle;
Daniel Veillard4255d502002-04-16 15:50:10 +00006292 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006293 xmlSchemaWildcardPtr wild;
6294 int min, max;
6295 xmlAttrPtr attr;
6296 xmlSchemaAnnotPtr annot = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00006297
6298 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6299 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006300 /*
6301 * Check for illegal attributes.
6302 */
6303 attr = node->properties;
6304 while (attr != NULL) {
6305 if (attr->ns == NULL) {
6306 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6307 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
6308 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
6309 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
6310 (!xmlStrEqual(attr->name, BAD_CAST "processContents"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006311 xmlSchemaPIllegalAttrErr(ctxt,
6312 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6313 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006314 }
6315 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006316 xmlSchemaPIllegalAttrErr(ctxt,
6317 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6318 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006319 }
6320 attr = attr->next;
6321 }
6322 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
6323 /*
6324 * minOccurs/maxOccurs.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006325 */
6326 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
6327 "(xs:nonNegativeInteger | unbounded)");
6328 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1,
6329 "xs:nonNegativeInteger");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006330 xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
6331 /*
6332 * Create & parse the wildcard.
6333 */
6334 wild = xmlSchemaAddWildcard(ctxt, schema, XML_SCHEMA_TYPE_ANY, node);
6335 if (wild == NULL)
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006336 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006337 xmlSchemaParseWildcardNs(ctxt, schema, wild, node);
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006338 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006339 * And now for the children...
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006340 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006341 child = node->children;
Daniel Veillard4255d502002-04-16 15:50:10 +00006342 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006343 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006344 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006345 }
6346 if (child != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006347 xmlSchemaPContentErr(ctxt,
6348 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006349 NULL, NULL, node, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006350 NULL, "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006351 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006352 /*
6353 * No component if minOccurs==maxOccurs==0.
6354 */
6355 if ((min == 0) && (max == 0)) {
6356 /* Don't free the wildcard, since it's already on the list. */
6357 return (NULL);
6358 }
6359 /*
6360 * Create the particle.
6361 */
6362 particle = xmlSchemaAddParticle(ctxt, schema, node, min, max);
6363 if (particle == NULL)
6364 return (NULL);
6365 particle->annot = annot;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006366 wild->minOccurs = min;
6367 wild->maxOccurs = max;
6368 particle->children = (xmlSchemaTreeItemPtr) wild;
Daniel Veillard4255d502002-04-16 15:50:10 +00006369
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006370 return (particle);
Daniel Veillard4255d502002-04-16 15:50:10 +00006371}
6372
6373/**
6374 * xmlSchemaParseNotation:
6375 * @ctxt: a schema validation context
6376 * @schema: the schema being built
6377 * @node: a subtree containing XML Schema informations
6378 *
6379 * parse a XML schema Notation declaration
6380 *
6381 * Returns the new structure or NULL in case of error
6382 */
6383static xmlSchemaNotationPtr
6384xmlSchemaParseNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006385 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00006386{
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006387 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00006388 xmlSchemaNotationPtr ret;
6389 xmlNodePtr child = NULL;
6390
6391 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6392 return (NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006393 name = xmlSchemaGetProp(ctxt, node, "name");
Daniel Veillard4255d502002-04-16 15:50:10 +00006394 if (name == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006395 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_NOTATION_NO_NAME,
6396 "Notation has no name\n", NULL, NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00006397 return (NULL);
6398 }
6399 ret = xmlSchemaAddNotation(ctxt, schema, name);
6400 if (ret == NULL) {
Daniel Veillard4255d502002-04-16 15:50:10 +00006401 return (NULL);
6402 }
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006403 ret->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00006404
6405 xmlSchemaPValAttrID(ctxt, NULL, (xmlSchemaTypePtr) ret,
6406 node, BAD_CAST "id");
6407
6408 if (IS_SCHEMA(child, "annotation")) {
6409 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6410 child = child->next;
6411 }
6412
Daniel Veillard4255d502002-04-16 15:50:10 +00006413 child = node->children;
6414 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006415 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6416 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006417 }
6418 if (child != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006419 xmlSchemaPContentErr(ctxt,
6420 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006421 NULL, NULL, node, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006422 NULL, "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006423 }
6424
6425 return (ret);
6426}
6427
6428/**
6429 * xmlSchemaParseAnyAttribute:
6430 * @ctxt: a schema validation context
6431 * @schema: the schema being built
6432 * @node: a subtree containing XML Schema informations
6433 *
6434 * parse a XML schema AnyAttrribute declaration
6435 * *WARNING* this interface is highly subject to change
6436 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006437 * Returns a wildcard or NULL.
Daniel Veillard4255d502002-04-16 15:50:10 +00006438 */
Daniel Veillard3646d642004-06-02 19:19:14 +00006439static xmlSchemaWildcardPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006440xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
6441 xmlSchemaPtr schema, xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00006442{
Daniel Veillard3646d642004-06-02 19:19:14 +00006443 xmlSchemaWildcardPtr ret;
Daniel Veillard4255d502002-04-16 15:50:10 +00006444 xmlNodePtr child = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006445 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00006446
6447 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6448 return (NULL);
6449
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006450 ret = xmlSchemaAddWildcard(ctxt, schema, XML_SCHEMA_TYPE_ANY_ATTRIBUTE,
6451 node);
Daniel Veillard4255d502002-04-16 15:50:10 +00006452 if (ret == NULL) {
6453 return (NULL);
6454 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006455 /*
6456 * Check for illegal attributes.
6457 */
6458 attr = node->properties;
6459 while (attr != NULL) {
6460 if (attr->ns == NULL) {
6461 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6462 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
6463 (!xmlStrEqual(attr->name, BAD_CAST "processContents"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006464 xmlSchemaPIllegalAttrErr(ctxt,
6465 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6466 NULL, NULL, attr);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006467 }
6468 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006469 xmlSchemaPIllegalAttrErr(ctxt,
6470 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6471 NULL, NULL, attr);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006472 }
6473 attr = attr->next;
6474 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00006475 xmlSchemaPValAttrID(ctxt, NULL, (xmlSchemaTypePtr) ret,
6476 node, BAD_CAST "id");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006477 /*
6478 * Parse the namespace list.
6479 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006480 if (xmlSchemaParseWildcardNs(ctxt, schema, ret, node) != 0)
Daniel Veillardc0826a72004-08-10 14:17:33 +00006481 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006482 /*
6483 * And now for the children...
6484 */
Daniel Veillard4255d502002-04-16 15:50:10 +00006485 child = node->children;
6486 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006487 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6488 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006489 }
6490 if (child != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006491 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006492 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006493 NULL, NULL, node, child,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006494 NULL, "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006495 }
6496
6497 return (ret);
6498}
6499
6500
6501/**
6502 * xmlSchemaParseAttribute:
6503 * @ctxt: a schema validation context
6504 * @schema: the schema being built
6505 * @node: a subtree containing XML Schema informations
6506 *
6507 * parse a XML schema Attrribute declaration
6508 * *WARNING* this interface is highly subject to change
6509 *
William M. Bracke7091952004-05-11 15:09:58 +00006510 * Returns the attribute declaration.
Daniel Veillard4255d502002-04-16 15:50:10 +00006511 */
6512static xmlSchemaAttributePtr
6513xmlSchemaParseAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
William M. Bracke7091952004-05-11 15:09:58 +00006514 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00006515{
Daniel Veillardc0826a72004-08-10 14:17:33 +00006516 const xmlChar *name, *attrValue;
6517 xmlChar *repName = NULL; /* The reported designation. */
Daniel Veillard4255d502002-04-16 15:50:10 +00006518 xmlSchemaAttributePtr ret;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006519 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006520 xmlAttrPtr attr, nameAttr;
6521 int isRef = 0;
William M. Bracke7091952004-05-11 15:09:58 +00006522
6523 /*
6524 * Note that the w3c spec assumes the schema to be validated with schema
6525 * for schemas beforehand.
6526 *
6527 * 3.2.3 Constraints on XML Representations of Attribute Declarations
William M. Bracke7091952004-05-11 15:09:58 +00006528 */
Daniel Veillard4255d502002-04-16 15:50:10 +00006529
6530 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6531 return (NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006532 attr = xmlSchemaGetPropNode(node, "ref");
6533 nameAttr = xmlSchemaGetPropNode(node, "name");
6534
6535 if ((attr == NULL) && (nameAttr == NULL)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006536 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006537 * 3.2.3 : 3.1
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006538 * One of ref or name must be present, but not both
Daniel Veillardc0826a72004-08-10 14:17:33 +00006539 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006540 xmlSchemaPMissingAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_1,
6541 NULL, node, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006542 "One of the attributes 'ref' or 'name' must be present");
6543 return (NULL);
6544 }
6545 if ((topLevel) || (attr == NULL)) {
6546 if (nameAttr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006547 xmlSchemaPMissingAttrErr(ctxt, XML_SCHEMAP_S4S_ATTR_MISSING,
6548 NULL, node, "name", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00006549 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006550 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006551 } else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006552 isRef = 1;
6553
Daniel Veillardc0826a72004-08-10 14:17:33 +00006554 if (isRef) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006555 char buf[50];
6556 const xmlChar *refNs = NULL, *ref = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006557
6558 /*
6559 * Parse as attribute reference.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006560 */
6561 if (xmlSchemaPValAttrNodeQName(ctxt, schema,
6562 (xmlChar **) &xmlSchemaElemDesAttrRef, NULL, attr, &refNs,
6563 &ref) != 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006564 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006565 }
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006566 snprintf(buf, 49, "#aRef%d", ctxt->counter++ + 1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006567 name = (const xmlChar *) buf;
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006568 ret = xmlSchemaAddAttribute(ctxt, schema, name, NULL, node, 0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006569 if (ret == NULL) {
6570 if (repName != NULL)
6571 xmlFree(repName);
6572 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00006573 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006574 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
6575 ret->node = node;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006576 ret->refNs = refNs;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00006577 ret->ref = ref;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006578 xmlSchemaCheckReference(ctxt, schema, node, (xmlSchemaBasicItemPtr) ret,
6579 refNs);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006580 /*
6581 xmlSchemaFormatTypeRep(&repName, (xmlSchemaTypePtr) ret, NULL, NULL);
6582 */
6583 if (nameAttr != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006584 xmlSchemaPMutualExclAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_1,
6585 &repName, (xmlSchemaTypePtr) ret, nameAttr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006586 "ref", "name");
6587 /*
6588 * Check for illegal attributes.
6589 */
6590 attr = node->properties;
6591 while (attr != NULL) {
6592 if (attr->ns == NULL) {
6593 if (xmlStrEqual(attr->name, BAD_CAST "type") ||
6594 xmlStrEqual(attr->name, BAD_CAST "form")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006595 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006596 * 3.2.3 : 3.2
6597 * If ref is present, then all of <simpleType>,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006598 * form and type must be absent.
Daniel Veillardc0826a72004-08-10 14:17:33 +00006599 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006600 xmlSchemaPIllegalAttrErr(ctxt,
6601 XML_SCHEMAP_SRC_ATTRIBUTE_3_2, &repName,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006602 (xmlSchemaTypePtr) ret, attr);
6603 } else if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
6604 (!xmlStrEqual(attr->name, BAD_CAST "use")) &&
6605 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006606 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
6607 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00006608 (!xmlStrEqual(attr->name, BAD_CAST "default"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006609 xmlSchemaPIllegalAttrErr(ctxt,
6610 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6611 &repName, (xmlSchemaTypePtr) ret, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006612 }
6613 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006614 xmlSchemaPIllegalAttrErr(ctxt,
6615 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6616 &repName, (xmlSchemaTypePtr) ret, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006617 }
6618 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006619 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +00006620 } else {
William M. Bracke7091952004-05-11 15:09:58 +00006621 const xmlChar *ns = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006622
Daniel Veillardc0826a72004-08-10 14:17:33 +00006623 /*
6624 * Parse as attribute declaration.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006625 */
6626 if (xmlSchemaPValAttrNode(ctxt,
6627 (xmlChar **) &xmlSchemaElemDesAttrDecl, NULL, nameAttr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006628 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
6629 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00006630 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006631 /*
6632 xmlSchemaFormatTypeRep(&repName, NULL, xmlSchemaElemDesAttrDecl, name);
6633 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006634 /*
6635 * 3.2.6 Schema Component Constraint: xmlns Not Allowed
6636 * TODO: Move this to the component layer.
Daniel Veillardc0826a72004-08-10 14:17:33 +00006637 */
6638 if (xmlStrEqual(name, BAD_CAST "xmlns")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006639 xmlSchemaPSimpleTypeErr(ctxt,
6640 XML_SCHEMAP_NO_XMLNS,
6641 NULL, (xmlNodePtr) nameAttr,
6642 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), NULL, NULL,
6643 "The value of type 'xs:NCName' must not match 'xmlns'",
6644 NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006645 if (repName != NULL)
6646 xmlFree(repName);
6647 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006648 }
6649 /*
6650 * Evaluate the target namespace
6651 */
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006652 if (topLevel) {
6653 ns = schema->targetNamespace;
6654 } else {
6655 attr = xmlSchemaGetPropNode(node, "form");
6656 if (attr != NULL) {
6657 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6658 if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
6659 ns = schema->targetNamespace;
6660 } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006661 xmlSchemaPSimpleTypeErr(ctxt,
6662 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6663 NULL, (xmlNodePtr) attr,
6664 NULL, "(qualified | unqualified)",
6665 attrValue, NULL, NULL, NULL);
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00006666 }
6667 } else if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006668 ns = schema->targetNamespace;
6669 }
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006670 ret = xmlSchemaAddAttribute(ctxt, schema, name, ns, node, topLevel);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006671 if (ret == NULL) {
6672 if (repName != NULL)
6673 xmlFree(repName);
Daniel Veillard3646d642004-06-02 19:19:14 +00006674 return (NULL);
William M. Bracke7091952004-05-11 15:09:58 +00006675 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006676 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006677 ret->node = node;
Daniel Veillardc0826a72004-08-10 14:17:33 +00006678 if (topLevel)
6679 ret->flags |= XML_SCHEMAS_ATTR_GLOBAL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006680 /*
6681 * 3.2.6 Schema Component Constraint: xsi: Not Allowed
6682 * TODO: Move this to the component layer.
6683 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00006684 if (xmlStrEqual(ret->targetNamespace, xmlSchemaInstanceNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006685 xmlSchemaPCustomErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006686 XML_SCHEMAP_NO_XSI,
6687 &repName, (xmlSchemaTypePtr) ret, node,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006688 "The target namespace must not match '%s'",
6689 xmlSchemaInstanceNs);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006690 }
6691 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006692 * Check for illegal attributes.
6693 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00006694 attr = node->properties;
6695 while (attr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006696 if (attr->ns == NULL) {
6697 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6698 (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
6699 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00006700 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
6701 (!xmlStrEqual(attr->name, BAD_CAST "type"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006702 if ((topLevel) ||
Daniel Veillardc0826a72004-08-10 14:17:33 +00006703 ((!xmlStrEqual(attr->name, BAD_CAST "form")) &&
6704 (!xmlStrEqual(attr->name, BAD_CAST "use")))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006705 xmlSchemaPIllegalAttrErr(ctxt,
6706 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6707 &repName, (xmlSchemaTypePtr) ret, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006708 }
6709 }
6710 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006711 xmlSchemaPIllegalAttrErr(ctxt, XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6712 &repName, (xmlSchemaTypePtr) ret, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006713 }
6714 attr = attr->next;
6715 }
6716 xmlSchemaPValAttrQName(ctxt, schema, &repName, (xmlSchemaTypePtr) ret,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006717 node, "type", &ret->typeNs, &ret->typeName);
6718 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00006719 xmlSchemaPValAttrID(ctxt, NULL, (xmlSchemaTypePtr) ret,
6720 node, BAD_CAST "id");
William M. Bracke7091952004-05-11 15:09:58 +00006721 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006722 * Attribute "fixed".
William M. Bracke7091952004-05-11 15:09:58 +00006723 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00006724 ret->defValue = xmlSchemaGetProp(ctxt, node, "fixed");
6725 if (ret->defValue != NULL)
6726 ret->flags |= XML_SCHEMAS_ATTR_FIXED;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006727 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006728 * Attribute "default".
6729 */
6730 attr = xmlSchemaGetPropNode(node, "default");
6731 if (attr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006732 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006733 * 3.2.3 : 1
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006734 * default and fixed must not both be present.
Daniel Veillardc0826a72004-08-10 14:17:33 +00006735 */
6736 if (ret->flags & XML_SCHEMAS_ATTR_FIXED) {
6737 xmlSchemaPMutualExclAttrErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_1,
6738 &repName, (xmlSchemaTypePtr) ret, attr, "default", "fixed");
6739 } else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006740 ret->defValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6741 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006742 if (topLevel == 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006743 /*
6744 * Attribute "use".
Daniel Veillardc0826a72004-08-10 14:17:33 +00006745 */
6746 attr = xmlSchemaGetPropNode(node, "use");
6747 if (attr != NULL) {
6748 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6749 if (xmlStrEqual(attrValue, BAD_CAST "optional"))
6750 ret->occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
6751 else if (xmlStrEqual(attrValue, BAD_CAST "prohibited"))
6752 ret->occurs = XML_SCHEMAS_ATTR_USE_PROHIBITED;
6753 else if (xmlStrEqual(attrValue, BAD_CAST "required"))
6754 ret->occurs = XML_SCHEMAS_ATTR_USE_REQUIRED;
6755 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006756 xmlSchemaPSimpleTypeErr(ctxt,
6757 XML_SCHEMAP_INVALID_ATTR_USE,
6758 (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
6759 NULL, "(optional | prohibited | required)",
6760 attrValue, NULL, NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006761 } else
6762 ret->occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006763 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006764 * 3.2.3 : 2
6765 * If default and use are both present, use must have
6766 * the actual value optional.
6767 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006768 if ((ret->occurs != XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
6769 (ret->defValue != NULL) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00006770 ((ret->flags & XML_SCHEMAS_ATTR_FIXED) == 0)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006771 xmlSchemaPSimpleTypeErr(ctxt,
6772 XML_SCHEMAP_SRC_ATTRIBUTE_2,
6773 (xmlSchemaTypePtr) ret, (xmlNodePtr) attr,
6774 NULL, "(optional | prohibited | required)", NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00006775 "The value must be 'optional' if the attribute "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006776 "'default' is present as well", NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00006777 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006778 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006779 /*
6780 * And now for the children...
6781 */
Daniel Veillard4255d502002-04-16 15:50:10 +00006782 child = node->children;
6783 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006784 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6785 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006786 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006787 if (isRef) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006788 if (child != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00006789 if (IS_SCHEMA(child, "simpleType"))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006790 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006791 * 3.2.3 : 3.2
6792 * If ref is present, then all of <simpleType>,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006793 * form and type must be absent.
Daniel Veillardc0826a72004-08-10 14:17:33 +00006794 */
6795 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_3_2,
6796 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
6797 "(annotation?)");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006798 else
Daniel Veillardc0826a72004-08-10 14:17:33 +00006799 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6800 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006801 "(annotation?)");
Daniel Veillardc0826a72004-08-10 14:17:33 +00006802 }
6803 } else {
6804 if (IS_SCHEMA(child, "simpleType")) {
6805 if (ret->typeName != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006806 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00006807 * 3.2.3 : 4
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006808 * type and <simpleType> must not both be present.
Daniel Veillardc0826a72004-08-10 14:17:33 +00006809 */
6810 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_SRC_ATTRIBUTE_4,
6811 &repName, (xmlSchemaTypePtr) ret, node, child,
6812 "The attribute 'type' and the <simpleType> child "
6813 "are mutually exclusive", NULL);
6814 } else
6815 ret->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
6816 child = child->next;
6817 }
6818 if (child != NULL)
6819 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6820 &repName, (xmlSchemaTypePtr) ret, node, child, NULL,
6821 "(annotation?, simpleType?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006822 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00006823 /*
6824 * Cleanup.
6825 */
6826 if (repName != NULL)
6827 xmlFree(repName);
Daniel Veillard4255d502002-04-16 15:50:10 +00006828 return (ret);
6829}
6830
6831/**
6832 * xmlSchemaParseAttributeGroup:
6833 * @ctxt: a schema validation context
6834 * @schema: the schema being built
6835 * @node: a subtree containing XML Schema informations
6836 *
6837 * parse a XML schema Attribute Group declaration
6838 * *WARNING* this interface is highly subject to change
6839 *
6840 * Returns the attribute group or NULL in case of error.
6841 */
6842static xmlSchemaAttributeGroupPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006843xmlSchemaParseAttributeGroup(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +00006844 xmlSchemaPtr schema, xmlNodePtr node,
6845 int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00006846{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006847 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00006848 xmlSchemaAttributeGroupPtr ret;
Daniel Veillard4255d502002-04-16 15:50:10 +00006849 xmlNodePtr child = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006850 const xmlChar *oldcontainer;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006851 xmlAttrPtr attr, nameAttr;
Daniel Veillard4255d502002-04-16 15:50:10 +00006852
6853 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6854 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006855
6856 nameAttr = xmlSchemaGetPropNode(node, "name");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006857 attr = xmlSchemaGetPropNode(node, "ref");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006858 if ((topLevel) || (attr == NULL)) {
6859 /*
6860 * Parse as an attribute group definition.
6861 * Note that those are allowed at top level only.
6862 */
6863 if (nameAttr == NULL) {
6864 xmlSchemaPMissingAttrErr(ctxt,
6865 XML_SCHEMAP_S4S_ATTR_MISSING,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006866 NULL, node, "name", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006867 return (NULL);
6868 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006869 /* REDUNDANT: name = xmlSchemaGetNodeContent(ctxt,
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00006870 * (xmlNodePtr) nameAttr);
6871 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006872 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006873 * The name is crucial, exit if invalid.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006874 */
6875 if (xmlSchemaPValAttrNode(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006876 NULL, NULL, nameAttr,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006877 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
6878 return (NULL);
6879 }
6880 ret = xmlSchemaAddAttributeGroup(ctxt, schema, name, node);
6881 if (ret == NULL)
6882 return (NULL);
6883 ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
6884 ret->flags |= XML_SCHEMAS_ATTRGROUP_GLOBAL;
6885 ret->node = node;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00006886 ret->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006887 } else {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006888 char buf[50];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006889 const xmlChar *refNs = NULL, *ref = NULL;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006890
6891 /*
6892 * Parse as an attribute group definition reference.
6893 */
6894 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006895 xmlSchemaPMissingAttrErr(ctxt,
6896 XML_SCHEMAP_S4S_ATTR_MISSING,
6897 NULL, node, "ref", NULL);
6898 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006899 xmlSchemaPValAttrNodeQName(ctxt, schema,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006900 NULL, NULL, attr, &refNs,&ref);
6901
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00006902 snprintf(buf, 49, "#agRef%d", ctxt->counter++ + 1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006903 name = (const xmlChar *) buf;
6904 if (name == NULL) {
6905 xmlSchemaPErrMemory(ctxt, "creating internal name for an "
6906 "attribute group definition reference", node);
6907 return (NULL);
6908 }
6909 ret = xmlSchemaAddAttributeGroup(ctxt, schema, name, node);
6910 if (ret == NULL)
6911 return (NULL);
6912 ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
6913 ret->ref = ref;
6914 ret->refNs = refNs;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006915 ret->node = node;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00006916 xmlSchemaCheckReference(ctxt, schema, node,
6917 (xmlSchemaBasicItemPtr) ret, refNs);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006918 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006919 /*
6920 * Check for illegal attributes.
6921 */
6922 attr = node->properties;
6923 while (attr != NULL) {
6924 if (attr->ns == NULL) {
6925 if ((((topLevel == 0) && (!xmlStrEqual(attr->name, BAD_CAST "ref"))) ||
6926 (topLevel && (!xmlStrEqual(attr->name, BAD_CAST "name")))) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006927 (!xmlStrEqual(attr->name, BAD_CAST "id")))
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006928 {
6929 xmlSchemaPIllegalAttrErr(ctxt,
6930 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6931 NULL, NULL, attr);
6932 }
6933 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6934 xmlSchemaPIllegalAttrErr(ctxt,
6935 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
6936 NULL, NULL, attr);
6937 }
6938 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006939 }
6940 /* TODO: Validate "id" ? */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006941 /*
6942 * And now for the children...
6943 */
Daniel Veillard4255d502002-04-16 15:50:10 +00006944 oldcontainer = ctxt->container;
Daniel Veillard4255d502002-04-16 15:50:10 +00006945 ctxt->container = name;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006946 child = node->children;
Daniel Veillard4255d502002-04-16 15:50:10 +00006947 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00006948 ret->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
6949 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00006950 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006951 if (topLevel) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006952 child = xmlSchemaParseAttrDecls(ctxt, schema, child, (xmlSchemaTypePtr) ret);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006953 if (IS_SCHEMA(child, "anyAttribute")) {
6954 ret->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
6955 child = child->next;
6956 }
6957 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006958 if (child != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006959 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006960 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6961 NULL, NULL, node, child, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00006962 "(annotation?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00006963 }
Daniel Veillard4255d502002-04-16 15:50:10 +00006964 ctxt->container = oldcontainer;
6965 return (ret);
6966}
6967
6968/**
William M. Brack2f2a6632004-08-20 23:09:47 +00006969 * xmlSchemaPValAttrFormDefault:
6970 * @value: the value
6971 * @flags: the flags to be modified
6972 * @flagQualified: the specific flag for "qualified"
6973 *
6974 * Returns 0 if the value is valid, 1 otherwise.
6975 */
6976static int
6977xmlSchemaPValAttrFormDefault(const xmlChar *value,
6978 int *flags,
6979 int flagQualified)
6980{
6981 if (xmlStrEqual(value, BAD_CAST "qualified")) {
6982 if ((*flags & flagQualified) == 0)
6983 *flags |= flagQualified;
6984 } else if (!xmlStrEqual(value, BAD_CAST "unqualified"))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00006985 return (1);
6986
William M. Brack2f2a6632004-08-20 23:09:47 +00006987 return (0);
6988}
6989
6990/**
Daniel Veillardc0826a72004-08-10 14:17:33 +00006991 * xmlSchemaPValAttrBlockFinal:
6992 * @value: the value
6993 * @flags: the flags to be modified
6994 * @flagAll: the specific flag for "#all"
6995 * @flagExtension: the specific flag for "extension"
6996 * @flagRestriction: the specific flag for "restriction"
6997 * @flagSubstitution: the specific flag for "substitution"
6998 * @flagList: the specific flag for "list"
6999 * @flagUnion: the specific flag for "union"
7000 *
7001 * Validates the value of the attribute "final" and "block". The value
7002 * is converted into the specified flag values and returned in @flags.
7003 *
7004 * Returns 0 if the value is valid, 1 otherwise.
7005 */
7006
7007static int
7008xmlSchemaPValAttrBlockFinal(const xmlChar *value,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007009 int *flags,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007010 int flagAll,
7011 int flagExtension,
7012 int flagRestriction,
7013 int flagSubstitution,
7014 int flagList,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007015 int flagUnion)
Daniel Veillardc0826a72004-08-10 14:17:33 +00007016{
7017 int ret = 0;
7018
7019 /*
7020 * TODO: This does not check for dublicate entries.
7021 */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00007022 if ((flags == NULL) || (value == NULL))
7023 return (-1);
7024 if (value[0] == 0)
7025 return (0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007026 if (xmlStrEqual(value, BAD_CAST "#all")) {
7027 if (flagAll != -1)
7028 *flags |= flagAll;
7029 else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007030 if (flagExtension != -1)
7031 *flags |= flagExtension;
7032 if (flagRestriction != -1)
Daniel Veillardc0826a72004-08-10 14:17:33 +00007033 *flags |= flagRestriction;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007034 if (flagSubstitution != -1)
Daniel Veillardc0826a72004-08-10 14:17:33 +00007035 *flags |= flagSubstitution;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007036 if (flagList != -1)
Daniel Veillardc0826a72004-08-10 14:17:33 +00007037 *flags |= flagList;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007038 if (flagUnion != -1)
Daniel Veillardc0826a72004-08-10 14:17:33 +00007039 *flags |= flagUnion;
7040 }
7041 } else {
7042 const xmlChar *end, *cur = value;
7043 xmlChar *item;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007044
Daniel Veillardc0826a72004-08-10 14:17:33 +00007045 do {
7046 while (IS_BLANK_CH(*cur))
7047 cur++;
7048 end = cur;
7049 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
7050 end++;
7051 if (end == cur)
7052 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007053 item = xmlStrndup(cur, end - cur);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007054 if (xmlStrEqual(item, BAD_CAST "extension")) {
7055 if (flagExtension != -1) {
7056 if ((*flags & flagExtension) == 0)
7057 *flags |= flagExtension;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007058 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00007059 ret = 1;
7060 } else if (xmlStrEqual(item, BAD_CAST "restriction")) {
7061 if (flagRestriction != -1) {
7062 if ((*flags & flagRestriction) == 0)
7063 *flags |= flagRestriction;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007064 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00007065 ret = 1;
7066 } else if (xmlStrEqual(item, BAD_CAST "substitution")) {
7067 if (flagSubstitution != -1) {
7068 if ((*flags & flagSubstitution) == 0)
7069 *flags |= flagSubstitution;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007070 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00007071 ret = 1;
7072 } else if (xmlStrEqual(item, BAD_CAST "list")) {
7073 if (flagList != -1) {
7074 if ((*flags & flagList) == 0)
7075 *flags |= flagList;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007076 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00007077 ret = 1;
7078 } else if (xmlStrEqual(item, BAD_CAST "union")) {
7079 if (flagUnion != -1) {
7080 if ((*flags & flagUnion) == 0)
7081 *flags |= flagUnion;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007082 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00007083 ret = 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007084 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00007085 ret = 1;
7086 if (item != NULL)
7087 xmlFree(item);
7088 cur = end;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007089 } while ((ret == 0) && (*cur != 0));
7090 }
7091
Daniel Veillardc0826a72004-08-10 14:17:33 +00007092 return (ret);
7093}
7094
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007095static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007096xmlSchemaCheckCSelectorXPath(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007097 xmlSchemaIDCPtr idc,
7098 xmlSchemaIDCSelectPtr selector,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007099 xmlAttrPtr attr,
7100 int isField)
7101{
7102 xmlNodePtr node;
7103
7104 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007105 * c-selector-xpath:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007106 * Schema Component Constraint: Selector Value OK
7107 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007108 * TODO: 1 The {selector} must be a valid XPath expression, as defined
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007109 * in [XPath].
7110 */
7111 if (selector == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007112 xmlSchemaPErr(ctxt, idc->node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007113 XML_SCHEMAP_INTERNAL,
7114 "Internal error: xmlSchemaCheckCSelectorXPath, "
7115 "the selector is not specified.\n", NULL, NULL);
7116 return (-1);
7117 }
7118 if (attr == NULL)
7119 node = idc->node;
7120 else
7121 node = (xmlNodePtr) attr;
7122 if (selector->xpath == NULL) {
7123 xmlSchemaPCustomErr(ctxt,
7124 /* TODO: Adjust error code. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007125 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
7126 NULL, NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007127 "The XPath expression of the selector is not valid", NULL);
7128 return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE);
7129 } else {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00007130 const xmlChar **nsArray = NULL;
7131 xmlNsPtr *nsList = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007132 /*
7133 * Compile the XPath expression.
7134 */
7135 /*
7136 * TODO: We need the array of in-scope namespaces for compilation.
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00007137 * TODO: Call xmlPatterncompile with different options for selector/
7138 * field.
7139 */
7140 nsList = xmlGetNsList(attr->doc, attr->parent);
7141 /*
7142 * Build an array of prefixes and namespaces.
7143 */
7144 if (nsList != NULL) {
7145 int i, count = 0;
7146 xmlNsPtr ns;
7147
7148 for (i = 0; nsList[i] != NULL; i++)
7149 count++;
7150
7151 nsArray = (const xmlChar **) xmlMalloc(
7152 (count * 2 + 1) * sizeof(const xmlChar *));
7153 if (nsArray == NULL) {
7154 xmlSchemaPErrMemory(ctxt, "allocating a namespace array",
7155 NULL);
7156 return (-1);
7157 }
7158 for (i = 0; i < count; i++) {
7159 ns = nsList[i];
7160 nsArray[2 * i] = nsList[i]->href;
7161 nsArray[2 * i + 1] = nsList[i]->prefix;
7162 }
7163 nsArray[count * 2] = NULL;
7164 xmlFree(nsList);
7165 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007166 /*
7167 * TODO: Differentiate between "selector" and "field".
7168 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00007169 if (isField)
7170 selector->xpathComp = (void *) xmlPatterncompile(selector->xpath,
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00007171 NULL, XML_PATTERN_XSFIELD, nsArray);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00007172 else
7173 selector->xpathComp = (void *) xmlPatterncompile(selector->xpath,
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00007174 NULL, XML_PATTERN_XSSEL, nsArray);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00007175 if (nsArray != NULL)
7176 xmlFree((xmlChar **) nsArray);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007177
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +00007178 if (selector->xpathComp == NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007179 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +00007180 /* TODO: Adjust error code? */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007181 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
7182 NULL, NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007183 "The XPath expression '%s' could not be "
7184 "compiled", selector->xpath);
7185 return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007186 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007187 }
7188 return (0);
7189}
7190
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007191#define ADD_ANNOTATION(annot) \
7192 xmlSchemaAnnotPtr cur = item->annot; \
7193 if (item->annot == NULL) { \
7194 item->annot = annot; \
7195 return (annot); \
7196 } \
7197 cur = item->annot; \
7198 if (cur->next != NULL) { \
7199 cur = cur->next; \
7200 } \
7201 cur->next = annot;
7202
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007203/**
7204 * xmlSchemaAssignAnnotation:
7205 * @item: the schema component
7206 * @annot: the annotation
7207 *
7208 * Adds the annotation to the given schema component.
7209 *
7210 * Returns the given annotaion.
7211 */
7212static xmlSchemaAnnotPtr
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007213xmlSchemaAddAnnotation(xmlSchemaAnnotItemPtr annItem,
7214 xmlSchemaAnnotPtr annot)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007215{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007216 if ((annItem == NULL) || (annot == NULL))
7217 return (NULL);
7218 switch (annItem->type) {
7219 case XML_SCHEMA_TYPE_ELEMENT: {
7220 xmlSchemaElementPtr item = (xmlSchemaElementPtr) annItem;
7221 ADD_ANNOTATION(annot)
7222 }
7223 break;
7224 case XML_SCHEMA_TYPE_ATTRIBUTE: {
7225 xmlSchemaAttributePtr item = (xmlSchemaAttributePtr) annItem;
7226 ADD_ANNOTATION(annot)
7227 }
7228 break;
7229 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
7230 case XML_SCHEMA_TYPE_ANY: {
7231 xmlSchemaWildcardPtr item = (xmlSchemaWildcardPtr) annItem;
7232 ADD_ANNOTATION(annot)
7233 }
7234 break;
7235 case XML_SCHEMA_TYPE_PARTICLE:
7236 case XML_SCHEMA_TYPE_IDC_KEY:
7237 case XML_SCHEMA_TYPE_IDC_KEYREF:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007238 case XML_SCHEMA_TYPE_IDC_UNIQUE: {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007239 xmlSchemaAnnotItemPtr item = (xmlSchemaAnnotItemPtr) annItem;
7240 ADD_ANNOTATION(annot)
7241 }
7242 break;
7243 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP: {
7244 xmlSchemaAttributeGroupPtr item =
7245 (xmlSchemaAttributeGroupPtr) annItem;
7246 ADD_ANNOTATION(annot)
7247 }
7248 break;
7249 case XML_SCHEMA_TYPE_NOTATION: {
7250 xmlSchemaNotationPtr item = (xmlSchemaNotationPtr) annItem;
7251 ADD_ANNOTATION(annot)
7252 }
7253 break;
7254 case XML_SCHEMA_FACET_MININCLUSIVE:
7255 case XML_SCHEMA_FACET_MINEXCLUSIVE:
7256 case XML_SCHEMA_FACET_MAXINCLUSIVE:
7257 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
7258 case XML_SCHEMA_FACET_TOTALDIGITS:
7259 case XML_SCHEMA_FACET_FRACTIONDIGITS:
7260 case XML_SCHEMA_FACET_PATTERN:
7261 case XML_SCHEMA_FACET_ENUMERATION:
7262 case XML_SCHEMA_FACET_WHITESPACE:
7263 case XML_SCHEMA_FACET_LENGTH:
7264 case XML_SCHEMA_FACET_MAXLENGTH:
7265 case XML_SCHEMA_FACET_MINLENGTH: {
7266 xmlSchemaFacetPtr item = (xmlSchemaFacetPtr) annItem;
7267 ADD_ANNOTATION(annot)
7268 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007269 break;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007270 case XML_SCHEMA_TYPE_SIMPLE:
7271 case XML_SCHEMA_TYPE_COMPLEX: {
7272 xmlSchemaTypePtr item = (xmlSchemaTypePtr) annItem;
7273 ADD_ANNOTATION(annot)
7274 }
7275 break;
7276 case XML_SCHEMA_TYPE_GROUP: {
7277 xmlSchemaModelGroupDefPtr item = (xmlSchemaModelGroupDefPtr) annItem;
7278 ADD_ANNOTATION(annot)
7279 }
7280 break;
7281 case XML_SCHEMA_TYPE_SEQUENCE:
7282 case XML_SCHEMA_TYPE_CHOICE:
7283 case XML_SCHEMA_TYPE_ALL: {
7284 xmlSchemaModelGroupPtr item = (xmlSchemaModelGroupPtr) annItem;
7285 ADD_ANNOTATION(annot)
7286 }
7287 break;
7288 default:
7289 xmlSchemaPCustomErr(NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007290 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007291 NULL, NULL, NULL,
7292 "Internal error: xmlSchemaAddAnnotation, "
7293 "The item is not a annotated schema component", NULL);
7294 break;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007295 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007296 return (annot);
7297}
7298
7299/**
7300 * xmlSchemaParseIDCSelectorAndField:
7301 * @ctxt: a schema validation context
7302 * @schema: the schema being built
7303 * @node: a subtree containing XML Schema informations
7304 *
7305 * Parses a XML Schema identity-contraint definition's
7306 * <selector> and <field> elements.
7307 *
7308 * Returns the parsed identity-constraint definition.
7309 */
7310static xmlSchemaIDCSelectPtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007311xmlSchemaParseIDCSelectorAndField(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007312 xmlSchemaPtr schema,
7313 xmlSchemaIDCPtr idc,
7314 xmlNodePtr node,
7315 int isField)
7316{
7317 xmlSchemaIDCSelectPtr item;
7318 xmlNodePtr child = NULL;
7319 xmlAttrPtr attr;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007320
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007321 /*
7322 * Check for illegal attributes.
7323 */
7324 attr = node->properties;
7325 while (attr != NULL) {
7326 if (attr->ns == NULL) {
7327 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7328 (!xmlStrEqual(attr->name, BAD_CAST "xpath"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007329 xmlSchemaPIllegalAttrErr(ctxt,
7330 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7331 NULL, NULL, attr);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007332 }
7333 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007334 xmlSchemaPIllegalAttrErr(ctxt,
7335 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7336 NULL, NULL, attr);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007337 }
7338 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007339 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007340 /*
7341 * Create the item.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007342 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007343 item = (xmlSchemaIDCSelectPtr) xmlMalloc(sizeof(xmlSchemaIDCSelect));
7344 if (item == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007345 xmlSchemaPErrMemory(ctxt,
7346 "allocating a 'selector' of an identity-constraint definition",
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007347 NULL);
7348 return (NULL);
7349 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007350 memset(item, 0, sizeof(xmlSchemaIDCSelect));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007351 /*
7352 * Attribute "xpath" (mandatory).
7353 */
7354 attr = xmlSchemaGetPropNode(node, "xpath");
7355 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007356 xmlSchemaPMissingAttrErr(ctxt,
7357 XML_SCHEMAP_S4S_ATTR_MISSING,
7358 NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007359 "name", NULL);
7360 } else {
7361 item->xpath = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
7362 /*
7363 * URGENT TODO: "field"s have an other syntax than "selector"s.
7364 */
7365
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +00007366 if (xmlSchemaCheckCSelectorXPath(ctxt, idc, item, attr,
7367 isField) == -1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007368 xmlSchemaPErr(ctxt,
7369 (xmlNodePtr) attr,
7370 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007371 "Internal error: xmlSchemaParseIDCSelectorAndField, "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007372 "validating the XPath expression of a IDC selector.\n",
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007373 NULL, NULL);
7374 }
7375
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007376 }
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00007377 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007378 /*
7379 * And now for the children...
7380 */
7381 child = node->children;
7382 if (IS_SCHEMA(child, "annotation")) {
7383 /*
7384 * Add the annotation to the parent IDC.
7385 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007386 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) idc,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007387 xmlSchemaParseAnnotation(ctxt, schema, child));
7388 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007389 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007390 if (child != NULL) {
7391 xmlSchemaPContentErr(ctxt,
7392 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007393 NULL, NULL, node, child,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007394 NULL, "(annotation?)");
7395 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007396
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007397 return (item);
7398}
7399
7400/**
7401 * xmlSchemaParseIDC:
7402 * @ctxt: a schema validation context
7403 * @schema: the schema being built
7404 * @node: a subtree containing XML Schema informations
7405 *
7406 * Parses a XML Schema identity-contraint definition.
7407 *
7408 * Returns the parsed identity-constraint definition.
7409 */
7410static xmlSchemaIDCPtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007411xmlSchemaParseIDC(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007412 xmlSchemaPtr schema,
7413 xmlNodePtr node,
7414 xmlSchemaTypeType idcCategory,
7415 const xmlChar *targetNamespace)
7416{
7417 xmlSchemaIDCPtr item = NULL;
7418 xmlNodePtr child = NULL;
7419 xmlAttrPtr attr;
7420 const xmlChar *name = NULL;
7421 xmlSchemaIDCSelectPtr field = NULL, lastField = NULL;
7422 int resAdd;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007423
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007424 /*
7425 * Check for illegal attributes.
7426 */
7427 attr = node->properties;
7428 while (attr != NULL) {
7429 if (attr->ns == NULL) {
7430 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7431 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
7432 ((idcCategory != XML_SCHEMA_TYPE_IDC_KEYREF) ||
7433 (!xmlStrEqual(attr->name, BAD_CAST "refer")))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007434 xmlSchemaPIllegalAttrErr(ctxt,
7435 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7436 NULL, NULL, attr);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007437 }
7438 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007439 xmlSchemaPIllegalAttrErr(ctxt,
7440 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7441 NULL, NULL, attr);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007442 }
7443 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007444 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007445 /*
7446 * Attribute "name" (mandatory).
7447 */
7448 attr = xmlSchemaGetPropNode(node, "name");
7449 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007450 xmlSchemaPMissingAttrErr(ctxt,
7451 XML_SCHEMAP_S4S_ATTR_MISSING,
7452 NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007453 "name", NULL);
7454 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007455 } else if (xmlSchemaPValAttrNode(ctxt,
7456 NULL, NULL, attr,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007457 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
7458 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007459 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007460 /*
7461 * Create the component.
7462 */
7463 if (schema->idcDef == NULL)
7464 schema->idcDef = xmlHashCreateDict(10, ctxt->dict);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007465 if (schema->idcDef == NULL)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007466 return (NULL);
7467
7468 item = (xmlSchemaIDCPtr) xmlMalloc(sizeof(xmlSchemaIDC));
7469 if (item == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007470 xmlSchemaPErrMemory(ctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007471 "allocating an identity-constraint definition", NULL);
7472 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007473 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007474 /*
7475 * Add the IDC to the list of IDCs on the schema component.
7476 */
7477 resAdd = xmlHashAddEntry2(schema->idcDef, name, targetNamespace, item);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007478 if (resAdd != 0) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007479 xmlSchemaPCustomErrExt(ctxt,
7480 XML_SCHEMAP_REDEFINED_TYPE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007481 NULL, NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007482 "An identity-constraint definition with the name '%s' "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007483 "and targetNamespace '%s' does already exist",
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007484 name, targetNamespace, NULL);
7485 xmlFree(item);
7486 return (NULL);
7487 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007488 memset(item, 0, sizeof(xmlSchemaIDC));
7489 item->name = name;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007490 item->type = idcCategory;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007491 item->node = node;
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +00007492 if (ctxt->assemble != NULL)
7493 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) item);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007494 /*
7495 * The target namespace of the parent element declaration.
7496 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007497 item->targetNamespace = targetNamespace;
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00007498 xmlSchemaPValAttrID(ctxt, NULL, (xmlSchemaTypePtr) item,
7499 node, BAD_CAST "id");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007500 if (idcCategory == XML_SCHEMA_TYPE_IDC_KEYREF) {
7501 /*
7502 * Attribute "refer" (mandatory).
7503 */
7504 attr = xmlSchemaGetPropNode(node, "refer");
7505 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007506 xmlSchemaPMissingAttrErr(ctxt,
7507 XML_SCHEMAP_S4S_ATTR_MISSING,
7508 NULL, node,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007509 "refer", NULL);
7510 } else {
7511 /*
7512 * Create a reference item.
7513 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007514 item->ref = xmlSchemaNewQNameRef(schema, XML_SCHEMA_TYPE_IDC_KEY,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007515 NULL, NULL);
7516 if (item->ref == NULL)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007517 return (NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007518 xmlSchemaPValAttrNodeQName(ctxt, schema,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007519 NULL, NULL, attr,
7520 &(item->ref->targetNamespace),
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007521 &(item->ref->name));
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007522 xmlSchemaCheckReference(ctxt, schema, node,
7523 (xmlSchemaBasicItemPtr) item,
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00007524 item->ref->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007525 }
7526 }
7527 /*
7528 * And now for the children...
7529 */
7530 child = node->children;
7531 if (IS_SCHEMA(child, "annotation")) {
7532 item->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7533 child = child->next;
7534 }
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00007535 if (child == NULL) {
7536 xmlSchemaPContentErr(ctxt,
7537 XML_SCHEMAP_S4S_ELEM_MISSING,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007538 NULL, NULL, node, child,
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +00007539 "A child element is missing",
7540 "(annotation?, (selector, field+))");
7541 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007542 /*
7543 * Child element <selector>.
7544 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007545 if (IS_SCHEMA(child, "selector")) {
7546 item->selector = xmlSchemaParseIDCSelectorAndField(ctxt, schema,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007547 item, child, 0);
7548 child = child->next;
7549 /*
7550 * Child elements <field>.
7551 */
7552 if (IS_SCHEMA(child, "field")) {
7553 do {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007554 field = xmlSchemaParseIDCSelectorAndField(ctxt, schema,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007555 item, child, 1);
7556 if (field != NULL) {
7557 field->index = item->nbFields;
7558 item->nbFields++;
7559 if (lastField != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007560 lastField->next = field;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007561 else
7562 item->fields = field;
7563 lastField = field;
7564 }
7565 child = child->next;
7566 } while (IS_SCHEMA(child, "field"));
7567 } else {
7568 xmlSchemaPContentErr(ctxt,
7569 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007570 NULL, NULL, node, child,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007571 NULL, "(annotation?, (selector, field+))");
7572 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007573 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007574 if (child != NULL) {
7575 xmlSchemaPContentErr(ctxt,
7576 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007577 NULL, NULL, node, child,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007578 NULL, "(annotation?, (selector, field+))");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007579 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007580
7581 return (item);
7582}
7583
Daniel Veillardc0826a72004-08-10 14:17:33 +00007584/**
Daniel Veillard4255d502002-04-16 15:50:10 +00007585 * xmlSchemaParseElement:
7586 * @ctxt: a schema validation context
7587 * @schema: the schema being built
7588 * @node: a subtree containing XML Schema informations
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007589 * @topLevel: indicates if this is global declaration
Daniel Veillard4255d502002-04-16 15:50:10 +00007590 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007591 * Parses a XML schema element declaration.
Daniel Veillard4255d502002-04-16 15:50:10 +00007592 * *WARNING* this interface is highly subject to change
7593 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007594 * Returns the element declaration or a particle; NULL in case
7595 * of an error or if the particle has minOccurs==maxOccurs==0.
Daniel Veillard4255d502002-04-16 15:50:10 +00007596 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007597static xmlSchemaBasicItemPtr
Daniel Veillard4255d502002-04-16 15:50:10 +00007598xmlSchemaParseElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00007599 xmlNodePtr node, int topLevel)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007600{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007601 xmlSchemaElementPtr decl = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007602 xmlSchemaParticlePtr particle = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007603 xmlSchemaAnnotPtr annot = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007604 xmlNodePtr child = NULL;
7605 xmlAttrPtr attr, nameAttr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007606 int min, max, isRef = 0;
7607 xmlChar *des = NULL;
William M. Bracke7091952004-05-11 15:09:58 +00007608
7609 /* 3.3.3 Constraints on XML Representations of Element Declarations */
7610 /* TODO: Complete implementation of 3.3.6 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007611
Daniel Veillard4255d502002-04-16 15:50:10 +00007612 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007613 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007614 /*
7615 * If we get a "ref" attribute on a local <element> we will assume it's
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007616 * a reference - even if there's a "name" attribute; this seems to be more
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007617 * robust.
7618 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00007619 nameAttr = xmlSchemaGetPropNode(node, "name");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007620 attr = xmlSchemaGetPropNode(node, "ref");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007621 if ((topLevel) || (attr == NULL)) {
7622 if (nameAttr == NULL) {
7623 xmlSchemaPMissingAttrErr(ctxt,
7624 XML_SCHEMAP_S4S_ATTR_MISSING,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007625 NULL, node, "name", NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007626 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007627 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007628 } else
Daniel Veillardc0826a72004-08-10 14:17:33 +00007629 isRef = 1;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007630
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007631 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007632 child = node->children;
7633 if (IS_SCHEMA(child, "annotation")) {
7634 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
7635 child = child->next;
7636 }
7637 /*
7638 * Skip particle part if a global declaration.
7639 */
7640 if (topLevel)
7641 goto declaration_part;
7642 /*
7643 * The particle part ==================================================
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007644 */
7645 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
7646 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1, "(xs:nonNegativeInteger | unbounded)");
7647 xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007648 particle = xmlSchemaAddParticle(ctxt, schema, node, min, max);
7649 if (particle == NULL)
7650 goto return_null;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007651
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007652 /* ret->flags |= XML_SCHEMAS_ELEM_REF; */
7653
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007654 if (isRef) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007655 const xmlChar *refNs = NULL, *ref = NULL;
7656 xmlSchemaQNameRefPtr refer = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007657 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007658 * The reference part =============================================
Daniel Veillardc0826a72004-08-10 14:17:33 +00007659 */
7660 xmlSchemaPValAttrNodeQName(ctxt, schema,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007661 NULL, NULL, attr, &refNs, &ref);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007662 xmlSchemaCheckReference(ctxt, schema, node, NULL, refNs);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007663 /*
7664 * SPEC (3.3.3 : 2.1) "One of ref or name must be present, but not both"
Daniel Veillardc0826a72004-08-10 14:17:33 +00007665 */
7666 if (nameAttr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007667 xmlSchemaPMutualExclAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007668 XML_SCHEMAP_SRC_ELEMENT_2_1,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007669 NULL, NULL, nameAttr, "ref", "name");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007670 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007671 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007672 * Check for illegal attributes.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007673 */
Daniel Veillardc0826a72004-08-10 14:17:33 +00007674 attr = node->properties;
7675 while (attr != NULL) {
7676 if (attr->ns == NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007677 if (xmlStrEqual(attr->name, BAD_CAST "ref") ||
7678 xmlStrEqual(attr->name, BAD_CAST "name") ||
7679 xmlStrEqual(attr->name, BAD_CAST "id") ||
7680 xmlStrEqual(attr->name, BAD_CAST "maxOccurs") ||
7681 xmlStrEqual(attr->name, BAD_CAST "minOccurs"))
7682 {
7683 attr = attr->next;
7684 continue;
7685 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007686 /* SPEC (3.3.3 : 2.2) */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007687 xmlSchemaPCustomAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007688 XML_SCHEMAP_SRC_ELEMENT_2_2,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007689 NULL, NULL, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007690 "Only the attributes 'minOccurs', 'maxOccurs' and "
7691 "'id' are allowed in addition to 'ref'");
7692 break;
7693 }
7694 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7695 xmlSchemaPIllegalAttrErr(ctxt,
7696 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007697 NULL, NULL, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007698 }
7699 attr = attr->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007700 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00007701 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007702 * No children except <annotation> expected.
Daniel Veillardc0826a72004-08-10 14:17:33 +00007703 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007704 if (child != NULL) {
7705 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7706 NULL, NULL, node, child, NULL, "(annotation?)");
7707 }
7708 if ((min == 0) && (max == 0))
7709 goto return_null;
7710 /*
7711 * Create the reference item.
7712 */
7713 refer = xmlSchemaNewQNameRef(schema, XML_SCHEMA_TYPE_ELEMENT,
7714 ref, refNs);
7715 if (refer == NULL)
7716 goto return_null;
7717 particle->children = (xmlSchemaTreeItemPtr) refer;
7718 particle->annot = annot;
7719 /*
7720 * Add to assembled items; the reference need to be resolved.
7721 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007722 if (ctxt->assemble != NULL)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007723 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) particle);
7724
7725 return ((xmlSchemaBasicItemPtr) particle);
7726 }
7727 /*
7728 * The declaration part ===============================================
7729 */
7730declaration_part:
7731 {
7732 const xmlChar *ns = NULL, *fixed, *name, *oldcontainer, *attrValue;
7733 xmlSchemaIDCPtr curIDC = NULL, lastIDC = NULL;
7734
7735 if (xmlSchemaPValAttrNode(ctxt, NULL, NULL, nameAttr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007736 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007737 goto return_null;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007738 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00007739 * Evaluate the target namespace.
7740 */
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00007741 if (topLevel) {
7742 ns = schema->targetNamespace;
7743 } else {
7744 attr = xmlSchemaGetPropNode(node, "form");
7745 if (attr != NULL) {
7746 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
7747 if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
William M. Bracke7091952004-05-11 15:09:58 +00007748 ns = schema->targetNamespace;
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00007749 } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007750 xmlSchemaPSimpleTypeErr(ctxt,
7751 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
7752 NULL, (xmlNodePtr) attr,
7753 NULL, "(qualified | unqualified)",
7754 attrValue, NULL, NULL, NULL);
Kasimier T. Buchcikb4a9e642004-08-30 10:56:53 +00007755 }
7756 } else if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007757 ns = schema->targetNamespace;
7758 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007759 decl = xmlSchemaAddElement(ctxt, schema, name, ns, node, topLevel);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007760 if (decl == NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007761 goto return_null;
William M. Bracke7091952004-05-11 15:09:58 +00007762 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007763 decl->type = XML_SCHEMA_TYPE_ELEMENT;
7764 decl->node = node;
7765 decl->targetNamespace = ns;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007766 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00007767 * Check for illegal attributes.
7768 */
William M. Bracke7091952004-05-11 15:09:58 +00007769 attr = node->properties;
7770 while (attr != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007771 if (attr->ns == NULL) {
7772 if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
7773 (!xmlStrEqual(attr->name, BAD_CAST "type")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007774 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00007775 (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007776 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00007777 (!xmlStrEqual(attr->name, BAD_CAST "block")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007778 (!xmlStrEqual(attr->name, BAD_CAST "nillable")))
7779 {
7780 if (topLevel == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007781 if ((!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00007782 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007783 (!xmlStrEqual(attr->name, BAD_CAST "form")))
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00007784 {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00007785 xmlSchemaPIllegalAttrErr(ctxt,
7786 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
7787 NULL, (xmlSchemaTypePtr) decl, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007788 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007789 } else if ((!xmlStrEqual(attr->name, BAD_CAST "final")) &&
7790 (!xmlStrEqual(attr->name, BAD_CAST "abstract")) &&
Daniel Veillardc0826a72004-08-10 14:17:33 +00007791 (!xmlStrEqual(attr->name, BAD_CAST "substitutionGroup"))) {
7792
7793 xmlSchemaPIllegalAttrErr(ctxt,
7794 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007795 NULL, (xmlSchemaTypePtr) decl, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007796 }
7797 }
7798 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007799
Daniel Veillardc0826a72004-08-10 14:17:33 +00007800 xmlSchemaPIllegalAttrErr(ctxt,
7801 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007802 NULL, (xmlSchemaTypePtr) decl, attr);
William M. Bracke7091952004-05-11 15:09:58 +00007803 }
7804 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007805 }
William M. Bracke7091952004-05-11 15:09:58 +00007806 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00007807 * Extract/validate attributes.
7808 */
7809 if (topLevel) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007810 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00007811 * Process top attributes of global element declarations here.
7812 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007813 decl->flags |= XML_SCHEMAS_ELEM_GLOBAL;
7814 decl->flags |= XML_SCHEMAS_ELEM_TOPLEVEL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007815 xmlSchemaPValAttrQName(ctxt, schema, NULL,
7816 (xmlSchemaTypePtr) decl, node, "substitutionGroup",
7817 &(decl->substGroupNs), &(decl->substGroup));
7818 if (xmlGetBooleanProp(ctxt, NULL, (xmlSchemaTypePtr) decl,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007819 node, "abstract", 0))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007820 decl->flags |= XML_SCHEMAS_ELEM_ABSTRACT;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007821 /*
7822 * Attribute "final".
7823 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007824 attr = xmlSchemaGetPropNode(node, "final");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007825 if (attr == NULL) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00007826 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
7827 decl->flags |= XML_SCHEMAS_ELEM_FINAL_EXTENSION;
7828 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
7829 decl->flags |= XML_SCHEMAS_ELEM_FINAL_RESTRICTION;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007830 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007831 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
7832 if (xmlSchemaPValAttrBlockFinal(attrValue, &(decl->flags),
Daniel Veillardc0826a72004-08-10 14:17:33 +00007833 -1,
7834 XML_SCHEMAS_ELEM_FINAL_EXTENSION,
7835 XML_SCHEMAS_ELEM_FINAL_RESTRICTION, -1, -1, -1) != 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007836 xmlSchemaPSimpleTypeErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007837 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007838 (xmlSchemaTypePtr) decl, (xmlNodePtr) attr,
7839 NULL, "(#all | List of (extension | restriction))",
Daniel Veillardc0826a72004-08-10 14:17:33 +00007840 attrValue, NULL, NULL, NULL);
7841 }
7842 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007843 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00007844 /*
7845 * Attribute "block".
7846 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007847 attr = xmlSchemaGetPropNode(node, "block");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007848 if (attr == NULL) {
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +00007849 /*
7850 * Apply default "block" values.
7851 */
7852 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
7853 decl->flags |= XML_SCHEMAS_ELEM_BLOCK_RESTRICTION;
7854 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
7855 decl->flags |= XML_SCHEMAS_ELEM_BLOCK_EXTENSION;
7856 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
7857 decl->flags |= XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007858 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007859 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
7860 if (xmlSchemaPValAttrBlockFinal(attrValue, &(decl->flags),
Daniel Veillardc0826a72004-08-10 14:17:33 +00007861 -1,
7862 XML_SCHEMAS_ELEM_BLOCK_EXTENSION,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007863 XML_SCHEMAS_ELEM_BLOCK_RESTRICTION,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007864 XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION, -1, -1) != 0) {
7865 xmlSchemaPSimpleTypeErr(ctxt,
7866 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007867 (xmlSchemaTypePtr) decl, (xmlNodePtr) attr,
William M. Brack2f2a6632004-08-20 23:09:47 +00007868 NULL, "(#all | List of (extension | "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007869 "restriction | substitution))", attrValue,
7870 NULL, NULL, NULL);
Daniel Veillardc0826a72004-08-10 14:17:33 +00007871 }
7872 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007873 if (xmlGetBooleanProp(ctxt, NULL, (xmlSchemaTypePtr) decl,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007874 node, "nillable", 0))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007875 decl->flags |= XML_SCHEMAS_ELEM_NILLABLE;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00007876
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007877 attr = xmlSchemaGetPropNode(node, "type");
7878 if (attr != NULL) {
7879 xmlSchemaPValAttrNodeQName(ctxt, schema,
7880 NULL, (xmlSchemaTypePtr) decl, attr,
7881 &(decl->namedTypeNs), &(decl->namedType));
7882 xmlSchemaCheckReference(ctxt, schema, node,
7883 (xmlSchemaBasicItemPtr) decl, decl->namedTypeNs);
7884 }
7885 decl->value = xmlSchemaGetProp(ctxt, node, "default");
7886 attr = xmlSchemaGetPropNode(node, "fixed");
Daniel Veillardc0826a72004-08-10 14:17:33 +00007887 if (attr != NULL) {
7888 fixed = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007889 if (decl->value != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007890 /*
7891 * 3.3.3 : 1
7892 * default and fixed must not both be present.
Daniel Veillardc0826a72004-08-10 14:17:33 +00007893 */
7894 xmlSchemaPMutualExclAttrErr(ctxt,
7895 XML_SCHEMAP_SRC_ELEMENT_1,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007896 NULL, (xmlSchemaTypePtr) decl, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007897 "default", "fixed");
7898 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007899 decl->flags |= XML_SCHEMAS_ELEM_FIXED;
7900 decl->value = fixed;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007901 }
William M. Bracke7091952004-05-11 15:09:58 +00007902 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007903 /*
7904 * And now for the children...
7905 */
7906 oldcontainer = ctxt->container;
7907 ctxt->container = decl->name;
William M. Bracke7091952004-05-11 15:09:58 +00007908 if (IS_SCHEMA(child, "complexType")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007909 /*
7910 * 3.3.3 : 3
Daniel Veillardc0826a72004-08-10 14:17:33 +00007911 * "type" and either <simpleType> or <complexType> are mutually
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007912 * exclusive
Daniel Veillardc0826a72004-08-10 14:17:33 +00007913 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007914 if (decl->namedType != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007915 xmlSchemaPContentErr(ctxt,
7916 XML_SCHEMAP_SRC_ELEMENT_3,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007917 NULL, (xmlSchemaTypePtr) decl, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007918 "The attribute 'type' and the <complexType> child are "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007919 "mutually exclusive", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00007920 } else
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00007921 ELEM_TYPE(decl) = xmlSchemaParseComplexType(ctxt, schema, child, 0);
William M. Bracke7091952004-05-11 15:09:58 +00007922 child = child->next;
7923 } else if (IS_SCHEMA(child, "simpleType")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007924 /*
7925 * 3.3.3 : 3
Daniel Veillardc0826a72004-08-10 14:17:33 +00007926 * "type" and either <simpleType> or <complexType> are
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007927 * mutually exclusive
Daniel Veillardc0826a72004-08-10 14:17:33 +00007928 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007929 if (decl->namedType != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007930 xmlSchemaPContentErr(ctxt,
7931 XML_SCHEMAP_SRC_ELEMENT_3,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007932 NULL, (xmlSchemaTypePtr) decl, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007933 "The attribute 'type' and the <simpleType> child are "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007934 "mutually exclusive", NULL);
William M. Bracke7091952004-05-11 15:09:58 +00007935 } else
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00007936 ELEM_TYPE(decl) = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
William M. Bracke7091952004-05-11 15:09:58 +00007937 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007938 }
William M. Bracke7091952004-05-11 15:09:58 +00007939 while ((IS_SCHEMA(child, "unique")) ||
Daniel Veillardc0826a72004-08-10 14:17:33 +00007940 (IS_SCHEMA(child, "key")) || (IS_SCHEMA(child, "keyref"))) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007941 if (IS_SCHEMA(child, "unique")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007942 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007943 XML_SCHEMA_TYPE_IDC_UNIQUE, decl->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007944 } else if (IS_SCHEMA(child, "key")) {
7945 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007946 XML_SCHEMA_TYPE_IDC_KEY, decl->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007947 } else if (IS_SCHEMA(child, "keyref")) {
7948 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007949 XML_SCHEMA_TYPE_IDC_KEYREF, decl->targetNamespace);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007950 }
7951 if (lastIDC != NULL)
7952 lastIDC->next = curIDC;
7953 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007954 decl->idcs = (void *) curIDC;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007955 lastIDC = curIDC;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +00007956 child = child->next;
William M. Bracke7091952004-05-11 15:09:58 +00007957 }
7958 if (child != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00007959 xmlSchemaPContentErr(ctxt,
7960 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007961 NULL, (xmlSchemaTypePtr) decl, node, child,
Daniel Veillardc0826a72004-08-10 14:17:33 +00007962 NULL, "(annotation?, ((simpleType | complexType)?, "
7963 "(unique | key | keyref)*))");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007964 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007965 ctxt->container = oldcontainer;
7966 decl->annot = annot;
Daniel Veillardc0826a72004-08-10 14:17:33 +00007967 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00007968 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007969 * NOTE: Element Declaration Representation OK 4. will be checked at a
Daniel Veillardc0826a72004-08-10 14:17:33 +00007970 * different layer.
7971 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007972 FREE_AND_NULL(des)
7973 if (topLevel)
7974 return ((xmlSchemaBasicItemPtr) decl);
7975 else {
7976 particle->children = (xmlSchemaTreeItemPtr) decl;
7977 return ((xmlSchemaBasicItemPtr) particle);
7978 }
7979
7980return_null:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007981 FREE_AND_NULL(des);
7982 if (annot != NULL) {
7983 if (particle != NULL)
7984 particle->annot = NULL;
7985 if (decl != NULL)
7986 decl->annot = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007987 xmlSchemaFreeAnnot(annot);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00007988 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00007989 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00007990}
7991
7992/**
7993 * xmlSchemaParseUnion:
7994 * @ctxt: a schema validation context
7995 * @schema: the schema being built
7996 * @node: a subtree containing XML Schema informations
7997 *
7998 * parse a XML schema Union definition
7999 * *WARNING* this interface is highly subject to change
8000 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008001 * Returns -1 in case of internal error, 0 in case of success and a positive
8002 * error code otherwise.
Daniel Veillard4255d502002-04-16 15:50:10 +00008003 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008004static int
Daniel Veillard4255d502002-04-16 15:50:10 +00008005xmlSchemaParseUnion(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008006 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00008007{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008008 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +00008009 xmlNodePtr child = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00008010 xmlAttrPtr attr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008011 const xmlChar *cur = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00008012
8013 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008014 return (-1);
8015 /* Not a component, don't create it. */
8016 type = ctxt->ctxtType;
8017 /*
8018 * Mark the simple type as being of variety "union".
8019 */
8020 type->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008021 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00008022 * SPEC (Base type) (2) "If the <list> or <union> alternative is chosen,
8023 * then the ·simple ur-type definition·."
8024 */
8025 type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
William M. Brack2f2a6632004-08-20 23:09:47 +00008026 /*
8027 * Check for illegal attributes.
8028 */
8029 attr = node->properties;
8030 while (attr != NULL) {
8031 if (attr->ns == NULL) {
8032 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8033 (!xmlStrEqual(attr->name, BAD_CAST "memberTypes"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008034 xmlSchemaPIllegalAttrErr(ctxt,
8035 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8036 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00008037 }
8038 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008039 xmlSchemaPIllegalAttrErr(ctxt,
8040 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8041 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00008042 }
8043 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008044 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00008045 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +00008046 /*
8047 * Attribute "memberTypes". This is a list of QNames.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008048 * TODO: Check the value to contain anything.
William M. Brack2f2a6632004-08-20 23:09:47 +00008049 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008050 attr = xmlSchemaGetPropNode(node, "memberTypes");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008051 if (attr != NULL) {
8052 const xmlChar *end;
8053 xmlChar *tmp;
8054 const xmlChar *localName, *nsName;
8055 xmlSchemaTypeLinkPtr link, lastLink = NULL;
8056 xmlSchemaQNameRefPtr ref;
8057
8058 cur = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008059 type->ref = cur;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008060 do {
8061 while (IS_BLANK_CH(*cur))
8062 cur++;
8063 end = cur;
8064 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
8065 end++;
8066 if (end == cur)
8067 break;
8068 tmp = xmlStrndup(cur, end - cur);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008069 if (xmlSchemaPValAttrNodeQNameValue(ctxt, schema, NULL,
8070 NULL, attr, BAD_CAST tmp, &nsName, &localName) == 0) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008071 /*
8072 * Create the member type link.
8073 */
8074 link = (xmlSchemaTypeLinkPtr)
8075 xmlMalloc(sizeof(xmlSchemaTypeLink));
8076 if (link == NULL) {
8077 xmlSchemaPErrMemory(ctxt, "xmlSchemaParseUnion, "
8078 "allocating a type link", NULL);
8079 return (-1);
8080 }
8081 link->type = NULL;
8082 link->next = NULL;
8083 if (lastLink == NULL)
8084 type->memberTypes = link;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008085 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008086 lastLink->next = link;
8087 lastLink = link;
8088 /*
8089 * Create a reference item.
8090 */
8091 ref = xmlSchemaNewQNameRef(schema, XML_SCHEMA_TYPE_SIMPLE,
8092 localName, nsName);
8093 if (ref == NULL) {
8094 FREE_AND_NULL(tmp)
8095 return (-1);
8096 }
8097 /*
8098 * Assign the reference to the link, it will be resolved
8099 * later during fixup of the union simple type.
8100 */
8101 link->type = (xmlSchemaTypePtr) ref;
8102 }
8103 FREE_AND_NULL(tmp)
8104 cur = end;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008105 } while (*cur != 0);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008106
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008107 }
William M. Brack2f2a6632004-08-20 23:09:47 +00008108 /*
8109 * And now for the children...
8110 */
Daniel Veillard4255d502002-04-16 15:50:10 +00008111 child = node->children;
8112 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008113 /*
8114 * Add the annotation to the simple type ancestor.
8115 */
8116 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
8117 xmlSchemaParseAnnotation(ctxt, schema, child));
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008118 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008119 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008120 if (IS_SCHEMA(child, "simpleType")) {
8121 xmlSchemaTypePtr subtype, last = NULL;
8122
8123 /*
8124 * Anchor the member types in the "subtypes" field of the
8125 * simple type.
8126 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008127 while (IS_SCHEMA(child, "simpleType")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008128 subtype = (xmlSchemaTypePtr)
8129 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
8130 if (subtype != NULL) {
8131 if (last == NULL) {
8132 type->subtypes = subtype;
8133 last = subtype;
8134 } else {
8135 last->next = subtype;
8136 last = subtype;
8137 }
8138 last->next = NULL;
8139 }
8140 child = child->next;
8141 }
Daniel Veillard4255d502002-04-16 15:50:10 +00008142 }
8143 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008144 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008145 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008146 NULL, NULL, node, child, NULL, "(annotation?, simpleType*)");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008147 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008148 if ((attr == NULL) && (type->subtypes == NULL)) {
8149 /*
8150 * src-union-memberTypes-or-simpleTypes
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008151 * Either the memberTypes [attribute] of the <union> element must
8152 * be non-empty or there must be at least one simpleType [child].
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008153 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008154 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008155 XML_SCHEMAP_SRC_UNION_MEMBERTYPES_OR_SIMPLETYPES,
8156 NULL, NULL, node,
8157 "Either the attribute 'memberTypes' or "
8158 "at least one <simpleType> child must be present", NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008159 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008160 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +00008161}
8162
8163/**
8164 * xmlSchemaParseList:
8165 * @ctxt: a schema validation context
8166 * @schema: the schema being built
8167 * @node: a subtree containing XML Schema informations
8168 *
8169 * parse a XML schema List definition
8170 * *WARNING* this interface is highly subject to change
8171 *
William M. Bracke7091952004-05-11 15:09:58 +00008172 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00008173 * 1 in case of success.
8174 */
8175static xmlSchemaTypePtr
8176xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008177 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00008178{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008179 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +00008180 xmlNodePtr child = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00008181 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +00008182
8183 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8184 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008185 /* Not a component, don't create it. */
8186 type = ctxt->ctxtType;
8187 /*
8188 * Mark the type as being of variety "list".
8189 */
8190 type->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008191 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00008192 * SPEC (Base type) (2) "If the <list> or <union> alternative is chosen,
8193 * then the ·simple ur-type definition·."
8194 */
8195 type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
William M. Brack2f2a6632004-08-20 23:09:47 +00008196 /*
8197 * Check for illegal attributes.
8198 */
8199 attr = node->properties;
8200 while (attr != NULL) {
8201 if (attr->ns == NULL) {
8202 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8203 (!xmlStrEqual(attr->name, BAD_CAST "itemType"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008204 xmlSchemaPIllegalAttrErr(ctxt,
8205 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8206 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00008207 }
8208 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008209 xmlSchemaPIllegalAttrErr(ctxt,
8210 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8211 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00008212 }
8213 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008214 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008215
8216 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
8217
William M. Brack2f2a6632004-08-20 23:09:47 +00008218 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008219 * Attribute "itemType". NOTE that we will use the "ref" and "refNs"
8220 * fields for holding the reference to the itemType.
William M. Brack2f2a6632004-08-20 23:09:47 +00008221 */
8222 xmlSchemaPValAttrQName(ctxt, schema, NULL, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008223 node, "itemType", &(type->refNs), &(type->ref));
William M. Brack2f2a6632004-08-20 23:09:47 +00008224 /*
8225 * And now for the children...
8226 */
Daniel Veillard4255d502002-04-16 15:50:10 +00008227 child = node->children;
8228 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008229 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
8230 xmlSchemaParseAnnotation(ctxt, schema, child));
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008231 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008232 }
William M. Brack2f2a6632004-08-20 23:09:47 +00008233 if (IS_SCHEMA(child, "simpleType")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008234 /*
8235 * src-list-itemType-or-simpleType
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008236 * Either the itemType [attribute] or the <simpleType> [child] of
8237 * the <list> element must be present, but not both.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008238 */
8239 if (type->ref != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008240 xmlSchemaPCustomErr(ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00008241 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008242 NULL, NULL, node,
William M. Brack2f2a6632004-08-20 23:09:47 +00008243 "The attribute 'itemType' and the <simpleType> child "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008244 "are mutually exclusive", NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008245 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008246 type->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
William M. Brack2f2a6632004-08-20 23:09:47 +00008247 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008248 child = child->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008249 } else if (type->ref == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008250 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008251 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008252 NULL, NULL, node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008253 "Either the attribute 'itemType' or the <simpleType> child "
8254 "must be present", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00008255 }
8256 if (child != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00008257 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008258 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008259 NULL, NULL, node, child, NULL, "(annotation?, simpleType?)");
Daniel Veillard4255d502002-04-16 15:50:10 +00008260 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008261 if ((type->ref == NULL) &&
8262 (type->subtypes == NULL) &&
8263 (xmlSchemaGetPropNode(node, "itemType") == NULL)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008264 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008265 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008266 NULL, NULL, node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008267 "Either the attribute 'itemType' or the <simpleType> child "
8268 "must be present", NULL);
8269 }
8270 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +00008271}
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008272
Daniel Veillard4255d502002-04-16 15:50:10 +00008273/**
8274 * xmlSchemaParseSimpleType:
8275 * @ctxt: a schema validation context
8276 * @schema: the schema being built
8277 * @node: a subtree containing XML Schema informations
8278 *
8279 * parse a XML schema Simple Type definition
8280 * *WARNING* this interface is highly subject to change
8281 *
William M. Bracke7091952004-05-11 15:09:58 +00008282 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillardc0826a72004-08-10 14:17:33 +00008283 * 1 in case of success.
Daniel Veillard4255d502002-04-16 15:50:10 +00008284 */
8285static xmlSchemaTypePtr
8286xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +00008287 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +00008288{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008289 xmlSchemaTypePtr type, oldCtxtType, oldParentItem;
Daniel Veillard4255d502002-04-16 15:50:10 +00008290 xmlNodePtr child = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008291 const xmlChar *attrValue = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008292 xmlAttrPtr attr;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00008293 int hasRestriction = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00008294
8295 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8296 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008297
Daniel Veillardc0826a72004-08-10 14:17:33 +00008298 if (topLevel) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008299 attr = xmlSchemaGetPropNode(node, "name");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008300 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008301 xmlSchemaPMissingAttrErr(ctxt,
8302 XML_SCHEMAP_S4S_ATTR_MISSING,
8303 NULL, node,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008304 "name", NULL);
8305 return (NULL);
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00008306 } else {
8307 if (xmlSchemaPValAttrNode(ctxt,
8308 NULL, NULL, attr,
8309 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &attrValue) != 0)
8310 return (NULL);
8311 /*
8312 * Skip built-in types.
8313 */
8314 if (ctxt->isS4S) {
8315 xmlSchemaTypePtr biType;
8316
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00008317 if (ctxt->isRedefine) {
8318 /*
8319 * REDEFINE: Disallow redefinition of built-in-types.
8320 * TODO: It seems that the spec does not say anything
8321 * about this case.
8322 */
8323 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_SRC_REDEFINE,
8324 NULL, NULL, node,
8325 "Redefinition of built-in simple types is not "
8326 "supported", NULL);
8327 return(NULL);
8328 }
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00008329 biType = xmlSchemaGetPredefinedType(attrValue, xmlSchemaNs);
8330 if (biType != NULL)
8331 return (biType);
8332 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00008333 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00008334 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008335
Daniel Veillardc0826a72004-08-10 14:17:33 +00008336 if (topLevel == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008337 char buf[40];
Daniel Veillardc0826a72004-08-10 14:17:33 +00008338
Daniel Veillard01fa6152004-06-29 17:04:39 +00008339 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +00008340 * Parse as local simple type definition.
Daniel Veillard01fa6152004-06-29 17:04:39 +00008341 */
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +00008342 snprintf(buf, 39, "#ST%d", ctxt->counter++ + 1);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00008343 type = xmlSchemaAddType(ctxt, schema, (const xmlChar *)buf, NULL,
8344 node, 0);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008345 if (type == NULL)
8346 return (NULL);
8347 type->node = node;
8348 type->type = XML_SCHEMA_TYPE_SIMPLE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008349 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008350 /*
8351 * Check for illegal attributes.
8352 */
8353 attr = node->properties;
8354 while (attr != NULL) {
8355 if (attr->ns == NULL) {
8356 if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008357 xmlSchemaPIllegalAttrErr(ctxt,
8358 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8359 NULL, type, attr);
Daniel Veillard01fa6152004-06-29 17:04:39 +00008360 }
Daniel Veillardc0826a72004-08-10 14:17:33 +00008361 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008362 xmlSchemaPIllegalAttrErr(ctxt,
8363 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8364 NULL, type, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008365 }
8366 attr = attr->next;
Daniel Veillard01fa6152004-06-29 17:04:39 +00008367 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008368 } else {
Daniel Veillardc0826a72004-08-10 14:17:33 +00008369 /*
8370 * Parse as global simple type definition.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008371 *
8372 * Note that attrValue is the value of the attribute "name" here.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008373 */
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00008374 type = xmlSchemaAddType(ctxt, schema, attrValue,
8375 schema->targetNamespace, node, 1);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008376 if (type == NULL)
8377 return (NULL);
8378 type->node = node;
8379 type->type = XML_SCHEMA_TYPE_SIMPLE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008380 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008381 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
8382 /*
8383 * Check for illegal attributes.
8384 */
8385 attr = node->properties;
8386 while (attr != NULL) {
8387 if (attr->ns == NULL) {
8388 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8389 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008390 (!xmlStrEqual(attr->name, BAD_CAST "final"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008391 xmlSchemaPIllegalAttrErr(ctxt,
8392 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8393 NULL, type, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008394 }
8395 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008396 xmlSchemaPIllegalAttrErr(ctxt,
8397 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8398 NULL, type, attr);
Daniel Veillardc0826a72004-08-10 14:17:33 +00008399 }
8400 attr = attr->next;
8401 }
8402 /*
8403 * Attribute "final".
8404 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008405 attr = xmlSchemaGetPropNode(node, "final");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008406 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008407 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
8408 type->flags |= XML_SCHEMAS_TYPE_FINAL_RESTRICTION;
8409 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST)
8410 type->flags |= XML_SCHEMAS_TYPE_FINAL_LIST;
8411 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION)
8412 type->flags |= XML_SCHEMAS_TYPE_FINAL_UNION;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008413 } else {
8414 attrValue = xmlSchemaGetProp(ctxt, node, "final");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008415 if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
8416 -1, -1, XML_SCHEMAS_TYPE_FINAL_RESTRICTION, -1,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008417 XML_SCHEMAS_TYPE_FINAL_LIST,
8418 XML_SCHEMAS_TYPE_FINAL_UNION) != 0) {
8419
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008420 xmlSchemaPSimpleTypeErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008421 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008422 type, (xmlNodePtr) attr,
8423 NULL, "(#all | List of (list | union | restriction)",
Daniel Veillardc0826a72004-08-10 14:17:33 +00008424 attrValue, NULL, NULL, NULL);
8425 }
8426 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008427 }
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +00008428 type->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +00008429 xmlSchemaPValAttrID(ctxt, NULL, type, node, BAD_CAST "id");
Daniel Veillardc0826a72004-08-10 14:17:33 +00008430 /*
8431 * And now for the children...
8432 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008433 oldCtxtType = ctxt->ctxtType;
8434 oldParentItem = ctxt->parentItem;
Daniel Veillardc0826a72004-08-10 14:17:33 +00008435 ctxt->ctxtType = type;
8436 ctxt->parentItem = type;
Daniel Veillard4255d502002-04-16 15:50:10 +00008437 child = node->children;
8438 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008439 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8440 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008441 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008442 if (child == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008443 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_MISSING,
8444 NULL, type, node, child, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008445 "(annotation?, (restriction | list | union))");
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00008446 } else if (IS_SCHEMA(child, "restriction")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008447 xmlSchemaParseRestriction(ctxt, schema, child,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00008448 XML_SCHEMA_TYPE_SIMPLE);
8449 hasRestriction = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008450 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008451 } else if (IS_SCHEMA(child, "list")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008452 xmlSchemaParseList(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008453 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008454 } else if (IS_SCHEMA(child, "union")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008455 xmlSchemaParseUnion(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +00008456 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +00008457 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008458 if (child != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008459 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8460 NULL, type, node, child, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008461 "(annotation?, (restriction | list | union))");
Daniel Veillard4255d502002-04-16 15:50:10 +00008462 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00008463 /*
8464 * REDEFINE: SPEC src-redefine (5)
8465 * "Within the [children], each <simpleType> must have a
8466 * <restriction> among its [children] ... the ·actual value· of whose
8467 * base [attribute] must be the same as the ·actual value· of its own
8468 * name attribute plus target namespace;"
8469 */
8470 if (topLevel && ctxt->isRedefine && (! hasRestriction)) {
8471 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_SRC_REDEFINE,
8472 NULL, NULL, node, "This is a redefinition, thus the "
8473 "<simpleType> must have a <restriction> child", NULL);
8474 }
8475
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00008476 ctxt->parentItem = oldParentItem;
8477 ctxt->ctxtType = oldCtxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +00008478 return (type);
8479}
8480
Daniel Veillard4255d502002-04-16 15:50:10 +00008481/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008482 * xmlSchemaParseModelGroupDefRef:
Daniel Veillard4255d502002-04-16 15:50:10 +00008483 * @ctxt: a schema validation context
8484 * @schema: the schema being built
8485 * @node: a subtree containing XML Schema informations
8486 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008487 * Parses a XML schema particle (reference to a model group definition).
Daniel Veillard4255d502002-04-16 15:50:10 +00008488 * *WARNING* this interface is highly subject to change
8489 *
William M. Bracke7091952004-05-11 15:09:58 +00008490 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00008491 * 1 in case of success.
8492 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008493static xmlSchemaTreeItemPtr
8494xmlSchemaParseModelGroupDefRef(xmlSchemaParserCtxtPtr ctxt,
8495 xmlSchemaPtr schema,
8496 xmlNodePtr node)
Daniel Veillard4255d502002-04-16 15:50:10 +00008497{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008498 xmlSchemaParticlePtr item;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008499 xmlNodePtr child = NULL;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008500 xmlAttrPtr attr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008501 const xmlChar *ref = NULL, *refNs = NULL;
8502 int min, max;
8503
8504 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008505 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008506
8507 attr = xmlSchemaGetPropNode(node, "ref");
8508 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008509 xmlSchemaPMissingAttrErr(ctxt,
8510 XML_SCHEMAP_S4S_ATTR_MISSING,
8511 NULL, node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008512 "ref", NULL);
8513 return (NULL);
8514 } else if (xmlSchemaPValAttrNodeQName(ctxt, schema, NULL, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008515 attr, &refNs, &ref) != 0) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008516 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008517 }
8518 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008519 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008520 "(xs:nonNegativeInteger | unbounded)");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008521 /*
8522 * Check for illegal attributes.
8523 */
8524 attr = node->properties;
8525 while (attr != NULL) {
8526 if (attr->ns == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008527 if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008528 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8529 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
8530 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008531 xmlSchemaPIllegalAttrErr(ctxt,
8532 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8533 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008534 }
8535 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008536 xmlSchemaPIllegalAttrErr(ctxt,
8537 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8538 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008539 }
8540 attr = attr->next;
8541 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008542 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008543 item = xmlSchemaAddParticle(ctxt, schema, node, min, max);
8544 if (item == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008545 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008546 /*
8547 * Create a reference item as the term; it will be substituted for
8548 * the model group after the reference has been resolved.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008549 */
8550 item->children = (xmlSchemaTreeItemPtr)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008551 xmlSchemaNewQNameRef(schema, XML_SCHEMA_TYPE_GROUP, ref, refNs);
8552 xmlSchemaCheckReference(ctxt, schema, node, (xmlSchemaBasicItemPtr) item, refNs);
8553 xmlSchemaPCheckParticleCorrect_2(ctxt, item, node, min, max);
8554 /*
8555 * And now for the children...
8556 */
8557 child = node->children;
8558 /* TODO: Is annotation even allowed for a model group reference? */
8559 if (IS_SCHEMA(child, "annotation")) {
8560 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008561 * TODO: What to do exactly with the annotation?
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008562 */
8563 item->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8564 child = child->next;
8565 }
8566 if (child != NULL) {
8567 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008568 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008569 NULL, NULL, node, child, NULL,
8570 "(annotation?)");
8571 }
8572 /*
8573 * Corresponds to no component at all if minOccurs==maxOccurs==0.
8574 */
8575 if ((min == 0) && (max == 0))
8576 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008577 if (ctxt->assemble != NULL)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008578 xmlSchemaAddAssembledItem(ctxt, (xmlSchemaTypePtr) item);
8579 return ((xmlSchemaTreeItemPtr) item);
8580}
8581
8582/**
8583 * xmlSchemaParseModelGroupDefinition:
8584 * @ctxt: a schema validation context
8585 * @schema: the schema being built
8586 * @node: a subtree containing XML Schema informations
8587 *
8588 * Parses a XML schema model group definition.
8589 * *WARNING* this interface is highly subject to change
8590 *
8591 * Returns -1 in case of error, 0 if the declaration is improper and
8592 * 1 in case of success.
8593 */
8594static xmlSchemaModelGroupDefPtr
8595xmlSchemaParseModelGroupDefinition(xmlSchemaParserCtxtPtr ctxt,
8596 xmlSchemaPtr schema,
8597 xmlNodePtr node)
8598{
8599 xmlSchemaModelGroupDefPtr item;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008600 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008601 xmlAttrPtr attr;
8602 const xmlChar *name;
Daniel Veillard4255d502002-04-16 15:50:10 +00008603
8604 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008605 return (NULL);
8606
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008607 attr = xmlSchemaGetPropNode(node, "name");
8608 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008609 xmlSchemaPMissingAttrErr(ctxt,
8610 XML_SCHEMAP_S4S_ATTR_MISSING,
8611 NULL, node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008612 "name", NULL);
8613 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008614 } else if (xmlSchemaPValAttrNode(ctxt,
8615 NULL, NULL, attr,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008616 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
8617 return (NULL);
8618 }
8619 item = xmlSchemaAddGroup(ctxt, schema, name, schema->targetNamespace, node);
8620 if (item == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008621 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008622 /*
8623 * Check for illegal attributes.
8624 */
8625 attr = node->properties;
8626 while (attr != NULL) {
8627 if (attr->ns == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008628 if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008629 (!xmlStrEqual(attr->name, BAD_CAST "id"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008630 xmlSchemaPIllegalAttrErr(ctxt,
8631 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8632 NULL, NULL, attr);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008633 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008634 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008635 xmlSchemaPIllegalAttrErr(ctxt,
8636 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
8637 NULL, NULL, attr);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008638 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008639 attr = attr->next;
8640 }
8641 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
8642 /*
8643 * And now for the children...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008644 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008645 child = node->children;
8646 if (IS_SCHEMA(child, "annotation")) {
8647 item->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8648 child = child->next;
8649 }
8650 if (IS_SCHEMA(child, "all")) {
8651 item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
8652 XML_SCHEMA_TYPE_ALL, 0);
8653 child = child->next;
8654 } else if (IS_SCHEMA(child, "choice")) {
8655 item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
8656 XML_SCHEMA_TYPE_CHOICE, 0);
8657 child = child->next;
8658 } else if (IS_SCHEMA(child, "sequence")) {
8659 item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
8660 XML_SCHEMA_TYPE_SEQUENCE, 0);
8661 child = child->next;
8662 }
8663 if (child != NULL) {
8664 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008665 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8666 NULL, NULL, node, child, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008667 "(annotation?, (all | choice | sequence)?)");
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008668 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008669
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008670 return (item);
Daniel Veillard4255d502002-04-16 15:50:10 +00008671}
8672
8673/**
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008674 * xmlSchemaCleanupDoc:
8675 * @ctxt: a schema validation context
8676 * @node: the root of the document.
8677 *
8678 * removes unwanted nodes in a schemas document tree
8679 */
8680static void
8681xmlSchemaCleanupDoc(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr root)
8682{
8683 xmlNodePtr delete, cur;
8684
8685 if ((ctxt == NULL) || (root == NULL)) return;
8686
8687 /*
8688 * Remove all the blank text nodes
8689 */
8690 delete = NULL;
8691 cur = root;
8692 while (cur != NULL) {
8693 if (delete != NULL) {
8694 xmlUnlinkNode(delete);
8695 xmlFreeNode(delete);
8696 delete = NULL;
8697 }
8698 if (cur->type == XML_TEXT_NODE) {
8699 if (IS_BLANK_NODE(cur)) {
8700 if (xmlNodeGetSpacePreserve(cur) != 1) {
8701 delete = cur;
8702 }
8703 }
8704 } else if ((cur->type != XML_ELEMENT_NODE) &&
8705 (cur->type != XML_CDATA_SECTION_NODE)) {
8706 delete = cur;
8707 goto skip_children;
8708 }
8709
8710 /*
8711 * Skip to next node
8712 */
8713 if (cur->children != NULL) {
8714 if ((cur->children->type != XML_ENTITY_DECL) &&
8715 (cur->children->type != XML_ENTITY_REF_NODE) &&
8716 (cur->children->type != XML_ENTITY_NODE)) {
8717 cur = cur->children;
8718 continue;
8719 }
8720 }
8721 skip_children:
8722 if (cur->next != NULL) {
8723 cur = cur->next;
8724 continue;
8725 }
8726
8727 do {
8728 cur = cur->parent;
8729 if (cur == NULL)
8730 break;
8731 if (cur == root) {
8732 cur = NULL;
8733 break;
8734 }
8735 if (cur->next != NULL) {
8736 cur = cur->next;
8737 break;
8738 }
8739 } while (cur != NULL);
8740 }
8741 if (delete != NULL) {
8742 xmlUnlinkNode(delete);
8743 xmlFreeNode(delete);
8744 delete = NULL;
8745 }
8746}
8747
William M. Brack2f2a6632004-08-20 23:09:47 +00008748
William M. Brack2f2a6632004-08-20 23:09:47 +00008749static void
8750xmlSchemaClearSchemaDefaults(xmlSchemaPtr schema)
8751{
8752 if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
8753 schema->flags ^= XML_SCHEMAS_QUALIF_ELEM;
8754
8755 if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
8756 schema->flags ^= XML_SCHEMAS_QUALIF_ATTR;
8757
8758 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
8759 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_EXTENSION;
8760 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
8761 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION;
8762 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST)
8763 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_LIST;
8764 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION)
8765 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_UNION;
8766
8767 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
8768 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION;
8769 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
8770 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION;
8771 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
8772 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION;
8773}
8774
8775static void
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008776xmlSchemaParseSchemaDefaults(xmlSchemaParserCtxtPtr ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00008777 xmlSchemaPtr schema,
8778 xmlNodePtr node)
8779{
8780 xmlAttrPtr attr;
8781 const xmlChar *val;
8782
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008783 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
8784 if (schema->version == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008785 xmlSchemaPValAttr(ctxt, NULL, NULL, node, "version",
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008786 xmlSchemaGetBuiltInType(XML_SCHEMAS_TOKEN), &(schema->version));
8787 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008788 xmlSchemaPValAttr(ctxt, NULL, NULL, node, "version",
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00008789 xmlSchemaGetBuiltInType(XML_SCHEMAS_TOKEN), NULL);
8790
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008791 attr = xmlSchemaGetPropNode(node, "elementFormDefault");
William M. Brack2f2a6632004-08-20 23:09:47 +00008792 if (attr != NULL) {
8793 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008794 if (xmlSchemaPValAttrFormDefault(val, &schema->flags,
William M. Brack2f2a6632004-08-20 23:09:47 +00008795 XML_SCHEMAS_QUALIF_ELEM) != 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008796 xmlSchemaPSimpleTypeErr(ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00008797 XML_SCHEMAP_ELEMFORMDEFAULT_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008798 NULL, (xmlNodePtr) attr, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +00008799 "(qualified | unqualified)", val, NULL, NULL, NULL);
8800 }
8801 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008802
8803 attr = xmlSchemaGetPropNode(node, "attributeFormDefault");
William M. Brack2f2a6632004-08-20 23:09:47 +00008804 if (attr != NULL) {
8805 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008806 if (xmlSchemaPValAttrFormDefault(val, &schema->flags,
William M. Brack2f2a6632004-08-20 23:09:47 +00008807 XML_SCHEMAS_QUALIF_ATTR) != 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008808 xmlSchemaPSimpleTypeErr(ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00008809 XML_SCHEMAP_ATTRFORMDEFAULT_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008810 NULL, (xmlNodePtr) attr, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +00008811 "(qualified | unqualified)", val, NULL, NULL, NULL);
8812 }
8813 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008814
8815 attr = xmlSchemaGetPropNode(node, "finalDefault");
William M. Brack2f2a6632004-08-20 23:09:47 +00008816 if (attr != NULL) {
8817 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8818 if (xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
8819 XML_SCHEMAS_FINAL_DEFAULT_EXTENSION,
8820 XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION,
8821 -1,
8822 XML_SCHEMAS_FINAL_DEFAULT_LIST,
8823 XML_SCHEMAS_FINAL_DEFAULT_UNION) != 0) {
8824 xmlSchemaPSimpleTypeErr(ctxt,
8825 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008826 NULL, (xmlNodePtr) attr, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +00008827 "(#all | List of (extension | restriction | list | union))",
8828 val, NULL, NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008829 }
William M. Brack2f2a6632004-08-20 23:09:47 +00008830 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008831
8832 attr = xmlSchemaGetPropNode(node, "blockDefault");
William M. Brack2f2a6632004-08-20 23:09:47 +00008833 if (attr != NULL) {
8834 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8835 if (xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
8836 XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION,
8837 XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION,
8838 XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION, -1, -1) != 0) {
8839 xmlSchemaPSimpleTypeErr(ctxt,
8840 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008841 NULL, (xmlNodePtr) attr, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +00008842 "(#all | List of (extension | restriction | substitution))",
8843 val, NULL, NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008844 }
William M. Brack2f2a6632004-08-20 23:09:47 +00008845 }
8846}
8847
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008848/**
8849 * xmlSchemaParseSchemaTopLevel:
8850 * @ctxt: a schema validation context
8851 * @schema: the schemas
8852 * @nodes: the list of top level nodes
8853 *
8854 * Returns the internal XML Schema structure built from the resource or
8855 * NULL in case of error
8856 */
8857static void
8858xmlSchemaParseSchemaTopLevel(xmlSchemaParserCtxtPtr ctxt,
8859 xmlSchemaPtr schema, xmlNodePtr nodes)
8860{
8861 xmlNodePtr child;
8862 xmlSchemaAnnotPtr annot;
8863
8864 if ((ctxt == NULL) || (schema == NULL) || (nodes == NULL))
8865 return;
8866
8867 child = nodes;
8868 while ((IS_SCHEMA(child, "include")) ||
8869 (IS_SCHEMA(child, "import")) ||
8870 (IS_SCHEMA(child, "redefine")) ||
8871 (IS_SCHEMA(child, "annotation"))) {
8872 if (IS_SCHEMA(child, "annotation")) {
8873 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8874 if (schema->annot == NULL)
8875 schema->annot = annot;
8876 else
8877 xmlSchemaFreeAnnot(annot);
8878 } else if (IS_SCHEMA(child, "import")) {
8879 xmlSchemaParseImport(ctxt, schema, child);
8880 } else if (IS_SCHEMA(child, "include")) {
Daniel Veillardb0f397e2003-12-23 23:30:53 +00008881 ctxt->includes++;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008882 xmlSchemaParseInclude(ctxt, schema, child);
Daniel Veillardb0f397e2003-12-23 23:30:53 +00008883 ctxt->includes--;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008884 } else if (IS_SCHEMA(child, "redefine")) {
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +00008885#ifdef ENABLE_REDEFINE
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00008886 xmlSchemaParseRedefine(ctxt, schema, child);
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +00008887#else
8888 TODO
8889#endif
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008890 }
8891 child = child->next;
8892 }
8893 while (child != NULL) {
8894 if (IS_SCHEMA(child, "complexType")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00008895 xmlSchemaParseComplexType(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008896 child = child->next;
8897 } else if (IS_SCHEMA(child, "simpleType")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00008898 xmlSchemaParseSimpleType(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008899 child = child->next;
8900 } else if (IS_SCHEMA(child, "element")) {
8901 xmlSchemaParseElement(ctxt, schema, child, 1);
8902 child = child->next;
8903 } else if (IS_SCHEMA(child, "attribute")) {
William M. Bracke7091952004-05-11 15:09:58 +00008904 xmlSchemaParseAttribute(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008905 child = child->next;
8906 } else if (IS_SCHEMA(child, "attributeGroup")) {
Daniel Veillard3646d642004-06-02 19:19:14 +00008907 xmlSchemaParseAttributeGroup(ctxt, schema, child, 1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008908 child = child->next;
8909 } else if (IS_SCHEMA(child, "group")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00008910 xmlSchemaParseModelGroupDefinition(ctxt, schema, child);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008911 child = child->next;
8912 } else if (IS_SCHEMA(child, "notation")) {
8913 xmlSchemaParseNotation(ctxt, schema, child);
8914 child = child->next;
8915 } else {
8916 xmlSchemaPErr2(ctxt, NULL, child,
8917 XML_SCHEMAP_UNKNOWN_SCHEMAS_CHILD,
Daniel Veillardc0826a72004-08-10 14:17:33 +00008918 "Unexpected element \"%s\" as child of <schema>.\n",
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008919 child->name, NULL);
8920 child = child->next;
8921 }
8922 while (IS_SCHEMA(child, "annotation")) {
8923 annot = xmlSchemaParseAnnotation(ctxt, schema, child);
8924 if (schema->annot == NULL)
8925 schema->annot = annot;
8926 else
8927 xmlSchemaFreeAnnot(annot);
8928 child = child->next;
8929 }
8930 }
Daniel Veillard01fa6152004-06-29 17:04:39 +00008931 ctxt->parentItem = NULL;
8932 ctxt->ctxtType = NULL;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00008933}
8934
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008935static xmlSchemaImportPtr
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008936xmlSchemaAddImport(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008937 xmlHashTablePtr *imports,
8938 const xmlChar *nsName)
8939{
8940 xmlSchemaImportPtr ret;
8941
8942 if (*imports == NULL) {
Daniel Veillardb9e2f262005-01-23 23:48:34 +00008943 *imports = xmlHashCreateDict(10, ctxt->dict);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008944 if (*imports == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008945 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008946 XML_SCHEMAP_FAILED_BUILD_IMPORT,
8947 NULL, NULL, (xmlNodePtr) ctxt->doc,
8948 "Internal error: failed to build the import table",
8949 NULL);
8950 return (NULL);
8951 }
8952 }
8953 ret = (xmlSchemaImport*) xmlMalloc(sizeof(xmlSchemaImport));
8954 if (ret == NULL) {
8955 xmlSchemaPErrMemory(NULL, "allocating import struct", NULL);
8956 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008957 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008958 memset(ret, 0, sizeof(xmlSchemaImport));
8959 if (nsName == NULL)
8960 nsName = XML_SCHEMAS_NO_NAMESPACE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00008961 xmlHashAddEntry(*imports, nsName, ret);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00008962
8963 return (ret);
8964}
8965
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +00008966#ifdef ENABLE_REDEFINE
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00008967static xmlSchemaSchemaRefPtr
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +00008968xmlSchemaSchemaRefCreate(void)
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00008969{
8970 xmlSchemaSchemaRefPtr ret;
8971
8972 ret = (xmlSchemaSchemaRefPtr) xmlMalloc(sizeof(xmlSchemaSchemaRef));
8973 if (ret == NULL) {
8974 xmlSchemaPErrMemory(NULL, "allocating schema reference", NULL);
8975 return(NULL);
8976 }
8977 memset(ret, 0, sizeof(xmlSchemaSchemaRef));
8978 return(ret);
8979}
8980
8981static void
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +00008982xmlSchemaSchemaRefFree(xmlSchemaSchemaRefPtr ref)
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00008983{
8984 xmlFree(ref);
8985}
8986#endif
8987
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +00008988static xmlSchemaParserCtxtPtr
8989xmlSchemaParserCtxtCreate(void)
8990{
8991 xmlSchemaParserCtxtPtr ret;
8992
8993 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
8994 if (ret == NULL) {
8995 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
8996 NULL);
8997 return (NULL);
8998 }
8999 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
9000 ret->type = XML_SCHEMA_CTXT_PARSER;
9001 ret->compContainer = xmlSchemaContainerCreate();
9002 if (ret->compContainer == NULL) {
9003 xmlSchemaFreeParserCtxt(ret);
9004 return(NULL);
9005 }
9006 return(ret);
9007}
9008
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009009/**
9010 * xmlSchemaNewParserCtxtUseDict:
9011 * @URL: the location of the schema
9012 * @dict: the dictionary to be used
9013 *
9014 * Create an XML Schemas parse context for that file/resource expected
9015 * to contain an XML Schemas file.
9016 *
9017 * Returns the parser context or NULL in case of error
9018 */
9019static xmlSchemaParserCtxtPtr
9020xmlSchemaNewParserCtxtUseDict(const char *URL, xmlDictPtr dict)
9021{
9022 xmlSchemaParserCtxtPtr ret;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009023
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +00009024 ret = xmlSchemaParserCtxtCreate();
9025 if (ret == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009026 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009027 ret->dict = dict;
9028 xmlDictReference(dict);
9029 if (URL != NULL)
9030 ret->URL = xmlDictLookup(dict, (const xmlChar *) URL, -1);
9031 ret->includes = 0;
9032 return (ret);
9033}
9034
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009035static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009036xmlSchemaCreatePCtxtOnVCtxt(xmlSchemaValidCtxtPtr vctxt)
9037{
9038 if (vctxt->pctxt == NULL) {
9039 if (vctxt->schema != NULL)
9040 vctxt->pctxt = xmlSchemaNewParserCtxtUseDict("*", vctxt->schema->dict);
9041 else
9042 vctxt->pctxt = xmlSchemaNewParserCtxt("*");
9043 if (vctxt->pctxt == NULL) {
9044 VERROR_INT("xmlSchemaCreatePCtxtOnVCtxt",
9045 "failed to create a temp. parser context");
9046 return (-1);
9047 }
9048 /* TODO: Pass user data. */
9049 xmlSchemaSetParserErrors(vctxt->pctxt, vctxt->error, vctxt->warning, NULL);
9050 }
9051 return (0);
9052}
9053
9054static int
9055xmlSchemaAcquireSchemaDoc(xmlSchemaAbstractCtxtPtr actxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +00009056 xmlSchemaPtr schema,
9057 xmlNodePtr node,
9058 const xmlChar *nsName,
9059 const xmlChar *location,
9060 xmlDocPtr *doc,
9061 const xmlChar **targetNamespace,
9062 int absolute)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009063{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009064 xmlSchemaParserCtxtPtr pctxt;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009065 xmlParserCtxtPtr parserCtxt;
9066 xmlSchemaImportPtr import;
9067 const xmlChar *ns;
9068 xmlNodePtr root;
9069
9070 /*
9071 * NOTE: This will be used for <import>, <xsi:schemaLocation> and
9072 * <xsi:noNamespaceSchemaLocation>.
9073 */
9074 *doc = NULL;
9075 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009076 * Given that the schemaLocation [attribute] is only a hint, it is open
9077 * to applications to ignore all but the first <import> for a given
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009078 * namespace, regardless of the ·actual value· of schemaLocation, but
9079 * such a strategy risks missing useful information when new
9080 * schemaLocations are offered.
9081 *
9082 * XSV (ver 2.5-2) does use the first <import> which resolves to a valid schema.
9083 * Xerces-J (ver 2.5.1) ignores all but the first given <import> - regardless if
9084 * valid or not.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009085 * We will follow XSV here.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009086 */
9087 if (location == NULL) {
9088 /*
9089 * Schema Document Location Strategy:
9090 *
9091 * 3 Based on the namespace name, identify an existing schema document,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009092 * either as a resource which is an XML document or a <schema> element
9093 * information item, in some local schema repository;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009094 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009095 * 5 Attempt to resolve the namespace name to locate such a resource.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009096 *
9097 * NOTE: Those stategies are not supported, so we will skip.
9098 */
9099 return (0);
9100 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009101 if (nsName == NULL)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009102 ns = XML_SCHEMAS_NO_NAMESPACE;
9103 else
9104 ns = nsName;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009105
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009106 import = xmlHashLookup(schema->schemasImports, ns);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009107 if (import != NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009108 /*
9109 * There was a valid resource for the specified namespace already
9110 * defined, so skip.
9111 * TODO: This might be changed someday to allow import of
9112 * components from multiple documents for a single target namespace.
9113 */
9114 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009115 }
9116 if (actxt->type == XML_SCHEMA_CTXT_PARSER)
9117 pctxt = (xmlSchemaParserCtxtPtr) actxt;
9118 else {
9119 xmlSchemaCreatePCtxtOnVCtxt((xmlSchemaValidCtxtPtr) actxt);
9120 pctxt = ((xmlSchemaValidCtxtPtr) actxt)->pctxt;
9121 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009122 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009123 * Schema Document Location Strategy:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009124 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009125 * 2 Based on the location URI, identify an existing schema document,
9126 * either as a resource which is an XML document or a <schema> element
9127 * information item, in some local schema repository;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009128 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009129 * 4 Attempt to resolve the location URI, to locate a resource on the
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009130 * web which is or contains or references a <schema> element;
9131 * TODO: Hmm, I don't know if the reference stuff in 4. will work.
9132 *
9133 */
9134 if ((absolute == 0) && (node != NULL)) {
9135 xmlChar *base, *URI;
9136
9137 base = xmlNodeGetBase(node->doc, node);
9138 if (base == NULL) {
9139 URI = xmlBuildURI(location, node->doc->URL);
9140 } else {
9141 URI = xmlBuildURI(location, base);
9142 xmlFree(base);
9143 }
9144 if (URI != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009145 location = xmlDictLookup(pctxt->dict, URI, -1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009146 xmlFree(URI);
9147 }
9148 }
9149 parserCtxt = xmlNewParserCtxt();
9150 if (parserCtxt == NULL) {
9151 xmlSchemaPErrMemory(NULL, "xmlSchemaParseImport: "
9152 "allocating a parser context", NULL);
9153 return(-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009154 }
9155 if ((pctxt->dict != NULL) && (parserCtxt->dict != NULL)) {
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00009156 xmlDictFree(parserCtxt->dict);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009157 parserCtxt->dict = pctxt->dict;
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00009158 xmlDictReference(parserCtxt->dict);
9159 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009160 *doc = xmlCtxtReadFile(parserCtxt, (const char *) location,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009161 NULL, SCHEMAS_PARSE_OPTIONS);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009162 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009163 * 2.1 The referent is (a fragment of) a resource which is an
9164 * XML document (see clause 1.1), which in turn corresponds to
9165 * a <schema> element information item in a well-formed information
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009166 * set, which in turn corresponds to a valid schema.
9167 * TODO: What to do with the "fragment" stuff?
9168 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009169 * 2.2 The referent is a <schema> element information item in
9170 * a well-formed information set, which in turn corresponds
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009171 * to a valid schema.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009172 * NOTE: 2.2 won't apply, since only XML documents will be processed
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009173 * here.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009174 */
9175 if (*doc == NULL) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009176 xmlErrorPtr lerr;
9177 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009178 * It is *not* an error for the application schema reference
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009179 * strategy to fail.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009180 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009181 * If the doc is NULL and the parser error is an IO error we
9182 * will assume that the resource could not be located or accessed.
9183 *
9184 * TODO: Try to find specific error codes to react only on
9185 * localisation failures.
9186 *
9187 * TODO, FIXME: Check the spec: is a namespace added to the imported
9188 * namespaces, even if the schemaLocation did not provide
9189 * a resource? I guess so, since omitting the "schemaLocation"
9190 * attribute, imports a namespace as well.
9191 */
9192 lerr = xmlGetLastError();
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009193 if ((lerr != NULL) && (lerr->domain == XML_FROM_IO)) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009194 xmlFreeParserCtxt(parserCtxt);
9195 return(0);
9196 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009197 xmlSchemaCustomErr(actxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009198 XML_SCHEMAP_SRC_IMPORT_2_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009199 node, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009200 "Failed to parse the resource '%s' for import",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009201 location, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009202 xmlFreeParserCtxt(parserCtxt);
9203 return(XML_SCHEMAP_SRC_IMPORT_2_1);
9204 }
9205 xmlFreeParserCtxt(parserCtxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009206
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009207 root = xmlDocGetRootElement(*doc);
9208 if (root == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009209 xmlSchemaCustomErr(actxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009210 XML_SCHEMAP_SRC_IMPORT_2_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009211 node, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009212 "The XML document '%s' to be imported has no document "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009213 "element", location, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009214 xmlFreeDoc(*doc);
9215 *doc = NULL;
9216 return (XML_SCHEMAP_SRC_IMPORT_2_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009217 }
9218
9219 xmlSchemaCleanupDoc(pctxt, root);
9220
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009221 if (!IS_SCHEMA(root, "schema")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009222 xmlSchemaCustomErr(actxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009223 XML_SCHEMAP_SRC_IMPORT_2_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009224 node, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009225 "The XML document '%s' to be imported is not a XML schema document",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009226 location, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009227 xmlFreeDoc(*doc);
9228 *doc = NULL;
9229 return (XML_SCHEMAP_SRC_IMPORT_2_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009230 }
9231 *targetNamespace = xmlSchemaGetProp(pctxt, root, "targetNamespace");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009232 /*
9233 * Schema Representation Constraint: Import Constraints and Semantics
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009234 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009235 if (nsName == NULL) {
9236 if (*targetNamespace != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009237 xmlSchemaCustomErr(actxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009238 XML_SCHEMAP_SRC_IMPORT_3_2,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009239 node, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009240 "The XML schema to be imported is not expected "
9241 "to have a target namespace; this differs from "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009242 "its target namespace of '%s'", *targetNamespace, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009243 xmlFreeDoc(*doc);
9244 *doc = NULL;
9245 return (XML_SCHEMAP_SRC_IMPORT_3_2);
9246 }
9247 } else {
9248 if (*targetNamespace == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009249 xmlSchemaCustomErr(actxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009250 XML_SCHEMAP_SRC_IMPORT_3_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009251 node, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009252 "The XML schema to be imported is expected to have a target "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009253 "namespace of '%s'", nsName, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009254 xmlFreeDoc(*doc);
9255 *doc = NULL;
9256 return (XML_SCHEMAP_SRC_IMPORT_3_1);
9257 } else if (!xmlStrEqual(*targetNamespace, nsName)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009258 xmlSchemaCustomErr(actxt,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009259 XML_SCHEMAP_SRC_IMPORT_3_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009260 node, NULL,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009261 "The XML schema to be imported is expected to have a "
9262 "target namespace of '%s'; this differs from "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009263 "its target namespace of '%s'",
9264 nsName, *targetNamespace);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009265 xmlFreeDoc(*doc);
9266 *doc = NULL;
9267 return (XML_SCHEMAP_SRC_IMPORT_3_1);
9268 }
9269 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009270 import = xmlSchemaAddImport(pctxt, &(schema->schemasImports), nsName);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009271 if (import == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009272 AERROR_INT("xmlSchemaAcquireSchemaDoc",
9273 "failed to build import table");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009274 xmlFreeDoc(*doc);
9275 *doc = NULL;
9276 return (-1);
9277 }
9278 import->schemaLocation = location;
9279 import->doc = *doc;
9280 return (0);
9281}
William M. Brack2f2a6632004-08-20 23:09:47 +00009282
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009283static void
9284xmlSchemaParseForImpInc(xmlSchemaParserCtxtPtr pctxt,
9285 xmlSchemaPtr schema,
9286 const xmlChar *targetNamespace,
9287 xmlNodePtr node)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009288{
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009289 const xmlChar *oldURL, **oldLocImps, *oldTNS;
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00009290 int oldFlags, oldNumLocImps, oldSizeLocImps, oldIsS4S;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009291
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009292 /*
9293 * Save and reset the context & schema.
9294 */
9295 oldURL = pctxt->URL;
9296 /* TODO: Is using the doc->URL here correct? */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009297 pctxt->URL = node->doc->URL;
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +00009298
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009299 oldLocImps = pctxt->localImports;
9300 pctxt->localImports = NULL;
9301 oldNumLocImps = pctxt->nbLocalImports;
9302 pctxt->nbLocalImports = 0;
9303 oldSizeLocImps = pctxt->sizeLocalImports;
9304 pctxt->sizeLocalImports = 0;
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +00009305
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009306 oldFlags = schema->flags;
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00009307 oldIsS4S = pctxt->isS4S;
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +00009308
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009309 xmlSchemaClearSchemaDefaults(schema);
9310 oldTNS = schema->targetNamespace;
9311 schema->targetNamespace = targetNamespace;
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00009312 if ((targetNamespace != NULL) &&
9313 xmlStrEqual(targetNamespace, xmlSchemaNs)) {
9314 /*
9315 * We are parsing the schema for schema!
9316 */
9317 pctxt->isS4S = 1;
9318 }
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009319 /*
9320 * Parse the schema.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009321 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009322 xmlSchemaParseSchemaDefaults(pctxt, schema, node);
9323 xmlSchemaParseSchemaTopLevel(pctxt, schema, node->children);
9324 /*
9325 * Restore the context & schema.
9326 */
9327 schema->flags = oldFlags;
9328 schema->targetNamespace = oldTNS;
9329 if (pctxt->localImports != NULL)
9330 xmlFree((xmlChar *) pctxt->localImports);
9331 pctxt->localImports = oldLocImps;
9332 pctxt->nbLocalImports = oldNumLocImps;
9333 pctxt->sizeLocalImports = oldSizeLocImps;
9334 pctxt->URL = oldURL;
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +00009335 pctxt->isS4S = oldIsS4S;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009336}
9337
William M. Brack2f2a6632004-08-20 23:09:47 +00009338/**
9339 * xmlSchemaParseImport:
9340 * @ctxt: a schema validation context
9341 * @schema: the schema being built
9342 * @node: a subtree containing XML Schema informations
9343 *
9344 * parse a XML schema Import definition
9345 * *WARNING* this interface is highly subject to change
9346 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009347 * Returns 0 in case of success, a positive error code if
9348 * not valid and -1 in case of an internal error.
William M. Brack2f2a6632004-08-20 23:09:47 +00009349 */
9350static int
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009351xmlSchemaParseImport(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema,
William M. Brack2f2a6632004-08-20 23:09:47 +00009352 xmlNodePtr node)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009353{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009354 xmlNodePtr child;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009355 const xmlChar *namespaceName = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00009356 const xmlChar *schemaLocation = NULL;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009357 const xmlChar *targetNamespace;
William M. Brack2f2a6632004-08-20 23:09:47 +00009358 xmlAttrPtr attr;
9359 xmlDocPtr doc;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009360 int ret = 0;
William M. Brack2f2a6632004-08-20 23:09:47 +00009361
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009362 if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
William M. Brack2f2a6632004-08-20 23:09:47 +00009363 return (-1);
9364
9365 /*
9366 * Check for illegal attributes.
9367 */
9368 attr = node->properties;
9369 while (attr != NULL) {
9370 if (attr->ns == NULL) {
9371 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9372 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
9373 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009374 xmlSchemaPIllegalAttrErr(pctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009375 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9376 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00009377 }
9378 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009379 xmlSchemaPIllegalAttrErr(pctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009380 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9381 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +00009382 }
9383 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009384 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009385 /*
9386 * Extract and validate attributes.
9387 */
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009388 if (xmlSchemaPValAttr(pctxt, NULL, NULL, node,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009389 "namespace", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009390 &namespaceName) != 0) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009391 xmlSchemaPSimpleTypeErr(pctxt,
9392 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009393 NULL, node,
9394 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009395 NULL, namespaceName, NULL, NULL, NULL);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009396 return (pctxt->err);
William M. Brack2f2a6632004-08-20 23:09:47 +00009397 }
9398
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009399 if (xmlSchemaPValAttr(pctxt, NULL, NULL, node,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009400 "schemaLocation", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
William M. Brack2f2a6632004-08-20 23:09:47 +00009401 &schemaLocation) != 0) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009402 xmlSchemaPSimpleTypeErr(pctxt,
9403 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009404 NULL, node,
9405 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009406 NULL, namespaceName, NULL, NULL, NULL);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009407 return (pctxt->err);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009408 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009409 /*
9410 * And now for the children...
9411 */
9412 child = node->children;
9413 if (IS_SCHEMA(child, "annotation")) {
9414 /*
9415 * the annotation here is simply discarded ...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009416 * TODO: really?
William M. Brack2f2a6632004-08-20 23:09:47 +00009417 */
9418 child = child->next;
9419 }
9420 if (child != NULL) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009421 xmlSchemaPContentErr(pctxt,
9422 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
William M. Brack2f2a6632004-08-20 23:09:47 +00009423 NULL, NULL, node, child, NULL,
9424 "(annotation?)");
9425 }
9426 /*
9427 * Apply additional constraints.
9428 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009429 if (namespaceName != NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +00009430 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009431 * 1.1 If the namespace [attribute] is present, then its ·actual value·
9432 * must not match the ·actual value· of the enclosing <schema>'s
William M. Brack2f2a6632004-08-20 23:09:47 +00009433 * targetNamespace [attribute].
9434 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009435 if (xmlStrEqual(schema->targetNamespace, namespaceName)) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009436 xmlSchemaPCustomErr(pctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00009437 XML_SCHEMAP_SRC_IMPORT_1_1,
9438 NULL, NULL, node,
9439 "The value of the attribute 'namespace' must not match "
9440 "the target namespace '%s' of the importing schema",
9441 schema->targetNamespace);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009442 return (pctxt->err);
William M. Brack2f2a6632004-08-20 23:09:47 +00009443 }
9444 } else {
9445 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009446 * 1.2 If the namespace [attribute] is not present, then the enclosing
William M. Brack2f2a6632004-08-20 23:09:47 +00009447 * <schema> must have a targetNamespace [attribute].
9448 */
9449 if (schema->targetNamespace == NULL) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009450 xmlSchemaPCustomErr(pctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +00009451 XML_SCHEMAP_SRC_IMPORT_1_2,
9452 NULL, NULL, node,
9453 "The attribute 'namespace' must be existent if "
9454 "the importing schema has no target namespace",
9455 NULL);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009456 return (pctxt->err);
William M. Brack2f2a6632004-08-20 23:09:47 +00009457 }
9458 }
William M. Brack2f2a6632004-08-20 23:09:47 +00009459 /*
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009460 * Add the namespace to the list of locally imported namespace.
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +00009461 * TODO: This could be removed if the schema-graph is ready. I.e.
9462 * use the graph for this info instead.
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009463 */
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009464 if (pctxt->localImports == NULL) {
9465 pctxt->localImports = (const xmlChar **) xmlMalloc(10 *
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009466 sizeof(const xmlChar*));
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009467 pctxt->sizeLocalImports = 10;
9468 pctxt->nbLocalImports = 0;
9469 } else if (pctxt->sizeLocalImports <= pctxt->nbLocalImports) {
9470 pctxt->sizeLocalImports *= 2;
9471 pctxt->localImports = (const xmlChar **) xmlRealloc(
9472 (xmlChar **) pctxt->localImports,
9473 pctxt->sizeLocalImports * sizeof(const xmlChar*));
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009474 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009475 pctxt->localImports[pctxt->nbLocalImports++] = namespaceName;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009476 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009477 * Locate and aquire the schema document.
William M. Brack2f2a6632004-08-20 23:09:47 +00009478 */
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009479 ret = xmlSchemaAcquireSchemaDoc((xmlSchemaAbstractCtxtPtr) pctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009480 schema, node, namespaceName,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009481 schemaLocation, &doc, &targetNamespace, 0);
9482 if (ret != 0) {
9483 if (doc != NULL)
William M. Brack2f2a6632004-08-20 23:09:47 +00009484 xmlFreeDoc(doc);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009485 return (ret);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009486 } else if (doc != NULL) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009487 xmlSchemaParseForImpInc(pctxt, schema, targetNamespace,
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009488 xmlDocGetRootElement(doc));
William M. Brack2f2a6632004-08-20 23:09:47 +00009489 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009490
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +00009491 return (0);
William M. Brack2f2a6632004-08-20 23:09:47 +00009492}
9493
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009494/**
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009495 * xmlSchemaParseIncludedDoc:
9496 * @pctxt: a schema validation context
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009497 * @schema: the schema being built
9498 * @node: a subtree containing XML Schema informations
9499 *
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009500 * Parse an included (and to-be-redefined) XML schema document.
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009501 *
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009502 * Returns 0 on success, a positive error code on errors and
9503 * -1 in case of an internal or API error.
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009504 */
9505static int
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009506xmlSchemaParseIncludedDoc(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema,
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +00009507 xmlNodePtr node, const xmlChar *schemaLocation,
9508 int *located)
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009509{
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009510 const xmlChar *targetNamespace;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009511 xmlDocPtr doc = NULL;
9512 xmlNodePtr root = NULL;
Daniel Veillardcffc1c72005-03-12 18:54:55 +00009513 xmlSchemaIncludePtr include = NULL;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009514 int wasConvertingNs = 0;
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00009515 xmlParserCtxtPtr parserCtxt;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009516
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +00009517 if (located == NULL)
9518 return(-1);
9519 (*located) = 0;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009520 /*
9521 * Check if this one was already processed to avoid incorrect
9522 * duplicate component errors and infinite circular inclusion.
9523 */
9524 include = schema->includes;
9525 while (include != NULL) {
9526 if (xmlStrEqual(include->schemaLocation, schemaLocation)) {
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +00009527 (*located) = 1;
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009528 targetNamespace = include->origTargetNamespace;
9529 if (targetNamespace == NULL) {
9530 /*
9531 * Chameleon include: skip only if it was build for
9532 * the targetNamespace of the including schema.
9533 */
9534 if (xmlStrEqual(schema->targetNamespace,
9535 include->targetNamespace)) {
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009536 goto check_targetNamespace;
9537 }
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +00009538 } else {
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009539 goto check_targetNamespace;
9540 }
9541 }
9542 include = include->next;
9543 }
9544 /*
9545 * First step is to parse the input document into an DOM/Infoset
9546 * TODO: Use xmlCtxtReadFile to share the dictionary?
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00009547 */
9548 parserCtxt = xmlNewParserCtxt();
9549 if (parserCtxt == NULL) {
9550 xmlSchemaPErrMemory(NULL, "xmlSchemaParseInclude: "
9551 "allocating a parser context", NULL);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009552 goto exit_failure;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009553 }
9554
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009555 if ((pctxt->dict != NULL) && (parserCtxt->dict != NULL)) {
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00009556 xmlDictFree(parserCtxt->dict);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009557 parserCtxt->dict = pctxt->dict;
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00009558 xmlDictReference(parserCtxt->dict);
9559 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009560
9561 doc = xmlCtxtReadFile(parserCtxt, (const char *) schemaLocation,
Kasimier T. Buchcik5dd55d92004-11-26 12:35:21 +00009562 NULL, SCHEMAS_PARSE_OPTIONS);
9563 xmlFreeParserCtxt(parserCtxt);
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +00009564 if (doc == NULL) {
9565 goto exit_not_located;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009566 }
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +00009567 (*located) = 1;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009568 /*
9569 * Then extract the root of the schema
9570 */
9571 root = xmlDocGetRootElement(doc);
9572 if (root == NULL) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009573 xmlSchemaPCustomErr(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009574 XML_SCHEMAP_NOROOT,
William M. Brack2f2a6632004-08-20 23:09:47 +00009575 NULL, NULL, node,
9576 "The included document '%s' has no document "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009577 "element", schemaLocation);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009578 goto exit_error;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009579 }
9580
9581 /*
9582 * Remove all the blank text nodes
9583 */
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009584 xmlSchemaCleanupDoc(pctxt, root);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009585
9586 /*
9587 * Check the schemas top level element
9588 */
9589 if (!IS_SCHEMA(root, "schema")) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009590 xmlSchemaPCustomErr(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009591 XML_SCHEMAP_NOT_SCHEMA,
William M. Brack2f2a6632004-08-20 23:09:47 +00009592 NULL, NULL, node,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009593 "The document '%s' to be included is not a schema document",
William M. Brack2f2a6632004-08-20 23:09:47 +00009594 schemaLocation);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009595 goto exit_error;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009596 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009597
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009598 targetNamespace = xmlSchemaGetProp(pctxt, root, "targetNamespace");
Daniel Veillardc0826a72004-08-10 14:17:33 +00009599 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009600 * 2.1 SII has a targetNamespace [attribute], and its ·actual
9601 * value· is identical to the ·actual value· of the targetNamespace
Daniel Veillardc0826a72004-08-10 14:17:33 +00009602 * [attribute] of SIIÂ’ (which must have such an [attribute]).
9603 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009604check_targetNamespace:
Daniel Veillardc0826a72004-08-10 14:17:33 +00009605 if (targetNamespace != NULL) {
9606 if (schema->targetNamespace == NULL) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009607 xmlSchemaPCustomErr(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009608 XML_SCHEMAP_SRC_INCLUDE,
William M. Brack2f2a6632004-08-20 23:09:47 +00009609 NULL, NULL, node,
9610 "The target namespace of the included schema "
9611 "'%s' has to be absent, since the including schema "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009612 "has no target namespace",
9613 schemaLocation);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009614 goto exit_error;
William M. Brack2f2a6632004-08-20 23:09:47 +00009615 } else if (!xmlStrEqual(targetNamespace, schema->targetNamespace)) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009616 xmlSchemaPCustomErrExt(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +00009617 XML_SCHEMAP_SRC_INCLUDE,
William M. Brack2f2a6632004-08-20 23:09:47 +00009618 NULL, NULL, node,
9619 "The target namespace '%s' of the included schema '%s' "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009620 "differs from '%s' of the including schema",
William M. Brack2f2a6632004-08-20 23:09:47 +00009621 targetNamespace, schemaLocation, schema->targetNamespace);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009622 goto exit_error;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009623 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009624 } else if (schema->targetNamespace != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +00009625 if ((schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) == 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009626 schema->flags |= XML_SCHEMAS_INCLUDING_CONVERT_NS;
Daniel Veillardc0826a72004-08-10 14:17:33 +00009627 } else
9628 wasConvertingNs = 1;
9629 }
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009630
9631 if (include != NULL)
9632 goto exit;
9633
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009634 /*
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009635 * URGENT TODO: If the schema is a chameleon-include then copy the
9636 * components into the including schema and modify the targetNamespace
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009637 * of those components, do nothing otherwise.
9638 * NOTE: This is currently worked-around by compiling the chameleon
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009639 * for every destinct including targetNamespace; thus not performant at
9640 * the moment.
9641 * TODO: Check when the namespace in wildcards for chameleons needs
9642 * to be converted: before we built wildcard intersections or after.
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009643 * Answer: after!
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009644 */
9645 /*
9646 * Register the include.
9647 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009648 include = (xmlSchemaIncludePtr) xmlMalloc(sizeof(xmlSchemaInclude));
9649 if (include == NULL) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009650 xmlSchemaPErrMemory(pctxt, "allocating include entry", NULL);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009651 goto exit_failure;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009652 }
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009653 memset(include, 0, sizeof(xmlSchemaInclude));
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009654 include->next = schema->includes;
9655 schema->includes = include;
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009656 /*
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009657 * TODO: Use the resolved URI for the this location, since it might
9658 * differ if using filenames/URIs simultaneosly.
Daniel Veillardc0826a72004-08-10 14:17:33 +00009659 */
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009660 include->schemaLocation = schemaLocation;
9661 include->doc = doc;
9662 /*
9663 * In case of chameleons, the original target namespace will differ
9664 * from the resulting namespace.
9665 */
9666 include->origTargetNamespace = targetNamespace;
9667 include->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00009668#ifdef DEBUG_INCLUDES
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009669 if (targetNamespace != schema->targetNamespace)
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +00009670 xmlGenericError(xmlGenericErrorContext,
9671 "INCLUDING CHAMELEON '%s'\n orig TNS '%s'\n"
9672 " into TNS '%s'\n", schemaLocation,
9673 targetNamespace, schema->targetNamespace);
9674 else
9675 xmlGenericError(xmlGenericErrorContext,
9676 "INCLUDING '%s'\n orig-TNS '%s'\n", schemaLocation,
9677 targetNamespace);
9678#endif
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009679 /*
9680 * Compile the included schema.
9681 */
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009682 xmlSchemaParseForImpInc(pctxt, schema, schema->targetNamespace, root);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009683
9684exit:
Daniel Veillardc0826a72004-08-10 14:17:33 +00009685 /*
9686 * Remove the converting flag.
9687 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009688 if ((wasConvertingNs == 0) &&
William M. Brack2f2a6632004-08-20 23:09:47 +00009689 (schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS))
Daniel Veillardc0826a72004-08-10 14:17:33 +00009690 schema->flags ^= XML_SCHEMAS_INCLUDING_CONVERT_NS;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009691 return (0);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009692
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009693exit_error:
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009694 if (doc != NULL) {
9695 if (include != NULL)
9696 include->doc = NULL;
9697 xmlFreeDoc(doc);
9698 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009699 return (pctxt->err);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009700
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +00009701exit_not_located:
9702 return(0);
9703
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +00009704exit_failure:
9705 if (doc != NULL) {
9706 if (include != NULL)
9707 include->doc = NULL;
9708 xmlFreeDoc(doc);
9709 }
9710 return (-1);
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009711}
9712
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009713
9714static int
9715xmlSchemaParseIncludeOrRedefineAttrs(xmlSchemaParserCtxtPtr pctxt,
9716 xmlSchemaPtr schema,
9717 xmlNodePtr node,
9718 xmlChar **schemaLocation,
9719 int isRedefine)
9720{
9721 xmlAttrPtr attr;
9722
9723 if ((pctxt == NULL) || (schema == NULL) || (node == NULL) ||
9724 (schemaLocation == NULL))
9725 return (-1);
9726
9727 *schemaLocation = NULL;
9728 /*
9729 * Check for illegal attributes.
9730 * Applies for both <include> and <redefine>.
9731 */
9732 attr = node->properties;
9733 while (attr != NULL) {
9734 if (attr->ns == NULL) {
9735 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9736 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
9737 xmlSchemaPIllegalAttrErr(pctxt,
9738 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9739 NULL, NULL, attr);
9740 }
9741 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9742 xmlSchemaPIllegalAttrErr(pctxt,
9743 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
9744 NULL, NULL, attr);
9745 }
9746 attr = attr->next;
9747 }
9748 xmlSchemaPValAttrID(pctxt, NULL, NULL, node, BAD_CAST "id");
9749 /*
9750 * Preliminary step, extract the URI-Reference and make an URI
9751 * from the base.
9752 */
9753 /*
9754 * Attribute "schemaLocation" is mandatory.
9755 */
9756 attr = xmlSchemaGetPropNode(node, "schemaLocation");
9757 if (attr != NULL) {
9758 xmlChar *base = NULL;
9759 xmlChar *uri = NULL;
9760
9761 if (xmlSchemaPValAttrNode(pctxt, NULL, NULL, attr,
9762 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
9763 (const xmlChar **) schemaLocation) != 0)
9764 goto exit_error;
9765 base = xmlNodeGetBase(node->doc, node);
9766 if (base == NULL) {
9767 uri = xmlBuildURI(*schemaLocation, node->doc->URL);
9768 } else {
9769 uri = xmlBuildURI(*schemaLocation, base);
9770 xmlFree(base);
9771 }
9772 if (uri == NULL) {
9773 PERROR_INT("xmlSchemaParseIncludeOrRedefine",
9774 "could not build an URI from the schemaLocation")
9775 goto exit_failure;
9776 }
9777 (*schemaLocation) = (xmlChar *) xmlDictLookup(pctxt->dict, uri, -1);
9778 xmlFree(uri);
9779 } else {
9780 xmlSchemaPMissingAttrErr(pctxt,
9781 XML_SCHEMAP_S4S_ATTR_MISSING,
9782 NULL, node, "schemaLocation", NULL);
9783 goto exit_error;
9784 }
9785 /*
9786 * Report self-inclusion and self-redefinition.
9787 */
9788 if (xmlStrEqual(*schemaLocation, pctxt->URL)) {
9789 if (isRedefine) {
9790 xmlSchemaPCustomErr(pctxt,
9791 XML_SCHEMAP_SRC_REDEFINE,
9792 NULL, NULL, node,
9793 "The schema document '%s' cannot redefine itself.",
9794 *schemaLocation);
9795 } else {
9796 xmlSchemaPCustomErr(pctxt,
9797 XML_SCHEMAP_SRC_INCLUDE,
9798 NULL, NULL, node,
9799 "The schema document '%s' cannot include itself.",
9800 *schemaLocation);
9801 }
9802 goto exit_error;
9803 }
9804
9805 return(0);
9806exit_error:
9807 return(pctxt->err);
9808exit_failure:
9809 return(-1);
9810}
9811
9812static int
9813xmlSchemaParseIncludeOrRedefine(xmlSchemaParserCtxtPtr pctxt,
9814 xmlSchemaPtr schema,
9815 xmlNodePtr node,
9816 int isRedefine)
9817{
9818 xmlNodePtr child = NULL;
9819 const xmlChar *schemaLocation = NULL;
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +00009820 int res = 0, located = 0, hasRedefinitions = 0;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009821
9822 if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
9823 return (-1);
9824
9825 /*
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +00009826 * Parse attributes. Note that the returned schemaLocation will
9827 * be already converted to an absolute URI.
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009828 */
9829 res = xmlSchemaParseIncludeOrRedefineAttrs(pctxt, schema,
9830 node, (xmlChar **) (&schemaLocation), isRedefine);
9831 if (res != 0)
9832 return(res);
9833
9834 /*
9835 * Include the schema.
9836 */
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +00009837 res = xmlSchemaParseIncludedDoc(pctxt, schema, node,
9838 schemaLocation, &located);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009839 if (res != 0)
9840 return(res);
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +00009841
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009842 /*
9843 * And now for the children...
9844 */
9845 child = node->children;
9846
9847 if (isRedefine) {
9848 /*
9849 * Parse (simpleType | complexType | group | attributeGroup))*
9850 */
9851 pctxt->isRedefine = 1;
9852 while (IS_SCHEMA(child, "annotation") ||
9853 IS_SCHEMA(child, "simpleType") ||
9854 IS_SCHEMA(child, "complexType") ||
9855 IS_SCHEMA(child, "group") ||
9856 IS_SCHEMA(child, "attributeGroup")) {
9857 if (IS_SCHEMA(child, "annotation")) {
9858 /*
9859 * TODO: discard or not?
9860 */
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +00009861 } else if (IS_SCHEMA(child, "simpleType")) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009862 xmlSchemaParseSimpleType(pctxt, schema, child, 1);
9863 } else if (IS_SCHEMA(child, "complexType")) {
9864 xmlSchemaParseComplexType(pctxt, schema, child, 1);
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +00009865 hasRedefinitions = 1;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009866 } else if (IS_SCHEMA(child, "group")) {
9867 TODO
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +00009868 hasRedefinitions = 1;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009869 /* xmlSchemaParseModelGroupDefinition(pctxt, schema, child); */
9870 } else if (IS_SCHEMA(child, "attributeGroup")) {
9871 TODO
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +00009872 hasRedefinitions = 1;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009873 /* xmlSchemaParseAttributeGroup(pctxt, schema, child, 1); */
9874 }
9875 child = child->next;
9876 }
9877 pctxt->isRedefine = 0;
9878 } else {
9879 if (IS_SCHEMA(child, "annotation")) {
9880 /*
9881 * TODO: discard or not?
9882 */
9883 child = child->next;
9884 }
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +00009885 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009886 if (child != NULL) {
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +00009887 res = XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009888 if (isRedefine) {
9889 xmlSchemaPContentErr(pctxt,
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +00009890 res,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009891 NULL, NULL, node, child, NULL,
9892 "(annotation | (simpleType | complexType | group | attributeGroup))*");
9893 } else {
9894 xmlSchemaPContentErr(pctxt,
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +00009895 res,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009896 NULL, NULL, node, child, NULL,
9897 "(annotation?)");
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +00009898 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009899 }
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +00009900 if (!located) {
9901 /*
9902 * TODO: This is all *not* yet OK, since we get a !located if the
9903 * document was not an XML document as well :-(
9904 */
9905 if (!isRedefine) {
9906 /*
9907 * WARNING for <include>:
9908 * We will raise an error if the schema cannot be located
9909 * for inclusions, since the that was the feedback from the
9910 * schema people. I.e. the following spec piece will *not* be
9911 * satisfied:
9912 * SPEC src-include: "It is not an error for the ·actual value· of the
9913 * schemaLocation [attribute] to fail to resolve it all, in which
9914 * case no corresponding inclusion is performed.
9915 * So do we need a warning report here?"
9916 */
9917 res = XML_SCHEMAP_SRC_INCLUDE;
9918 xmlSchemaPCustomErr(pctxt, res,
9919 NULL, NULL, node,
9920 "Failed to load the document '%s' for inclusion",
9921 schemaLocation);
9922 } else if (hasRedefinitions) {
9923 /*
9924 * SPEC src-redefine (1)
9925 * "If there are any element information items among the [children]
9926 * other than <annotation> then the ·actual value· of the
9927 * schemaLocation [attribute] must successfully resolve."
9928 * TODO: Ask the WG if a the location has to resolve here as well!
9929 */
9930 res = XML_SCHEMAP_SRC_REDEFINE;
9931 xmlSchemaPCustomErr(pctxt, res,
9932 NULL, NULL, node,
9933 "Failed to load the document '%s' for redefinition",
9934 schemaLocation);
9935 }
9936 }
9937 return(res);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009938}
9939
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +00009940#ifdef ENABLE_REDEFINE
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +00009941static int
9942xmlSchemaParseRedefine(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema,
9943 xmlNodePtr node)
9944{
9945 int res;
9946
9947 res = xmlSchemaParseIncludeOrRedefine(pctxt, schema, node, 1);
9948 if (res != 0)
9949 return(res);
9950 return(0);
9951}
9952#endif
9953
9954static int
9955xmlSchemaParseInclude(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema,
9956 xmlNodePtr node)
9957{
9958 int res;
9959
9960 res = xmlSchemaParseIncludeOrRedefine(pctxt, schema, node, 0);
9961 if (res != 0)
9962 return(res);
9963 return(0);
9964}
9965
Daniel Veillardbd2904b2003-11-25 15:38:59 +00009966/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009967 * xmlSchemaParseModelGroup:
Daniel Veillard4255d502002-04-16 15:50:10 +00009968 * @ctxt: a schema validation context
9969 * @schema: the schema being built
9970 * @node: a subtree containing XML Schema informations
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009971 * @type: the "compositor" type
9972 * @particleNeeded: if a a model group with a particle
Daniel Veillard4255d502002-04-16 15:50:10 +00009973 *
9974 * parse a XML schema Sequence definition
9975 * *WARNING* this interface is highly subject to change
9976 *
William M. Bracke7091952004-05-11 15:09:58 +00009977 * Returns -1 in case of error, 0 if the declaration is improper and
Daniel Veillard4255d502002-04-16 15:50:10 +00009978 * 1 in case of success.
9979 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009980static xmlSchemaTreeItemPtr
9981xmlSchemaParseModelGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
9982 xmlNodePtr node, xmlSchemaTypeType type,
9983 int withParticle)
Daniel Veillard4255d502002-04-16 15:50:10 +00009984{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009985 xmlSchemaModelGroupPtr item;
9986 xmlSchemaParticlePtr particle = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +00009987 xmlNodePtr child = NULL;
William M. Brack2f2a6632004-08-20 23:09:47 +00009988 xmlAttrPtr attr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009989 const xmlChar *oldcontainer, *container;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +00009990 int min = 0, max = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +00009991
9992 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +00009993 return (NULL);
9994 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009995 * Create a model group with the given compositor.
William M. Brack2f2a6632004-08-20 23:09:47 +00009996 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +00009997 item = xmlSchemaAddModelGroup(ctxt, schema, type, &container, node);
9998 if (item == NULL)
9999 return (NULL);
10000
10001 if (withParticle) {
10002 if (type == XML_SCHEMA_TYPE_ALL) {
10003 min = xmlGetMinOccurs(ctxt, node, 0, 1, 1, "(0 | 1)");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010004 max = xmlGetMaxOccurs(ctxt, node, 1, 1, 1, "1");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010005 } else {
10006 /* choice + sequence */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010007 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
10008 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
10009 "(xs:nonNegativeInteger | unbounded)");
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010010 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010011 xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
10012 /*
10013 * Create a particle
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010014 */
10015 particle = xmlSchemaAddParticle(ctxt, schema, node, min, max);
10016 if (particle == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010017 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010018 particle->children = (xmlSchemaTreeItemPtr) item;
10019 /*
10020 * Check for illegal attributes.
10021 */
10022 attr = node->properties;
10023 while (attr != NULL) {
10024 if (attr->ns == NULL) {
10025 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
10026 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
10027 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010028 xmlSchemaPIllegalAttrErr(ctxt,
10029 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10030 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010031 }
10032 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010033 xmlSchemaPIllegalAttrErr(ctxt,
10034 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10035 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +000010036 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010037 attr = attr->next;
William M. Brack2f2a6632004-08-20 23:09:47 +000010038 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010039 } else {
10040 /*
10041 * Check for illegal attributes.
10042 */
10043 attr = node->properties;
10044 while (attr != NULL) {
10045 if (attr->ns == NULL) {
10046 if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010047 xmlSchemaPIllegalAttrErr(ctxt,
10048 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10049 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010050 }
10051 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010052 xmlSchemaPIllegalAttrErr(ctxt,
10053 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10054 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010055 }
10056 attr = attr->next;
10057 }
10058
William M. Brack2f2a6632004-08-20 23:09:47 +000010059 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010060
William M. Brack2f2a6632004-08-20 23:09:47 +000010061 /*
10062 * Extract and validate attributes.
10063 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010064 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +000010065 /*
10066 * And now for the children...
10067 */
Daniel Veillard4255d502002-04-16 15:50:10 +000010068 child = node->children;
10069 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010070 item->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010071 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010072 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010073 oldcontainer = ctxt->container;
10074 ctxt->container = container;
10075 if (type == XML_SCHEMA_TYPE_ALL) {
10076 xmlSchemaParticlePtr part, last = NULL;
10077
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010078 while (IS_SCHEMA(child, "element")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010079 part = (xmlSchemaParticlePtr) xmlSchemaParseElement(ctxt,
10080 schema, child, 0);
10081 if (part != NULL) {
10082 if (part->minOccurs > 1)
10083 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INVALID_MINOCCURS,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010084 NULL, NULL, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010085 "Invalid value for minOccurs (must be 0 or 1)", NULL);
10086 if (part->maxOccurs > 1)
10087 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INVALID_MAXOCCURS,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010088 NULL, NULL, child,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010089 "Invalid value for maxOccurs (must be 0 or 1)",
10090 NULL);
10091 if (last == NULL)
10092 item->children = (xmlSchemaTreeItemPtr) part;
10093 else
10094 last->next = (xmlSchemaTreeItemPtr) part;
10095 last = part;
10096 }
10097 child = child->next;
10098 }
10099 if (child != NULL) {
10100 xmlSchemaPContentErr(ctxt,
10101 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
10102 NULL, NULL, node, child, NULL,
10103 "(annotation?, (annotation?, element*)");
10104 }
10105 } else {
10106 /* choice + sequence */
10107 xmlSchemaTreeItemPtr part = NULL, last = NULL;
10108
10109 while ((IS_SCHEMA(child, "element")) ||
10110 (IS_SCHEMA(child, "group")) ||
10111 (IS_SCHEMA(child, "any")) ||
10112 (IS_SCHEMA(child, "choice")) ||
10113 (IS_SCHEMA(child, "sequence"))) {
10114
10115 if (IS_SCHEMA(child, "element")) {
10116 part = (xmlSchemaTreeItemPtr)
10117 xmlSchemaParseElement(ctxt, schema, child, 0);
10118 } else if (IS_SCHEMA(child, "group")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010119 part =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010120 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
10121 } else if (IS_SCHEMA(child, "any")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010122 part = (xmlSchemaTreeItemPtr)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010123 xmlSchemaParseAny(ctxt, schema, child);
10124 } else if (IS_SCHEMA(child, "choice")) {
10125 part = xmlSchemaParseModelGroup(ctxt, schema, child,
10126 XML_SCHEMA_TYPE_CHOICE, 1);
10127 } else if (IS_SCHEMA(child, "sequence")) {
10128 part = xmlSchemaParseModelGroup(ctxt, schema, child,
10129 XML_SCHEMA_TYPE_SEQUENCE, 1);
10130 }
10131 if (part != NULL) {
10132 if (last == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010133 item->children = part;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010134 else
10135 last->next = part;
10136 last = part;
10137 }
10138 child = child->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010139 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010140 if (child != NULL) {
10141 xmlSchemaPContentErr(ctxt,
10142 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
10143 NULL, NULL, node, child, NULL,
10144 "(annotation?, (element | group | choice | sequence | any)*)");
10145 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010146 }
William M. Brack2f2a6632004-08-20 23:09:47 +000010147 ctxt->container = oldcontainer;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000010148 if (withParticle) {
10149 if ((min == 0) && (max == 0))
10150 return (NULL);
10151 else
10152 return ((xmlSchemaTreeItemPtr) particle);
10153 } else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010154 return ((xmlSchemaTreeItemPtr) item);
Daniel Veillard4255d502002-04-16 15:50:10 +000010155}
10156
10157/**
10158 * xmlSchemaParseRestriction:
10159 * @ctxt: a schema validation context
10160 * @schema: the schema being built
10161 * @node: a subtree containing XML Schema informations
Daniel Veillard4255d502002-04-16 15:50:10 +000010162 *
10163 * parse a XML schema Restriction definition
10164 * *WARNING* this interface is highly subject to change
10165 *
10166 * Returns the type definition or NULL in case of error
10167 */
10168static xmlSchemaTypePtr
10169xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010170 xmlNodePtr node, xmlSchemaTypeType parentType)
Daniel Veillard4255d502002-04-16 15:50:10 +000010171{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010172 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000010173 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010174 char buf[30];
10175 const xmlChar *oldcontainer, *container;
William M. Brack2f2a6632004-08-20 23:09:47 +000010176 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +000010177
10178 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
10179 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010180 /* Not a component, don't create it. */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010181 type = ctxt->ctxtType;
10182 type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010183
10184 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010185 * TODO: Is the container needed at all? the anonymous
10186 * items inside should generate unique names already.
10187 */
10188 snprintf(buf, 29, "#restr%d", ctxt->counter++ + 1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010189 container = xmlDictLookup(ctxt->dict, BAD_CAST buf, -1);
William M. Brack2f2a6632004-08-20 23:09:47 +000010190 /*
10191 * Check for illegal attributes.
10192 */
10193 attr = node->properties;
10194 while (attr != NULL) {
10195 if (attr->ns == NULL) {
10196 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
10197 (!xmlStrEqual(attr->name, BAD_CAST "base"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010198 xmlSchemaPIllegalAttrErr(ctxt,
10199 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10200 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +000010201 }
10202 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010203 xmlSchemaPIllegalAttrErr(ctxt,
10204 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10205 NULL, NULL, attr);
William M. Brack2f2a6632004-08-20 23:09:47 +000010206 }
10207 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010208 }
William M. Brack2f2a6632004-08-20 23:09:47 +000010209 /*
10210 * Extract and validate attributes.
10211 */
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000010212 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
William M. Brack2f2a6632004-08-20 23:09:47 +000010213 /*
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010214 * Attribute
William M. Brack2f2a6632004-08-20 23:09:47 +000010215 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010216 /*
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010217 * Extract the base type. The "base" attribute is mandatory if inside
10218 * a complex type or if redefining.
10219 *
10220 * SPEC (1.2) "...otherwise (<restriction> has no <simpleType> "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010221 * among its [children]), the simple type definition which is
10222 * the {content type} of the type definition ·resolved· to by
10223 * the ·actual value· of the base [attribute]"
10224 */
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010225 if (xmlSchemaPValAttrQName(ctxt, schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010226 NULL, NULL, node, "base",
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010227 &(type->baseNs), &(type->base)) == 0)
10228 {
10229 if ((type->base == NULL) && (type->type == XML_SCHEMA_TYPE_COMPLEX)) {
10230 xmlSchemaPMissingAttrErr(ctxt,
10231 XML_SCHEMAP_S4S_ATTR_MISSING,
10232 type, node, "base", NULL);
10233 } else if ((ctxt->isRedefine) &&
10234 (type->flags & XML_SCHEMAS_TYPE_GLOBAL))
10235 {
10236 if (type->base == NULL) {
10237 xmlSchemaPMissingAttrErr(ctxt,
10238 XML_SCHEMAP_S4S_ATTR_MISSING,
10239 type, node, "base", NULL);
10240 } else if ((! xmlStrEqual(type->base, type->name)) ||
10241 (! xmlStrEqual(type->baseNs, type->targetNamespace)))
10242 {
10243 xmlChar *str1 = NULL, *str2 = NULL;
10244 /*
10245 * REDEFINE: SPEC src-redefine (5)
10246 * "Within the [children], each <simpleType> must have a
10247 * <restriction> among its [children] ... the ·actual value· of
10248 * whose base [attribute] must be the same as the ·actual value·
10249 * of its own name attribute plus target namespace;"
10250 */
10251 xmlSchemaPCustomErrExt(ctxt, XML_SCHEMAP_SRC_REDEFINE,
10252 NULL, NULL, node, "This is a redefinition, but the QName "
10253 "value '%s' of the 'base' attribute does not match the "
10254 "type's designation '%s'",
10255 xmlSchemaFormatQName(&str1, type->baseNs, type->base),
10256 xmlSchemaFormatQName(&str1, type->targetNamespace,
10257 type->name), NULL);
10258 FREE_AND_NULL(str1);
10259 FREE_AND_NULL(str2);
10260 }
10261 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010262 }
William M. Brack2f2a6632004-08-20 23:09:47 +000010263 /*
10264 * And now for the children...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010265 */
Daniel Veillard4255d502002-04-16 15:50:10 +000010266 child = node->children;
10267 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010268 /*
10269 * Add the annotation to the simple type ancestor.
10270 */
10271 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
10272 xmlSchemaParseAnnotation(ctxt, schema, child));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010273 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010274 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010275 oldcontainer = ctxt->container;
10276 ctxt->container = container;
10277 if (parentType == XML_SCHEMA_TYPE_SIMPLE) {
10278 /*
10279 * Corresponds to <simpleType><restriction><simpleType>.
10280 */
William M. Brack2f2a6632004-08-20 23:09:47 +000010281 if (IS_SCHEMA(child, "simpleType")) {
10282 if (type->base != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010283 /*
William M. Brack2f2a6632004-08-20 23:09:47 +000010284 * src-restriction-base-or-simpleType
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010285 * Either the base [attribute] or the simpleType [child] of the
10286 * <restriction> element must be present, but not both.
William M. Brack2f2a6632004-08-20 23:09:47 +000010287 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010288 xmlSchemaPContentErr(ctxt,
William M. Brack2f2a6632004-08-20 23:09:47 +000010289 XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010290 NULL, NULL, node, child,
William M. Brack2f2a6632004-08-20 23:09:47 +000010291 "The attribute 'base' and the <simpleType> child are "
10292 "mutually exclusive", NULL);
10293 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010294 type->baseType = (xmlSchemaTypePtr)
William M. Brack2f2a6632004-08-20 23:09:47 +000010295 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010296 }
William M. Brack2f2a6632004-08-20 23:09:47 +000010297 child = child->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010298 } else if (type->base == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010299 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010300 XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
10301 NULL, NULL, node, child,
10302 "Either the attribute 'base' or a <simpleType> child "
10303 "must be present", NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +000010304 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010305 } else if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
10306 /*
10307 * Corresponds to <complexType><complexContent><restriction>...
10308 * followed by:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010309 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010310 * Model groups <all>, <choice> and <sequence>.
10311 */
10312 if (IS_SCHEMA(child, "all")) {
10313 type->subtypes = (xmlSchemaTypePtr)
10314 xmlSchemaParseModelGroup(ctxt, schema, child,
10315 XML_SCHEMA_TYPE_ALL, 1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010316 child = child->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010317 } else if (IS_SCHEMA(child, "choice")) {
10318 type->subtypes = (xmlSchemaTypePtr)
10319 xmlSchemaParseModelGroup(ctxt,
10320 schema, child, XML_SCHEMA_TYPE_CHOICE, 1);
10321 child = child->next;
10322 } else if (IS_SCHEMA(child, "sequence")) {
10323 type->subtypes = (xmlSchemaTypePtr)
10324 xmlSchemaParseModelGroup(ctxt, schema, child,
10325 XML_SCHEMA_TYPE_SEQUENCE, 1);
10326 child = child->next;
10327 /*
10328 * Model group reference <group>.
10329 */
10330 } else if (IS_SCHEMA(child, "group")) {
10331 type->subtypes = (xmlSchemaTypePtr)
10332 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
10333 child = child->next;
10334 }
10335 } else if (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010336 /*
10337 * Corresponds to <complexType><simpleContent><restriction>...
10338 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010339 * "1.1 the simple type definition corresponding to the <simpleType>
10340 * among the [children] of <restriction> if there is one;"
10341 */
10342 if (IS_SCHEMA(child, "simpleType")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010343 /*
10344 * We will store the to-be-restricted simple type in
10345 * type->contentTypeDef *temporarily*.
10346 */
10347 type->contentTypeDef = (xmlSchemaTypePtr)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010348 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010349 if ( type->contentTypeDef == NULL)
10350 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010351 child = child->next;
10352 }
William M. Brack2f2a6632004-08-20 23:09:47 +000010353 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010354
10355 if ((parentType == XML_SCHEMA_TYPE_SIMPLE) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010356 (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010357 xmlSchemaFacetPtr facet, lastfacet = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010358 /*
10359 * Corresponds to <complexType><simpleContent><restriction>...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010360 * <simpleType><restriction>...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010361 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010362
Daniel Veillard01fa6152004-06-29 17:04:39 +000010363 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010364 * Add the facets to the simple type ancestor.
Daniel Veillard01fa6152004-06-29 17:04:39 +000010365 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000010366 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010367 * TODO: Datatypes: 4.1.3 Constraints on XML Representation of
10368 * Simple Type Definition Schema Representation Constraint:
Daniel Veillardc0826a72004-08-10 14:17:33 +000010369 * *Single Facet Value*
10370 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000010371 while ((IS_SCHEMA(child, "minInclusive")) ||
10372 (IS_SCHEMA(child, "minExclusive")) ||
10373 (IS_SCHEMA(child, "maxInclusive")) ||
10374 (IS_SCHEMA(child, "maxExclusive")) ||
10375 (IS_SCHEMA(child, "totalDigits")) ||
10376 (IS_SCHEMA(child, "fractionDigits")) ||
10377 (IS_SCHEMA(child, "pattern")) ||
10378 (IS_SCHEMA(child, "enumeration")) ||
10379 (IS_SCHEMA(child, "whiteSpace")) ||
10380 (IS_SCHEMA(child, "length")) ||
10381 (IS_SCHEMA(child, "maxLength")) ||
10382 (IS_SCHEMA(child, "minLength"))) {
10383 facet = xmlSchemaParseFacet(ctxt, schema, child);
10384 if (facet != NULL) {
10385 if (lastfacet == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010386 type->facets = facet;
Daniel Veillard01fa6152004-06-29 17:04:39 +000010387 else
10388 lastfacet->next = facet;
10389 lastfacet = facet;
10390 lastfacet->next = NULL;
10391 }
10392 child = child->next;
10393 }
10394 /*
10395 * Create links for derivation and validation.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010396 */
10397 if (type->facets != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000010398 xmlSchemaFacetLinkPtr facetLink, lastFacetLink = NULL;
10399
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010400 facet = type->facets;
10401 do {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010402 facetLink = (xmlSchemaFacetLinkPtr)
10403 xmlMalloc(sizeof(xmlSchemaFacetLink));
Daniel Veillard01fa6152004-06-29 17:04:39 +000010404 if (facetLink == NULL) {
William M. Brack2f2a6632004-08-20 23:09:47 +000010405 xmlSchemaPErrMemory(ctxt, "allocating a facet link", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000010406 xmlFree(facetLink);
10407 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010408 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000010409 facetLink->facet = facet;
10410 facetLink->next = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010411 if (lastFacetLink == NULL)
10412 type->facetSet = facetLink;
Daniel Veillard01fa6152004-06-29 17:04:39 +000010413 else
10414 lastFacetLink->next = facetLink;
10415 lastFacetLink = facetLink;
10416 facet = facet->next;
10417 } while (facet != NULL);
10418 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010419 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010420 if (type->type == XML_SCHEMA_TYPE_COMPLEX) {
10421 /*
10422 * Attribute uses/declarations.
10423 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010424 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010425 /*
10426 * Attribute wildcard.
10427 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010428 if (IS_SCHEMA(child, "anyAttribute")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010429 type->attributeWildcard =
10430 xmlSchemaParseAnyAttribute(ctxt, schema, child);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010431 child = child->next;
10432 }
10433 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010434 if (child != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010435 if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
10436 xmlSchemaPContentErr(ctxt,
10437 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010438 NULL, NULL, node, child, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +000010439 "annotation?, (group | all | choice | sequence)?, "
10440 "((attribute | attributeGroup)*, anyAttribute?))");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010441 } else if (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010442 xmlSchemaPContentErr(ctxt,
10443 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010444 NULL, NULL, node, child, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +000010445 "(annotation?, (simpleType?, (minExclusive | minInclusive | "
10446 "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
10447 "length | minLength | maxLength | enumeration | whiteSpace | "
10448 "pattern)*)?, ((attribute | attributeGroup)*, anyAttribute?))");
10449 } else {
10450 /* Simple type */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010451 xmlSchemaPContentErr(ctxt,
10452 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010453 NULL, NULL, node, child, NULL,
William M. Brack2f2a6632004-08-20 23:09:47 +000010454 "(annotation?, (simpleType?, (minExclusive | minInclusive | "
10455 "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
10456 "length | minLength | maxLength | enumeration | whiteSpace | "
10457 "pattern)*))");
10458 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010459 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010460 ctxt->container = oldcontainer;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010461 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000010462}
10463
10464/**
10465 * xmlSchemaParseExtension:
10466 * @ctxt: a schema validation context
10467 * @schema: the schema being built
10468 * @node: a subtree containing XML Schema informations
10469 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010470 * Parses an <extension>, which is found inside a
10471 * <simpleContent> or <complexContent>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010472 * *WARNING* this interface is highly subject to change.
Daniel Veillard4255d502002-04-16 15:50:10 +000010473 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010474 * TODO: Returns the type definition or NULL in case of error
Daniel Veillard4255d502002-04-16 15:50:10 +000010475 */
10476static xmlSchemaTypePtr
10477xmlSchemaParseExtension(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010478 xmlNodePtr node, xmlSchemaTypeType parentType)
Daniel Veillard4255d502002-04-16 15:50:10 +000010479{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010480 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000010481 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010482 char buf[30];
10483 const xmlChar *oldcontainer, *container;
10484 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +000010485
10486 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
10487 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010488 /* Not a component, don't create it. */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010489 type = ctxt->ctxtType;
10490 type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION;
Daniel Veillard4255d502002-04-16 15:50:10 +000010491
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010492 snprintf(buf, 29, "#ext%d", ctxt->counter++ + 1);
10493 container = xmlDictLookup(ctxt->dict, BAD_CAST buf, -1);
10494 /*
10495 * Check for illegal attributes.
10496 */
10497 attr = node->properties;
10498 while (attr != NULL) {
10499 if (attr->ns == NULL) {
10500 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
10501 (!xmlStrEqual(attr->name, BAD_CAST "base"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010502 xmlSchemaPIllegalAttrErr(ctxt,
10503 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10504 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010505 }
10506 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010507 xmlSchemaPIllegalAttrErr(ctxt,
10508 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10509 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010510 }
10511 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010512 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000010513
10514 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010515
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +000010516 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010517 * Attribute "base" - mandatory.
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +000010518 */
10519 if ((xmlSchemaPValAttrQName(ctxt, schema,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010520 NULL, NULL, node, "base", &(type->baseNs), &(type->base)) == 0) &&
10521 (type->base == NULL)) {
Kasimier T. Buchcik289dbb42005-03-17 12:39:31 +000010522 xmlSchemaPMissingAttrErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010523 XML_SCHEMAP_S4S_ATTR_MISSING,
10524 NULL, node, "base", NULL);
10525 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010526 /*
10527 * And now for the children...
10528 */
Daniel Veillard4255d502002-04-16 15:50:10 +000010529 child = node->children;
10530 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010531 /*
10532 * Add the annotation to the type ancestor.
10533 */
10534 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
10535 xmlSchemaParseAnnotation(ctxt, schema, child));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010536 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010537 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010538 oldcontainer = ctxt->container;
10539 ctxt->container = container;
10540 if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
10541 /*
10542 * Corresponds to <complexType><complexContent><extension>... and:
10543 *
10544 * Model groups <all>, <choice>, <sequence> and <group>.
10545 */
10546 if (IS_SCHEMA(child, "all")) {
10547 type->subtypes = (xmlSchemaTypePtr)
10548 xmlSchemaParseModelGroup(ctxt, schema,
10549 child, XML_SCHEMA_TYPE_ALL, 1);
10550 child = child->next;
10551 } else if (IS_SCHEMA(child, "choice")) {
10552 type->subtypes = (xmlSchemaTypePtr)
10553 xmlSchemaParseModelGroup(ctxt, schema,
10554 child, XML_SCHEMA_TYPE_CHOICE, 1);
10555 child = child->next;
10556 } else if (IS_SCHEMA(child, "sequence")) {
10557 type->subtypes = (xmlSchemaTypePtr)
10558 xmlSchemaParseModelGroup(ctxt, schema,
10559 child, XML_SCHEMA_TYPE_SEQUENCE, 1);
10560 child = child->next;
10561 } else if (IS_SCHEMA(child, "group")) {
10562 type->subtypes = (xmlSchemaTypePtr)
10563 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
10564 child = child->next;
10565 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010566 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010567 if (child != NULL) {
10568 /*
10569 * Attribute uses/declarations.
10570 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010571 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010572 /*
10573 * Attribute wildcard.
10574 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010575 if (IS_SCHEMA(child, "anyAttribute")) {
10576 ctxt->ctxtType->attributeWildcard =
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000010577 xmlSchemaParseAnyAttribute(ctxt, schema, child);
10578 child = child->next;
10579 }
10580 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010581 if (child != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010582 if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
10583 /* Complex content extension. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010584 xmlSchemaPContentErr(ctxt,
10585 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010586 NULL, NULL, node, child, NULL,
10587 "(annotation?, ((group | all | choice | sequence)?, "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010588 "((attribute | attributeGroup)*, anyAttribute?)))");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010589 } else {
10590 /* Simple content extension. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010591 xmlSchemaPContentErr(ctxt,
10592 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010593 NULL, NULL, node, child, NULL,
10594 "(annotation?, ((attribute | attributeGroup)*, "
10595 "anyAttribute?))");
10596 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010597 }
10598 ctxt->container = oldcontainer;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010599 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000010600}
10601
10602/**
10603 * xmlSchemaParseSimpleContent:
10604 * @ctxt: a schema validation context
10605 * @schema: the schema being built
10606 * @node: a subtree containing XML Schema informations
10607 *
10608 * parse a XML schema SimpleContent definition
10609 * *WARNING* this interface is highly subject to change
10610 *
10611 * Returns the type definition or NULL in case of error
10612 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010613static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010614xmlSchemaParseSimpleContent(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010615 xmlSchemaPtr schema, xmlNodePtr node,
10616 int *hasRestrictionOrExtension)
Daniel Veillard4255d502002-04-16 15:50:10 +000010617{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010618 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000010619 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010620 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +000010621
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010622 if ((ctxt == NULL) || (schema == NULL) || (node == NULL) ||
10623 (hasRestrictionOrExtension == NULL))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010624 return (-1);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010625 *hasRestrictionOrExtension = 0;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010626 /* Not a component, don't create it. */
10627 type = ctxt->ctxtType;
10628 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
10629 /*
10630 * Check for illegal attributes.
10631 */
10632 attr = node->properties;
10633 while (attr != NULL) {
10634 if (attr->ns == NULL) {
10635 if ((!xmlStrEqual(attr->name, BAD_CAST "id"))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010636 xmlSchemaPIllegalAttrErr(ctxt,
10637 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10638 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010639 }
10640 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010641 xmlSchemaPIllegalAttrErr(ctxt,
10642 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10643 NULL, NULL, attr);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010644 }
10645 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010646 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000010647
10648 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
Daniel Veillard4255d502002-04-16 15:50:10 +000010649
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010650 /*
10651 * And now for the children...
10652 */
Daniel Veillard4255d502002-04-16 15:50:10 +000010653 child = node->children;
10654 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010655 /*
10656 * Add the annotation to the complex type ancestor.
10657 */
10658 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
10659 xmlSchemaParseAnnotation(ctxt, schema, child));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010660 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010661 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010662 if (child == NULL) {
10663 xmlSchemaPContentErr(ctxt,
10664 XML_SCHEMAP_S4S_ELEM_MISSING,
10665 NULL, NULL, node, NULL, NULL,
10666 "(annotation?, (restriction | extension))");
10667 }
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000010668 if (child == NULL) {
10669 xmlSchemaPContentErr(ctxt,
10670 XML_SCHEMAP_S4S_ELEM_MISSING,
10671 NULL, NULL, node, NULL, NULL,
10672 "(annotation?, (restriction | extension))");
10673 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010674 if (IS_SCHEMA(child, "restriction")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010675 xmlSchemaParseRestriction(ctxt, schema, child,
10676 XML_SCHEMA_TYPE_SIMPLE_CONTENT);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010677 (*hasRestrictionOrExtension) = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010678 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010679 } else if (IS_SCHEMA(child, "extension")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010680 xmlSchemaParseExtension(ctxt, schema, child,
10681 XML_SCHEMA_TYPE_SIMPLE_CONTENT);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010682 (*hasRestrictionOrExtension) = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010683 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010684 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010685 if (child != NULL) {
10686 xmlSchemaPContentErr(ctxt,
10687 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010688 NULL, NULL, node, child, NULL,
10689 "(annotation?, (restriction | extension))");
Daniel Veillard4255d502002-04-16 15:50:10 +000010690 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010691 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000010692}
10693
10694/**
10695 * xmlSchemaParseComplexContent:
10696 * @ctxt: a schema validation context
10697 * @schema: the schema being built
10698 * @node: a subtree containing XML Schema informations
10699 *
10700 * parse a XML schema ComplexContent definition
10701 * *WARNING* this interface is highly subject to change
10702 *
10703 * Returns the type definition or NULL in case of error
10704 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010705static int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010706xmlSchemaParseComplexContent(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010707 xmlSchemaPtr schema, xmlNodePtr node,
10708 int *hasRestrictionOrExtension)
Daniel Veillard4255d502002-04-16 15:50:10 +000010709{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010710 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000010711 xmlNodePtr child = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010712 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +000010713
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010714 if ((ctxt == NULL) || (schema == NULL) || (node == NULL) ||
10715 (hasRestrictionOrExtension == NULL))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010716 return (-1);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010717 *hasRestrictionOrExtension = 0;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010718 /* Not a component, don't create it. */
10719 type = ctxt->ctxtType;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010720 /*
10721 * Check for illegal attributes.
10722 */
10723 attr = node->properties;
10724 while (attr != NULL) {
10725 if (attr->ns == NULL) {
10726 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010727 (!xmlStrEqual(attr->name, BAD_CAST "mixed")))
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010728 {
10729 xmlSchemaPIllegalAttrErr(ctxt,
10730 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10731 NULL, NULL, attr);
10732 }
10733 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
10734 xmlSchemaPIllegalAttrErr(ctxt,
10735 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
10736 NULL, NULL, attr);
10737 }
10738 attr = attr->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010739 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000010740
10741 xmlSchemaPValAttrID(ctxt, NULL, NULL, node, BAD_CAST "id");
10742
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010743 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010744 * Set the 'mixed' on the complex type ancestor.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010745 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010746 if (xmlGetBooleanProp(ctxt, NULL, NULL, node, "mixed", 0)) {
10747 if ((type->flags & XML_SCHEMAS_TYPE_MIXED) == 0)
10748 type->flags |= XML_SCHEMAS_TYPE_MIXED;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010749 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010750 child = node->children;
10751 if (IS_SCHEMA(child, "annotation")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010752 /*
10753 * Add the annotation to the complex type ancestor.
10754 */
10755 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
10756 xmlSchemaParseAnnotation(ctxt, schema, child));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010757 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010758 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010759 if (child == NULL) {
10760 xmlSchemaPContentErr(ctxt,
10761 XML_SCHEMAP_S4S_ELEM_MISSING,
10762 NULL, NULL, node, NULL,
10763 NULL, "(annotation?, (restriction | extension))");
10764 }
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000010765 if (child == NULL) {
10766 xmlSchemaPContentErr(ctxt,
10767 XML_SCHEMAP_S4S_ELEM_MISSING,
10768 NULL, NULL, node, NULL,
10769 NULL, "(annotation?, (restriction | extension))");
10770 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010771 if (IS_SCHEMA(child, "restriction")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010772 xmlSchemaParseRestriction(ctxt, schema, child,
10773 XML_SCHEMA_TYPE_COMPLEX_CONTENT);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010774 (*hasRestrictionOrExtension) = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010775 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010776 } else if (IS_SCHEMA(child, "extension")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010777 xmlSchemaParseExtension(ctxt, schema, child,
10778 XML_SCHEMA_TYPE_COMPLEX_CONTENT);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010779 (*hasRestrictionOrExtension) = 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010780 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010781 }
Daniel Veillard4255d502002-04-16 15:50:10 +000010782 if (child != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010783 xmlSchemaPContentErr(ctxt,
10784 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
10785 NULL, NULL, node, child,
10786 NULL, "(annotation?, (restriction | extension))");
Daniel Veillard4255d502002-04-16 15:50:10 +000010787 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010788 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000010789}
10790
10791/**
10792 * xmlSchemaParseComplexType:
10793 * @ctxt: a schema validation context
10794 * @schema: the schema being built
10795 * @node: a subtree containing XML Schema informations
10796 *
10797 * parse a XML schema Complex Type definition
10798 * *WARNING* this interface is highly subject to change
10799 *
10800 * Returns the type definition or NULL in case of error
10801 */
10802static xmlSchemaTypePtr
10803xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
Daniel Veillard3646d642004-06-02 19:19:14 +000010804 xmlNodePtr node, int topLevel)
Daniel Veillard4255d502002-04-16 15:50:10 +000010805{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010806 xmlSchemaTypePtr type, ctxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +000010807 xmlNodePtr child = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010808 const xmlChar *oldcontainer, *name = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010809 xmlAttrPtr attr;
10810 const xmlChar *attrValue;
Daniel Veillard1a380b82004-10-21 16:00:06 +000010811 char buf[40];
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010812 int final = 0, block = 0, hasRestrictionOrExtension = 0;
Daniel Veillard1a380b82004-10-21 16:00:06 +000010813
Daniel Veillard4255d502002-04-16 15:50:10 +000010814
10815 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
10816 return (NULL);
10817
Daniel Veillard01fa6152004-06-29 17:04:39 +000010818 ctxtType = ctxt->ctxtType;
10819
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010820 if (topLevel) {
10821 attr = xmlSchemaGetPropNode(node, "name");
10822 if (attr == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010823 xmlSchemaPMissingAttrErr(ctxt,
10824 XML_SCHEMAP_S4S_ATTR_MISSING, NULL, node, "name", NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010825 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010826 } else if (xmlSchemaPValAttrNode(ctxt,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010827 NULL, NULL, attr,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010828 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
10829 return (NULL);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010830 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010831 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010832
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010833 if (topLevel == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010834 /*
10835 * Parse as local complex type definition.
10836 */
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +000010837 snprintf(buf, 39, "#CT%d", ctxt->counter++ + 1);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010838 type = xmlSchemaAddType(ctxt, schema, (const xmlChar *)buf, NULL,
10839 node, 0);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010840 if (type == NULL)
10841 return (NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010842 name = type->name;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010843 type->node = node;
10844 type->type = XML_SCHEMA_TYPE_COMPLEX;
10845 /*
10846 * TODO: We need the target namespace.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010847 */
10848 } else {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010849 /*
10850 * Parse as global complex type definition.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010851 */
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010852 type = xmlSchemaAddType(ctxt, schema, name, schema->targetNamespace,
10853 node, 1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010854 if (type == NULL)
10855 return (NULL);
10856 type->node = node;
10857 type->type = XML_SCHEMA_TYPE_COMPLEX;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010858 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
Kasimier T. Buchcik31113c72005-01-13 16:57:20 +000010859 }
10860 type->targetNamespace = schema->targetNamespace;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010861 /*
10862 * Handle attributes.
10863 */
10864 attr = node->properties;
10865 while (attr != NULL) {
10866 if (attr->ns == NULL) {
10867 if (xmlStrEqual(attr->name, BAD_CAST "id")) {
10868 /*
10869 * Attribute "id".
10870 */
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000010871 xmlSchemaPValAttrID(ctxt, NULL, type, node,
10872 BAD_CAST "id");
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010873 } else if (xmlStrEqual(attr->name, BAD_CAST "mixed")) {
10874 /*
10875 * Attribute "mixed".
10876 */
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010877 if (xmlSchemaPGetBoolNodeValue(ctxt, NULL, type,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010878 (xmlNodePtr) attr))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010879 type->flags |= XML_SCHEMAS_TYPE_MIXED;
10880 } else if (topLevel) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010881 /*
10882 * Attributes of global complex type definitions.
10883 */
10884 if (xmlStrEqual(attr->name, BAD_CAST "name")) {
10885 /* Pass. */
10886 } else if (xmlStrEqual(attr->name, BAD_CAST "abstract")) {
10887 /*
10888 * Attribute "abstract".
10889 */
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010890 if (xmlSchemaPGetBoolNodeValue(ctxt, NULL, type,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010891 (xmlNodePtr) attr))
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010892 type->flags |= XML_SCHEMAS_TYPE_ABSTRACT;
10893 } else if (xmlStrEqual(attr->name, BAD_CAST "final")) {
10894 /*
10895 * Attribute "final".
10896 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010897 attrValue = xmlSchemaGetNodeContent(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010898 (xmlNodePtr) attr);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010899 if (xmlSchemaPValAttrBlockFinal(attrValue,
10900 &(type->flags),
10901 -1,
10902 XML_SCHEMAS_TYPE_FINAL_EXTENSION,
10903 XML_SCHEMAS_TYPE_FINAL_RESTRICTION,
10904 -1, -1, -1) != 0)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010905 {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010906 xmlSchemaPSimpleTypeErr(ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010907 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010908 type, (xmlNodePtr) attr, NULL,
10909 "(#all | List of (extension | restriction))",
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010910 attrValue, NULL, NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010911 } else
10912 final = 1;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010913 } else if (xmlStrEqual(attr->name, BAD_CAST "block")) {
10914 /*
10915 * Attribute "block".
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010916 */
10917 attrValue = xmlSchemaGetNodeContent(ctxt,
10918 (xmlNodePtr) attr);
10919 if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010920 -1,
10921 XML_SCHEMAS_TYPE_BLOCK_EXTENSION,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010922 XML_SCHEMAS_TYPE_BLOCK_RESTRICTION,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010923 -1, -1, -1) != 0) {
10924 xmlSchemaPSimpleTypeErr(ctxt,
10925 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010926 type, (xmlNodePtr) attr, NULL,
10927 "(#all | List of (extension | restriction)) ",
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010928 attrValue, NULL, NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010929 } else
10930 block = 1;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010931 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010932 xmlSchemaPIllegalAttrErr(ctxt,
10933 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010934 NULL, type, attr);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010935 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010936 } else {
10937 xmlSchemaPIllegalAttrErr(ctxt,
10938 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010939 NULL, type, attr);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010940 }
10941 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010942 xmlSchemaPIllegalAttrErr(ctxt,
10943 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010944 NULL, type, attr);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010945 }
10946 attr = attr->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010947 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010948 if (! block) {
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000010949 /*
10950 * Apply default "block" values.
10951 */
10952 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
10953 type->flags |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
10954 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
10955 type->flags |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
10956 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010957 if (! final) {
10958 /*
10959 * Apply default "block" values.
10960 */
10961 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
10962 type->flags |= XML_SCHEMAS_TYPE_FINAL_RESTRICTION;
10963 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
10964 type->flags |= XML_SCHEMAS_TYPE_FINAL_EXTENSION;
10965 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010966 /*
10967 * And now for the children...
10968 */
10969 oldcontainer = ctxt->container;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010970 ctxt->container = name;
Daniel Veillard4255d502002-04-16 15:50:10 +000010971 child = node->children;
10972 if (IS_SCHEMA(child, "annotation")) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010973 type->annot = xmlSchemaParseAnnotation(ctxt, schema, child);
10974 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010975 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000010976 ctxt->ctxtType = type;
Daniel Veillard4255d502002-04-16 15:50:10 +000010977 if (IS_SCHEMA(child, "simpleContent")) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010978 /*
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010979 * <complexType><simpleContent>...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000010980 * 3.4.3 : 2.2
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000010981 * Specifying mixed='true' when the <simpleContent>
10982 * alternative is chosen has no effect
10983 */
William M. Bracke7091952004-05-11 15:09:58 +000010984 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
10985 type->flags ^= XML_SCHEMAS_TYPE_MIXED;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010986 xmlSchemaParseSimpleContent(ctxt, schema, child,
10987 &hasRestrictionOrExtension);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010988 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010989 } else if (IS_SCHEMA(child, "complexContent")) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010990 /*
10991 * <complexType><complexContent>...
10992 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010993 type->contentType = XML_SCHEMA_CONTENT_EMPTY;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010994 xmlSchemaParseComplexContent(ctxt, schema, child,
10995 &hasRestrictionOrExtension);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000010996 child = child->next;
Daniel Veillard4255d502002-04-16 15:50:10 +000010997 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000010998 /*
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000010999 * E.g <complexType><sequence>... or <complexType><attribute>... etc.
11000 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011001 * SPEC
11002 * "...the third alternative (neither <simpleContent> nor
11003 * <complexContent>) is chosen. This case is understood as shorthand
11004 * for complex content restricting the ·ur-type definition·, and the
11005 * details of the mappings should be modified as necessary.
11006 */
11007 type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
11008 type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011009 /*
11010 * Parse model groups.
11011 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011012 if (IS_SCHEMA(child, "all")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011013 type->subtypes = (xmlSchemaTypePtr)
11014 xmlSchemaParseModelGroup(ctxt, schema, child,
11015 XML_SCHEMA_TYPE_ALL, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011016 child = child->next;
11017 } else if (IS_SCHEMA(child, "choice")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011018 type->subtypes = (xmlSchemaTypePtr)
11019 xmlSchemaParseModelGroup(ctxt, schema, child,
11020 XML_SCHEMA_TYPE_CHOICE, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011021 child = child->next;
11022 } else if (IS_SCHEMA(child, "sequence")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011023 type->subtypes = (xmlSchemaTypePtr)
11024 xmlSchemaParseModelGroup(ctxt, schema, child,
11025 XML_SCHEMA_TYPE_SEQUENCE, 1);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011026 child = child->next;
11027 } else if (IS_SCHEMA(child, "group")) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011028 type->subtypes = (xmlSchemaTypePtr)
11029 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011030 child = child->next;
11031 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011032 /*
11033 * Parse attribute decls/refs.
11034 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011035 child = xmlSchemaParseAttrDecls(ctxt, schema, child, type);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011036 /*
11037 * Parse attribute wildcard.
11038 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011039 if (IS_SCHEMA(child, "anyAttribute")) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011040 type->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
11041 child = child->next;
11042 }
Daniel Veillard4255d502002-04-16 15:50:10 +000011043 }
11044 if (child != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011045 xmlSchemaPContentErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011046 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011047 NULL, type, node, child,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011048 NULL, "(annotation?, (simpleContent | complexContent | "
11049 "((group | all | choice | sequence)?, ((attribute | "
11050 "attributeGroup)*, anyAttribute?))))");
Daniel Veillard4255d502002-04-16 15:50:10 +000011051 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011052 /*
11053 * REDEFINE: SPEC src-redefine (5)
11054 */
11055 if (topLevel && ctxt->isRedefine && (! hasRestrictionOrExtension)) {
11056 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_SRC_REDEFINE,
11057 NULL, NULL, node, "This is a redefinition, thus the "
11058 "<complexType> must have a <restriction> or <extension> "
11059 "grand-child", NULL);
11060 }
Daniel Veillard4255d502002-04-16 15:50:10 +000011061 ctxt->container = oldcontainer;
Daniel Veillard01fa6152004-06-29 17:04:39 +000011062 ctxt->ctxtType = ctxtType;
Daniel Veillard4255d502002-04-16 15:50:10 +000011063 return (type);
11064}
11065
Daniel Veillard4255d502002-04-16 15:50:10 +000011066/**
11067 * xmlSchemaParseSchema:
11068 * @ctxt: a schema validation context
11069 * @node: a subtree containing XML Schema informations
11070 *
11071 * parse a XML schema definition from a node set
11072 * *WARNING* this interface is highly subject to change
11073 *
11074 * Returns the internal XML Schema structure built from the resource or
11075 * NULL in case of error
11076 */
11077static xmlSchemaPtr
11078xmlSchemaParseSchema(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
11079{
11080 xmlSchemaPtr schema = NULL;
Daniel Veillardbe9c6322003-11-22 20:37:51 +000011081 const xmlChar *val;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000011082 int nberrors;
Daniel Veillardc0826a72004-08-10 14:17:33 +000011083 xmlAttrPtr attr;
Daniel Veillard4255d502002-04-16 15:50:10 +000011084
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011085 /*
11086 * This one is called by xmlSchemaParse only and is used if
11087 * the schema to be parsed was specified via the API; i.e. not
11088 * automatically by the validated instance document.
11089 */
Daniel Veillard4255d502002-04-16 15:50:10 +000011090 if ((ctxt == NULL) || (node == NULL))
11091 return (NULL);
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000011092 nberrors = ctxt->nberrors;
11093 ctxt->nberrors = 0;
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000011094 ctxt->isS4S = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000011095 if (IS_SCHEMA(node, "schema")) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011096 xmlSchemaImportPtr import;
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000011097#ifdef ENABLE_REDEFINE
11098 xmlSchemaSchemaRefPtr ref;
11099#endif
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011100
Daniel Veillard4255d502002-04-16 15:50:10 +000011101 schema = xmlSchemaNewSchema(ctxt);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011102 if (schema == NULL)
11103 return (NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011104 attr = xmlSchemaGetPropNode(node, "targetNamespace");
Daniel Veillardc0826a72004-08-10 14:17:33 +000011105 if (attr != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011106 xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011107 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), &val);
11108 /*
11109 * TODO: Should we proceed with an invalid target namespace?
11110 */
Daniel Veillardbe9c6322003-11-22 20:37:51 +000011111 schema->targetNamespace = xmlDictLookup(ctxt->dict, val, -1);
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000011112 if (xmlStrEqual(schema->targetNamespace, xmlSchemaNs)) {
11113 /*
11114 * We are parsing the schema for schema!
11115 */
11116 ctxt->isS4S = 1;
11117 }
Daniel Veillardbe9c6322003-11-22 20:37:51 +000011118 } else {
11119 schema->targetNamespace = NULL;
11120 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011121 /*
11122 * Add the current ns name and location to the import table;
11123 * this is needed to have a consistent mechanism, regardless
11124 * if all schemata are constructed dynamically fired by the
11125 * instance or if the schema to be used was specified via
11126 * the API.
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011127 * TODO
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011128 */
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000011129#ifdef ENABLE_REDEFINE
11130 ref = xmlSchemaSchemaRefCreate();
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011131 if (ref == NULL) {
11132 xmlSchemaFree(schema);
11133 schema = NULL;
11134 return NULL;
11135 }
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000011136 ref->schema = schema;
11137#endif
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011138
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011139 import = xmlSchemaAddImport(ctxt, &(schema->schemasImports),
11140 schema->targetNamespace);
11141 if (import == NULL) {
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000011142 xmlSchemaPInternalErr(ctxt, "xmlSchemaParseSchema",
11143 "failed to add an import entry", NULL, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011144 xmlSchemaFree(schema);
11145 schema = NULL;
11146 return (NULL);
11147 }
11148 import->schemaLocation = ctxt->URL;
11149 /*
11150 * NOTE: We won't set the doc here, otherwise it will be freed
11151 * if the import struct is freed.
11152 * import->doc = ctxt->doc;
11153 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011154 xmlSchemaParseSchemaDefaults(ctxt, schema, node);
Daniel Veillardbd2904b2003-11-25 15:38:59 +000011155 xmlSchemaParseSchemaTopLevel(ctxt, schema, node->children);
11156 } else {
11157 xmlDocPtr doc;
11158
11159 doc = node->doc;
11160
11161 if ((doc != NULL) && (doc->URL != NULL)) {
11162 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
11163 XML_SCHEMAP_NOT_SCHEMA,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011164 "The file \"%s\" is not a XML schema.\n", doc->URL, NULL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +000011165 } else {
11166 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
11167 XML_SCHEMAP_NOT_SCHEMA,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011168 "The file is not a XML schema.\n", NULL, NULL);
Daniel Veillardbd2904b2003-11-25 15:38:59 +000011169 }
11170 return(NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000011171 }
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000011172 if (ctxt->nberrors != 0) {
11173 if (schema != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011174 xmlSchemaFree(schema);
11175 schema = NULL;
11176 }
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000011177 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011178 if (schema != NULL)
11179 schema->counter = ctxt->counter;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000011180 ctxt->nberrors = nberrors;
Daniel Veillard4255d502002-04-16 15:50:10 +000011181#ifdef DEBUG
11182 if (schema == NULL)
11183 xmlGenericError(xmlGenericErrorContext,
11184 "xmlSchemaParse() failed\n");
11185#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000011186 return (schema);
11187}
11188
11189/************************************************************************
11190 * *
11191 * Validating using Schemas *
11192 * *
11193 ************************************************************************/
11194
11195/************************************************************************
11196 * *
11197 * Reading/Writing Schemas *
11198 * *
11199 ************************************************************************/
11200
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011201#if 0 /* Will be enabled if it is clear what options are needed. */
11202/**
11203 * xmlSchemaParserCtxtSetOptions:
11204 * @ctxt: a schema parser context
11205 * @options: a combination of xmlSchemaParserOption
11206 *
11207 * Sets the options to be used during the parse.
11208 *
11209 * Returns 0 in case of success, -1 in case of an
11210 * API error.
11211 */
11212static int
11213xmlSchemaParserCtxtSetOptions(xmlSchemaParserCtxtPtr ctxt,
11214 int options)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011215
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011216{
11217 int i;
11218
11219 if (ctxt == NULL)
11220 return (-1);
11221 /*
11222 * WARNING: Change the start value if adding to the
11223 * xmlSchemaParseOption.
11224 */
11225 for (i = 1; i < (int) sizeof(int) * 8; i++) {
11226 if (options & 1<<i) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011227 return (-1);
11228 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011229 }
11230 ctxt->options = options;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011231 return (0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011232}
11233
11234/**
11235 * xmlSchemaValidCtxtGetOptions:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011236 * @ctxt: a schema parser context
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011237 *
11238 * Returns the option combination of the parser context.
11239 */
11240static int
11241xmlSchemaParserCtxtGetOptions(xmlSchemaParserCtxtPtr ctxt)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011242
11243{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011244 if (ctxt == NULL)
11245 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011246 else
11247 return (ctxt->options);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011248}
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011249#endif
11250
Daniel Veillard4255d502002-04-16 15:50:10 +000011251/**
11252 * xmlSchemaNewParserCtxt:
11253 * @URL: the location of the schema
11254 *
11255 * Create an XML Schemas parse context for that file/resource expected
11256 * to contain an XML Schemas file.
11257 *
11258 * Returns the parser context or NULL in case of error
11259 */
11260xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011261xmlSchemaNewParserCtxt(const char *URL)
11262{
Daniel Veillard4255d502002-04-16 15:50:10 +000011263 xmlSchemaParserCtxtPtr ret;
11264
11265 if (URL == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011266 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000011267
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000011268 ret = xmlSchemaParserCtxtCreate();
11269 if (ret == NULL)
11270 return(NULL);
Daniel Veillardbe9c6322003-11-22 20:37:51 +000011271 ret->dict = xmlDictCreate();
11272 ret->URL = xmlDictLookup(ret->dict, (const xmlChar *) URL, -1);
Daniel Veillardb0f397e2003-12-23 23:30:53 +000011273 ret->includes = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000011274 return (ret);
11275}
11276
11277/**
Daniel Veillard6045c902002-10-09 21:13:59 +000011278 * xmlSchemaNewMemParserCtxt:
11279 * @buffer: a pointer to a char array containing the schemas
11280 * @size: the size of the array
11281 *
11282 * Create an XML Schemas parse context for that memory buffer expected
11283 * to contain an XML Schemas file.
11284 *
11285 * Returns the parser context or NULL in case of error
11286 */
11287xmlSchemaParserCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011288xmlSchemaNewMemParserCtxt(const char *buffer, int size)
11289{
Daniel Veillard6045c902002-10-09 21:13:59 +000011290 xmlSchemaParserCtxtPtr ret;
11291
11292 if ((buffer == NULL) || (size <= 0))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011293 return (NULL);
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000011294 ret = xmlSchemaParserCtxtCreate();
11295 if (ret == NULL)
11296 return(NULL);
Daniel Veillard6045c902002-10-09 21:13:59 +000011297 ret->buffer = buffer;
11298 ret->size = size;
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000011299 ret->dict = xmlDictCreate();
Daniel Veillard6045c902002-10-09 21:13:59 +000011300 return (ret);
11301}
11302
11303/**
Daniel Veillard9d751502003-10-29 13:21:47 +000011304 * xmlSchemaNewDocParserCtxt:
11305 * @doc: a preparsed document tree
11306 *
11307 * Create an XML Schemas parse context for that document.
11308 * NB. The document may be modified during the parsing process.
11309 *
11310 * Returns the parser context or NULL in case of error
11311 */
11312xmlSchemaParserCtxtPtr
11313xmlSchemaNewDocParserCtxt(xmlDocPtr doc)
11314{
11315 xmlSchemaParserCtxtPtr ret;
11316
11317 if (doc == NULL)
11318 return (NULL);
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000011319 ret = xmlSchemaParserCtxtCreate();
11320 if (ret == NULL)
11321 return(NULL);
Daniel Veillard9d751502003-10-29 13:21:47 +000011322 ret->doc = doc;
William M. Brackcf9eadf2003-12-25 13:24:05 +000011323 ret->dict = xmlDictCreate();
Daniel Veillarddda22c12004-01-24 08:31:30 +000011324 /* The application has responsibility for the document */
11325 ret->preserve = 1;
Daniel Veillard9d751502003-10-29 13:21:47 +000011326
11327 return (ret);
11328}
11329
11330/**
Daniel Veillard4255d502002-04-16 15:50:10 +000011331 * xmlSchemaFreeParserCtxt:
11332 * @ctxt: the schema parser context
11333 *
11334 * Free the resources associated to the schema parser context
11335 */
11336void
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011337xmlSchemaFreeParserCtxt(xmlSchemaParserCtxtPtr ctxt)
11338{
Daniel Veillard4255d502002-04-16 15:50:10 +000011339 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011340 return;
Daniel Veillarddda22c12004-01-24 08:31:30 +000011341 if (ctxt->doc != NULL && !ctxt->preserve)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011342 xmlFreeDoc(ctxt->doc);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011343 if (ctxt->assemble != NULL) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011344 xmlFree((xmlSchemaTypePtr *) ctxt->assemble->items);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011345 xmlFree(ctxt->assemble);
11346 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011347 if (ctxt->vctxt != NULL) {
11348 xmlSchemaFreeValidCtxt(ctxt->vctxt);
11349 }
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000011350 if (ctxt->localImports != NULL)
11351 xmlFree((xmlChar *) ctxt->localImports);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011352 if (ctxt->substGroups != NULL)
11353 xmlHashFree(ctxt->substGroups,
11354 (xmlHashDeallocator) xmlSchemaFreeSubstGroup);
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000011355 xmlSchemaContainerFree(ctxt->compContainer);
Daniel Veillardbe9c6322003-11-22 20:37:51 +000011356 xmlDictFree(ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +000011357 xmlFree(ctxt);
11358}
11359
11360/************************************************************************
11361 * *
11362 * Building the content models *
11363 * *
11364 ************************************************************************/
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011365
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011366static void
11367xmlSchemaBuildContentModelForSubstGroup(xmlSchemaParserCtxtPtr pctxt,
Daniel Veillarda980bef2005-07-18 21:34:03 +000011368 xmlSchemaParticlePtr particle, int counter, xmlAutomataStatePtr end)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011369{
Daniel Veillarda980bef2005-07-18 21:34:03 +000011370 xmlAutomataStatePtr start, tmp;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000011371 xmlSchemaElementPtr elemDecl, member;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000011372 xmlSchemaSubstGroupPtr substGroup;
11373 int i;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011374
11375 elemDecl = (xmlSchemaElementPtr) particle->children;
11376 /*
11377 * Wrap the substitution group with a CHOICE.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011378 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011379 start = pctxt->state;
Daniel Veillarda980bef2005-07-18 21:34:03 +000011380 if (end == NULL)
11381 end = xmlAutomataNewState(pctxt->am);
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000011382 substGroup = xmlSchemaGetElementSubstitutionGroup(pctxt, elemDecl);
11383 if (substGroup == NULL) {
11384 xmlSchemaPErr(pctxt, GET_NODE(particle),
11385 XML_SCHEMAP_INTERNAL,
11386 "Internal error: xmlSchemaBuildContentModelForSubstGroup, "
11387 "declaration is marked having a subst. group but none "
11388 "available.\n", elemDecl->name, NULL);
11389 return;
11390 }
Daniel Veillarda980bef2005-07-18 21:34:03 +000011391 if (counter >= 0) {
11392 /*
11393 * NOTE that we put the declaration in, even if it's abstract,
11394 */
11395 tmp = xmlAutomataNewCountedTrans(pctxt->am, start, NULL, counter);
11396 xmlAutomataNewTransition2(pctxt->am, tmp, end,
11397 elemDecl->name, elemDecl->targetNamespace, elemDecl);
11398 /*
11399 * Add subst. group members.
11400 */
11401 for (i = 0; i < substGroup->members->nbItems; i++) {
11402 member = (xmlSchemaElementPtr) substGroup->members->items[i];
11403 xmlAutomataNewTransition2(pctxt->am, tmp, end,
11404 member->name, member->targetNamespace, member);
11405 }
11406 } else if (particle->maxOccurs == 1) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011407 /*
11408 * NOTE that we put the declaration in, even if it's abstract,
11409 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011410 xmlAutomataNewEpsilon(pctxt->am,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011411 xmlAutomataNewTransition2(pctxt->am,
11412 start, NULL,
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000011413 elemDecl->name, elemDecl->targetNamespace, elemDecl), end);
11414 /*
11415 * Add subst. group members.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011416 */
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000011417 for (i = 0; i < substGroup->members->nbItems; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011418 member = (xmlSchemaElementPtr) substGroup->members->items[i];
Daniel Veillarda980bef2005-07-18 21:34:03 +000011419 tmp = xmlAutomataNewOnceTrans2(pctxt->am, start, NULL,
11420 member->name, member->targetNamespace,
11421 1, 1, member);
11422 xmlAutomataNewEpsilon(pctxt->am, tmp, end);
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000011423 }
11424 } else {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011425 xmlAutomataStatePtr hop;
11426 int maxOccurs = particle->maxOccurs == UNBOUNDED ?
11427 UNBOUNDED : particle->maxOccurs - 1;
11428 int minOccurs = particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
11429
11430 counter =
11431 xmlAutomataNewCounter(pctxt->am, minOccurs,
11432 maxOccurs);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011433 hop = xmlAutomataNewState(pctxt->am);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011434
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011435 xmlAutomataNewEpsilon(pctxt->am,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011436 xmlAutomataNewTransition2(pctxt->am,
11437 start, NULL,
11438 elemDecl->name, elemDecl->targetNamespace, elemDecl),
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000011439 hop);
11440 /*
Daniel Veillarda980bef2005-07-18 21:34:03 +000011441 * Add subst. group members.
11442 */
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000011443 for (i = 0; i < substGroup->members->nbItems; i++) {
11444 member = (xmlSchemaElementPtr) substGroup->members->items[i];
11445 xmlAutomataNewEpsilon(pctxt->am,
11446 xmlAutomataNewTransition2(pctxt->am,
11447 start, NULL,
11448 member->name, member->targetNamespace, member),
11449 hop);
11450 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011451 xmlAutomataNewCountedTrans(pctxt->am, hop, start, counter);
11452 xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
11453 }
11454 if (particle->minOccurs == 0)
11455 xmlAutomataNewEpsilon(pctxt->am, start, end);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011456 pctxt->state = end;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011457}
11458
11459static void
11460xmlSchemaBuildContentModelForElement(xmlSchemaParserCtxtPtr ctxt,
11461 xmlSchemaParticlePtr particle)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011462{
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000011463 if (((xmlSchemaElementPtr) particle->children)->flags &
11464 XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011465 /*
11466 * Substitution groups.
11467 */
Daniel Veillarda980bef2005-07-18 21:34:03 +000011468 xmlSchemaBuildContentModelForSubstGroup(ctxt, particle, -1, NULL);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011469 } else {
11470 xmlSchemaElementPtr elemDecl;
11471 xmlAutomataStatePtr start;
11472
11473 elemDecl = (xmlSchemaElementPtr) particle->children;
11474
11475 if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011476 return;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011477 if (particle->maxOccurs == 1) {
11478 start = ctxt->state;
11479 ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
Daniel Veillarda980bef2005-07-18 21:34:03 +000011480 elemDecl->name, elemDecl->targetNamespace, elemDecl);
11481 } else if ((particle->maxOccurs >= UNBOUNDED) &&
11482 (particle->minOccurs < 2)) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011483 /* Special case. */
11484 start = ctxt->state;
11485 ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
11486 elemDecl->name, elemDecl->targetNamespace, elemDecl);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011487 xmlAutomataNewEpsilon(ctxt->am, ctxt->state, start);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011488 } else {
11489 int counter;
11490 int maxOccurs = particle->maxOccurs == UNBOUNDED ?
11491 UNBOUNDED : particle->maxOccurs - 1;
11492 int minOccurs = particle->minOccurs < 1 ?
11493 0 : particle->minOccurs - 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011494
11495 start = xmlAutomataNewEpsilon(ctxt->am, ctxt->state, NULL);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011496 counter = xmlAutomataNewCounter(ctxt->am, minOccurs, maxOccurs);
11497 ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
11498 elemDecl->name, elemDecl->targetNamespace, elemDecl);
11499 xmlAutomataNewCountedTrans(ctxt->am, ctxt->state, start, counter);
11500 ctxt->state = xmlAutomataNewCounterTrans(ctxt->am, ctxt->state,
11501 NULL, counter);
11502 }
11503 if (particle->minOccurs == 0)
11504 xmlAutomataNewEpsilon(ctxt->am, start, ctxt->state);
11505 }
11506}
11507
Daniel Veillard4255d502002-04-16 15:50:10 +000011508/**
11509 * xmlSchemaBuildAContentModel:
Daniel Veillard4255d502002-04-16 15:50:10 +000011510 * @ctxt: the schema parser context
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011511 * @particle: the particle component
11512 * @name: the complex type's name whose content is being built
Daniel Veillard4255d502002-04-16 15:50:10 +000011513 *
11514 * Generate the automata sequence needed for that type
11515 */
11516static void
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011517xmlSchemaBuildAContentModel(xmlSchemaParserCtxtPtr pctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011518 xmlSchemaParticlePtr particle,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011519 const xmlChar * name)
11520{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011521 if (particle == NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011522 PERROR_INT("xmlSchemaBuildAContentModel", "particle is NULL");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011523 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000011524 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011525 if (particle->children == NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011526 PERROR_INT("xmlSchemaBuildAContentModel", "no term on particle");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011527 return;
11528 }
11529
11530 switch (particle->children->type) {
11531 case XML_SCHEMA_TYPE_ANY: {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011532 xmlAutomataStatePtr start, end;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011533 xmlSchemaWildcardPtr wild;
Daniel Veillardc0826a72004-08-10 14:17:33 +000011534 xmlSchemaWildcardNsPtr ns;
Daniel Veillard32370232002-10-16 14:08:14 +000011535
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011536 wild = (xmlSchemaWildcardPtr) particle->children;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011537
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011538 start = pctxt->state;
11539 end = xmlAutomataNewState(pctxt->am);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011540
11541 if (particle->maxOccurs == 1) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011542 if (wild->any == 1) {
11543 /*
11544 * We need to add both transitions:
11545 *
11546 * 1. the {"*", "*"} for elements in a namespace.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011547 */
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011548 pctxt->state =
11549 xmlAutomataNewTransition2(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011550 start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011551 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011552 /*
11553 * 2. the {"*"} for elements in no namespace.
11554 */
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011555 pctxt->state =
11556 xmlAutomataNewTransition2(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011557 start, NULL, BAD_CAST "*", NULL, wild);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011558 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011559
11560 } else if (wild->nsSet != NULL) {
11561 ns = wild->nsSet;
11562 do {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011563 pctxt->state = start;
11564 pctxt->state = xmlAutomataNewTransition2(pctxt->am,
11565 pctxt->state, NULL, BAD_CAST "*", ns->value, wild);
11566 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011567 ns = ns->next;
11568 } while (ns != NULL);
11569
11570 } else if (wild->negNsSet != NULL) {
Daniel Veillard6e65e152005-08-09 11:09:52 +000011571 pctxt->state = xmlAutomataNewNegTrans(pctxt->am,
11572 start, end, BAD_CAST "*", wild->negNsSet->value,
11573 wild);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011574 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000011575 } else {
11576 int counter;
11577 xmlAutomataStatePtr hop;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011578 int maxOccurs =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011579 particle->maxOccurs == UNBOUNDED ? UNBOUNDED : particle->maxOccurs - 1;
Daniel Veillardc0826a72004-08-10 14:17:33 +000011580 int minOccurs =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011581 particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011582
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011583 counter = xmlAutomataNewCounter(pctxt->am, minOccurs, maxOccurs);
11584 hop = xmlAutomataNewState(pctxt->am);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011585 if (wild->any == 1) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011586 pctxt->state =
11587 xmlAutomataNewTransition2(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011588 start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011589 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
11590 pctxt->state =
11591 xmlAutomataNewTransition2(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011592 start, NULL, BAD_CAST "*", NULL, wild);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011593 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011594 } else if (wild->nsSet != NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011595 ns = wild->nsSet;
11596 do {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011597 pctxt->state =
11598 xmlAutomataNewTransition2(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011599 start, NULL, BAD_CAST "*", ns->value, wild);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011600 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011601 ns = ns->next;
11602 } while (ns != NULL);
11603
11604 } else if (wild->negNsSet != NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011605 pctxt->state = xmlAutomataNewNegTrans(pctxt->am,
Daniel Veillard9efc4762005-07-19 14:33:55 +000011606 start, hop, BAD_CAST "*", wild->negNsSet->value,
11607 wild);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011608 }
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011609 xmlAutomataNewCountedTrans(pctxt->am, hop, start, counter);
11610 xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
Daniel Veillardc0826a72004-08-10 14:17:33 +000011611 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011612 if (particle->minOccurs == 0) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011613 xmlAutomataNewEpsilon(pctxt->am, start, end);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011614 }
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011615 pctxt->state = end;
Daniel Veillardc0826a72004-08-10 14:17:33 +000011616 break;
11617 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011618 case XML_SCHEMA_TYPE_ELEMENT:
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011619 xmlSchemaBuildContentModelForElement(pctxt, particle);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011620 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011621 case XML_SCHEMA_TYPE_SEQUENCE:{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011622 xmlSchemaTreeItemPtr sub;
Daniel Veillardb39bc392002-10-26 19:29:51 +000011623
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011624 /*
11625 * If max and min occurances are default (1) then
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011626 * simply iterate over the particles of the <sequence>.
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011627 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011628 if ((particle->minOccurs == 1) && (particle->maxOccurs == 1)) {
11629 sub = particle->children->children;
11630 while (sub != NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011631 xmlSchemaBuildAContentModel(pctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011632 (xmlSchemaParticlePtr) sub, name);
11633 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011634 }
11635 } else {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011636 xmlAutomataStatePtr oldstate = pctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +000011637
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011638 if (particle->maxOccurs >= UNBOUNDED) {
11639 if (particle->minOccurs > 1) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011640 xmlAutomataStatePtr tmp;
11641 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +000011642
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011643 pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011644 oldstate, NULL);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011645 oldstate = pctxt->state;
Daniel Veillardb39bc392002-10-26 19:29:51 +000011646
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011647 counter = xmlAutomataNewCounter(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011648 particle->minOccurs - 1, UNBOUNDED);
Daniel Veillardb39bc392002-10-26 19:29:51 +000011649
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011650 sub = particle->children->children;
11651 while (sub != NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011652 xmlSchemaBuildAContentModel(pctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011653 (xmlSchemaParticlePtr) sub, name);
11654 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011655 }
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011656 tmp = pctxt->state;
11657 xmlAutomataNewCountedTrans(pctxt->am, tmp,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011658 oldstate, counter);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011659 pctxt->state =
11660 xmlAutomataNewCounterTrans(pctxt->am, tmp,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011661 NULL, counter);
Daniel Veillardb39bc392002-10-26 19:29:51 +000011662
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011663 } else {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011664 pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
Daniel Veillardafc05b62005-07-17 06:11:19 +000011665 oldstate, NULL);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011666 oldstate = pctxt->state;
Daniel Veillardafc05b62005-07-17 06:11:19 +000011667
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011668 sub = particle->children->children;
11669 while (sub != NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011670 xmlSchemaBuildAContentModel(pctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011671 (xmlSchemaParticlePtr) sub, name);
11672 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011673 }
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011674 xmlAutomataNewEpsilon(pctxt->am, pctxt->state,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011675 oldstate);
Daniel Veillardafc05b62005-07-17 06:11:19 +000011676 /*
11677 * epsilon needed to block previous trans from
11678 * being allowed to enter back from another
11679 * construct
11680 */
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011681 pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
11682 pctxt->state, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011683 if (particle->minOccurs == 0) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011684 xmlAutomataNewEpsilon(pctxt->am,
11685 oldstate, pctxt->state);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011686 }
11687 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011688 } else if ((particle->maxOccurs > 1)
11689 || (particle->minOccurs > 1)) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011690 xmlAutomataStatePtr tmp;
11691 int counter;
Daniel Veillardb39bc392002-10-26 19:29:51 +000011692
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011693 pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011694 oldstate, NULL);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011695 oldstate = pctxt->state;
Daniel Veillard4255d502002-04-16 15:50:10 +000011696
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011697 counter = xmlAutomataNewCounter(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011698 particle->minOccurs - 1,
11699 particle->maxOccurs - 1);
Daniel Veillard4255d502002-04-16 15:50:10 +000011700
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011701 sub = particle->children->children;
11702 while (sub != NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011703 xmlSchemaBuildAContentModel(pctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011704 (xmlSchemaParticlePtr) sub, name);
11705 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011706 }
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011707 tmp = pctxt->state;
11708 xmlAutomataNewCountedTrans(pctxt->am,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011709 tmp, oldstate, counter);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011710 pctxt->state =
11711 xmlAutomataNewCounterTrans(pctxt->am, tmp, NULL,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011712 counter);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011713 if (particle->minOccurs == 0) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011714 xmlAutomataNewEpsilon(pctxt->am,
11715 oldstate, pctxt->state);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011716 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011717 } else {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011718 sub = particle->children->children;
11719 while (sub != NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011720 xmlSchemaBuildAContentModel(pctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011721 (xmlSchemaParticlePtr) sub, name);
11722 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011723 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011724 if (particle->minOccurs == 0) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011725 xmlAutomataNewEpsilon(pctxt->am, oldstate,
11726 pctxt->state);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011727 }
11728 }
11729 }
11730 break;
11731 }
11732 case XML_SCHEMA_TYPE_CHOICE:{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011733 xmlSchemaTreeItemPtr sub;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011734 xmlAutomataStatePtr start, end;
Daniel Veillardb509f152002-04-17 16:28:10 +000011735
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011736 start = pctxt->state;
11737 end = xmlAutomataNewState(pctxt->am);
Daniel Veillard7646b182002-04-20 06:41:40 +000011738
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011739 /*
11740 * iterate over the subtypes and remerge the end with an
11741 * epsilon transition
11742 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011743 if (particle->maxOccurs == 1) {
11744 sub = particle->children->children;
11745 while (sub != NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011746 pctxt->state = start;
11747 xmlSchemaBuildAContentModel(pctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011748 (xmlSchemaParticlePtr) sub, name);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011749 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011750 sub = sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011751 }
11752 } else {
11753 int counter;
Daniel Veillardafc05b62005-07-17 06:11:19 +000011754 xmlAutomataStatePtr hop, base;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011755 int maxOccurs = particle->maxOccurs == UNBOUNDED ?
11756 UNBOUNDED : particle->maxOccurs - 1;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011757 int minOccurs =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011758 particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
Daniel Veillard7646b182002-04-20 06:41:40 +000011759
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011760 /*
11761 * use a counter to keep track of the number of transtions
11762 * which went through the choice.
11763 */
11764 counter =
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011765 xmlAutomataNewCounter(pctxt->am, minOccurs, maxOccurs);
11766 hop = xmlAutomataNewState(pctxt->am);
11767 base = xmlAutomataNewState(pctxt->am);
Daniel Veillard6231e842002-04-18 11:54:04 +000011768
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011769 sub = particle->children->children;
11770 while (sub != NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011771 pctxt->state = base;
11772 xmlSchemaBuildAContentModel(pctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011773 (xmlSchemaParticlePtr) sub, name);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011774 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011775 sub = sub->next;
Daniel Veillarda980bef2005-07-18 21:34:03 +000011776 }
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011777 xmlAutomataNewEpsilon(pctxt->am, start, base);
11778 xmlAutomataNewCountedTrans(pctxt->am, hop, base, counter);
11779 xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011780 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011781 if (particle->minOccurs == 0) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011782 xmlAutomataNewEpsilon(pctxt->am, start, end);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011783 }
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011784 pctxt->state = end;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011785 break;
11786 }
11787 case XML_SCHEMA_TYPE_ALL:{
Kasimier T. Buchcik2c9aac02005-07-21 22:14:12 +000011788 xmlAutomataStatePtr start;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011789 xmlSchemaParticlePtr sub;
11790 xmlSchemaElementPtr elemDecl;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011791 int lax;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011792
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011793 sub = (xmlSchemaParticlePtr) particle->children->children;
11794 if (sub == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011795 break;
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011796 start = pctxt->state;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011797 while (sub != NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011798 pctxt->state = start;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011799
11800 elemDecl = (xmlSchemaElementPtr) sub->children;
11801 if (elemDecl == NULL) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011802 PERROR_INT("xmlSchemaBuildAContentModel",
11803 "<element> particle has no term");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011804 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011805 };
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000011806 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011807 * NOTE: The {max occurs} of all the particles in the
Kasimier T. Buchcikff858ca2005-02-18 11:37:58 +000011808 * {particles} of the group must be 0 or 1; this is
11809 * already ensured during the parse of the content of
11810 * <all>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011811 */
Daniel Veillarda980bef2005-07-18 21:34:03 +000011812 if (elemDecl->flags & XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) {
11813 int counter;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011814
Daniel Veillarda980bef2005-07-18 21:34:03 +000011815 /*
11816 * This is an abstract group, we need to share
11817 * the same counter for all the element transitions
11818 * derived from the group
11819 */
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011820 counter = xmlAutomataNewCounter(pctxt->am,
Daniel Veillarda980bef2005-07-18 21:34:03 +000011821 sub->minOccurs, sub->maxOccurs);
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011822 xmlSchemaBuildContentModelForSubstGroup(pctxt,
11823 sub, counter, pctxt->state);
Daniel Veillarda980bef2005-07-18 21:34:03 +000011824 } else {
11825 if ((sub->minOccurs == 1) &&
11826 (sub->maxOccurs == 1)) {
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011827 xmlAutomataNewOnceTrans2(pctxt->am, pctxt->state,
11828 pctxt->state,
Daniel Veillarda980bef2005-07-18 21:34:03 +000011829 elemDecl->name,
11830 elemDecl->targetNamespace,
11831 1, 1, elemDecl);
11832 } else if ((sub->minOccurs == 0) &&
11833 (sub->maxOccurs == 1)) {
11834
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011835 xmlAutomataNewCountTrans2(pctxt->am, pctxt->state,
11836 pctxt->state,
Daniel Veillarda980bef2005-07-18 21:34:03 +000011837 elemDecl->name,
11838 elemDecl->targetNamespace,
11839 0,
11840 1,
11841 elemDecl);
11842 }
11843 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011844 sub = (xmlSchemaParticlePtr) sub->next;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011845 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011846 lax = particle->minOccurs == 0;
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011847 pctxt->state =
11848 xmlAutomataNewAllTrans(pctxt->am, pctxt->state, NULL, lax);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011849 break;
11850 }
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011851 case XML_SCHEMA_TYPE_GROUP:
11852 /*
11853 * If we hit a model group definition, then this means that
11854 * it was empty, thus was not substituted for the containing
11855 * model group. Just do nothing in this case.
11856 */
11857 break;
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011858 default:
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011859 xmlSchemaPInternalErr(pctxt, "xmlSchemaBuildAContentModel",
11860 "found unexpected term of type '%s' in content model of complex "
Kasimier T. Buchcik11162b72005-07-28 00:50:22 +000011861 "type '%s'",
Kasimier T. Buchcik041c5ff2005-07-23 14:42:34 +000011862 xmlSchemaCompTypeToString(particle->children->type), name);
Kasimier T. Buchcik11162b72005-07-28 00:50:22 +000011863 xmlGenericError(xmlGenericErrorContext,
11864 "Unexpected type: %d\n", particle->children->type);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011865 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000011866 }
11867}
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011868
Daniel Veillard4255d502002-04-16 15:50:10 +000011869/**
11870 * xmlSchemaBuildContentModel:
Daniel Veillard4255d502002-04-16 15:50:10 +000011871 * @ctxt: the schema parser context
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011872 * @type: the complex type definition
Daniel Veillarda84c0b32003-06-02 16:58:46 +000011873 * @name: the element name
Daniel Veillard4255d502002-04-16 15:50:10 +000011874 *
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011875 * Builds the content model of the complex type.
Daniel Veillard4255d502002-04-16 15:50:10 +000011876 */
11877static void
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011878xmlSchemaBuildContentModel(xmlSchemaTypePtr type,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011879 xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011880 const xmlChar * name)
11881{
Daniel Veillard4255d502002-04-16 15:50:10 +000011882 xmlAutomataStatePtr start;
11883
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011884 if ((type->type != XML_SCHEMA_TYPE_COMPLEX) ||
11885 (type->contModel != NULL) ||
11886 ((type->contentType != XML_SCHEMA_CONTENT_ELEMENTS) &&
11887 (type->contentType != XML_SCHEMA_CONTENT_MIXED)))
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011888 return;
Daniel Veillarddecd64d2002-04-18 14:41:51 +000011889
11890#ifdef DEBUG_CONTENT
11891 xmlGenericError(xmlGenericErrorContext,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011892 "Building content model for %s\n", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +000011893#endif
11894
Daniel Veillard4255d502002-04-16 15:50:10 +000011895 ctxt->am = xmlNewAutomata();
11896 if (ctxt->am == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011897 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011898 "Cannot create automata for complex type %s\n", name);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011899 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000011900 }
11901 start = ctxt->state = xmlAutomataGetInitState(ctxt->am);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011902 xmlSchemaBuildAContentModel(ctxt, (xmlSchemaParticlePtr) type->subtypes, name);
Daniel Veillard4255d502002-04-16 15:50:10 +000011903 xmlAutomataSetFinalState(ctxt->am, ctxt->state);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011904 type->contModel = xmlAutomataCompile(ctxt->am);
11905 if (type->contModel == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011906 xmlSchemaPCustomErr(ctxt,
11907 XML_SCHEMAP_INTERNAL,
11908 NULL, type, type->node,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011909 "Failed to compile the content model", NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011910 } else if (xmlRegexpIsDeterminist(type->contModel) != 1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011911 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000011912 XML_SCHEMAP_NOT_DETERMINISTIC,
11913 /* XML_SCHEMAS_ERR_NOTDETERMINIST, */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011914 NULL, type, type->node,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011915 "The content model is not determinist", NULL);
Daniel Veillarde19fc232002-04-22 16:01:24 +000011916 } else {
Daniel Veillard118aed72002-09-24 14:13:13 +000011917#ifdef DEBUG_CONTENT_REGEXP
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011918 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011919 "Content model of %s:\n", type->name);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000011920 xmlRegexpPrint(stderr, type->contModel);
Daniel Veillard4255d502002-04-16 15:50:10 +000011921#endif
Daniel Veillarde19fc232002-04-22 16:01:24 +000011922 }
Daniel Veillarda84c0b32003-06-02 16:58:46 +000011923 ctxt->state = NULL;
Daniel Veillard4255d502002-04-16 15:50:10 +000011924 xmlFreeAutomata(ctxt->am);
11925 ctxt->am = NULL;
11926}
11927
11928/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011929 * xmlSchemaElementFixup:
Daniel Veillard4255d502002-04-16 15:50:10 +000011930 * @elem: the schema element context
11931 * @ctxt: the schema parser context
11932 *
Daniel Veillardc0826a72004-08-10 14:17:33 +000011933 * Resolves the references of an element declaration
11934 * or particle, which has an element declaration as it's
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011935 * term.
Daniel Veillard4255d502002-04-16 15:50:10 +000011936 */
11937static void
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011938xmlSchemaElementFixup(xmlSchemaElementPtr elemDecl,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011939 xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011940 const xmlChar * name ATTRIBUTE_UNUSED,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011941 const xmlChar * context ATTRIBUTE_UNUSED,
11942 const xmlChar * namespace ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +000011943{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011944 if ((ctxt == NULL) || (elemDecl == NULL) ||
11945 ((elemDecl != NULL) &&
11946 (elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_RESOLVED)))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000011947 return;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011948 elemDecl->flags |= XML_SCHEMAS_ELEM_INTERNAL_RESOLVED;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011949
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011950 if ((elemDecl->subtypes == NULL) && (elemDecl->namedType != NULL)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011951 xmlSchemaTypePtr type;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011952
11953 /* (type definition) ... otherwise the type definition ·resolved·
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011954 * to by the ·actual value· of the type [attribute] ...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011955 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011956 type = xmlSchemaGetType(ctxt->schema, elemDecl->namedType,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011957 elemDecl->namedTypeNs);
11958 if (type == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000011959 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000011960 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011961 (xmlSchemaTypePtr) elemDecl, elemDecl->node,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011962 "type", elemDecl->namedType, elemDecl->namedTypeNs,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011963 XML_SCHEMA_TYPE_BASIC, "type definition");
11964 } else
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011965 elemDecl->subtypes = type;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011966 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011967 if (elemDecl->substGroup != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011968 xmlSchemaElementPtr substHead;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011969
Daniel Veillardc0826a72004-08-10 14:17:33 +000011970 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011971 * FIXME TODO: Do we need a new field in _xmlSchemaElement for
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011972 * substitutionGroup?
Daniel Veillard01fa6152004-06-29 17:04:39 +000011973 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011974 substHead = xmlSchemaGetElem(ctxt->schema, elemDecl->substGroup,
11975 elemDecl->substGroupNs);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011976 if (substHead == NULL) {
11977 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000011978 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011979 (xmlSchemaTypePtr) elemDecl, NULL,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011980 "substitutionGroup", elemDecl->substGroup,
11981 elemDecl->substGroupNs, XML_SCHEMA_TYPE_ELEMENT, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011982 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011983 xmlSchemaElementFixup(substHead, ctxt, NULL, NULL, NULL);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011984 /*
11985 * Set the "substitution group affiliation".
11986 * NOTE that now we use the "refDecl" field for this.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011987 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011988 elemDecl->refDecl = substHead;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011989 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011990 * (type definition)...otherwise the {type definition} of the
11991 * element declaration ·resolved· to by the ·actual value· of
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011992 * the substitutionGroup [attribute], if present
11993 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000011994 if (elemDecl->subtypes == NULL)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011995 elemDecl->subtypes = substHead->subtypes;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000011996 }
11997 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000011998 if ((elemDecl->subtypes == NULL) && (elemDecl->namedType == NULL) &&
11999 (elemDecl->substGroup == NULL))
12000 elemDecl->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
William M. Bracke7091952004-05-11 15:09:58 +000012001}
12002
12003/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012004 * xmlSchemaResolveUnionMemberTypes:
William M. Bracke7091952004-05-11 15:09:58 +000012005 * @ctxt: the schema parser context
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012006 * @type: the schema simple type definition
William M. Bracke7091952004-05-11 15:09:58 +000012007 *
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012008 * Checks and builds the "member type definitions" property of the union
12009 * simple type. This handles part (1), part (2) is done in
12010 * xmlSchemaFinishMemberTypeDefinitionsProperty()
12011 *
Daniel Veillard01fa6152004-06-29 17:04:39 +000012012 * Returns -1 in case of an internal error, 0 otherwise.
William M. Bracke7091952004-05-11 15:09:58 +000012013 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000012014static int
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012015xmlSchemaResolveUnionMemberTypes(xmlSchemaParserCtxtPtr ctxt,
12016 xmlSchemaTypePtr type)
Daniel Veillard377e1a92004-04-16 16:30:05 +000012017{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012018
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012019 xmlSchemaTypeLinkPtr link, lastLink, newLink;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012020 xmlSchemaTypePtr memberType;
Daniel Veillard377e1a92004-04-16 16:30:05 +000012021
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012022 /*
12023 * SPEC (1) "If the <union> alternative is chosen, then [Definition:]
12024 * define the explicit members as the type definitions ·resolved·
12025 * to by the items in the ·actual value· of the memberTypes [attribute],
12026 * if any, followed by the type definitions corresponding to the
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000012027 * <simpleType>s among the [children] of <union>, if any."
Daniel Veillard01fa6152004-06-29 17:04:39 +000012028 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012029 /*
12030 * Resolve references.
12031 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012032 link = type->memberTypes;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012033 lastLink = NULL;
12034 while (link != NULL) {
12035 const xmlChar *name, *nsName;
Daniel Veillardc0826a72004-08-10 14:17:33 +000012036
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012037 name = ((xmlSchemaQNameRefPtr) link->type)->name;
12038 nsName = ((xmlSchemaQNameRefPtr) link->type)->targetNamespace;
12039
12040 memberType = xmlSchemaGetType(ctxt->schema, name, nsName);
12041 if ((memberType == NULL) || (! IS_SIMPLE_TYPE(memberType))) {
12042 xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012043 type, type->node, "memberTypes",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012044 name, nsName, XML_SCHEMA_TYPE_SIMPLE, NULL);
12045 /*
12046 * Remove the member type link.
12047 */
12048 if (lastLink == NULL)
12049 type->memberTypes = link->next;
12050 else
12051 lastLink->next = link->next;
12052 newLink = link;
12053 link = link->next;
12054 xmlFree(newLink);
12055 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012056 link->type = memberType;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012057 lastLink = link;
12058 link = link->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012059 }
12060 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000012061 /*
12062 * Add local simple types,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012063 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000012064 memberType = type->subtypes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012065 while (memberType != NULL) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000012066 link = (xmlSchemaTypeLinkPtr) xmlMalloc(sizeof(xmlSchemaTypeLink));
12067 if (link == NULL) {
12068 xmlSchemaPErrMemory(ctxt, "allocating a type link", NULL);
12069 return (-1);
12070 }
12071 link->type = memberType;
12072 link->next = NULL;
12073 if (lastLink == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012074 type->memberTypes = link;
12075 else
Daniel Veillard01fa6152004-06-29 17:04:39 +000012076 lastLink->next = link;
12077 lastLink = link;
12078 memberType = memberType->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012079 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000012080 return (0);
Daniel Veillard377e1a92004-04-16 16:30:05 +000012081}
12082
Daniel Veillard4255d502002-04-16 15:50:10 +000012083/**
Daniel Veillard3646d642004-06-02 19:19:14 +000012084 * xmlSchemaIsDerivedFromBuiltInType:
12085 * @ctxt: the schema parser context
12086 * @type: the type definition
12087 * @valType: the value type
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012088 *
Daniel Veillard3646d642004-06-02 19:19:14 +000012089 *
12090 * Returns 1 if the type has the given value type, or
12091 * is derived from such a type.
12092 */
William M. Brack803812b2004-06-03 02:11:24 +000012093static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012094xmlSchemaIsDerivedFromBuiltInType(xmlSchemaTypePtr type, int valType)
Daniel Veillard3646d642004-06-02 19:19:14 +000012095{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012096 if (type == NULL)
12097 return (0);
12098 if (IS_COMPLEX_TYPE(type))
12099 return (0);
12100 if (type->type == XML_SCHEMA_TYPE_BASIC) {
12101 if (type->builtInType == valType)
12102 return(1);
12103 if ((type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) ||
12104 (type->builtInType == XML_SCHEMAS_ANYTYPE))
12105 return (0);
12106 return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
12107 } else
12108 return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
Daniel Veillard3646d642004-06-02 19:19:14 +000012109
12110 return (0);
12111}
12112
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012113#if 0
12114/**
12115 * xmlSchemaIsDerivedFromBuiltInType:
12116 * @ctxt: the schema parser context
12117 * @type: the type definition
12118 * @valType: the value type
12119 *
12120 *
12121 * Returns 1 if the type has the given value type, or
12122 * is derived from such a type.
12123 */
12124static int
12125xmlSchemaIsUserDerivedFromBuiltInType(xmlSchemaTypePtr type, int valType)
12126{
12127 if (type == NULL)
12128 return (0);
12129 if (IS_COMPLEX_TYPE(type))
12130 return (0);
12131 if (type->type == XML_SCHEMA_TYPE_BASIC) {
12132 if (type->builtInType == valType)
12133 return(1);
12134 return (0);
12135 } else
12136 return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
12137
12138 return (0);
12139}
12140#endif
12141
12142static xmlSchemaTypePtr
12143xmlSchemaQueryBuiltInType(xmlSchemaTypePtr type)
12144{
12145 if (type == NULL)
12146 return (NULL);
12147 if (IS_COMPLEX_TYPE(type))
12148 return (NULL);
12149 if (type->type == XML_SCHEMA_TYPE_BASIC)
12150 return(type);
12151 else
12152 return(xmlSchemaQueryBuiltInType(type->subtypes));
12153
12154 return (NULL);
12155}
12156
Daniel Veillard3646d642004-06-02 19:19:14 +000012157/**
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000012158 * xmlSchemaGetPrimitiveType:
Daniel Veillard01fa6152004-06-29 17:04:39 +000012159 * @type: the simpleType definition
12160 *
12161 * Returns the primitive type of the given type or
12162 * NULL in case of error.
12163 */
12164static xmlSchemaTypePtr
12165xmlSchemaGetPrimitiveType(xmlSchemaTypePtr type)
12166{
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000012167
Daniel Veillard01fa6152004-06-29 17:04:39 +000012168 while (type != NULL) {
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000012169 /*
12170 * Note that anySimpleType is actually not a primitive type
12171 * but we need that here.
12172 */
12173 if ((type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) ||
12174 (type->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE))
Daniel Veillard01fa6152004-06-29 17:04:39 +000012175 return (type);
12176 type = type->baseType;
12177 }
12178
12179 return (NULL);
12180}
12181
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000012182#if 0
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000012183/**
12184 * xmlSchemaGetBuiltInTypeAncestor:
12185 * @type: the simpleType definition
12186 *
12187 * Returns the primitive type of the given type or
12188 * NULL in case of error.
12189 */
12190static xmlSchemaTypePtr
12191xmlSchemaGetBuiltInTypeAncestor(xmlSchemaTypePtr type)
12192{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012193 if (VARIETY_LIST(type) || VARIETY_UNION(type))
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000012194 return (0);
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000012195 while (type != NULL) {
12196 if (type->type == XML_SCHEMA_TYPE_BASIC)
12197 return (type);
12198 type = type->baseType;
12199 }
12200
12201 return (NULL);
12202}
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000012203#endif
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000012204
Daniel Veillard01fa6152004-06-29 17:04:39 +000012205/**
Daniel Veillard3646d642004-06-02 19:19:14 +000012206 * xmlSchemaBuildAttributeUsesOwned:
12207 * @ctxt: the schema parser context
12208 * @type: the complex type definition
12209 * @cur: the attribute declaration list
12210 * @lastUse: the top of the attribute use list
12211 *
12212 * Builds the attribute uses list on the given complex type.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012213 * This one is supposed to be called by
Daniel Veillard3646d642004-06-02 19:19:14 +000012214 * xmlSchemaBuildAttributeValidation only.
12215 */
12216static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012217xmlSchemaBuildAttributeUsesOwned(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +000012218 xmlSchemaAttributePtr cur,
12219 xmlSchemaAttributeLinkPtr *uses,
12220 xmlSchemaAttributeLinkPtr *lastUse)
12221{
12222 xmlSchemaAttributeLinkPtr tmp;
12223 while (cur != NULL) {
12224 if (cur->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012225 /*
12226 * W3C: "2 The {attribute uses} of the attribute groups ·resolved·
12227 * to by the ·actual value·s of the ref [attribute] of the
Daniel Veillard3646d642004-06-02 19:19:14 +000012228 * <attributeGroup> [children], if any."
12229 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012230 if (xmlSchemaBuildAttributeUsesOwned(ctxt,
12231 ((xmlSchemaAttributeGroupPtr) cur)->attributes, uses,
Daniel Veillard3646d642004-06-02 19:19:14 +000012232 lastUse) == -1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012233 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000012234 }
12235 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012236 /* W3C: "1 The set of attribute uses corresponding to the
Daniel Veillard3646d642004-06-02 19:19:14 +000012237 * <attribute> [children], if any."
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012238 */
12239 tmp = (xmlSchemaAttributeLinkPtr)
Daniel Veillard3646d642004-06-02 19:19:14 +000012240 xmlMalloc(sizeof(xmlSchemaAttributeLink));
12241 if (tmp == NULL) {
12242 xmlSchemaPErrMemory(ctxt, "building attribute uses", NULL);
12243 return (-1);
12244 }
12245 tmp->attr = cur;
12246 tmp->next = NULL;
12247 if (*uses == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012248 *uses = tmp;
12249 else
Daniel Veillard3646d642004-06-02 19:19:14 +000012250 (*lastUse)->next = tmp;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012251 *lastUse = tmp;
12252 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012253 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012254 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012255 return (0);
12256}
12257
Daniel Veillard50355f02004-06-08 17:52:16 +000012258/**
12259 * xmlSchemaCloneWildcardNsConstraints:
12260 * @ctxt: the schema parser context
12261 * @dest: the destination wildcard
12262 * @source: the source wildcard
12263 *
12264 * Clones the namespace constraints of source
12265 * and assignes them to dest.
12266 * Returns -1 on internal error, 0 otherwise.
12267 */
Daniel Veillard3646d642004-06-02 19:19:14 +000012268static int
12269xmlSchemaCloneWildcardNsConstraints(xmlSchemaParserCtxtPtr ctxt,
12270 xmlSchemaWildcardPtr *dest,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012271 xmlSchemaWildcardPtr source)
Daniel Veillard3646d642004-06-02 19:19:14 +000012272{
12273 xmlSchemaWildcardNsPtr cur, tmp, last;
12274
12275 if ((source == NULL) || (*dest == NULL))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012276 return(-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000012277 (*dest)->any = source->any;
12278 cur = source->nsSet;
12279 last = NULL;
12280 while (cur != NULL) {
12281 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
12282 if (tmp == NULL)
12283 return(-1);
12284 tmp->value = cur->value;
12285 if (last == NULL)
12286 (*dest)->nsSet = tmp;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012287 else
Daniel Veillard3646d642004-06-02 19:19:14 +000012288 last->next = tmp;
12289 last = tmp;
12290 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012291 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012292 if ((*dest)->negNsSet != NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012293 xmlSchemaFreeWildcardNsSet((*dest)->negNsSet);
Daniel Veillard3646d642004-06-02 19:19:14 +000012294 if (source->negNsSet != NULL) {
12295 (*dest)->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
12296 if ((*dest)->negNsSet == NULL)
12297 return(-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012298 (*dest)->negNsSet->value = source->negNsSet->value;
Daniel Veillard3646d642004-06-02 19:19:14 +000012299 } else
12300 (*dest)->negNsSet = NULL;
12301 return(0);
12302}
12303
Daniel Veillard50355f02004-06-08 17:52:16 +000012304/**
12305 * xmlSchemaUnionWildcards:
12306 * @ctxt: the schema parser context
12307 * @completeWild: the first wildcard
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012308 * @curWild: the second wildcard
Daniel Veillard50355f02004-06-08 17:52:16 +000012309 *
12310 * Unions the namespace constraints of the given wildcards.
12311 * @completeWild will hold the resulting union.
12312 * Returns a positive error code on failure, -1 in case of an
12313 * internal error, 0 otherwise.
12314 */
Daniel Veillard3646d642004-06-02 19:19:14 +000012315static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012316xmlSchemaUnionWildcards(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +000012317 xmlSchemaWildcardPtr completeWild,
12318 xmlSchemaWildcardPtr curWild)
12319{
12320 xmlSchemaWildcardNsPtr cur, curB, tmp;
12321
12322 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012323 * 1 If O1 and O2 are the same value, then that value must be the
Daniel Veillard3646d642004-06-02 19:19:14 +000012324 * value.
12325 */
12326 if ((completeWild->any == curWild->any) &&
12327 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
12328 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012329
Daniel Veillard3646d642004-06-02 19:19:14 +000012330 if ((completeWild->negNsSet == NULL) ||
12331 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012332
Daniel Veillard3646d642004-06-02 19:19:14 +000012333 if (completeWild->nsSet != NULL) {
William M. Brack803812b2004-06-03 02:11:24 +000012334 int found = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012335
12336 /*
12337 * Check equality of sets.
Daniel Veillard3646d642004-06-02 19:19:14 +000012338 */
12339 cur = completeWild->nsSet;
12340 while (cur != NULL) {
12341 found = 0;
12342 curB = curWild->nsSet;
12343 while (curB != NULL) {
12344 if (cur->value == curB->value) {
12345 found = 1;
12346 break;
12347 }
12348 curB = curB->next;
12349 }
12350 if (!found)
12351 break;
12352 cur = cur->next;
12353 }
12354 if (found)
12355 return(0);
12356 } else
12357 return(0);
12358 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012359 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012360 /*
12361 * 2 If either O1 or O2 is any, then any must be the value
12362 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012363 if (completeWild->any != curWild->any) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012364 if (completeWild->any == 0) {
12365 completeWild->any = 1;
12366 if (completeWild->nsSet != NULL) {
12367 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
12368 completeWild->nsSet = NULL;
12369 }
12370 if (completeWild->negNsSet != NULL) {
12371 xmlFree(completeWild->negNsSet);
12372 completeWild->negNsSet = NULL;
12373 }
12374 }
Daniel Veillard50355f02004-06-08 17:52:16 +000012375 return (0);
Daniel Veillard3646d642004-06-02 19:19:14 +000012376 }
12377 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012378 * 3 If both O1 and O2 are sets of (namespace names or ·absent·),
Daniel Veillard3646d642004-06-02 19:19:14 +000012379 * then the union of those sets must be the value.
12380 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012381 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012382 int found;
12383 xmlSchemaWildcardNsPtr start;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012384
Daniel Veillard3646d642004-06-02 19:19:14 +000012385 cur = curWild->nsSet;
12386 start = completeWild->nsSet;
12387 while (cur != NULL) {
12388 found = 0;
12389 curB = start;
12390 while (curB != NULL) {
12391 if (cur->value == curB->value) {
12392 found = 1;
12393 break;
12394 }
12395 curB = curB->next;
12396 }
12397 if (!found) {
12398 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012399 if (tmp == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000012400 return (-1);
12401 tmp->value = cur->value;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012402 tmp->next = completeWild->nsSet;
Daniel Veillard3646d642004-06-02 19:19:14 +000012403 completeWild->nsSet = tmp;
12404 }
12405 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012406 }
12407
Daniel Veillard3646d642004-06-02 19:19:14 +000012408 return(0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012409 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012410 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012411 * 4 If the two are negations of different values (namespace names
Daniel Veillard3646d642004-06-02 19:19:14 +000012412 * or ·absent·), then a pair of not and ·absent· must be the value.
12413 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012414 if ((completeWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000012415 (curWild->negNsSet != NULL) &&
12416 (completeWild->negNsSet->value != curWild->negNsSet->value)) {
12417 completeWild->negNsSet->value = NULL;
Daniel Veillard50355f02004-06-08 17:52:16 +000012418
12419 return(0);
Daniel Veillard3646d642004-06-02 19:19:14 +000012420 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012421 /*
Daniel Veillard3646d642004-06-02 19:19:14 +000012422 * 5.
12423 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012424 if (((completeWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000012425 (completeWild->negNsSet->value != NULL) &&
12426 (curWild->nsSet != NULL)) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012427 ((curWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000012428 (curWild->negNsSet->value != NULL) &&
12429 (completeWild->nsSet != NULL))) {
12430
12431 int nsFound, absentFound = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012432
Daniel Veillard3646d642004-06-02 19:19:14 +000012433 if (completeWild->nsSet != NULL) {
12434 cur = completeWild->nsSet;
12435 curB = curWild->negNsSet;
12436 } else {
12437 cur = curWild->nsSet;
12438 curB = completeWild->negNsSet;
12439 }
12440 nsFound = 0;
12441 while (cur != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012442 if (cur->value == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000012443 absentFound = 1;
12444 else if (cur->value == curB->value)
12445 nsFound = 1;
12446 if (nsFound && absentFound)
12447 break;
12448 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012449 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012450
12451 if (nsFound && absentFound) {
12452 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012453 * 5.1 If the set S includes both the negated namespace
Daniel Veillard3646d642004-06-02 19:19:14 +000012454 * name and ·absent·, then any must be the value.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012455 */
Daniel Veillard3646d642004-06-02 19:19:14 +000012456 completeWild->any = 1;
12457 if (completeWild->nsSet != NULL) {
12458 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
12459 completeWild->nsSet = NULL;
12460 }
12461 if (completeWild->negNsSet != NULL) {
12462 xmlFree(completeWild->negNsSet);
12463 completeWild->negNsSet = NULL;
12464 }
12465 } else if (nsFound && (!absentFound)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012466 /*
12467 * 5.2 If the set S includes the negated namespace name
12468 * but not ·absent·, then a pair of not and ·absent· must
Daniel Veillard3646d642004-06-02 19:19:14 +000012469 * be the value.
12470 */
12471 if (completeWild->nsSet != NULL) {
12472 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
12473 completeWild->nsSet = NULL;
12474 }
12475 if (completeWild->negNsSet == NULL) {
12476 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
12477 if (completeWild->negNsSet == NULL)
12478 return (-1);
12479 }
12480 completeWild->negNsSet->value = NULL;
12481 } else if ((!nsFound) && absentFound) {
12482 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012483 * 5.3 If the set S includes ·absent· but not the negated
Daniel Veillard3646d642004-06-02 19:19:14 +000012484 * namespace name, then the union is not expressible.
12485 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012486 xmlSchemaPErr(ctxt, completeWild->node,
Daniel Veillard3646d642004-06-02 19:19:14 +000012487 XML_SCHEMAP_UNION_NOT_EXPRESSIBLE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012488 "The union of the wilcard is not expressible.\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012489 NULL, NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +000012490 return(XML_SCHEMAP_UNION_NOT_EXPRESSIBLE);
Daniel Veillard3646d642004-06-02 19:19:14 +000012491 } else if ((!nsFound) && (!absentFound)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012492 /*
12493 * 5.4 If the set S does not include either the negated namespace
12494 * name or ·absent·, then whichever of O1 or O2 is a pair of not
Daniel Veillard3646d642004-06-02 19:19:14 +000012495 * and a namespace name must be the value.
12496 */
12497 if (completeWild->negNsSet == NULL) {
12498 if (completeWild->nsSet != NULL) {
12499 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
12500 completeWild->nsSet = NULL;
12501 }
12502 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
12503 if (completeWild->negNsSet == NULL)
12504 return (-1);
12505 completeWild->negNsSet->value = curWild->negNsSet->value;
12506 }
12507 }
12508 return (0);
12509 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012510 /*
Daniel Veillard3646d642004-06-02 19:19:14 +000012511 * 6.
12512 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012513 if (((completeWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000012514 (completeWild->negNsSet->value == NULL) &&
12515 (curWild->nsSet != NULL)) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012516 ((curWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000012517 (curWild->negNsSet->value == NULL) &&
12518 (completeWild->nsSet != NULL))) {
12519
12520 if (completeWild->nsSet != NULL) {
12521 cur = completeWild->nsSet;
12522 } else {
12523 cur = curWild->nsSet;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012524 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012525 while (cur != NULL) {
12526 if (cur->value == NULL) {
12527 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012528 * 6.1 If the set S includes ·absent·, then any must be the
Daniel Veillard3646d642004-06-02 19:19:14 +000012529 * value.
12530 */
12531 completeWild->any = 1;
12532 if (completeWild->nsSet != NULL) {
12533 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
12534 completeWild->nsSet = NULL;
12535 }
12536 if (completeWild->negNsSet != NULL) {
12537 xmlFree(completeWild->negNsSet);
12538 completeWild->negNsSet = NULL;
12539 }
12540 return (0);
12541 }
12542 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012543 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012544 if (completeWild->negNsSet == NULL) {
12545 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012546 * 6.2 If the set S does not include ·absent·, then a pair of not
Daniel Veillard3646d642004-06-02 19:19:14 +000012547 * and ·absent· must be the value.
12548 */
12549 if (completeWild->nsSet != NULL) {
12550 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
12551 completeWild->nsSet = NULL;
12552 }
12553 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
12554 if (completeWild->negNsSet == NULL)
12555 return (-1);
12556 completeWild->negNsSet->value = NULL;
12557 }
12558 return (0);
12559 }
12560 return (0);
12561
12562}
12563
Daniel Veillard50355f02004-06-08 17:52:16 +000012564/**
12565 * xmlSchemaIntersectWildcards:
12566 * @ctxt: the schema parser context
12567 * @completeWild: the first wildcard
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012568 * @curWild: the second wildcard
Daniel Veillard50355f02004-06-08 17:52:16 +000012569 *
12570 * Intersects the namespace constraints of the given wildcards.
12571 * @completeWild will hold the resulting intersection.
12572 * Returns a positive error code on failure, -1 in case of an
12573 * internal error, 0 otherwise.
12574 */
Daniel Veillard3646d642004-06-02 19:19:14 +000012575static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012576xmlSchemaIntersectWildcards(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard3646d642004-06-02 19:19:14 +000012577 xmlSchemaWildcardPtr completeWild,
12578 xmlSchemaWildcardPtr curWild)
12579{
William M. Brack803812b2004-06-03 02:11:24 +000012580 xmlSchemaWildcardNsPtr cur, curB, prev, tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000012581
12582 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012583 * 1 If O1 and O2 are the same value, then that value must be the
Daniel Veillard3646d642004-06-02 19:19:14 +000012584 * value.
12585 */
12586 if ((completeWild->any == curWild->any) &&
12587 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
12588 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012589
Daniel Veillard3646d642004-06-02 19:19:14 +000012590 if ((completeWild->negNsSet == NULL) ||
12591 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012592
Daniel Veillard3646d642004-06-02 19:19:14 +000012593 if (completeWild->nsSet != NULL) {
William M. Brack803812b2004-06-03 02:11:24 +000012594 int found = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012595
12596 /*
12597 * Check equality of sets.
Daniel Veillard3646d642004-06-02 19:19:14 +000012598 */
12599 cur = completeWild->nsSet;
12600 while (cur != NULL) {
12601 found = 0;
12602 curB = curWild->nsSet;
12603 while (curB != NULL) {
12604 if (cur->value == curB->value) {
12605 found = 1;
12606 break;
12607 }
12608 curB = curB->next;
12609 }
12610 if (!found)
12611 break;
12612 cur = cur->next;
12613 }
12614 if (found)
12615 return(0);
12616 } else
12617 return(0);
12618 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012619 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012620 /*
12621 * 2 If either O1 or O2 is any, then the other must be the value.
12622 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012623 if ((completeWild->any != curWild->any) && (completeWild->any)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012624 if (xmlSchemaCloneWildcardNsConstraints(ctxt, &completeWild, curWild) == -1)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012625 return(-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000012626 return(0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012627 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012628 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012629 * 3 If either O1 or O2 is a pair of not and a value (a namespace
12630 * name or ·absent·) and the other is a set of (namespace names or
12631 * ·absent·), then that set, minus the negated value if it was in
Daniel Veillard3646d642004-06-02 19:19:14 +000012632 * the set, minus ·absent· if it was in the set, must be the value.
12633 */
12634 if (((completeWild->negNsSet != NULL) && (curWild->nsSet != NULL)) ||
12635 ((curWild->negNsSet != NULL) && (completeWild->nsSet != NULL))) {
12636 const xmlChar *neg;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012637
Daniel Veillard3646d642004-06-02 19:19:14 +000012638 if (completeWild->nsSet == NULL) {
12639 neg = completeWild->negNsSet->value;
12640 if (xmlSchemaCloneWildcardNsConstraints(ctxt, &completeWild, curWild) == -1)
12641 return(-1);
12642 } else
12643 neg = curWild->negNsSet->value;
12644 /*
12645 * Remove absent and negated.
12646 */
12647 prev = NULL;
12648 cur = completeWild->nsSet;
12649 while (cur != NULL) {
12650 if (cur->value == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012651 if (prev == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000012652 completeWild->nsSet = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012653 else
Daniel Veillard3646d642004-06-02 19:19:14 +000012654 prev->next = cur->next;
12655 xmlFree(cur);
12656 break;
12657 }
12658 prev = cur;
12659 cur = cur->next;
12660 }
12661 if (neg != NULL) {
12662 prev = NULL;
12663 cur = completeWild->nsSet;
12664 while (cur != NULL) {
12665 if (cur->value == neg) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012666 if (prev == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000012667 completeWild->nsSet = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012668 else
Daniel Veillard3646d642004-06-02 19:19:14 +000012669 prev->next = cur->next;
12670 xmlFree(cur);
12671 break;
12672 }
12673 prev = cur;
12674 cur = cur->next;
12675 }
12676 }
12677
12678 return(0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012679 }
Daniel Veillard3646d642004-06-02 19:19:14 +000012680 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012681 * 4 If both O1 and O2 are sets of (namespace names or ·absent·),
Daniel Veillard3646d642004-06-02 19:19:14 +000012682 * then the intersection of those sets must be the value.
12683 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012684 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012685 int found;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012686
Daniel Veillard3646d642004-06-02 19:19:14 +000012687 cur = completeWild->nsSet;
12688 prev = NULL;
12689 while (cur != NULL) {
12690 found = 0;
12691 curB = curWild->nsSet;
12692 while (curB != NULL) {
12693 if (cur->value == curB->value) {
12694 found = 1;
12695 break;
12696 }
12697 curB = curB->next;
12698 }
12699 if (!found) {
12700 if (prev == NULL)
12701 completeWild->nsSet = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012702 else
Daniel Veillard3646d642004-06-02 19:19:14 +000012703 prev->next = cur->next;
12704 tmp = cur->next;
12705 xmlFree(cur);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012706 cur = tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000012707 continue;
12708 }
12709 prev = cur;
12710 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012711 }
12712
Daniel Veillard3646d642004-06-02 19:19:14 +000012713 return(0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012714 }
12715 /* 5 If the two are negations of different namespace names,
Daniel Veillard3646d642004-06-02 19:19:14 +000012716 * then the intersection is not expressible
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012717 */
12718 if ((completeWild->negNsSet != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000012719 (curWild->negNsSet != NULL) &&
12720 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012721 (completeWild->negNsSet->value != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000012722 (curWild->negNsSet->value != NULL)) {
12723
12724 xmlSchemaPErr(ctxt, completeWild->node, XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000012725 "The intersection of the wilcard is not expressible.\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012726 NULL, NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +000012727 return(XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012728 }
12729 /*
12730 * 6 If the one is a negation of a namespace name and the other
12731 * is a negation of ·absent·, then the one which is the negation
Daniel Veillard3646d642004-06-02 19:19:14 +000012732 * of a namespace name must be the value.
12733 */
12734 if ((completeWild->negNsSet != NULL) && (curWild->negNsSet != NULL) &&
12735 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012736 (completeWild->negNsSet->value == NULL)) {
12737 completeWild->negNsSet->value = curWild->negNsSet->value;
Daniel Veillard3646d642004-06-02 19:19:14 +000012738 }
12739 return(0);
12740}
12741
Daniel Veillard50355f02004-06-08 17:52:16 +000012742/**
12743 * xmlSchemaIsWildcardNsConstraintSubset:
12744 * @ctxt: the schema parser context
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012745 * @sub: the first wildcard
12746 * @super: the second wildcard
Daniel Veillard50355f02004-06-08 17:52:16 +000012747 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012748 * Schema Component Constraint: Wildcard Subset (cos-ns-subset)
12749 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012750 * Returns 0 if the namespace constraint of @sub is an intensional
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012751 * subset of @super, 1 otherwise.
Daniel Veillard50355f02004-06-08 17:52:16 +000012752 */
12753static int
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012754xmlSchemaCheckCOSNSSubset(xmlSchemaWildcardPtr sub,
12755 xmlSchemaWildcardPtr super)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012756{
Daniel Veillard50355f02004-06-08 17:52:16 +000012757 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012758 * 1 super must be any.
Daniel Veillard50355f02004-06-08 17:52:16 +000012759 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012760 if (super->any)
12761 return (0);
Daniel Veillard50355f02004-06-08 17:52:16 +000012762 /*
12763 * 2.1 sub must be a pair of not and a namespace name or ·absent·.
12764 * 2.2 super must be a pair of not and the same value.
12765 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012766 if ((sub->negNsSet != NULL) &&
12767 (super->negNsSet != NULL) &&
12768 (sub->negNsSet->value == sub->negNsSet->value))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012769 return (0);
12770 /*
12771 * 3.1 sub must be a set whose members are either namespace names or ·absent·.
Daniel Veillard50355f02004-06-08 17:52:16 +000012772 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012773 if (sub->nsSet != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000012774 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012775 * 3.2.1 super must be the same set or a superset thereof.
Daniel Veillard50355f02004-06-08 17:52:16 +000012776 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012777 if (super->nsSet != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000012778 xmlSchemaWildcardNsPtr cur, curB;
12779 int found = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012780
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012781 cur = sub->nsSet;
Daniel Veillard50355f02004-06-08 17:52:16 +000012782 while (cur != NULL) {
12783 found = 0;
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012784 curB = super->nsSet;
Daniel Veillard50355f02004-06-08 17:52:16 +000012785 while (curB != NULL) {
12786 if (cur->value == curB->value) {
12787 found = 1;
12788 break;
12789 }
12790 curB = curB->next;
12791 }
12792 if (!found)
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012793 return (1);
Daniel Veillard50355f02004-06-08 17:52:16 +000012794 cur = cur->next;
12795 }
12796 if (found)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012797 return (0);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012798 } else if (super->negNsSet != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000012799 xmlSchemaWildcardNsPtr cur;
12800 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012801 * 3.2.2 super must be a pair of not and a namespace name or
12802 * ·absent· and that value must not be in sub's set.
Daniel Veillard50355f02004-06-08 17:52:16 +000012803 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012804 cur = sub->nsSet;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012805 while (cur != NULL) {
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012806 if (cur->value == super->negNsSet->value)
12807 return (1);
Daniel Veillard50355f02004-06-08 17:52:16 +000012808 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012809 }
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012810 return (0);
Daniel Veillard50355f02004-06-08 17:52:16 +000012811 }
12812 }
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000012813 return (1);
Daniel Veillard50355f02004-06-08 17:52:16 +000012814}
12815
12816/**
12817 * xmlSchemaBuildCompleteAttributeWildcard:
12818 * @ctxt: the schema parser context
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012819 * @attrs: the attribute list
Daniel Veillard50355f02004-06-08 17:52:16 +000012820 * @completeWild: the resulting complete wildcard
12821 *
12822 * Returns -1 in case of an internal error, 0 otherwise.
12823 */
12824static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012825xmlSchemaBuildCompleteAttributeWildcard(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard50355f02004-06-08 17:52:16 +000012826 xmlSchemaAttributePtr attrs,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012827 xmlSchemaWildcardPtr *completeWild)
12828{
Daniel Veillard3646d642004-06-02 19:19:14 +000012829 while (attrs != NULL) {
12830 if (attrs->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
12831 xmlSchemaAttributeGroupPtr group;
12832
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012833 group = (xmlSchemaAttributeGroupPtr) attrs;
12834 /*
12835 * Handle attribute group references.
12836 */
12837 if (group->ref != NULL) {
12838 if (group->refItem == NULL) {
12839 /*
12840 * TODO: Should we raise a warning here?
12841 */
12842 /*
12843 * The referenced attribute group definition could not
12844 * be resolved beforehand, so skip.
12845 */
12846 attrs = attrs->next;
12847 continue;
12848 } else
12849 group = group->refItem;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012850 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012851 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012852 * For every attribute group definition, an intersected wildcard
12853 * will be created (assumed that a wildcard exists on the
12854 * particular attr. gr. def. or on any contained attr. gr. def
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000012855 * at all).
12856 * The flag XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED ensures
12857 * that the intersection will be performed only once.
12858 */
Daniel Veillard3646d642004-06-02 19:19:14 +000012859 if ((group->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED) == 0) {
12860 if (group->attributes != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012861 if (xmlSchemaBuildCompleteAttributeWildcard(ctxt,
Daniel Veillard50355f02004-06-08 17:52:16 +000012862 group->attributes, &group->attributeWildcard) == -1)
12863 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000012864 }
12865 group->flags |= XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012866 }
12867 if (group->attributeWildcard != NULL) {
Daniel Veillard50355f02004-06-08 17:52:16 +000012868 if (*completeWild == NULL) {
Daniel Veillard3646d642004-06-02 19:19:14 +000012869 /*
12870 * Copy the first encountered wildcard as context, except for the annotation.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012871 *
12872 * Although the complete wildcard might not correspond to any
12873 * node in the schema, we will save this context node.
Daniel Veillard3646d642004-06-02 19:19:14 +000012874 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012875 *completeWild = xmlSchemaAddWildcard(ctxt, ctxt->schema,
12876 XML_SCHEMA_TYPE_ANY_ATTRIBUTE,
12877 group->attributeWildcard->node);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012878 if (xmlSchemaCloneWildcardNsConstraints(ctxt,
Daniel Veillard50355f02004-06-08 17:52:16 +000012879 completeWild, group->attributeWildcard) == -1)
12880 return (-1);
12881 (*completeWild)->processContents = group->attributeWildcard->processContents;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000012882 (*completeWild)->node = group->attributeWildcard->node;
12883 } else if (xmlSchemaIntersectWildcards(ctxt, *completeWild, group->attributeWildcard) == -1)
Daniel Veillard50355f02004-06-08 17:52:16 +000012884 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000012885 }
12886 }
12887 attrs = attrs->next;
12888 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012889
12890 return (0);
Daniel Veillard3646d642004-06-02 19:19:14 +000012891}
12892
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012893static int
12894xmlSchemaGetEffectiveValueConstraint(xmlSchemaAttributePtr item,
12895 int *fixed,
12896 const xmlChar **value,
12897 xmlSchemaValPtr *val)
12898{
12899 *fixed = 0;
12900 *value = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012901 if (val != 0)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012902 *val = NULL;
12903
12904 if (item->defValue == NULL)
12905 item = item->refDecl;
12906
12907 if (item == NULL)
12908 return (0);
12909
12910 if (item->defValue != NULL) {
12911 *value = item->defValue;
12912 if (val != 0)
12913 *val = item->defVal;
12914 if (item->flags & XML_SCHEMAS_ATTR_FIXED)
12915 *fixed = 1;
12916 return (1);
12917 }
12918 return (0);
12919}
Daniel Veillard3646d642004-06-02 19:19:14 +000012920/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012921 * xmlSchemaCheckCVCWildcardNamespace:
Daniel Veillard3646d642004-06-02 19:19:14 +000012922 * @wild: the wildcard
12923 * @ns: the namespace
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012924 *
12925 * Validation Rule: Wildcard allows Namespace Name
12926 * (cvc-wildcard-namespace)
12927 *
Daniel Veillard3646d642004-06-02 19:19:14 +000012928 *
12929 * Returns 1 if the given namespace matches the wildcard,
12930 * 0 otherwise.
12931 */
12932static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012933xmlSchemaCheckCVCWildcardNamespace(xmlSchemaWildcardPtr wild,
12934 const xmlChar* ns)
Daniel Veillard3646d642004-06-02 19:19:14 +000012935{
12936 if (wild == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012937 return(-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000012938
12939 if (wild->any)
12940 return(1);
12941 else if (wild->nsSet != NULL) {
12942 xmlSchemaWildcardNsPtr cur;
12943
12944 cur = wild->nsSet;
12945 while (cur != NULL) {
12946 if (xmlStrEqual(cur->value, ns))
12947 return(1);
12948 cur = cur->next;
12949 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012950 } else if ((wild->negNsSet != NULL) && (ns != NULL) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000012951 (!xmlStrEqual(wild->negNsSet->value, ns)))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012952 return(1);
12953
Daniel Veillard3646d642004-06-02 19:19:14 +000012954 return(0);
12955}
12956
12957/**
12958 * xmlSchemaBuildAttributeValidation:
12959 * @ctxt: the schema parser context
12960 * @type: the complex type definition
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012961 *
Daniel Veillard3646d642004-06-02 19:19:14 +000012962 *
12963 * Builds the wildcard and the attribute uses on the given complex type.
12964 * Returns -1 if an internal error occurs, 0 otherwise.
12965 */
12966static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012967xmlSchemaBuildAttributeValidation(xmlSchemaParserCtxtPtr pctxt,
12968 xmlSchemaTypePtr type)
Daniel Veillard3646d642004-06-02 19:19:14 +000012969{
12970 xmlSchemaTypePtr baseType = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012971 xmlSchemaAttributeLinkPtr cur, base, tmp, id = NULL,
12972 prev = NULL, uses = NULL, lastUse = NULL, lastBaseUse = NULL;
Daniel Veillard3646d642004-06-02 19:19:14 +000012973 xmlSchemaAttributePtr attrs;
Daniel Veillard01fa6152004-06-29 17:04:39 +000012974 xmlSchemaTypePtr anyType;
Daniel Veillardc0826a72004-08-10 14:17:33 +000012975 xmlChar *str = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000012976 int err = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000012977
Daniel Veillard01fa6152004-06-29 17:04:39 +000012978 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012979 /*
Daniel Veillard3646d642004-06-02 19:19:14 +000012980 * Complex Type Definition with complex content Schema Component.
12981 *
12982 * Attribute uses.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000012983 * TODO: Add checks for absent referenced attribute declarations and
12984 * simple types.
Daniel Veillard3646d642004-06-02 19:19:14 +000012985 */
12986 if (type->attributeUses != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012987 PERROR_INT("xmlSchemaBuildAttributeValidation",
12988 "attribute uses already builded");
Daniel Veillard3646d642004-06-02 19:19:14 +000012989 return (-1);
12990 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000012991 if (type->baseType == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000012992 PERROR_INT("xmlSchemaBuildAttributeValidation",
12993 "no base type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000012994 return (-1);
12995 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012996 baseType = type->baseType;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000012997 /*
12998 * Inherit the attribute uses of the base type.
12999 */
13000 /*
13001 * NOTE: It is allowed to "extend" the anyType complex type.
13002 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013003 if (! IS_ANYTYPE(baseType)) {
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000013004 if (baseType != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013005 for (cur = baseType->attributeUses; cur != NULL;
13006 cur = cur->next) {
13007 tmp = (xmlSchemaAttributeLinkPtr)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000013008 xmlMalloc(sizeof(xmlSchemaAttributeLink));
13009 if (tmp == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013010 xmlSchemaPErrMemory(pctxt,
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000013011 "building attribute uses of complexType", NULL);
13012 return (-1);
Daniel Veillard3646d642004-06-02 19:19:14 +000013013 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000013014 tmp->attr = cur->attr;
13015 tmp->next = NULL;
13016 if (type->attributeUses == NULL) {
13017 type->attributeUses = tmp;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013018 } else
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000013019 lastBaseUse->next = tmp;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013020 lastBaseUse = tmp;
Daniel Veillard3646d642004-06-02 19:19:14 +000013021 }
13022 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000013023 }
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000013024 attrs = type->attributes;
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000013025 /*
13026 * Handle attribute wildcards.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013027 */
13028 err = xmlSchemaBuildCompleteAttributeWildcard(pctxt,
13029 attrs, &type->attributeWildcard);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013030 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013031 * NOTE: During the parse time, the wildcard is created on the complexType
13032 * directly, if encountered in a <restriction> or <extension> element.
Daniel Veillard01fa6152004-06-29 17:04:39 +000013033 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013034 if (err == -1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013035 PERROR_INT("xmlSchemaBuildAttributeValidation",
13036 "failed to build an intersected attribute wildcard");
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000013037 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013038 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000013039
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013040 if ((type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) &&
13041 ((IS_ANYTYPE(baseType)) ||
13042 ((baseType != NULL) &&
13043 (baseType->type == XML_SCHEMA_TYPE_COMPLEX) &&
13044 (baseType->attributeWildcard != NULL)))) {
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000013045 if (type->attributeWildcard != NULL) {
13046 /*
13047 * Union the complete wildcard with the base wildcard.
13048 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013049 if (xmlSchemaUnionWildcards(pctxt, type->attributeWildcard,
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000013050 baseType->attributeWildcard) == -1)
13051 return (-1);
13052 } else {
13053 /*
13054 * Just inherit the wildcard.
13055 */
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013056 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013057 * NOTE: This is the only case where an attribute
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000013058 * wildcard is shared.
13059 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000013060 type->attributeWildcard = baseType->attributeWildcard;
Daniel Veillard50355f02004-06-08 17:52:16 +000013061 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000013062 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013063
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000013064 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
13065 if (type->attributeWildcard != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013066 /*
13067 * Derivation Valid (Restriction, Complex)
13068 * 4.1 The {base type definition} must also have one.
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000013069 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013070 if (baseType->attributeWildcard == NULL) {
13071 xmlSchemaPCustomErr(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013072 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013073 NULL, type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013074 "The type has an attribute wildcard, "
13075 "but the base type %s does not have one",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013076 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013077 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000013078 return (1);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013079 } else if (xmlSchemaCheckCOSNSSubset(
13080 type->attributeWildcard, baseType->attributeWildcard)) {
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000013081 /* 4.2 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013082 xmlSchemaPCustomErr(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013083 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_2,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013084 NULL, type, NULL,
13085 "The attribute wildcard is not a valid "
Daniel Veillardc0826a72004-08-10 14:17:33 +000013086 "subset of the wildcard in the base type %s",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013087 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL));
13088 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000013089 return (1);
13090 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013091 /* 4.3 Unless the {base type definition} is the ·ur-type
13092 * definition·, the complex type definition's {attribute
13093 * wildcard}'s {process contents} must be identical to or
13094 * stronger than the {base type definition}'s {attribute
13095 * wildcard}'s {process contents}, where strict is stronger
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000013096 * than lax is stronger than skip.
13097 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013098 if ((! IS_ANYTYPE(baseType)) &&
13099 (type->attributeWildcard->processContents <
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000013100 baseType->attributeWildcard->processContents)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013101 xmlSchemaPCustomErr(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013102 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_3,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013103 NULL, type, NULL,
13104 "The 'process contents' of the attribute wildcard is "
13105 "weaker than the one in the base type %s",
13106 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013107 FREE_AND_NULL(str)
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000013108 return (1);
13109 }
13110 }
13111 } else if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
13112 /*
13113 * Derivation Valid (Extension)
13114 * At this point the type and the base have both, either
13115 * no wildcard or a wildcard.
13116 */
13117 if ((baseType->attributeWildcard != NULL) &&
13118 (baseType->attributeWildcard != type->attributeWildcard)) {
13119 /* 1.3 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013120 if (xmlSchemaCheckCOSNSSubset(
13121 baseType->attributeWildcard, type->attributeWildcard)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013122 xmlSchemaPCustomErr(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013123 XML_SCHEMAP_COS_CT_EXTENDS_1_3,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013124 NULL, type, NULL,
13125 "The attribute wildcard is not a valid "
Daniel Veillardc0826a72004-08-10 14:17:33 +000013126 "superset of the one in the base type %s",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013127 xmlSchemaFormatItemForReport(&str, NULL, baseType, NULL));
13128 FREE_AND_NULL(str)
13129 return (1);
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000013130 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013131 }
13132 }
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000013133
Daniel Veillard3646d642004-06-02 19:19:14 +000013134 /*
13135 * Gather attribute uses defined by this type.
13136 */
13137 if (attrs != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013138 if (xmlSchemaBuildAttributeUsesOwned(pctxt, attrs,
Daniel Veillard3646d642004-06-02 19:19:14 +000013139 &uses, &lastUse) == -1) {
13140 return (-1);
13141 }
13142 }
13143 /* 3.4.6 -> Complex Type Definition Properties Correct 4.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013144 * "Two distinct attribute declarations in the {attribute uses} must
Daniel Veillard3646d642004-06-02 19:19:14 +000013145 * not have identical {name}s and {target namespace}s."
13146 *
13147 * For "extension" this is done further down.
13148 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013149 if ((uses != NULL) && ((type->flags &
13150 XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) == 0)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000013151 cur = uses;
13152 while (cur != NULL) {
13153 tmp = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013154 while (tmp != NULL) {
13155 if ((xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
Daniel Veillardc0826a72004-08-10 14:17:33 +000013156 xmlSchemaGetAttrName(tmp->attr))) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013157 (xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr),
Daniel Veillardc0826a72004-08-10 14:17:33 +000013158 xmlSchemaGetAttrTargetNsURI(tmp->attr)))) {
13159
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013160 xmlSchemaPAttrUseErr(pctxt,
13161 XML_SCHEMAP_CT_PROPS_CORRECT_4,
13162 type, cur->attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013163 "Duplicate attribute use %s specified",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013164 xmlSchemaFormatQName(&str,
13165 xmlSchemaGetAttrTargetNsURI(tmp->attr),
13166 xmlSchemaGetAttrName(tmp->attr)));
13167 FREE_AND_NULL(str)
Daniel Veillard3646d642004-06-02 19:19:14 +000013168 break;
13169 }
13170 tmp = tmp->next;
13171 }
13172 cur = cur->next;
13173 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013174 }
13175 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
Daniel Veillard3646d642004-06-02 19:19:14 +000013176 /*
13177 * Derive by restriction.
13178 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013179 if (IS_ANYTYPE(baseType)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000013180 type->attributeUses = uses;
13181 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013182 int found, valid;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013183 const xmlChar *bEffValue;
13184 int effFixed;
Daniel Veillard3646d642004-06-02 19:19:14 +000013185
13186 cur = uses;
13187 while (cur != NULL) {
13188 found = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013189 valid = 1;
Daniel Veillard3646d642004-06-02 19:19:14 +000013190 base = type->attributeUses;
13191 while (base != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013192 if (xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
Daniel Veillardc0826a72004-08-10 14:17:33 +000013193 xmlSchemaGetAttrName(base->attr)) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013194 xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr),
Daniel Veillardc0826a72004-08-10 14:17:33 +000013195 xmlSchemaGetAttrTargetNsURI(base->attr))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013196
13197 found = 1;
Daniel Veillard3646d642004-06-02 19:19:14 +000013198
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013199 if ((cur->attr->occurs ==
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000013200 XML_SCHEMAS_ATTR_USE_PROHIBITED) &&
13201 (base->attr->occurs ==
13202 XML_SCHEMAS_ATTR_USE_OPTIONAL)) {
13203 /*
13204 * NOOP.
13205 */
13206 } else if ((cur->attr->occurs ==
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013207 XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
13208 (base->attr->occurs ==
13209 XML_SCHEMAS_ATTR_USE_REQUIRED)) {
Daniel Veillard3646d642004-06-02 19:19:14 +000013210 /*
13211 * derivation-ok-restriction 2.1.1
Daniel Veillard3646d642004-06-02 19:19:14 +000013212 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013213 xmlSchemaPAttrUseErr(pctxt,
13214 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_1,
13215 type, cur->attr,
13216 "The 'optional' use is inconsistent with a "
13217 "matching 'required' use of the base type",
13218 NULL);
13219 } else if ((cur->attr->occurs ==
13220 XML_SCHEMAS_ATTR_USE_PROHIBITED) &&
13221 (base->attr->occurs ==
13222 XML_SCHEMAS_ATTR_USE_REQUIRED)) {
13223 /*
13224 * derivation-ok-restriction 3
13225 */
13226 xmlSchemaPCustomErr(pctxt,
13227 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_3,
13228 NULL, type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013229 "A matching attribute use for the 'required' "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013230 "attribute use '%s' of the base type is "
13231 "missing",
13232 xmlSchemaFormatQName(&str,
13233 xmlSchemaGetAttrTargetNsURI(base->attr),
13234 xmlSchemaGetAttrName(base->attr)));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013235 FREE_AND_NULL(str)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013236 } else if (xmlSchemaCheckCOSSTDerivedOK(
13237 cur->attr->subtypes, base->attr->subtypes, 0) != 0) {
13238
13239 /*
13240 * SPEC (2.1.2) "R's {attribute declaration}'s
13241 * {type definition} must be validly derived from
13242 * B's {type definition} given the empty set as
13243 * defined in Type Derivation OK (Simple) (§3.14.6)."
13244 */
13245 xmlSchemaPAttrUseErr(pctxt,
13246 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_2,
13247 type, cur->attr,
13248 "The attribute declaration's type "
13249 "definition is not validly derived from "
13250 "the corresponding definition in the "
13251 "base type", NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +000013252 } else {
13253 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013254 * 2.1.3 [Definition:] Let the effective value
13255 * constraint of an attribute use be its {value
13256 * constraint}, if present, otherwise its {attribute
13257 * declaration}'s {value constraint} .
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013258 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013259 xmlSchemaGetEffectiveValueConstraint(base->attr,
Daniel Veillard24505b02005-07-28 23:49:35 +000013260 &effFixed, &bEffValue, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013261 /*
13262 * 2.1.3 ... one of the following must be true
13263 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013264 * 2.1.3.1 B's ·effective value constraint· is
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013265 * ·absent· or default.
13266 */
13267 if ((bEffValue != NULL) &&
13268 (effFixed == 1)) {
13269 const xmlChar *rEffValue = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013270
13271 xmlSchemaGetEffectiveValueConstraint(base->attr,
Daniel Veillard24505b02005-07-28 23:49:35 +000013272 &effFixed, &rEffValue, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013273 /*
13274 * 2.1.3.2 R's ·effective value constraint· is
13275 * fixed with the same string as B's.
13276 * TODO: Compare the computed values.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013277 */
13278 if ((effFixed == 0) ||
13279 (! xmlStrEqual(rEffValue, bEffValue))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013280 xmlSchemaPAttrUseErr(pctxt,
13281 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_3,
13282 type, cur->attr,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013283 "The effective value constraint of the "
13284 "attribute use is inconsistent with "
13285 "its correspondent of the base type",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013286 NULL);
13287 } else {
13288 /*
13289 * Override the attribute use.
13290 */
13291 base->attr = cur->attr;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000013292 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013293 } else
13294 base->attr = cur->attr;
Daniel Veillard3646d642004-06-02 19:19:14 +000013295 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013296
Daniel Veillard3646d642004-06-02 19:19:14 +000013297 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013298 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013299 base = base->next;
13300 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013301
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013302 if ((!found) && (cur->attr->occurs !=
13303 XML_SCHEMAS_ATTR_USE_PROHIBITED)) {
13304 /*
13305 * derivation-ok-restriction 2.2
13306 */
13307 if ((baseType->attributeWildcard == NULL) ||
13308 (xmlSchemaCheckCVCWildcardNamespace(
13309 baseType->attributeWildcard,
13310 cur->attr->targetNamespace) != 1)) {
13311 xmlSchemaPAttrUseErr(pctxt,
13312 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_2,
13313 type, cur->attr,
13314 "Neither a matching attribute use, "
13315 "nor a matching wildcard in the base type does exist",
13316 NULL);
13317 } else {
13318 /*
13319 * Add the attribute use.
13320 *
13321 * Note that this may lead to funny derivation error reports, if
13322 * multiple equal attribute uses exist; but this is not
13323 * allowed anyway, and it will be reported beforehand.
13324 */
13325 tmp = cur;
13326 if (prev != NULL)
13327 prev->next = cur->next;
13328 else
13329 uses = cur->next;
13330 cur = cur->next;
13331 tmp->next = NULL;
13332 if (type->attributeUses == NULL) {
13333 type->attributeUses = tmp;
13334 } else
13335 lastBaseUse->next = tmp;
13336 lastBaseUse = tmp;
13337
13338 continue;
Daniel Veillard3646d642004-06-02 19:19:14 +000013339 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013340 }
13341 prev = cur;
Daniel Veillard3646d642004-06-02 19:19:14 +000013342 cur = cur->next;
13343 }
13344 if (uses != NULL)
13345 xmlSchemaFreeAttributeUseList(uses);
13346 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013347 } else if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
Daniel Veillard3646d642004-06-02 19:19:14 +000013348 /*
13349 * The spec allows only appending, and not other kinds of extensions.
13350 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013351 * This ensures: Schema Component Constraint: Derivation Valid (Extension) : 1.2
Daniel Veillard3646d642004-06-02 19:19:14 +000013352 */
13353 if (uses != NULL) {
13354 if (type->attributeUses == NULL) {
13355 type->attributeUses = uses;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013356 } else
Daniel Veillard3646d642004-06-02 19:19:14 +000013357 lastBaseUse->next = uses;
Daniel Veillard50355f02004-06-08 17:52:16 +000013358 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013359 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013360 PERROR_INT("xmlSchemaBuildAttributeValidation",
13361 "no derivation method");
13362 return (-1);
Daniel Veillard50355f02004-06-08 17:52:16 +000013363 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013364 /*
13365 * 3.4.6 -> Complex Type Definition Properties Correct
13366 */
13367 if (type->attributeUses != NULL) {
13368 cur = type->attributeUses;
13369 prev = NULL;
13370 while (cur != NULL) {
13371 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013372 * 4. Two distinct attribute declarations in the {attribute uses} must
Daniel Veillard3646d642004-06-02 19:19:14 +000013373 * not have identical {name}s and {target namespace}s.
Daniel Veillard50355f02004-06-08 17:52:16 +000013374 *
Daniel Veillard3646d642004-06-02 19:19:14 +000013375 * Note that this was already done for "restriction" and types derived from
13376 * the ur-type.
Daniel Veillard50355f02004-06-08 17:52:16 +000013377 */
Daniel Veillard3646d642004-06-02 19:19:14 +000013378 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) {
13379 tmp = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013380 while (tmp != NULL) {
13381 if ((xmlStrEqual(xmlSchemaGetAttrName(cur->attr),
Daniel Veillardc0826a72004-08-10 14:17:33 +000013382 xmlSchemaGetAttrName(tmp->attr))) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013383 (xmlStrEqual(xmlSchemaGetAttrTargetNsURI(cur->attr ),
Daniel Veillardc0826a72004-08-10 14:17:33 +000013384 xmlSchemaGetAttrTargetNsURI(tmp->attr)))) {
Daniel Veillard3646d642004-06-02 19:19:14 +000013385
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013386 xmlSchemaPAttrUseErr(pctxt,
13387 XML_SCHEMAP_CT_PROPS_CORRECT_4,
13388 type, tmp->attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013389 "Duplicate attribute use specified", NULL);
Daniel Veillard50355f02004-06-08 17:52:16 +000013390 break;
13391 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013392 tmp = tmp->next;
Daniel Veillard50355f02004-06-08 17:52:16 +000013393 }
13394 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013395 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013396 * 5. Two distinct attribute declarations in the {attribute uses} must
Daniel Veillard3646d642004-06-02 19:19:14 +000013397 * not have {type definition}s which are or are derived from ID.
13398 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013399 if ((cur->attr->subtypes != NULL) &&
13400 (xmlSchemaIsDerivedFromBuiltInType(cur->attr->subtypes,
13401 XML_SCHEMAS_ID))) {
Daniel Veillard3646d642004-06-02 19:19:14 +000013402 if (id != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013403 xmlSchemaPAttrUseErr(pctxt,
13404 XML_SCHEMAP_CT_PROPS_CORRECT_5,
13405 type, cur->attr,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013406 "There must not exist more than one attribute use, "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013407 "declared of type 'ID' or derived from it",
Daniel Veillardc0826a72004-08-10 14:17:33 +000013408 NULL);
13409 FREE_AND_NULL(str)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013410 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013411 id = cur;
13412 }
13413 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013414 * Remove "prohibited" attribute uses. The reason this is done at this late
Daniel Veillard3646d642004-06-02 19:19:14 +000013415 * stage is to be able to catch dublicate attribute uses. So we had to keep
13416 * prohibited uses in the list as well.
13417 */
13418 if (cur->attr->occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) {
13419 tmp = cur;
13420 if (prev == NULL)
13421 type->attributeUses = cur->next;
13422 else
13423 prev->next = cur->next;
13424 cur = cur->next;
Daniel Veillard50355f02004-06-08 17:52:16 +000013425 xmlFree(tmp);
Daniel Veillard3646d642004-06-02 19:19:14 +000013426 } else {
13427 prev = cur;
13428 cur = cur->next;
13429 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013430 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013431 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013432 /*
Daniel Veillard3646d642004-06-02 19:19:14 +000013433 * TODO: This check should be removed if we are 100% sure of
13434 * the base type attribute uses already being built.
13435 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013436 if ((baseType != NULL) && (! IS_ANYTYPE(baseType)) &&
Daniel Veillard3646d642004-06-02 19:19:14 +000013437 (baseType->type == XML_SCHEMA_TYPE_COMPLEX) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013438 (IS_NOT_TYPEFIXED(baseType))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013439 PERROR_INT("xmlSchemaBuildAttributeValidation",
13440 "attribute uses not builded on base type");
13441 }
Daniel Veillard3646d642004-06-02 19:19:14 +000013442 return (0);
13443}
13444
13445/**
Daniel Veillard01fa6152004-06-29 17:04:39 +000013446 * xmlSchemaTypeFinalContains:
13447 * @schema: the schema
13448 * @type: the type definition
13449 * @final: the final
13450 *
13451 * Evaluates if a type definition contains the given "final".
13452 * This does take "finalDefault" into account as well.
13453 *
13454 * Returns 1 if the type does containt the given "final",
13455 * 0 otherwise.
13456 */
13457static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013458xmlSchemaTypeFinalContains(xmlSchemaTypePtr type, int final)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013459{
Daniel Veillard01fa6152004-06-29 17:04:39 +000013460 if (type == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013461 return (0);
13462 if (type->flags & final)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013463 return (1);
13464 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013465 return (0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013466}
13467
13468/**
13469 * xmlSchemaGetUnionSimpleTypeMemberTypes:
13470 * @type: the Union Simple Type
13471 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013472 * Returns a list of member types of @type if existing,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013473 * returns NULL otherwise.
13474 */
Daniel Veillardb7c6ac42004-06-29 22:01:27 +000013475static xmlSchemaTypeLinkPtr
Daniel Veillard01fa6152004-06-29 17:04:39 +000013476xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type)
13477{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013478 while ((type != NULL) && (type->type == XML_SCHEMA_TYPE_SIMPLE)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013479 if (type->memberTypes != NULL)
13480 return (type->memberTypes);
13481 else
13482 type = type->baseType;
13483 }
13484 return (NULL);
13485}
13486
13487/**
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013488 * xmlSchemaGetParticleTotalRangeMin:
13489 * @particle: the particle
13490 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013491 * Schema Component Constraint: Effective Total Range
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013492 * (all and sequence) + (choice)
13493 *
13494 * Returns the minimun Effective Total Range.
13495 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013496static int
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013497xmlSchemaGetParticleTotalRangeMin(xmlSchemaParticlePtr particle)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013498{
13499 if ((particle->children == NULL) ||
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013500 (particle->minOccurs == 0))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013501 return (0);
13502 if (particle->children->type == XML_SCHEMA_TYPE_CHOICE) {
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013503 int min = -1, cur;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013504 xmlSchemaParticlePtr part =
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013505 (xmlSchemaParticlePtr) particle->children->children;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013506
13507 if (part == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013508 return (0);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013509 while (part != NULL) {
13510 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
13511 (part->children->type == XML_SCHEMA_TYPE_ANY))
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013512 cur = part->minOccurs;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013513 else
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013514 cur = xmlSchemaGetParticleTotalRangeMin(part);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013515 if (cur == 0)
13516 return (0);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013517 if ((min > cur) || (min == -1))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013518 min = cur;
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013519 part = (xmlSchemaParticlePtr) part->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013520 }
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013521 return (particle->minOccurs * min);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013522 } else {
13523 /* <all> and <sequence> */
13524 int sum = 0;
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013525 xmlSchemaParticlePtr part =
13526 (xmlSchemaParticlePtr) particle->children->children;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013527
13528 if (part == NULL)
13529 return (0);
13530 do {
13531 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
13532 (part->children->type == XML_SCHEMA_TYPE_ANY))
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013533 sum += part->minOccurs;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013534 else
13535 sum += xmlSchemaGetParticleTotalRangeMin(part);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013536 part = (xmlSchemaParticlePtr) part->next;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013537 } while (part != NULL);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013538 return (particle->minOccurs * sum);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013539 }
13540}
13541
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013542/**
13543 * xmlSchemaGetParticleTotalRangeMax:
13544 * @particle: the particle
13545 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013546 * Schema Component Constraint: Effective Total Range
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013547 * (all and sequence) + (choice)
13548 *
13549 * Returns the maximum Effective Total Range.
13550 */
13551static int
13552xmlSchemaGetParticleTotalRangeMax(xmlSchemaParticlePtr particle)
13553{
13554 if ((particle->children == NULL) ||
13555 (particle->children->children == NULL))
13556 return (0);
13557 if (particle->children->type == XML_SCHEMA_TYPE_CHOICE) {
13558 int max = -1, cur;
13559 xmlSchemaParticlePtr part =
13560 (xmlSchemaParticlePtr) particle->children->children;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013561
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013562 for (; part != NULL; part = (xmlSchemaParticlePtr) part->next) {
13563 if (part->children == NULL)
13564 continue;
13565 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
13566 (part->children->type == XML_SCHEMA_TYPE_ANY))
13567 cur = part->maxOccurs;
13568 else
13569 cur = xmlSchemaGetParticleTotalRangeMax(part);
13570 if (cur == UNBOUNDED)
13571 return (UNBOUNDED);
13572 if ((max < cur) || (max == -1))
13573 max = cur;
13574 }
13575 /* TODO: Handle overflows? */
13576 return (particle->maxOccurs * max);
13577 } else {
13578 /* <all> and <sequence> */
13579 int sum = 0, cur;
13580 xmlSchemaParticlePtr part =
13581 (xmlSchemaParticlePtr) particle->children->children;
13582
13583 for (; part != NULL; part = (xmlSchemaParticlePtr) part->next) {
13584 if (part->children == NULL)
13585 continue;
13586 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
13587 (part->children->type == XML_SCHEMA_TYPE_ANY))
13588 cur = part->maxOccurs;
13589 else
13590 cur = xmlSchemaGetParticleTotalRangeMax(part);
13591 if (cur == UNBOUNDED)
13592 return (UNBOUNDED);
13593 if ((cur > 0) && (particle->maxOccurs == UNBOUNDED))
13594 return (UNBOUNDED);
13595 sum += cur;
13596 }
13597 /* TODO: Handle overflows? */
13598 return (particle->maxOccurs * sum);
13599 }
13600}
13601
13602/**
13603 * xmlSchemaIsParticleEmptiable:
13604 * @particle: the particle
13605 *
13606 * Schema Component Constraint: Particle Emptiable
13607 * Checks whether the given particle is emptiable.
13608 *
13609 * Returns 1 if emptiable, 0 otherwise.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013610 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013611static int
13612xmlSchemaIsParticleEmptiable(xmlSchemaParticlePtr particle)
13613{
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013614 /*
13615 * SPEC (1) "Its {min occurs} is 0."
13616 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013617 if ((particle == NULL) || (particle->minOccurs == 0) ||
13618 (particle->children == NULL))
13619 return (1);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013620 /*
13621 * SPEC (2) "Its {term} is a group and the minimum part of the
13622 * effective total range of that group, [...] is 0."
13623 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013624 if (IS_MODEL_GROUP(particle->children)) {
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013625 if (xmlSchemaGetParticleTotalRangeMin(particle) == 0)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013626 return (1);
13627 }
13628 return (0);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013629}
13630
13631/**
13632 * xmlSchemaCheckCOSSTDerivedOK:
13633 * @type: the derived simple type definition
13634 * @baseType: the base type definition
13635 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013636 * Schema Component Constraint:
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013637 * Type Derivation OK (Simple) (cos-st-derived-OK)
13638 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013639 * Checks wheter @type can be validly
Daniel Veillard01fa6152004-06-29 17:04:39 +000013640 * derived from @baseType.
13641 *
13642 * Returns 0 on success, an positive error code otherwise.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013643 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013644static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013645xmlSchemaCheckCOSSTDerivedOK(xmlSchemaTypePtr type,
13646 xmlSchemaTypePtr baseType,
13647 int subset)
13648{
Daniel Veillard01fa6152004-06-29 17:04:39 +000013649 /*
Daniel Veillard01fa6152004-06-29 17:04:39 +000013650 * 1 They are the same type definition.
13651 * TODO: The identy check might have to be more complex than this.
13652 */
13653 if (type == baseType)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013654 return (0);
13655 /*
Daniel Veillard01fa6152004-06-29 17:04:39 +000013656 * 2.1 restriction is not in the subset, or in the {final}
13657 * of its own {base type definition};
13658 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013659 if ((subset & SUBSET_RESTRICTION) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013660 (xmlSchemaTypeFinalContains(type->baseType,
13661 XML_SCHEMAS_TYPE_FINAL_RESTRICTION))) {
13662 return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013663 }
13664 /* 2.2 */
13665 if (type->baseType == baseType) {
13666 /*
13667 * 2.2.1 D's ·base type definition· is B.
13668 */
13669 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013670 }
13671 /*
13672 * 2.2.2 D's ·base type definition· is not the ·ur-type definition·
13673 * and is validly derived from B given the subset, as defined by this
13674 * constraint.
Daniel Veillard01fa6152004-06-29 17:04:39 +000013675 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013676 if ((! IS_ANYTYPE(type->baseType)) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013677 (xmlSchemaCheckCOSSTDerivedOK(type->baseType,
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013678 baseType, subset) == 0)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013679 return (0);
13680 }
13681 /*
13682 * 2.2.3 D's {variety} is list or union and B is the ·simple ur-type
Daniel Veillard01fa6152004-06-29 17:04:39 +000013683 * definition·.
13684 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000013685 if (IS_ANY_SIMPLE_TYPE(baseType) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013686 (VARIETY_LIST(type) || VARIETY_UNION(type))) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013687 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013688 }
13689 /*
13690 * 2.2.4 B's {variety} is union and D is validly derived from a type
13691 * definition in B's {member type definitions} given the subset, as
Daniel Veillard01fa6152004-06-29 17:04:39 +000013692 * defined by this constraint.
13693 *
13694 * NOTE: This seems not to involve built-in types, since there is no
13695 * built-in Union Simple Type.
13696 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013697 if (VARIETY_UNION(baseType)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013698 xmlSchemaTypeLinkPtr cur;
13699
13700 cur = baseType->memberTypes;
13701 while (cur != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013702 if (xmlSchemaCheckCOSSTDerivedOK(type, cur->type, subset) == 0)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013703 return (0);
13704 cur = cur->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013705 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013706 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013707
Daniel Veillard01fa6152004-06-29 17:04:39 +000013708 return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_2);
13709}
13710
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013711/**
13712 * xmlSchemaCheckTypeDefCircularInternal:
13713 * @pctxt: the schema parser context
13714 * @ctxtType: the type definition
13715 * @ancestor: an ancestor of @ctxtType
13716 *
13717 * Checks st-props-correct (2) + ct-props-correct (3).
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013718 * Circular type definitions are not allowed.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013719 *
13720 * Returns XML_SCHEMAP_ST_PROPS_CORRECT_2 if the given type is
13721 * circular, 0 otherwise.
13722 */
13723static int
13724xmlSchemaCheckTypeDefCircularInternal(xmlSchemaParserCtxtPtr pctxt,
13725 xmlSchemaTypePtr ctxtType,
13726 xmlSchemaTypePtr ancestor)
13727{
13728 int ret;
13729
13730 if ((ancestor == NULL) || (ancestor->type == XML_SCHEMA_TYPE_BASIC))
13731 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013732
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013733 if (ctxtType == ancestor) {
13734 xmlSchemaPCustomErr(pctxt,
13735 XML_SCHEMAP_ST_PROPS_CORRECT_2,
13736 NULL, ctxtType, GET_NODE(ctxtType),
13737 "The definition is circular", NULL);
13738 return (XML_SCHEMAP_ST_PROPS_CORRECT_2);
13739 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013740 if (ancestor->flags & XML_SCHEMAS_TYPE_MARKED) {
13741 /*
13742 * Avoid inifinite recursion on circular types not yet checked.
13743 */
13744 return (0);
13745 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013746 ancestor->flags |= XML_SCHEMAS_TYPE_MARKED;
13747 ret = xmlSchemaCheckTypeDefCircularInternal(pctxt, ctxtType,
13748 ancestor->baseType);
13749 ancestor->flags ^= XML_SCHEMAS_TYPE_MARKED;
13750 return (ret);
13751}
13752
13753/**
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013754 * xmlSchemaCheckTypeDefCircular:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013755 * @item: the complex/simple type definition
13756 * @ctxt: the parser context
13757 * @name: the name
13758 *
13759 * Checks for circular type definitions.
13760 */
13761static void
13762xmlSchemaCheckTypeDefCircular(xmlSchemaTypePtr item,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013763 xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013764 const xmlChar * name ATTRIBUTE_UNUSED)
13765{
13766 if ((item == NULL) ||
13767 ((item->type != XML_SCHEMA_TYPE_COMPLEX) &&
13768 (item->type != XML_SCHEMA_TYPE_SIMPLE)))
13769 return;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000013770 if (item->redef != NULL) {
13771 xmlSchemaTypePtr cur = item;
13772 do {
13773 xmlSchemaCheckTypeDefCircularInternal(ctxt, cur, cur->baseType);
13774 cur = cur->redef;
13775 } while (cur != NULL);
13776 } else
13777 xmlSchemaCheckTypeDefCircularInternal(ctxt, item, item->baseType);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013778}
Daniel Veillard01fa6152004-06-29 17:04:39 +000013779
13780/**
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013781 * xmlSchemaResolveTypeDefs:
13782 * @item: the complex/simple type definition
13783 * @ctxt: the parser context
13784 * @name: the name
13785 *
13786 * Checks for circular type definitions.
13787 */
13788static void
13789xmlSchemaResolveTypeDefs(xmlSchemaTypePtr typeDef,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013790 xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013791 const xmlChar * name ATTRIBUTE_UNUSED)
13792{
13793 if (typeDef == NULL)
13794 return;
13795
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013796 /*
13797 * Resolve the base type.
13798 */
13799 if (typeDef->baseType == NULL) {
13800 typeDef->baseType = xmlSchemaGetType(ctxt->schema,
13801 typeDef->base, typeDef->baseNs);
13802 if (typeDef->baseType == NULL) {
13803 xmlSchemaPResCompAttrErr(ctxt,
13804 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013805 typeDef, typeDef->node,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013806 "base", typeDef->base, typeDef->baseNs,
13807 XML_SCHEMA_TYPE_SIMPLE, NULL);
13808 return;
13809 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013810 }
13811 if (IS_SIMPLE_TYPE(typeDef)) {
13812 if (VARIETY_UNION(typeDef)) {
13813 /*
13814 * Resolve the memberTypes.
13815 */
13816 xmlSchemaResolveUnionMemberTypes(ctxt, typeDef);
13817 return;
13818 } else if (VARIETY_LIST(typeDef)) {
13819 /*
13820 * Resolve the itemType.
13821 */
13822 if ((typeDef->subtypes == NULL) && (typeDef->ref != NULL)) {
13823 typeDef->subtypes = xmlSchemaGetType(ctxt->schema,
13824 typeDef->ref, typeDef->refNs);
13825 if ((typeDef->subtypes == NULL) ||
13826 (! IS_SIMPLE_TYPE(typeDef->subtypes))) {
13827 typeDef->subtypes = NULL;
13828 xmlSchemaPResCompAttrErr(ctxt,
13829 XML_SCHEMAP_SRC_RESOLVE,
13830 typeDef, typeDef->node,
13831 "itemType", typeDef->ref, typeDef->refNs,
13832 XML_SCHEMA_TYPE_SIMPLE, NULL);
13833 }
13834 }
13835 return;
13836 }
13837 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000013838}
13839
13840
13841
13842/**
Daniel Veillard01fa6152004-06-29 17:04:39 +000013843 * xmlSchemaCheckSTPropsCorrect:
13844 * @ctxt: the schema parser context
13845 * @type: the simple type definition
13846 *
13847 * Checks st-props-correct.
13848 *
13849 * Returns 0 if the properties are correct,
13850 * if not, a positive error code and -1 on internal
13851 * errors.
13852 */
13853static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013854xmlSchemaCheckSTPropsCorrect(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013855 xmlSchemaTypePtr type)
13856{
13857 xmlSchemaTypePtr baseType = type->baseType, anySimpleType,
13858 anyType;
Daniel Veillardc0826a72004-08-10 14:17:33 +000013859 xmlChar *str = NULL;
Daniel Veillard01fa6152004-06-29 17:04:39 +000013860
Daniel Veillardc0826a72004-08-10 14:17:33 +000013861 /* STATE: error funcs converted. */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013862 /*
13863 * Schema Component Constraint: Simple Type Definition Properties Correct
13864 *
13865 * NOTE: This is somehow redundant, since we actually built a simple type
13866 * to have all the needed information; this acts as an self test.
13867 */
13868 anySimpleType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
13869 anyType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013870 /* Base type: If the datatype has been ·derived· by ·restriction·
13871 * then the Simple Type Definition component from which it is ·derived·,
13872 * otherwise the Simple Type Definition for anySimpleType (§4.1.6).
Daniel Veillard01fa6152004-06-29 17:04:39 +000013873 */
13874 if (baseType == NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013875 /*
13876 * TODO: Think about: "modulo the impact of Missing
13877 * Sub-components (§5.3)."
13878 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000013879 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013880 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013881 NULL, type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013882 "No base type existent", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013883 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013884
Daniel Veillard01fa6152004-06-29 17:04:39 +000013885 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013886 if (! IS_SIMPLE_TYPE(baseType)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013887 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013888 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013889 NULL, type, NULL,
13890 "The base type '%s' is not a simple type",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013891 xmlSchemaGetComponentQName(&str, baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013892 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013893 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
13894 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013895 if ( (VARIETY_LIST(type) || VARIETY_UNION(type)) &&
13896 ((type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) == 0) &&
13897 (! IS_ANY_SIMPLE_TYPE(baseType))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013898 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013899 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013900 NULL, type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013901 "A type, derived by list or union, must have"
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013902 "the simple ur-type definition as base type, not '%s'",
13903 xmlSchemaGetComponentQName(&str, baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013904 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013905 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
13906 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013907 /*
13908 * Variety: One of {atomic, list, union}.
Daniel Veillard01fa6152004-06-29 17:04:39 +000013909 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013910 if ((! VARIETY_ATOMIC(type)) && (! VARIETY_UNION(type)) &&
13911 (! VARIETY_LIST(type))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000013912 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013913 XML_SCHEMAP_ST_PROPS_CORRECT_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013914 NULL, type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013915 "The variety is absent", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000013916 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
13917 }
Daniel Veillardc0826a72004-08-10 14:17:33 +000013918 /* TODO: Finish this. Hmm, is this finished? */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013919
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013920 /*
13921 * 3 The {final} of the {base type definition} must not contain restriction.
13922 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013923 if (xmlSchemaTypeFinalContains(baseType,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013924 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
13925 xmlSchemaPCustomErr(ctxt,
13926 XML_SCHEMAP_ST_PROPS_CORRECT_3,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013927 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013928 "The 'final' of its base type '%s' must not contain "
13929 "'restriction'",
13930 xmlSchemaGetComponentQName(&str, baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013931 FREE_AND_NULL(str)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013932 return (XML_SCHEMAP_ST_PROPS_CORRECT_3);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013933 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000013934
13935 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013936 * 2 All simple type definitions must be derived ultimately from the ·simple
13937 * ur-type definition (so· circular definitions are disallowed). That is, it
13938 * must be possible to reach a built-in primitive datatype or the ·simple
13939 * ur-type definition· by repeatedly following the {base type definition}.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013940 *
13941 * NOTE: this is done in xmlSchemaCheckTypeDefCircular().
Daniel Veillard01fa6152004-06-29 17:04:39 +000013942 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000013943 return (0);
13944}
13945
13946/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013947 * xmlSchemaCheckCOSSTRestricts:
Daniel Veillard01fa6152004-06-29 17:04:39 +000013948 * @ctxt: the schema parser context
13949 * @type: the simple type definition
13950 *
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000013951 * Schema Component Constraint:
13952 * Derivation Valid (Restriction, Simple) (cos-st-restricts)
13953
13954 * Checks if the given @type (simpleType) is derived validly by restriction.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013955 * STATUS:
Daniel Veillard01fa6152004-06-29 17:04:39 +000013956 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013957 * Returns -1 on internal errors, 0 if the type is validly derived,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013958 * a positive error code otherwise.
13959 */
13960static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013961xmlSchemaCheckCOSSTRestricts(xmlSchemaParserCtxtPtr pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000013962 xmlSchemaTypePtr type)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013963{
Daniel Veillardc0826a72004-08-10 14:17:33 +000013964 xmlChar *str = NULL;
13965
Daniel Veillard01fa6152004-06-29 17:04:39 +000013966 if (type->type != XML_SCHEMA_TYPE_SIMPLE) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013967 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
13968 "given type is not a user-derived simpleType");
Daniel Veillard01fa6152004-06-29 17:04:39 +000013969 return (-1);
13970 }
13971
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013972 if (VARIETY_ATOMIC(type)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000013973 xmlSchemaTypePtr primitive;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013974 /*
13975 * 1.1 The {base type definition} must be an atomic simple
Daniel Veillard01fa6152004-06-29 17:04:39 +000013976 * type definition or a built-in primitive datatype.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013977 */
13978 if (! VARIETY_ATOMIC(type->baseType)) {
13979 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013980 XML_SCHEMAP_COS_ST_RESTRICTS_1_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013981 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013982 "The base type '%s' is not an atomic simple type",
13983 xmlSchemaGetComponentQName(&str, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013984 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013985 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_1);
13986 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013987 /* 1.2 The {final} of the {base type definition} must not contain
Daniel Veillard01fa6152004-06-29 17:04:39 +000013988 * restriction.
13989 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000013990 /* OPTIMIZE TODO : This is already done in xmlSchemaCheckStPropsCorrect */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013991 if (xmlSchemaTypeFinalContains(type->baseType,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013992 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013993 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000013994 XML_SCHEMAP_COS_ST_RESTRICTS_1_2,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000013995 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000013996 "The final of its base type '%s' must not contain 'restriction'",
13997 xmlSchemaGetComponentQName(&str, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000013998 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000013999 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_2);
14000 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014001
14002 /*
Daniel Veillard01fa6152004-06-29 17:04:39 +000014003 * 1.3.1 DF must be an allowed constraining facet for the {primitive
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014004 * type definition}, as specified in the appropriate subsection of 3.2
Daniel Veillard01fa6152004-06-29 17:04:39 +000014005 * Primitive datatypes.
14006 */
14007 if (type->facets != NULL) {
14008 xmlSchemaFacetPtr facet;
14009 int ok = 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014010
Daniel Veillard01fa6152004-06-29 17:04:39 +000014011 primitive = xmlSchemaGetPrimitiveType(type);
14012 if (primitive == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014013 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
14014 "failed to get primitive type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000014015 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014016 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000014017 facet = type->facets;
14018 do {
14019 if (xmlSchemaIsBuiltInTypeFacet(primitive, facet->type) == 0) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000014020 ok = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014021 xmlSchemaPIllegalFacetAtomicErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014022 XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014023 NULL, type, primitive, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014024 }
14025 facet = facet->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014026 } while (facet != NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014027 if (ok == 0)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014028 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014029 }
14030 /*
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014031 * SPEC (1.3.2) "If there is a facet of the same kind in the {facets}
14032 * of the {base type definition} (call this BF),then the DF's {value}
14033 * must be a valid restriction of BF's {value} as defined in
14034 * [XML Schemas: Datatypes]."
14035 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014036 * NOTE (1.3.2) Facet derivation constraints are currently handled in
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014037 * xmlSchemaDeriveAndValidateFacets()
Daniel Veillard01fa6152004-06-29 17:04:39 +000014038 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014039 } else if (VARIETY_LIST(type)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000014040 xmlSchemaTypePtr itemType = NULL;
14041
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014042 itemType = type->subtypes;
14043 if ((itemType == NULL) || (! IS_SIMPLE_TYPE(itemType))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014044 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
14045 "failed to evaluate the item type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000014046 return (-1);
14047 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014048 if (IS_NOT_TYPEFIXED(itemType))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014049 xmlSchemaTypeFixup(itemType, pctxt, NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014050 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014051 * 2.1 The {item type definition} must have a {variety} of atomic or
14052 * union (in which case all the {member type definitions}
Daniel Veillard01fa6152004-06-29 17:04:39 +000014053 * must be atomic).
14054 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014055 if ((! VARIETY_ATOMIC(itemType)) &&
14056 (! VARIETY_UNION(itemType))) {
14057 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014058 XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014059 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014060 "The item type '%s' does not have a variety of atomic or union",
14061 xmlSchemaGetComponentQName(&str, itemType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014062 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000014063 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014064 } else if (VARIETY_UNION(itemType)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000014065 xmlSchemaTypeLinkPtr member;
14066
14067 member = itemType->memberTypes;
14068 while (member != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014069 if (! VARIETY_ATOMIC(member->type)) {
14070 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014071 XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014072 NULL, type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014073 "The item type is a union type, but the "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014074 "member type '%s' of this item type is not atomic",
14075 xmlSchemaGetComponentQName(&str, member->type));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014076 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000014077 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
14078 }
14079 member = member->next;
14080 }
14081 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014082
14083 if (IS_ANY_SIMPLE_TYPE(type->baseType)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000014084 xmlSchemaFacetPtr facet;
14085 /*
14086 * This is the case if we have: <simpleType><list ..
14087 */
14088 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014089 * 2.3.1
14090 * 2.3.1.1 The {final} of the {item type definition} must not
Daniel Veillard01fa6152004-06-29 17:04:39 +000014091 * contain list.
14092 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014093 if (xmlSchemaTypeFinalContains(itemType,
14094 XML_SCHEMAS_TYPE_FINAL_LIST)) {
14095 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014096 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014097 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014098 "The final of its item type '%s' must not contain 'list'",
14099 xmlSchemaGetComponentQName(&str, itemType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014100 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000014101 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1);
14102 }
14103 /*
14104 * 2.3.1.2 The {facets} must only contain the whiteSpace
14105 * facet component.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014106 * OPTIMIZE TODO: the S4S already disallows any facet
14107 * to be specified.
Daniel Veillard01fa6152004-06-29 17:04:39 +000014108 */
14109 if (type->facets != NULL) {
14110 facet = type->facets;
14111 do {
Daniel Veillardc0826a72004-08-10 14:17:33 +000014112 if (facet->type != XML_SCHEMA_FACET_WHITESPACE) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014113 xmlSchemaPIllegalFacetListUnionErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014114 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014115 NULL, type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014116 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2);
14117 }
14118 facet = facet->next;
14119 } while (facet != NULL);
14120 }
14121 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014122 * MAYBE TODO: (Hmm, not really) Datatypes states:
14123 * A ·list· datatype can be ·derived· from an ·atomic· datatype
14124 * whose ·lexical space· allows space (such as string or anyURI)or
14125 * a ·union· datatype any of whose {member type definitions}'s
Daniel Veillard01fa6152004-06-29 17:04:39 +000014126 * ·lexical space· allows space.
14127 */
14128 } else {
14129 /*
14130 * This is the case if we have: <simpleType><restriction ...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014131 * I.e. the variety of "list" is inherited.
Daniel Veillard01fa6152004-06-29 17:04:39 +000014132 */
14133 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014134 * 2.3.2
Daniel Veillard01fa6152004-06-29 17:04:39 +000014135 * 2.3.2.1 The {base type definition} must have a {variety} of list.
14136 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014137 if (! VARIETY_LIST(type->baseType)) {
14138 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014139 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014140 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014141 "The base type '%s' must be a list type",
14142 xmlSchemaGetComponentQName(&str, type->baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014143 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000014144 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1);
14145 }
14146 /*
14147 * 2.3.2.2 The {final} of the {base type definition} must not
14148 * contain restriction.
14149 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014150 if (xmlSchemaTypeFinalContains(type->baseType,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014151 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014152 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014153 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014154 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014155 "The 'final' of the base type '%s' must not contain 'restriction'",
14156 xmlSchemaGetComponentQName(&str, type->baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014157 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000014158 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2);
14159 }
14160 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014161 * 2.3.2.3 The {item type definition} must be validly derived
Daniel Veillard01fa6152004-06-29 17:04:39 +000014162 * from the {base type definition}'s {item type definition} given
14163 * the empty set, as defined in Type Derivation OK (Simple) (§3.14.6).
14164 */
14165 {
14166 xmlSchemaTypePtr baseItemType;
14167
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014168 baseItemType = type->baseType->subtypes;
14169 if ((baseItemType == NULL) || (! IS_SIMPLE_TYPE(baseItemType))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014170 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
14171 "failed to eval the item type of a base type");
Daniel Veillard01fa6152004-06-29 17:04:39 +000014172 return (-1);
14173 }
14174 if ((itemType != baseItemType) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014175 (xmlSchemaCheckCOSSTDerivedOK(itemType,
14176 baseItemType, 0) != 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000014177 xmlChar *strBIT = NULL, *strBT = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014178 xmlSchemaPCustomErrExt(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014179 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014180 NULL, type, NULL,
14181 "The item type '%s' is not validly derived from "
14182 "the item type '%s' of the base type '%s'",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014183 xmlSchemaGetComponentQName(&str, itemType),
14184 xmlSchemaGetComponentQName(&strBIT, baseItemType),
14185 xmlSchemaGetComponentQName(&strBT, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000014186
14187 FREE_AND_NULL(str)
14188 FREE_AND_NULL(strBIT)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014189 FREE_AND_NULL(strBT)
Daniel Veillard01fa6152004-06-29 17:04:39 +000014190 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3);
14191 }
14192 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014193
Daniel Veillard01fa6152004-06-29 17:04:39 +000014194 if (type->facets != NULL) {
14195 xmlSchemaFacetPtr facet;
14196 int ok = 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014197 /*
14198 * 2.3.2.4 Only length, minLength, maxLength, whiteSpace, pattern
Daniel Veillard01fa6152004-06-29 17:04:39 +000014199 * and enumeration facet components are allowed among the {facets}.
14200 */
14201 facet = type->facets;
14202 do {
14203 switch (facet->type) {
14204 case XML_SCHEMA_FACET_LENGTH:
14205 case XML_SCHEMA_FACET_MINLENGTH:
14206 case XML_SCHEMA_FACET_MAXLENGTH:
14207 case XML_SCHEMA_FACET_WHITESPACE:
14208 /*
14209 * TODO: 2.5.1.2 List datatypes
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014210 * The value of ·whiteSpace· is fixed to the value collapse.
Daniel Veillard01fa6152004-06-29 17:04:39 +000014211 */
14212 case XML_SCHEMA_FACET_PATTERN:
14213 case XML_SCHEMA_FACET_ENUMERATION:
14214 break;
14215 default: {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014216 xmlSchemaPIllegalFacetListUnionErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014217 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014218 NULL, type, facet);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014219 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014220 * We could return, but it's nicer to report all
Daniel Veillard01fa6152004-06-29 17:04:39 +000014221 * invalid facets.
14222 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014223 ok = 0;
Daniel Veillard01fa6152004-06-29 17:04:39 +000014224 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014225 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000014226 facet = facet->next;
14227 } while (facet != NULL);
14228 if (ok == 0)
14229 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4);
14230 /*
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014231 * SPEC (2.3.2.5) (same as 1.3.2)
14232 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014233 * NOTE (2.3.2.5) This is currently done in
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014234 * xmlSchemaDeriveAndValidateFacets()
Daniel Veillard01fa6152004-06-29 17:04:39 +000014235 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014236 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000014237 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014238 } else if (VARIETY_UNION(type)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000014239 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014240 * 3.1 The {member type definitions} must all have {variety} of
Daniel Veillard01fa6152004-06-29 17:04:39 +000014241 * atomic or list.
14242 */
14243 xmlSchemaTypeLinkPtr member;
14244
14245 member = type->memberTypes;
14246 while (member != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014247 if (IS_NOT_TYPEFIXED(member->type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014248 xmlSchemaTypeFixup(member->type, pctxt, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014249
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014250 if ((! VARIETY_ATOMIC(member->type)) &&
14251 (! VARIETY_LIST(member->type))) {
14252 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014253 XML_SCHEMAP_COS_ST_RESTRICTS_3_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014254 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014255 "The member type '%s' is neither an atomic, nor a list type",
14256 xmlSchemaGetComponentQName(&str, member->type));
Daniel Veillardc0826a72004-08-10 14:17:33 +000014257 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000014258 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_1);
14259 }
14260 member = member->next;
14261 }
14262 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014263 * 3.3.1 If the {base type definition} is the ·simple ur-type
14264 * definition·
Daniel Veillard01fa6152004-06-29 17:04:39 +000014265 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014266 if (type->baseType->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000014267 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014268 * 3.3.1.1 All of the {member type definitions} must have a
Daniel Veillard01fa6152004-06-29 17:04:39 +000014269 * {final} which does not contain union.
14270 */
14271 member = type->memberTypes;
14272 while (member != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014273 if (xmlSchemaTypeFinalContains(member->type,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014274 XML_SCHEMAS_TYPE_FINAL_UNION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014275 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014276 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014277 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014278 "The 'final' of member type '%s' contains 'union'",
14279 xmlSchemaGetComponentQName(&str, member->type));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014280 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000014281 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1);
14282 }
14283 member = member->next;
14284 }
14285 /*
14286 * 3.3.1.2 The {facets} must be empty.
14287 */
14288 if (type->facetSet != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014289 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014290 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014291 NULL, type, NULL,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014292 "No facets allowed", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014293 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2);
14294 }
14295 } else {
14296 /*
14297 * 3.3.2.1 The {base type definition} must have a {variety} of union.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014298 * I.e. the variety of "list" is inherited.
Daniel Veillard01fa6152004-06-29 17:04:39 +000014299 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014300 if (! VARIETY_UNION(type->baseType)) {
14301 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014302 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014303 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014304 "The base type '%s' is not a union type",
14305 xmlSchemaGetComponentQName(&str, type->baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014306 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000014307 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1);
14308 }
14309 /*
14310 * 3.3.2.2 The {final} of the {base type definition} must not contain restriction.
14311 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014312 if (xmlSchemaTypeFinalContains(type->baseType,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014313 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014314 xmlSchemaPCustomErr(pctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014315 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014316 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014317 "The 'final' of its base type '%s' must not contain 'restriction'",
14318 xmlSchemaGetComponentQName(&str, type->baseType));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014319 FREE_AND_NULL(str)
Daniel Veillard01fa6152004-06-29 17:04:39 +000014320 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2);
14321 }
14322 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014323 * 3.3.2.3 The {member type definitions}, in order, must be validly
14324 * derived from the corresponding type definitions in the {base
14325 * type definition}'s {member type definitions} given the empty set,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014326 * as defined in Type Derivation OK (Simple) (§3.14.6).
14327 */
14328 {
14329 xmlSchemaTypeLinkPtr baseMember;
14330
14331 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014332 * OPTIMIZE: if the type is restricting, it has no local defined
14333 * member types and inherits the member types of the base type;
Daniel Veillard01fa6152004-06-29 17:04:39 +000014334 * thus a check for equality can be skipped.
14335 */
14336 /*
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000014337 * Even worse: I cannot see a scenario where a restricting
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014338 * union simple type can have other member types as the member
Daniel Veillard01fa6152004-06-29 17:04:39 +000014339 * types of it's base type. This check seems not necessary with
14340 * respect to the derivation process in libxml2.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000014341 * But necessary if constructing types with an API.
Daniel Veillard01fa6152004-06-29 17:04:39 +000014342 */
14343 if (type->memberTypes != NULL) {
14344 member = type->memberTypes;
14345 baseMember = xmlSchemaGetUnionSimpleTypeMemberTypes(type->baseType);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014346 if ((member == NULL) && (baseMember != NULL)) {
14347 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
14348 "different number of member types in base");
14349 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000014350 while (member != NULL) {
14351 if (baseMember == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014352 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
14353 "different number of member types in base");
Daniel Veillard01fa6152004-06-29 17:04:39 +000014354 }
14355 if ((member->type != baseMember->type) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014356 (xmlSchemaCheckCOSSTDerivedOK(
14357 member->type, baseMember->type, 0) != 0)) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000014358 xmlChar *strBMT = NULL, *strBT = NULL;
14359
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014360 xmlSchemaPCustomErrExt(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014361 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3,
14362 NULL, type, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014363 "The member type %s is not validly "
14364 "derived from its corresponding member "
14365 "type %s of the base type %s",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014366 xmlSchemaGetComponentQName(&str, member->type),
14367 xmlSchemaGetComponentQName(&strBMT, baseMember->type),
14368 xmlSchemaGetComponentQName(&strBT, type->baseType));
Daniel Veillardc0826a72004-08-10 14:17:33 +000014369 FREE_AND_NULL(str)
14370 FREE_AND_NULL(strBMT)
14371 FREE_AND_NULL(strBT)
Daniel Veillard01fa6152004-06-29 17:04:39 +000014372 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014373 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000014374 member = member->next;
14375 baseMember = baseMember->next;
14376 }
14377 }
14378 }
14379 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014380 * 3.3.2.4 Only pattern and enumeration facet components are
Daniel Veillard01fa6152004-06-29 17:04:39 +000014381 * allowed among the {facets}.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014382 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000014383 if (type->facets != NULL) {
14384 xmlSchemaFacetPtr facet;
14385 int ok = 1;
14386
14387 facet = type->facets;
14388 do {
14389 if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
14390 (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014391 xmlSchemaPIllegalFacetListUnionErr(pctxt,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014392 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014393 NULL, type, facet);
14394 ok = 0;
14395 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000014396 facet = facet->next;
14397 } while (facet != NULL);
14398 if (ok == 0)
14399 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014400
Daniel Veillard01fa6152004-06-29 17:04:39 +000014401 }
14402 /*
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014403 * SPEC (3.3.2.5) (same as 1.3.2)
14404 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014405 * NOTE (3.3.2.5) This is currently done in
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014406 * xmlSchemaDeriveAndValidateFacets()
Daniel Veillard01fa6152004-06-29 17:04:39 +000014407 */
14408 }
14409 }
14410
14411 return (0);
14412}
14413
14414/**
14415 * xmlSchemaCheckSRCSimpleType:
14416 * @ctxt: the schema parser context
14417 * @type: the simple type definition
14418 *
14419 * Checks crc-simple-type constraints.
14420 *
14421 * Returns 0 if the constraints are satisfied,
14422 * if not a positive error code and -1 on internal
14423 * errors.
14424 */
14425static int
14426xmlSchemaCheckSRCSimpleType(xmlSchemaParserCtxtPtr ctxt,
14427 xmlSchemaTypePtr type)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014428{
14429 /*
Daniel Veillard01fa6152004-06-29 17:04:39 +000014430 * src-simple-type.1 The corresponding simple type definition, if any,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014431 * must satisfy the conditions set out in Constraints on Simple Type
14432 * Definition Schema Components (§3.14.6).
Daniel Veillard01fa6152004-06-29 17:04:39 +000014433 */
14434 if ((xmlSchemaCheckSTPropsCorrect(ctxt, type) != 0) ||
14435 (xmlSchemaCheckCOSSTRestricts(ctxt, type) != 0)) {
14436 /*
14437 * TODO: Removed this, since it got annoying to get an
14438 * extra error report, if anything failed until now.
14439 * Enable this if needed.
14440 */
14441 /*
14442 xmlSchemaPErr(ctxt, type->node,
14443 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014444 "Simple type '%s' does not satisfy the constraints "
Daniel Veillard01fa6152004-06-29 17:04:39 +000014445 "on simple type definitions.\n",
14446 type->name, NULL);
14447 */
14448 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_1);
14449 }
14450
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014451 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000014452 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014453 * src-simple-type.2 If the <restriction> alternative is chosen,
14454 * either it must have a base [attribute] or a <simpleType> among its
Daniel Veillard01fa6152004-06-29 17:04:39 +000014455 * [children], but not both.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014456 */
William M. Brack2f2a6632004-08-20 23:09:47 +000014457 /*
14458 * XML_SCHEMAP_SRC_SIMPLE_TYPE_2
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014459 * NOTE: This is checked in the parse function of <restriction>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014460 */
14461 } else if (VARIETY_LIST(type)) {
14462 /* src-simple-type.3 If the <list> alternative is chosen, either it must have
14463 * an itemType [attribute] or a <simpleType> among its [children],
Daniel Veillard01fa6152004-06-29 17:04:39 +000014464 * but not both.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014465 *
14466 * REMOVED: This is checked in the parse function of <list>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014467 */
14468 } else if (VARIETY_UNION(type)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000014469 xmlSchemaTypeLinkPtr member;
14470 xmlSchemaTypePtr ancestor, anySimpleType;
14471
14472 anySimpleType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
14473
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014474 /* src-simple-type.4 Circular union type definition is disallowed. That is, if
14475 * the <union> alternative is chosen, there must not be any entries
14476 * in the memberTypes [attribute] at any depth which resolve to the
Daniel Veillard01fa6152004-06-29 17:04:39 +000014477 * component corresponding to the <simpleType>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014478 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000014479 member = type->memberTypes;
14480 while (member != NULL) {
14481 ancestor = member->type;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014482 while ((ancestor != NULL) && (ancestor->type != XML_SCHEMA_TYPE_BASIC)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014483 if (ancestor == type) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014484 xmlSchemaPCustomErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000014485 XML_SCHEMAP_SRC_SIMPLE_TYPE_4,
Daniel Veillardc0826a72004-08-10 14:17:33 +000014486 NULL, type, NULL,
14487 "The definition is circular", NULL);
Daniel Veillard01fa6152004-06-29 17:04:39 +000014488 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_4);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014489 }
14490 if (IS_NOT_TYPEFIXED(ancestor))
14491 xmlSchemaTypeFixup(ancestor, ctxt, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014492 if (VARIETY_LIST(ancestor)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000014493 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000014494 * TODO, FIXME: Although a list simple type must not have a union ST
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014495 * type as item type, which in turn has a list ST as member
14496 * type, we will assume this here as well, since this check
Daniel Veillard01fa6152004-06-29 17:04:39 +000014497 * was not yet performed.
14498 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000014499 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014500
Daniel Veillard01fa6152004-06-29 17:04:39 +000014501 ancestor = ancestor->baseType;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014502 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000014503 member = member->next;
14504 }
Daniel Veillard01fa6152004-06-29 17:04:39 +000014505 }
14506
14507 return (0);
14508}
14509
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014510static int
14511xmlSchemaCreateVCtxtOnPCtxt(xmlSchemaParserCtxtPtr ctxt)
14512{
14513 if (ctxt->vctxt == NULL) {
14514 ctxt->vctxt = xmlSchemaNewValidCtxt(NULL);
14515 if (ctxt->vctxt == NULL) {
14516 xmlSchemaPErr(ctxt, NULL,
Kasimier T. Buchcikbea23542004-08-25 20:35:45 +000014517 XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014518 "Internal error: xmlSchemaCreateVCtxtOnPCtxt, "
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014519 "failed to create a temp. validation context.\n",
14520 NULL, NULL);
14521 return (-1);
14522 }
14523 /* TODO: Pass user data. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014524 xmlSchemaSetValidErrors(ctxt->vctxt, ctxt->error, ctxt->warning, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014525 }
14526 return (0);
14527}
14528
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014529static int
14530xmlSchemaVCheckCVCSimpleType(xmlSchemaAbstractCtxtPtr actxt,
14531 xmlNodePtr node,
14532 xmlSchemaTypePtr type,
14533 const xmlChar *value,
14534 xmlSchemaValPtr *retVal,
14535 int fireErrors,
14536 int normalize,
14537 int isNormalized);
14538
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014539/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014540 * xmlSchemaParseCheckCOSValidDefault:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014541 * @pctxt: the schema parser context
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014542 * @type: the simple type definition
14543 * @value: the default value
14544 * @node: an optional node (the holder of the value)
14545 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014546 * Schema Component Constraint: Element Default Valid (Immediate)
14547 * (cos-valid-default)
14548 * This will be used by the parser only. For the validator there's
14549 * an other version.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014550 *
14551 * Returns 0 if the constraints are satisfied,
14552 * if not, a positive error code and -1 on internal
14553 * errors.
14554 */
14555static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014556xmlSchemaParseCheckCOSValidDefault(xmlSchemaParserCtxtPtr pctxt,
14557 xmlNodePtr node,
14558 xmlSchemaTypePtr type,
14559 const xmlChar *value,
14560 xmlSchemaValPtr *val)
14561{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014562 int ret = 0;
14563
14564 /*
14565 * cos-valid-default:
14566 * Schema Component Constraint: Element Default Valid (Immediate)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014567 * For a string to be a valid default with respect to a type
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014568 * definition the appropriate case among the following must be true:
14569 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014570 if IS_COMPLEX_TYPE(type) {
William M. Brack2f2a6632004-08-20 23:09:47 +000014571 /*
14572 * Complex type.
14573 *
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014574 * SPEC (2.1) "its {content type} must be a simple type definition
14575 * or mixed."
14576 * SPEC (2.2.2) "If the {content type} is mixed, then the {content
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014577 * type}'s particle must be ·emptiable· as defined by
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014578 * Particle Emptiable (§3.9.6)."
William M. Brack2f2a6632004-08-20 23:09:47 +000014579 */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014580 if ((! HAS_SIMPLE_CONTENT(type)) &&
14581 ((! HAS_MIXED_CONTENT(type)) || (! IS_PARTICLE_EMPTIABLE(type)))) {
14582 /* NOTE that this covers (2.2.2) as well. */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014583 xmlSchemaPCustomErr(pctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014584 XML_SCHEMAP_COS_VALID_DEFAULT_2_1,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014585 NULL, type, type->node,
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014586 "For a string to be a valid default, the type definition "
14587 "must be a simple type or a complex type with mixed content "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014588 "and a particle emptiable", NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014589 return(XML_SCHEMAP_COS_VALID_DEFAULT_2_1);
14590 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014591 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014592 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014593 * 1 If the type definition is a simple type definition, then the string
14594 * must be ·valid· with respect to that definition as defined by String
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014595 * Valid (§3.14.4).
14596 *
14597 * AND
14598 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014599 * 2.2.1 If the {content type} is a simple type definition, then the
14600 * string must be ·valid· with respect to that simple type definition
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014601 * as defined by String Valid (§3.14.4).
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014602 */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014603 if (IS_SIMPLE_TYPE(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014604 ret = xmlSchemaVCheckCVCSimpleType((xmlSchemaAbstractCtxtPtr) pctxt, node,
14605 type, value, val, 1, 1, 0);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014606 else if (HAS_SIMPLE_CONTENT(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014607 ret = xmlSchemaVCheckCVCSimpleType((xmlSchemaAbstractCtxtPtr) pctxt, node,
14608 type->contentTypeDef, value, val, 1, 1, 0);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014609 else
14610 return (ret);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014611
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014612 if (ret < 0) {
14613 PERROR_INT("xmlSchemaParseCheckCOSValidDefault",
14614 "calling xmlSchemaVCheckCVCSimpleType()");
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014615 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014616
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000014617 return (ret);
William M. Brack2f2a6632004-08-20 23:09:47 +000014618}
14619
14620/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014621 * xmlSchemaCheckCTPropsCorrect:
William M. Brack2f2a6632004-08-20 23:09:47 +000014622 * @ctxt: the schema parser context
14623 * @type: the complex type definition
14624 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014625 *.(4.6) Constraints on Complex Type Definition Schema Components
14626 * Schema Component Constraint:
14627 * Complex Type Definition Properties Correct (ct-props-correct)
14628 * STATUS: (seems) complete
William M. Brack2f2a6632004-08-20 23:09:47 +000014629 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014630 * Returns 0 if the constraints are satisfied, a positive
14631 * error code if not and -1 if an internal error occured.
William M. Brack2f2a6632004-08-20 23:09:47 +000014632 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014633static int
14634xmlSchemaCheckCTPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
14635 xmlSchemaTypePtr type)
William M. Brack2f2a6632004-08-20 23:09:47 +000014636{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014637 /*
14638 * TODO: Correct the error code; XML_SCHEMAP_SRC_CT_1 is used temporarily.
14639 *
14640 * SPEC (1) "The values of the properties of a complex type definition must
14641 * be as described in the property tableau in The Complex Type Definition
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014642 * Schema Component (§3.4.1), modulo the impact of Missing
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014643 * Sub-components (§5.3)."
14644 */
14645 if ((type->baseType != NULL) &&
14646 (IS_SIMPLE_TYPE(type->baseType)) &&
14647 ((type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) == 0)) {
14648 /*
14649 * SPEC (2) "If the {base type definition} is a simple type definition,
14650 * the {derivation method} must be extension."
14651 */
14652 xmlSchemaPCustomErr(pctxt,
14653 XML_SCHEMAP_SRC_CT_1,
14654 NULL, type, NULL,
14655 "If the base type is a simple type, the derivation method must be "
14656 "'extension'", NULL);
14657 return (XML_SCHEMAP_SRC_CT_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014658 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014659 /*
14660 * SPEC (3) "Circular definitions are disallowed, except for the ·ur-type
14661 * definition·. That is, it must be possible to reach the ·ur-type
14662 * definition by repeatedly following the {base type definition}."
14663 *
14664 * NOTE (3) is done in xmlSchemaCheckTypeDefCircular().
14665 *
14666 * SPEC (4) "Two distinct attribute declarations in the {attribute uses}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014667 * must not have identical {name}s and {target namespace}s."
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014668 * SPEC (5) "Two distinct attribute declarations in the {attribute uses}
14669 * must not have {type definition}s which are or are derived from ID."
14670 *
14671 * NOTE (4) and (5) are done in xmlSchemaBuildAttributeValidation().
14672 */
14673 return (0);
William M. Brack2f2a6632004-08-20 23:09:47 +000014674}
14675
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014676static int
14677xmlSchemaAreEqualTypes(xmlSchemaTypePtr typeA,
14678 xmlSchemaTypePtr typeB)
14679{
14680 /*
14681 * TODO: This should implement component-identity
14682 * in the future.
14683 */
14684 if ((typeA == NULL) || (typeB == NULL))
14685 return (0);
14686 return (typeA == typeB);
14687}
14688
14689/**
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000014690 * xmlSchemaCheckCOSCTDerivedOK:
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014691 * @ctxt: the schema parser context
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000014692 * @type: the to-be derived complex type definition
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014693 * @baseType: the base complex type definition
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000014694 * @set: the given set
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014695 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014696 * Schema Component Constraint:
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014697 * Type Derivation OK (Complex) (cos-ct-derived-ok)
14698 *
14699 * STATUS: completed
14700 *
14701 * Returns 0 if the constraints are satisfied, or 1
14702 * if not.
14703 */
14704static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014705xmlSchemaCheckCOSCTDerivedOK(xmlSchemaTypePtr type,
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014706 xmlSchemaTypePtr baseType,
14707 int set)
14708{
14709 int equal = xmlSchemaAreEqualTypes(type, baseType);
14710 /* TODO: Error codes. */
14711 /*
14712 * SPEC "For a complex type definition (call it D, for derived)
14713 * to be validly derived from a type definition (call this
14714 * B, for base) given a subset of {extension, restriction}
14715 * all of the following must be true:"
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014716 */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014717 if (! equal) {
14718 /*
14719 * SPEC (1) "If B and D are not the same type definition, then the
14720 * {derivation method} of D must not be in the subset."
14721 */
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014722 if (((set & SUBSET_EXTENSION) &&
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014723 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION)) ||
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014724 ((set & SUBSET_RESTRICTION) &&
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014725 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION)))
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014726 return (1);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014727 } else {
14728 /*
14729 * SPEC (2.1) "B and D must be the same type definition."
14730 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014731 return (0);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014732 }
14733 /*
14734 * SPEC (2.2) "B must be D's {base type definition}."
14735 */
14736 if (type->baseType == baseType)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014737 return (0);
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014738 /*
14739 * SPEC (2.3.1) "D's {base type definition} must not be the ·ur-type
14740 * definition·."
14741 */
14742 if (IS_ANYTYPE(type->baseType))
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000014743 return (1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014744
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014745 if (IS_COMPLEX_TYPE(type->baseType)) {
14746 /*
14747 * SPEC (2.3.2.1) "If D's {base type definition} is complex, then it
14748 * must be validly derived from B given the subset as defined by this
14749 * constraint."
14750 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014751 return (xmlSchemaCheckCOSCTDerivedOK(type->baseType,
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014752 baseType, set));
14753 } else {
14754 /*
14755 * SPEC (2.3.2.2) "If D's {base type definition} is simple, then it
14756 * must be validly derived from B given the subset as defined in Type
14757 * Derivation OK (Simple) (§3.14.6).
14758 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014759 return (xmlSchemaCheckCOSSTDerivedOK(type->baseType, baseType, set));
14760 }
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014761}
14762
14763/**
14764 * xmlSchemaCheckCOSDerivedOK:
14765 * @type: the derived simple type definition
14766 * @baseType: the base type definition
14767 *
14768 * Calls:
14769 * Type Derivation OK (Simple) AND Type Derivation OK (Complex)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014770 *
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014771 * Checks wheter @type can be validly derived from @baseType.
14772 *
14773 * Returns 0 on success, an positive error code otherwise.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014774 */
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014775static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014776xmlSchemaCheckCOSDerivedOK(xmlSchemaTypePtr type,
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000014777 xmlSchemaTypePtr baseType,
14778 int set)
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014779{
14780 if (IS_SIMPLE_TYPE(type))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014781 return (xmlSchemaCheckCOSSTDerivedOK(type, baseType, set));
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014782 else
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014783 return (xmlSchemaCheckCOSCTDerivedOK(type, baseType, set));
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000014784}
14785
William M. Brack2f2a6632004-08-20 23:09:47 +000014786/**
14787 * xmlSchemaCheckCOSCTExtends:
14788 * @ctxt: the schema parser context
14789 * @type: the complex type definition
14790 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014791 * (3.4.6) Constraints on Complex Type Definition Schema Components
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014792 * Schema Component Constraint:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014793 * Derivation Valid (Extension) (cos-ct-extends)
14794 *
14795 * STATUS:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014796 * missing:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014797 * (1.5)
14798 * (1.4.3.2.2.2) "Particle Valid (Extension)", which is not really needed.
William M. Brack2f2a6632004-08-20 23:09:47 +000014799 *
14800 * Returns 0 if the constraints are satisfied, a positive
14801 * error code if not and -1 if an internal error occured.
14802 */
14803static int
14804xmlSchemaCheckCOSCTExtends(xmlSchemaParserCtxtPtr ctxt,
14805 xmlSchemaTypePtr type)
14806{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014807 xmlSchemaTypePtr base = type->baseType;
14808 /*
14809 * TODO: Correct the error code; XML_SCHEMAP_COS_CT_EXTENDS_1_1 is used
14810 * temporarily only.
William M. Brack2f2a6632004-08-20 23:09:47 +000014811 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014812 /*
14813 * SPEC (1) "If the {base type definition} is a complex type definition,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014814 * then all of the following must be true:"
14815 */
Kasimier T. Buchcik11162b72005-07-28 00:50:22 +000014816 if (IS_COMPLEX_TYPE(base)) {
William M. Brack2f2a6632004-08-20 23:09:47 +000014817 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014818 * SPEC (1.1) "The {final} of the {base type definition} must not
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014819 * contain extension."
William M. Brack2f2a6632004-08-20 23:09:47 +000014820 */
14821 if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
14822 xmlSchemaPCustomErr(ctxt,
14823 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14824 NULL, type, NULL,
14825 "The 'final' of the base type definition "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014826 "contains 'extension'", NULL);
William M. Brack2f2a6632004-08-20 23:09:47 +000014827 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14828 }
14829 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014830 * SPEC (1.2) "Its {attribute uses} must be a subset of the {attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014831 * uses}
14832 * of the complex type definition itself, that is, for every attribute
14833 * use in the {attribute uses} of the {base type definition}, there
14834 * must be an attribute use in the {attribute uses} of the complex
14835 * type definition itself whose {attribute declaration} has the same
14836 * {name}, {target namespace} and {type definition} as its attribute
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014837 * declaration"
William M. Brack2f2a6632004-08-20 23:09:47 +000014838 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014839 * NOTE (1.2): This will be already satisfied by the way the attribute
14840 * uses are extended in xmlSchemaBuildAttributeValidation(); thus this
14841 * check is not needed.
William M. Brack2f2a6632004-08-20 23:09:47 +000014842 */
14843
14844 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014845 * SPEC (1.3) "If it has an {attribute wildcard}, the complex type
14846 * definition must also have one, and the base type definition's
14847 * {attribute wildcard}'s {namespace constraint} must be a subset
14848 * of the complex type definition's {attribute wildcard}'s {namespace
14849 * constraint}, as defined by Wildcard Subset (§3.10.6)."
William M. Brack2f2a6632004-08-20 23:09:47 +000014850 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014851 * NOTE (1.3) This is already checked in
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014852 * xmlSchemaBuildAttributeValidation; thus this check is not needed.
William M. Brack2f2a6632004-08-20 23:09:47 +000014853 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014854 * SPEC (1.4) "One of the following must be true:"
William M. Brack2f2a6632004-08-20 23:09:47 +000014855 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014856 if ((type->contentTypeDef != NULL) &&
14857 (type->contentTypeDef == base->contentTypeDef)) {
14858 /*
14859 * SPEC (1.4.1) "The {content type} of the {base type definition}
14860 * and the {content type} of the complex type definition itself
14861 * must be the same simple type definition"
14862 * PASS
14863 */
14864 } else if ((type->contentType == XML_SCHEMA_CONTENT_EMPTY) &&
14865 (base->contentType == XML_SCHEMA_CONTENT_EMPTY) ) {
14866 /*
14867 * SPEC (1.4.2) "The {content type} of both the {base type
14868 * definition} and the complex type definition itself must
14869 * be empty."
14870 * PASS
14871 */
14872 } else {
14873 /*
14874 * SPEC (1.4.3) "All of the following must be true:"
14875 */
14876 if (type->subtypes == NULL) {
14877 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014878 * SPEC 1.4.3.1 The {content type} of the complex type
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014879 * definition itself must specify a particle.
14880 */
14881 xmlSchemaPCustomErr(ctxt,
14882 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14883 NULL, type, NULL,
14884 "The content type must specify a particle", NULL);
14885 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14886 }
14887 /*
14888 * SPEC (1.4.3.2) "One of the following must be true:"
14889 */
14890 if (base->contentType == XML_SCHEMA_CONTENT_EMPTY) {
14891 /*
14892 * SPEC (1.4.3.2.1) "The {content type} of the {base type
14893 * definition} must be empty.
14894 * PASS
14895 */
14896 } else {
14897 /*
14898 * SPEC (1.4.3.2.2) "All of the following must be true:"
14899 */
14900 if ((type->contentType != base->contentType) ||
14901 ((type->contentType != XML_SCHEMA_CONTENT_MIXED) &&
14902 (type->contentType != XML_SCHEMA_CONTENT_ELEMENTS))) {
14903 /*
14904 * SPEC (1.4.3.2.2.1) "Both {content type}s must be mixed
14905 * or both must be element-only."
14906 */
14907 xmlSchemaPCustomErr(ctxt,
14908 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14909 NULL, type, NULL,
14910 "The content type of both, the type and its base "
14911 "type, must either 'mixed' or 'element-only'", NULL);
14912 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014913 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014914 /*
14915 * FUTURE TODO SPEC (1.4.3.2.2.2) "The particle of the
14916 * complex type definition must be a ·valid extension·
14917 * of the {base type definition}'s particle, as defined
14918 * in Particle Valid (Extension) (§3.9.6)."
14919 *
14920 * NOTE that we won't check "Particle Valid (Extension)",
14921 * since it is ensured by the derivation process in
14922 * xmlSchemaTypeFixup(). We need to implement this when heading
14923 * for a construction API
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014924 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014925 }
14926 /*
14927 * TODO (1.5)
14928 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014929 }
William M. Brack2f2a6632004-08-20 23:09:47 +000014930 } else {
14931 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014932 * SPEC (2) "If the {base type definition} is a simple type definition,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014933 * then all of the following must be true:"
William M. Brack2f2a6632004-08-20 23:09:47 +000014934 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014935 if (type->contentTypeDef != base) {
14936 /*
14937 * SPEC (2.1) "The {content type} must be the same simple type
14938 * definition."
14939 */
14940 xmlSchemaPCustomErr(ctxt,
14941 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14942 NULL, type, NULL,
14943 "The content type must be the simple base type", NULL);
14944 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
14945 }
14946 if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
14947 /*
14948 * SPEC (2.2) "The {final} of the {base type definition} must not
14949 * contain extension"
14950 * NOTE that this is the same as (1.1).
14951 */
14952 xmlSchemaPCustomErr(ctxt,
14953 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14954 NULL, type, NULL,
14955 "The 'final' of the base type definition "
14956 "contains 'extension'", NULL);
14957 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014958 }
William M. Brack2f2a6632004-08-20 23:09:47 +000014959 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014960 return (0);
William M. Brack2f2a6632004-08-20 23:09:47 +000014961}
14962
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014963/**
14964 * xmlSchemaCheckDerivationOKRestriction:
14965 * @ctxt: the schema parser context
14966 * @type: the complex type definition
14967 *
14968 * (3.4.6) Constraints on Complex Type Definition Schema Components
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014969 * Schema Component Constraint:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014970 * Derivation Valid (Restriction, Complex) (derivation-ok-restriction)
14971 *
14972 * STATUS:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014973 * missing:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014974 * (5.4.2), (5.2.2.1)
14975 *
14976 * Returns 0 if the constraints are satisfied, a positive
14977 * error code if not and -1 if an internal error occured.
14978 */
14979static int
14980xmlSchemaCheckDerivationOKRestriction(xmlSchemaParserCtxtPtr ctxt,
14981 xmlSchemaTypePtr type)
14982{
14983 xmlSchemaTypePtr base;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014984
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014985 /*
14986 * TODO: Correct the error code; XML_SCHEMAP_COS_CT_EXTENDS_1_1 is used
14987 * temporarily only.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000014988 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000014989 base = type->baseType;
14990 if (base->flags & XML_SCHEMAS_TYPE_FINAL_RESTRICTION) {
14991 /*
14992 * SPEC (1) "The {base type definition} must be a complex type
14993 * definition whose {final} does not contain restriction."
14994 */
14995 xmlSchemaPCustomErr(ctxt,
14996 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
14997 NULL, type, NULL,
14998 "The 'final' of the base type definition "
14999 "contains 'restriction'", NULL);
15000 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
15001 }
15002 /*
15003 * NOTE (3) and (4) are done in xmlSchemaBuildAttributeValidation().
15004 *
15005 * SPEC (5) "One of the following must be true:"
15006 */
15007 if (base->builtInType == XML_SCHEMAS_ANYTYPE) {
15008 /*
15009 * SPEC (5.1) "The {base type definition} must be the
15010 * ·ur-type definition·."
15011 * PASS
15012 */
15013 } else if ((type->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
15014 (type->contentType == XML_SCHEMA_CONTENT_BASIC)) {
15015 /*
15016 * SPEC (5.2.1) "The {content type} of the complex type definition
15017 * must be a simple type definition"
15018 *
15019 * SPEC (5.2.2) "One of the following must be true:"
15020 */
15021 if ((base->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
15022 (base->contentType == XML_SCHEMA_CONTENT_BASIC)) {
15023 /*
15024 * SPEC (5.2.2.1) "The {content type} of the {base type
15025 * definition} must be a simple type definition from which
15026 * the {content type} is validly derived given the empty
15027 * set as defined in Type Derivation OK (Simple) (§3.14.6)."
15028 * URGENT TODO
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015029 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015030 } else if ((base->contentType == XML_SCHEMA_CONTENT_MIXED) &&
15031 (xmlSchemaIsParticleEmptiable(
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015032 (xmlSchemaParticlePtr) base->subtypes))) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015033 /*
15034 * SPEC (5.2.2.2) "The {base type definition} must be mixed
15035 * and have a particle which is ·emptiable· as defined in
15036 * Particle Emptiable (§3.9.6)."
15037 * PASS
15038 */
15039 } else {
15040 xmlSchemaPCustomErr(ctxt,
15041 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
15042 NULL, type, NULL,
15043 "The content type of the base type must be either "
15044 "a simple type or 'mixed' and an emptiable particle", NULL);
15045 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
15046 }
15047 } else if (type->contentType == XML_SCHEMA_CONTENT_EMPTY) {
15048 /*
15049 * SPEC (5.3.1) "The {content type} of the complex type itself must
15050 * be empty"
15051 */
15052 if (base->contentType == XML_SCHEMA_CONTENT_EMPTY) {
15053 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015054 * SPEC (5.3.2.1) "The {content type} of the {base type
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015055 * definition} must also be empty."
15056 * PASS
15057 */
15058 } else if (((base->contentType == XML_SCHEMA_CONTENT_ELEMENTS) ||
15059 (base->contentType == XML_SCHEMA_CONTENT_MIXED)) &&
15060 xmlSchemaIsParticleEmptiable(
15061 (xmlSchemaParticlePtr) base->subtypes)) {
15062 /*
15063 * SPEC (5.3.2.2) "The {content type} of the {base type
15064 * definition} must be elementOnly or mixed and have a particle
15065 * which is ·emptiable· as defined in Particle Emptiable (§3.9.6)."
15066 * PASS
15067 */
15068 } else {
15069 xmlSchemaPCustomErr(ctxt,
15070 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
15071 NULL, type, NULL,
15072 "The content type of the base type must be either "
15073 "empty or 'mixed' (or 'elements-only') and an emptiable "
15074 "particle", NULL);
15075 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
15076 }
15077 } else if ((type->contentType == XML_SCHEMA_CONTENT_ELEMENTS) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015078 HAS_MIXED_CONTENT(type)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015079 /*
15080 * SPEC (5.4.1.1) "The {content type} of the complex type definition
15081 * itself must be element-only"
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015082 */
15083 if (HAS_MIXED_CONTENT(type) && (! HAS_MIXED_CONTENT(base))) {
15084 /*
15085 * SPEC (5.4.1.2) "The {content type} of the complex type
15086 * definition itself and of the {base type definition} must be
15087 * mixed"
15088 */
15089 xmlSchemaPCustomErr(ctxt,
15090 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
15091 NULL, type, NULL,
15092 "If the content type is 'mixed', then the content type of the "
15093 "base type must also be 'mixed'", NULL);
15094 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
15095 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015096 /*
15097 * SPEC (5.4.2) "The particle of the complex type definition itself
15098 * must be a ·valid restriction· of the particle of the {content
15099 * type} of the {base type definition} as defined in Particle Valid
15100 * (Restriction) (§3.9.6).
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015101 *
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015102 * URGENT TODO: (5.4.2)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015103 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015104 } else {
15105 xmlSchemaPCustomErr(ctxt,
15106 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
15107 NULL, type, NULL,
15108 "The type is not a valid restriction of its base type", NULL);
15109 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
15110 }
15111 return (0);
15112}
15113
15114/**
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015115 * xmlSchemaCheckCTComponent:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015116 * @ctxt: the schema parser context
15117 * @type: the complex type definition
15118 *
15119 * (3.4.6) Constraints on Complex Type Definition Schema Components
15120 *
15121 * Returns 0 if the constraints are satisfied, a positive
15122 * error code if not and -1 if an internal error occured.
15123 */
15124static int
15125xmlSchemaCheckCTComponent(xmlSchemaParserCtxtPtr ctxt,
15126 xmlSchemaTypePtr type)
15127{
15128 int ret;
15129 /*
15130 * Complex Type Definition Properties Correct
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015131 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015132 ret = xmlSchemaCheckCTPropsCorrect(ctxt, type);
15133 if (ret != 0)
15134 return (ret);
15135 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION)
15136 ret = xmlSchemaCheckCOSCTExtends(ctxt, type);
15137 else
15138 ret = xmlSchemaCheckDerivationOKRestriction(ctxt, type);
15139 return (ret);
15140}
15141
15142/**
15143 * xmlSchemaCheckSRCCT:
15144 * @ctxt: the schema parser context
15145 * @type: the complex type definition
15146 *
15147 * (3.4.3) Constraints on XML Representations of Complex Type Definitions:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015148 * Schema Representation Constraint:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015149 * Complex Type Definition Representation OK (src-ct)
15150 *
15151 * Returns 0 if the constraints are satisfied, a positive
15152 * error code if not and -1 if an internal error occured.
15153 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015154static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015155xmlSchemaCheckSRCCT(xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015156 xmlSchemaTypePtr type)
15157{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015158 xmlSchemaTypePtr base;
15159 int ret = 0;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015160
15161 /*
15162 * TODO: Adjust the error codes here, as I used
15163 * XML_SCHEMAP_SRC_CT_1 only yet.
15164 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015165 base = type->baseType;
Kasimier T. Buchcik5e371a02005-04-05 15:08:05 +000015166 if (! HAS_SIMPLE_CONTENT(type)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015167 /*
15168 * 1 If the <complexContent> alternative is chosen, the type definition
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015169 * ·resolved· to by the ·actual value· of the base [attribute]
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015170 * must be a complex type definition;
15171 */
15172 if (! IS_COMPLEX_TYPE(base)) {
15173 xmlChar *str = NULL;
15174 xmlSchemaPCustomErr(ctxt,
15175 XML_SCHEMAP_SRC_CT_1,
15176 NULL, type, type->node,
15177 "If using <complexContent>, the base type is expected to be "
15178 "a complex type. The base type '%s' is a simple type",
15179 xmlSchemaFormatQName(&str, base->targetNamespace,
15180 base->name));
15181 FREE_AND_NULL(str)
15182 return (XML_SCHEMAP_SRC_CT_1);
15183 }
15184 } else {
15185 /*
15186 * SPEC
15187 * 2 If the <simpleContent> alternative is chosen, all of the
15188 * following must be true:
15189 * 2.1 The type definition ·resolved· to by the ·actual value· of the
15190 * base [attribute] must be one of the following:
15191 */
15192 if (IS_SIMPLE_TYPE(base)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015193 if ((type->flags &
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015194 XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) == 0) {
15195 xmlChar *str = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015196 /*
15197 * 2.1.3 only if the <extension> alternative is also
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015198 * chosen, a simple type definition.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015199 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015200 /* TODO: Change error code to ..._SRC_CT_2_1_3. */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015201 xmlSchemaPCustomErr(ctxt,
15202 XML_SCHEMAP_SRC_CT_1,
15203 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015204 "If using <simpleContent> and <restriction>, the base "
15205 "type must be a complex type. The base type '%s' is "
15206 "a simple type",
15207 xmlSchemaFormatQName(&str, base->targetNamespace,
15208 base->name));
15209 FREE_AND_NULL(str)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015210 return (XML_SCHEMAP_SRC_CT_1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015211 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015212 } else {
15213 /* Base type is a complex type. */
15214 if ((base->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
15215 (base->contentType == XML_SCHEMA_CONTENT_BASIC)) {
15216 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015217 * 2.1.1 a complex type definition whose {content type} is a
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015218 * simple type definition;
15219 * PASS
15220 */
15221 if (base->contentTypeDef == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015222 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015223 NULL, type, NULL,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015224 "Internal error: xmlSchemaCheckSRCCT, "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015225 "'%s', base type has no content type",
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015226 type->name);
15227 return (-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015228 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015229 } else if ((base->contentType == XML_SCHEMA_CONTENT_MIXED) &&
15230 (type->flags &
15231 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION)) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015232
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015233 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015234 * 2.1.2 only if the <restriction> alternative is also
15235 * chosen, a complex type definition whose {content type}
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015236 * is mixed and a particle emptiable.
15237 */
15238 if (! xmlSchemaIsParticleEmptiable(
15239 (xmlSchemaParticlePtr) base->subtypes)) {
15240 ret = XML_SCHEMAP_SRC_CT_1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015241 } else
15242 /*
15243 * Attention: at this point the <simpleType> child is in
15244 * ->contentTypeDef (put there during parsing).
15245 */
15246 if (type->contentTypeDef == NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015247 xmlChar *str = NULL;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015248 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015249 * 2.2 If clause 2.1.2 above is satisfied, then there
15250 * must be a <simpleType> among the [children] of
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015251 * <restriction>.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015252 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015253 /* TODO: Change error code to ..._SRC_CT_2_2. */
15254 xmlSchemaPCustomErr(ctxt,
15255 XML_SCHEMAP_SRC_CT_1,
15256 NULL, type, NULL,
15257 "A <simpleType> is expected among the children "
15258 "of <restriction>, if <simpleContent> is used and "
15259 "the base type '%s' is a complex type",
15260 xmlSchemaFormatQName(&str, base->targetNamespace,
15261 base->name));
15262 FREE_AND_NULL(str)
15263 return (XML_SCHEMAP_SRC_CT_1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015264 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015265 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015266 ret = XML_SCHEMAP_SRC_CT_1;
15267 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015268 }
15269 if (ret > 0) {
15270 xmlChar *str = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015271 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015272 xmlSchemaPCustomErr(ctxt,
15273 XML_SCHEMAP_SRC_CT_1,
15274 NULL, type, NULL,
15275 "If <simpleContent> and <restriction> is used, the "
15276 "base type must be a simple type or a complex type with "
15277 "mixed content and particle emptiable. The base type "
15278 "'%s' is none of those",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015279 xmlSchemaFormatQName(&str, base->targetNamespace,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015280 base->name));
15281 } else {
15282 xmlSchemaPCustomErr(ctxt,
15283 XML_SCHEMAP_SRC_CT_1,
15284 NULL, type, NULL,
15285 "If <simpleContent> and <extension> is used, the "
15286 "base type must be a simple type. The base type '%s' "
15287 "is a complex type",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015288 xmlSchemaFormatQName(&str, base->targetNamespace,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015289 base->name));
15290 }
15291 FREE_AND_NULL(str)
15292 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015293 }
15294 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015295 * SPEC (3) "The corresponding complex type definition component must
15296 * satisfy the conditions set out in Constraints on Complex Type
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015297 * Definition Schema Components (§3.4.6);"
15298 * NOTE (3) will be done in xmlSchemaTypeFixup().
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015299 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015300 /*
15301 * SPEC (4) If clause 2.2.1 or clause 2.2.2 in the correspondence specification
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015302 * above for {attribute wildcard} is satisfied, the intensional
15303 * intersection must be expressible, as defined in Attribute Wildcard
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015304 * Intersection (§3.10.6).
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015305 * NOTE (4) is done in xmlSchemaBuildAttributeValidation().
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015306 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015307 return (ret);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015308}
William M. Brack2f2a6632004-08-20 23:09:47 +000015309
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015310#ifdef ENABLE_PARTICLE_RESTRICTION
15311/**
15312 * xmlSchemaCheckParticleRangeOK:
15313 * @ctxt: the schema parser context
15314 * @type: the complex type definition
15315 *
15316 * (3.9.6) Constraints on Particle Schema Components
15317 * Schema Component Constraint:
15318 * Occurrence Range OK (range-ok)
15319 *
15320 * STATUS: complete
15321 *
15322 * Returns 0 if the constraints are satisfied, a positive
15323 * error code if not and -1 if an internal error occured.
15324 */
15325static int
15326xmlSchemaCheckParticleRangeOK(int rmin, int rmax,
15327 int bmin, int bmax)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015328{
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015329 if (rmin < bmin)
15330 return (1);
15331 if ((bmax != UNBOUNDED) &&
15332 (rmax > bmax))
15333 return (1);
15334 return (0);
15335}
15336
15337/**
15338 * xmlSchemaCheckRCaseNameAndTypeOK:
15339 * @ctxt: the schema parser context
15340 * @r: the restricting element declaration particle
15341 * @b: the base element declaration particle
15342 *
15343 * (3.9.6) Constraints on Particle Schema Components
15344 * Schema Component Constraint:
15345 * Particle Restriction OK (Elt:Elt -- NameAndTypeOK)
15346 * (rcase-NameAndTypeOK)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015347 *
15348 * STATUS:
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015349 * MISSING (3.2.3)
15350 * CLARIFY: (3.2.2)
15351 *
15352 * Returns 0 if the constraints are satisfied, a positive
15353 * error code if not and -1 if an internal error occured.
15354 */
15355static int
15356xmlSchemaCheckRCaseNameAndTypeOK(xmlSchemaParserCtxtPtr ctxt,
15357 xmlSchemaParticlePtr r,
15358 xmlSchemaParticlePtr b)
15359{
15360 xmlSchemaElementPtr elemR, elemB;
15361
15362 /* TODO: Error codes (rcase-NameAndTypeOK). */
15363 elemR = (xmlSchemaElementPtr) r->children;
15364 elemB = (xmlSchemaElementPtr) b->children;
15365 /*
15366 * SPEC (1) "The declarations' {name}s and {target namespace}s are
15367 * the same."
15368 */
15369 if ((elemR != elemB) &&
15370 ((! xmlStrEqual(elemR->name, elemB->name)) ||
15371 (! xmlStrEqual(elemR->targetNamespace, elemB->targetNamespace))))
15372 return (1);
15373 /*
15374 * SPEC (2) "R's occurrence range is a valid restriction of B's
15375 * occurrence range as defined by Occurrence Range OK (§3.9.6)."
15376 */
15377 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
15378 b->minOccurs, b->maxOccurs) != 0)
15379 return (1);
15380 /*
15381 * SPEC (3.1) "Both B's declaration's {scope} and R's declaration's
15382 * {scope} are global."
15383 */
15384 if (elemR == elemB)
15385 return (0);
15386 /*
15387 * SPEC (3.2.1) "Either B's {nillable} is true or R's {nillable} is false."
15388 */
15389 if (((elemB->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) &&
15390 (elemR->flags & XML_SCHEMAS_ELEM_NILLABLE))
15391 return (1);
15392 /*
15393 * SPEC (3.2.2) "either B's declaration's {value constraint} is absent,
15394 * or is not fixed, or R's declaration's {value constraint} is fixed
15395 * with the same value."
15396 */
15397 if ((elemB->value != NULL) && (elemB->flags & XML_SCHEMAS_ELEM_FIXED) &&
15398 ((elemR->value == NULL) ||
15399 ((elemR->flags & XML_SCHEMAS_ELEM_FIXED) == 0) ||
15400 /* TODO: Equality of the initial value or normalized or canonical? */
15401 (! xmlStrEqual(elemR->value, elemB->value))))
15402 return (1);
15403 /*
15404 * TODO: SPEC (3.2.3) "R's declaration's {identity-constraint
15405 * definitions} is a subset of B's declaration's {identity-constraint
15406 * definitions}, if any."
15407 */
15408 if (elemB->idcs != NULL) {
15409 /* TODO */
15410 }
15411 /*
15412 * SPEC (3.2.4) "R's declaration's {disallowed substitutions} is a
15413 * superset of B's declaration's {disallowed substitutions}."
15414 */
15415 if (((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) &&
15416 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) == 0)) ||
15417 ((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) &&
15418 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) == 0)) ||
15419 ((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION) &&
15420 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION) == 0)))
15421 return (1);
15422 /*
15423 * SPEC (3.2.5) "R's {type definition} is validly derived given
15424 * {extension, list, union} from B's {type definition}"
15425 *
15426 * BADSPEC TODO: What's the point of adding "list" and "union" to the
15427 * set, if the corresponding constraints handle "restriction" and
15428 * "extension" only?
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015429 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015430 */
15431 {
15432 int set = 0;
15433
15434 set |= SUBSET_EXTENSION;
15435 set |= SUBSET_LIST;
15436 set |= SUBSET_UNION;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015437 if (xmlSchemaCheckCOSDerivedOK(elemR->subtypes,
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015438 elemB->subtypes, set) != 0)
15439 return (1);
15440 }
15441 return (0);
15442}
15443
15444/**
15445 * xmlSchemaCheckRCaseNSCompat:
15446 * @ctxt: the schema parser context
15447 * @r: the restricting element declaration particle
15448 * @b: the base wildcard particle
15449 *
15450 * (3.9.6) Constraints on Particle Schema Components
15451 * Schema Component Constraint:
15452 * Particle Derivation OK (Elt:Any -- NSCompat)
15453 * (rcase-NSCompat)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015454 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015455 * STATUS: complete
15456 *
15457 * Returns 0 if the constraints are satisfied, a positive
15458 * error code if not and -1 if an internal error occured.
15459 */
15460static int
15461xmlSchemaCheckRCaseNSCompat(xmlSchemaParserCtxtPtr ctxt,
15462 xmlSchemaParticlePtr r,
15463 xmlSchemaParticlePtr b)
15464{
15465 /* TODO:Error codes (rcase-NSCompat). */
15466 /*
15467 * SPEC "For an element declaration particle to be a ·valid restriction·
15468 * of a wildcard particle all of the following must be true:"
15469 *
15470 * SPEC (1) "The element declaration's {target namespace} is ·valid·
15471 * with respect to the wildcard's {namespace constraint} as defined by
15472 * Wildcard allows Namespace Name (§3.10.4)."
15473 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015474 if (xmlSchemaCheckCVCWildcardNamespace((xmlSchemaWildcardPtr) b->children,
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015475 ((xmlSchemaElementPtr) r->children)->targetNamespace) != 0)
15476 return (1);
15477 /*
15478 * SPEC (2) "R's occurrence range is a valid restriction of B's
15479 * occurrence range as defined by Occurrence Range OK (§3.9.6)."
15480 */
15481 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
15482 b->minOccurs, b->maxOccurs) != 0)
15483 return (1);
15484
15485 return (0);
15486}
15487
15488/**
15489 * xmlSchemaCheckRCaseRecurseAsIfGroup:
15490 * @ctxt: the schema parser context
15491 * @r: the restricting element declaration particle
15492 * @b: the base model group particle
15493 *
15494 * (3.9.6) Constraints on Particle Schema Components
15495 * Schema Component Constraint:
15496 * Particle Derivation OK (Elt:All/Choice/Sequence -- RecurseAsIfGroup)
15497 * (rcase-RecurseAsIfGroup)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015498 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015499 * STATUS: TODO
15500 *
15501 * Returns 0 if the constraints are satisfied, a positive
15502 * error code if not and -1 if an internal error occured.
15503 */
15504static int
15505xmlSchemaCheckRCaseRecurseAsIfGroup(xmlSchemaParserCtxtPtr ctxt,
15506 xmlSchemaParticlePtr r,
15507 xmlSchemaParticlePtr b)
15508{
15509 /* TODO: Error codes (rcase-RecurseAsIfGroup). */
15510 TODO
15511 return (0);
15512}
15513
15514/**
15515 * xmlSchemaCheckRCaseNSSubset:
15516 * @ctxt: the schema parser context
15517 * @r: the restricting wildcard particle
15518 * @b: the base wildcard particle
15519 *
15520 * (3.9.6) Constraints on Particle Schema Components
15521 * Schema Component Constraint:
15522 * Particle Derivation OK (Any:Any -- NSSubset)
15523 * (rcase-NSSubset)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015524 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015525 * STATUS: complete
15526 *
15527 * Returns 0 if the constraints are satisfied, a positive
15528 * error code if not and -1 if an internal error occured.
15529 */
15530static int
15531xmlSchemaCheckRCaseNSSubset(xmlSchemaParserCtxtPtr ctxt,
15532 xmlSchemaParticlePtr r,
15533 xmlSchemaParticlePtr b,
15534 int isAnyTypeBase)
15535{
15536 /* TODO: Error codes (rcase-NSSubset). */
15537 /*
15538 * SPEC (1) "R's occurrence range is a valid restriction of B's
15539 * occurrence range as defined by Occurrence Range OK (§3.9.6)."
15540 */
15541 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
15542 b->minOccurs, b->maxOccurs))
15543 return (1);
15544 /*
15545 * SPEC (2) "R's {namespace constraint} must be an intensional subset
15546 * of B's {namespace constraint} as defined by Wildcard Subset (§3.10.6)."
15547 */
15548 if (xmlSchemaCheckCOSNSSubset((xmlSchemaWildcardPtr) r->children,
15549 (xmlSchemaWildcardPtr) b->children))
15550 return (1);
15551 /*
15552 * SPEC (3) "Unless B is the content model wildcard of the ·ur-type
15553 * definition·, R's {process contents} must be identical to or stronger
15554 * than B's {process contents}, where strict is stronger than lax is
15555 * stronger than skip."
15556 */
15557 if (! isAnyTypeBase) {
15558 if ( ((xmlSchemaWildcardPtr) r->children)->processContents <
15559 ((xmlSchemaWildcardPtr) b->children)->processContents)
15560 return (1);
15561 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015562
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015563 return (0);
15564}
15565
15566/**
15567 * xmlSchemaCheckCOSParticleRestrict:
15568 * @ctxt: the schema parser context
15569 * @type: the complex type definition
15570 *
15571 * (3.9.6) Constraints on Particle Schema Components
15572 * Schema Component Constraint:
15573 * Particle Valid (Restriction) (cos-particle-restrict)
15574 *
15575 * STATUS: TODO
15576 *
15577 * Returns 0 if the constraints are satisfied, a positive
15578 * error code if not and -1 if an internal error occured.
15579 */
15580static int
15581xmlSchemaCheckCOSParticleRestrict(xmlSchemaParserCtxtPtr ctxt,
15582 xmlSchemaParticlePtr r,
15583 xmlSchemaParticlePtr b)
15584{
15585 int ret = 0;
15586
15587 /*part = GET_PARTICLE(type);
15588 basePart = GET_PARTICLE(base);
15589 */
15590
15591 TODO
15592
15593 /*
15594 * SPEC (1) "They are the same particle."
15595 */
15596 if (r == b)
15597 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015598
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015599
15600 return (0);
15601}
15602
15603/**
15604 * xmlSchemaCheckRCaseNSRecurseCheckCardinality:
15605 * @ctxt: the schema parser context
15606 * @r: the model group particle
15607 * @b: the base wildcard particle
15608 *
15609 * (3.9.6) Constraints on Particle Schema Components
15610 * Schema Component Constraint:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015611 * Particle Derivation OK (All/Choice/Sequence:Any --
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015612 * NSRecurseCheckCardinality)
15613 * (rcase-NSRecurseCheckCardinality)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015614 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015615 * STATUS: TODO: subst-groups
15616 *
15617 * Returns 0 if the constraints are satisfied, a positive
15618 * error code if not and -1 if an internal error occured.
15619 */
15620static int
15621xmlSchemaCheckRCaseNSRecurseCheckCardinality(xmlSchemaParserCtxtPtr ctxt,
15622 xmlSchemaParticlePtr r,
15623 xmlSchemaParticlePtr b)
15624{
15625 xmlSchemaParticlePtr part;
15626 /* TODO: Error codes (rcase-NSRecurseCheckCardinality). */
15627 if ((r->children == NULL) || (r->children->children == NULL))
15628 return (-1);
15629 /*
15630 * SPEC "For a group particle to be a ·valid restriction· of a
15631 * wildcard particle..."
15632 *
15633 * SPEC (1) "Every member of the {particles} of the group is a ·valid
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015634 * restriction· of the wildcard as defined by
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015635 * Particle Valid (Restriction) (§3.9.6)."
15636 */
15637 part = (xmlSchemaParticlePtr) r->children->children;
15638 do {
15639 if (xmlSchemaCheckCOSParticleRestrict(ctxt, part, b))
15640 return (1);
15641 part = (xmlSchemaParticlePtr) part->next;
15642 } while (part != NULL);
15643 /*
15644 * SPEC (2) "The effective total range of the group [...] is a
15645 * valid restriction of B's occurrence range as defined by
15646 * Occurrence Range OK (§3.9.6)."
15647 */
15648 if (xmlSchemaCheckParticleRangeOK(
15649 xmlSchemaGetParticleTotalRangeMin(r),
15650 xmlSchemaGetParticleTotalRangeMax(r),
15651 b->minOccurs, b->maxOccurs) != 0)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015652 return (1);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015653 return (0);
15654}
15655
15656/**
15657 * xmlSchemaCheckRCaseRecurse:
15658 * @ctxt: the schema parser context
15659 * @r: the <all> or <sequence> model group particle
15660 * @b: the base <all> or <sequence> model group particle
15661 *
15662 * (3.9.6) Constraints on Particle Schema Components
15663 * Schema Component Constraint:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015664 * Particle Derivation OK (All:All,Sequence:Sequence --
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015665 Recurse)
15666 * (rcase-Recurse)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015667 *
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015668 * STATUS: ?
15669 * TODO: subst-groups
15670 *
15671 * Returns 0 if the constraints are satisfied, a positive
15672 * error code if not and -1 if an internal error occured.
15673 */
15674static int
15675xmlSchemaCheckRCaseRecurse(xmlSchemaParserCtxtPtr ctxt,
15676 xmlSchemaParticlePtr r,
15677 xmlSchemaParticlePtr b)
15678{
15679 /* xmlSchemaParticlePtr part; */
15680 /* TODO: Error codes (rcase-Recurse). */
15681 if ((r->children == NULL) || (b->children == NULL) ||
15682 (r->children->type != b->children->type))
15683 return (-1);
15684 /*
15685 * SPEC "For an all or sequence group particle to be a ·valid
15686 * restriction· of another group particle with the same {compositor}..."
15687 *
15688 * SPEC (1) "R's occurrence range is a valid restriction of B's
15689 * occurrence range as defined by Occurrence Range OK (§3.9.6)."
15690 */
15691 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
15692 b->minOccurs, b->maxOccurs))
15693 return (1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015694
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000015695
15696 return (0);
15697}
15698
15699#endif
15700
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015701#define FACET_RESTR_MUTUAL_ERR(fac1, fac2) \
15702 xmlSchemaPCustomErrExt(pctxt, \
15703 XML_SCHEMAP_INVALID_FACET_VALUE, \
15704 NULL, (xmlSchemaTypePtr) fac1, fac1->node, \
15705 "It is an error for both '%s' and '%s' to be specified on the "\
15706 "same type definition", \
15707 BAD_CAST xmlSchemaFacetTypeToString(fac1->type), \
15708 BAD_CAST xmlSchemaFacetTypeToString(fac2->type), NULL);
15709
15710#define FACET_RESTR_ERR(fac1, msg) \
15711 xmlSchemaPCustomErr(pctxt, \
15712 XML_SCHEMAP_INVALID_FACET_VALUE, \
15713 NULL, (xmlSchemaTypePtr) fac1, fac1->node, \
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015714 msg, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015715
15716#define FACET_RESTR_FIXED_ERR(fac) \
15717 xmlSchemaPCustomErr(pctxt, \
15718 XML_SCHEMAP_INVALID_FACET_VALUE, \
15719 NULL, (xmlSchemaTypePtr) fac, fac->node, \
15720 "The base type's facet is 'fixed', thus the value must not " \
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015721 "differ", NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015722
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000015723static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015724xmlSchemaDeriveFacetErr(xmlSchemaParserCtxtPtr pctxt,
15725 xmlSchemaFacetPtr facet1,
15726 xmlSchemaFacetPtr facet2,
15727 int lessGreater,
15728 int orEqual,
15729 int ofBase)
15730{
15731 xmlChar *msg = NULL;
15732
15733 msg = xmlStrdup(BAD_CAST "'");
15734 msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facet1->type));
15735 msg = xmlStrcat(msg, BAD_CAST "' has to be");
15736 if (lessGreater == 0)
15737 msg = xmlStrcat(msg, BAD_CAST " equal to");
15738 if (lessGreater == 1)
15739 msg = xmlStrcat(msg, BAD_CAST " greater than");
15740 else
15741 msg = xmlStrcat(msg, BAD_CAST " less than");
15742
15743 if (orEqual)
15744 msg = xmlStrcat(msg, BAD_CAST " or equal to");
15745 msg = xmlStrcat(msg, BAD_CAST " '");
15746 msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facet2->type));
15747 if (ofBase)
15748 msg = xmlStrcat(msg, BAD_CAST "' of the base type");
15749 else
15750 msg = xmlStrcat(msg, BAD_CAST "'");
15751
15752 xmlSchemaPCustomErr(pctxt,
15753 XML_SCHEMAP_INVALID_FACET_VALUE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015754 NULL, (xmlSchemaTypePtr) facet1, facet1->node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015755 (const char *) msg, NULL);
15756
15757 if (msg != NULL)
15758 xmlFree(msg);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000015759}
15760
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015761static int
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015762xmlSchemaDeriveAndValidateFacets(xmlSchemaParserCtxtPtr pctxt,
15763 xmlSchemaTypePtr type)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015764{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015765 xmlSchemaTypePtr base = type->baseType;
15766 xmlSchemaFacetLinkPtr link, cur, last = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015767 xmlSchemaFacetPtr facet, bfacet,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015768 flength = NULL, ftotdig = NULL, ffracdig = NULL,
15769 fmaxlen = NULL, fminlen = NULL, /* facets of the current type */
15770 fmininc = NULL, fmaxinc = NULL,
15771 fminexc = NULL, fmaxexc = NULL,
15772 bflength = NULL, bftotdig = NULL, bffracdig = NULL,
15773 bfmaxlen = NULL, bfminlen = NULL, /* facets of the base type */
15774 bfmininc = NULL, bfmaxinc = NULL,
15775 bfminexc = NULL, bfmaxexc = NULL;
15776 int res, err = 0, fixedErr;
15777 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015778 * 3 The {facets} of R are the union of S and the {facets}
15779 * of B, eliminating duplicates. To eliminate duplicates,
15780 * when a facet of the same kind occurs in both S and the
15781 * {facets} of B, the one in the {facets} of B is not
15782 * included, with the exception of enumeration and pattern
15783 * facets, for which multiple occurrences with distinct values
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015784 * are allowed.
15785 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015786
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015787 if ((type->facetSet == NULL) && (base->facetSet == NULL))
15788 return (0);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015789
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015790 last = type->facetSet;
15791 if (last != NULL)
15792 while (last->next != NULL)
15793 last = last->next;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015794
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015795 for (cur = type->facetSet; cur != NULL; cur = cur->next) {
15796 facet = cur->facet;
15797 switch (facet->type) {
15798 case XML_SCHEMA_FACET_LENGTH:
15799 flength = facet; break;
15800 case XML_SCHEMA_FACET_MINLENGTH:
15801 fminlen = facet; break;
15802 case XML_SCHEMA_FACET_MININCLUSIVE:
15803 fmininc = facet; break;
15804 case XML_SCHEMA_FACET_MINEXCLUSIVE:
15805 fminexc = facet; break;
15806 case XML_SCHEMA_FACET_MAXLENGTH:
15807 fmaxlen = facet; break;
15808 case XML_SCHEMA_FACET_MAXINCLUSIVE:
15809 fmaxinc = facet; break;
15810 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
15811 fmaxexc = facet; break;
15812 case XML_SCHEMA_FACET_TOTALDIGITS:
15813 ftotdig = facet; break;
15814 case XML_SCHEMA_FACET_FRACTIONDIGITS:
15815 ffracdig = facet; break;
15816 default:
15817 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015818 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015819 }
15820 for (cur = base->facetSet; cur != NULL; cur = cur->next) {
15821 facet = cur->facet;
15822 switch (facet->type) {
15823 case XML_SCHEMA_FACET_LENGTH:
15824 bflength = facet; break;
15825 case XML_SCHEMA_FACET_MINLENGTH:
15826 bfminlen = facet; break;
15827 case XML_SCHEMA_FACET_MININCLUSIVE:
15828 bfmininc = facet; break;
15829 case XML_SCHEMA_FACET_MINEXCLUSIVE:
15830 bfminexc = facet; break;
15831 case XML_SCHEMA_FACET_MAXLENGTH:
15832 bfmaxlen = facet; break;
15833 case XML_SCHEMA_FACET_MAXINCLUSIVE:
15834 bfmaxinc = facet; break;
15835 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
15836 bfmaxexc = facet; break;
15837 case XML_SCHEMA_FACET_TOTALDIGITS:
15838 bftotdig = facet; break;
15839 case XML_SCHEMA_FACET_FRACTIONDIGITS:
15840 bffracdig = facet; break;
15841 default:
15842 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015843 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015844 }
15845 err = 0;
15846 /*
15847 * length and minLength or maxLength (2.2) + (3.2)
15848 */
15849 if (flength && (fminlen || fmaxlen)) {
15850 FACET_RESTR_ERR(flength, "It is an error for both 'length' and "
15851 "either of 'minLength' or 'maxLength' to be specified on "
15852 "the same type definition")
15853 }
15854 /*
15855 * Mutual exclusions in the same derivation step.
15856 */
15857 if ((fmaxinc) && (fmaxexc)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015858 /*
15859 * SCC "maxInclusive and maxExclusive"
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015860 */
15861 FACET_RESTR_MUTUAL_ERR(fmaxinc, fmaxexc)
15862 }
15863 if ((fmininc) && (fminexc)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015864 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015865 * SCC "minInclusive and minExclusive"
15866 */
15867 FACET_RESTR_MUTUAL_ERR(fmininc, fminexc)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000015868 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015869
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015870 if (flength && bflength) {
15871 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015872 * SCC "length valid restriction"
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015873 * The values have to be equal.
15874 */
15875 res = xmlSchemaCompareValues(flength->val, bflength->val);
15876 if (res == -2)
15877 goto internal_error;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015878 if (res != 0)
15879 xmlSchemaDeriveFacetErr(pctxt, flength, bflength, 0, 0, 1);
15880 if ((res != 0) && (bflength->fixed)) {
15881 FACET_RESTR_FIXED_ERR(flength)
15882 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015883
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015884 }
15885 if (fminlen && bfminlen) {
15886 /*
15887 * SCC "minLength valid restriction"
15888 * minLength >= BASE minLength
15889 */
15890 res = xmlSchemaCompareValues(fminlen->val, bfminlen->val);
15891 if (res == -2)
15892 goto internal_error;
15893 if (res == -1)
15894 xmlSchemaDeriveFacetErr(pctxt, fminlen, bfminlen, 1, 1, 1);
15895 if ((res != 0) && (bfminlen->fixed)) {
15896 FACET_RESTR_FIXED_ERR(fminlen)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015897 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015898 }
15899 if (fmaxlen && bfmaxlen) {
15900 /*
15901 * SCC "maxLength valid restriction"
15902 * maxLength <= BASE minLength
15903 */
15904 res = xmlSchemaCompareValues(fmaxlen->val, bfmaxlen->val);
15905 if (res == -2)
15906 goto internal_error;
15907 if (res == 1)
15908 xmlSchemaDeriveFacetErr(pctxt, fmaxlen, bfmaxlen, -1, 1, 1);
15909 if ((res != 0) && (bfmaxlen->fixed)) {
15910 FACET_RESTR_FIXED_ERR(fmaxlen)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015911 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015912 }
15913 /*
15914 * SCC "length and minLength or maxLength"
15915 */
15916 if (! flength)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015917 flength = bflength;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015918 if (flength) {
15919 if (! fminlen)
15920 flength = bflength;
15921 if (fminlen) {
15922 /* (1.1) length >= minLength */
15923 res = xmlSchemaCompareValues(flength->val, fminlen->val);
15924 if (res == -2)
15925 goto internal_error;
15926 if (res == -1)
15927 xmlSchemaDeriveFacetErr(pctxt, flength, fminlen, 1, 1, 0);
15928 }
15929 if (! fmaxlen)
15930 fmaxlen = bfmaxlen;
15931 if (fmaxlen) {
15932 /* (2.1) length <= maxLength */
15933 res = xmlSchemaCompareValues(flength->val, fmaxlen->val);
15934 if (res == -2)
15935 goto internal_error;
15936 if (res == 1)
15937 xmlSchemaDeriveFacetErr(pctxt, flength, fmaxlen, -1, 1, 0);
15938 }
15939 }
15940 if (fmaxinc) {
15941 /*
15942 * "maxInclusive"
15943 */
15944 if (fmininc) {
15945 /* SCC "maxInclusive >= minInclusive" */
15946 res = xmlSchemaCompareValues(fmaxinc->val, fmininc->val);
15947 if (res == -2)
15948 goto internal_error;
15949 if (res == -1) {
15950 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, fmininc, 1, 1, 0);
15951 }
15952 }
15953 /*
15954 * SCC "maxInclusive valid restriction"
15955 */
15956 if (bfmaxinc) {
15957 /* maxInclusive <= BASE maxInclusive */
15958 res = xmlSchemaCompareValues(fmaxinc->val, bfmaxinc->val);
15959 if (res == -2)
15960 goto internal_error;
15961 if (res == 1)
15962 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmaxinc, -1, 1, 1);
15963 if ((res != 0) && (bfmaxinc->fixed)) {
15964 FACET_RESTR_FIXED_ERR(fmaxinc)
15965 }
15966 }
15967 if (bfmaxexc) {
15968 /* maxInclusive < BASE maxExclusive */
15969 res = xmlSchemaCompareValues(fmaxinc->val, bfmaxexc->val);
15970 if (res == -2)
15971 goto internal_error;
15972 if (res != -1) {
15973 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmaxexc, -1, 0, 1);
15974 }
15975 }
15976 if (bfmininc) {
15977 /* maxInclusive >= BASE minInclusive */
15978 res = xmlSchemaCompareValues(fmaxinc->val, bfmininc->val);
15979 if (res == -2)
15980 goto internal_error;
15981 if (res == -1) {
15982 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmininc, 1, 1, 1);
15983 }
15984 }
15985 if (bfminexc) {
15986 /* maxInclusive > BASE minExclusive */
15987 res = xmlSchemaCompareValues(fmaxinc->val, bfminexc->val);
15988 if (res == -2)
15989 goto internal_error;
15990 if (res != 1) {
15991 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfminexc, 1, 0, 1);
15992 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000015993 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000015994 }
15995 if (fmaxexc) {
15996 /*
15997 * "maxExclusive >= minExclusive"
15998 */
15999 if (fminexc) {
16000 res = xmlSchemaCompareValues(fmaxexc->val, fminexc->val);
16001 if (res == -2)
16002 goto internal_error;
16003 if (res == -1) {
16004 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, fminexc, 1, 1, 0);
16005 }
16006 }
16007 /*
16008 * "maxExclusive valid restriction"
16009 */
16010 if (bfmaxexc) {
16011 /* maxExclusive <= BASE maxExclusive */
16012 res = xmlSchemaCompareValues(fmaxexc->val, bfmaxexc->val);
16013 if (res == -2)
16014 goto internal_error;
16015 if (res == 1) {
16016 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmaxexc, -1, 1, 1);
16017 }
16018 if ((res != 0) && (bfmaxexc->fixed)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016019 FACET_RESTR_FIXED_ERR(fmaxexc)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016020 }
16021 }
16022 if (bfmaxinc) {
16023 /* maxExclusive <= BASE maxInclusive */
16024 res = xmlSchemaCompareValues(fmaxexc->val, bfmaxinc->val);
16025 if (res == -2)
16026 goto internal_error;
16027 if (res == 1) {
16028 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmaxinc, -1, 1, 1);
16029 }
16030 }
16031 if (bfmininc) {
16032 /* maxExclusive > BASE minInclusive */
16033 res = xmlSchemaCompareValues(fmaxexc->val, bfmininc->val);
16034 if (res == -2)
16035 goto internal_error;
16036 if (res != 1) {
16037 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmininc, 1, 0, 1);
16038 }
16039 }
16040 if (bfminexc) {
16041 /* maxExclusive > BASE minExclusive */
16042 res = xmlSchemaCompareValues(fmaxexc->val, bfminexc->val);
16043 if (res == -2)
16044 goto internal_error;
16045 if (res != 1) {
16046 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfminexc, 1, 0, 1);
16047 }
16048 }
16049 }
16050 if (fminexc) {
16051 /*
16052 * "minExclusive < maxInclusive"
16053 */
16054 if (fmaxinc) {
16055 res = xmlSchemaCompareValues(fminexc->val, fmaxinc->val);
16056 if (res == -2)
16057 goto internal_error;
16058 if (res != -1) {
16059 xmlSchemaDeriveFacetErr(pctxt, fminexc, fmaxinc, -1, 0, 0);
16060 }
16061 }
16062 /*
16063 * "minExclusive valid restriction"
16064 */
16065 if (bfminexc) {
16066 /* minExclusive >= BASE minExclusive */
16067 res = xmlSchemaCompareValues(fminexc->val, bfminexc->val);
16068 if (res == -2)
16069 goto internal_error;
16070 if (res == -1) {
16071 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfminexc, 1, 1, 1);
16072 }
16073 if ((res != 0) && (bfminexc->fixed)) {
16074 FACET_RESTR_FIXED_ERR(fminexc)
16075 }
16076 }
16077 if (bfmaxinc) {
16078 /* minExclusive <= BASE maxInclusive */
16079 res = xmlSchemaCompareValues(fminexc->val, bfmaxinc->val);
16080 if (res == -2)
16081 goto internal_error;
16082 if (res == 1) {
16083 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmaxinc, -1, 1, 1);
16084 }
16085 }
16086 if (bfmininc) {
16087 /* minExclusive >= BASE minInclusive */
16088 res = xmlSchemaCompareValues(fminexc->val, bfmininc->val);
16089 if (res == -2)
16090 goto internal_error;
16091 if (res == -1) {
16092 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmininc, 1, 1, 1);
16093 }
16094 }
16095 if (bfmaxexc) {
16096 /* minExclusive < BASE maxExclusive */
16097 res = xmlSchemaCompareValues(fminexc->val, bfmaxexc->val);
16098 if (res == -2)
16099 goto internal_error;
16100 if (res != -1) {
16101 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmaxexc, -1, 0, 1);
16102 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016103 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016104 }
16105 if (fmininc) {
16106 /*
16107 * "minInclusive < maxExclusive"
16108 */
16109 if (fmaxexc) {
16110 res = xmlSchemaCompareValues(fmininc->val, fmaxexc->val);
16111 if (res == -2)
16112 goto internal_error;
16113 if (res != -1) {
16114 xmlSchemaDeriveFacetErr(pctxt, fmininc, fmaxexc, -1, 0, 0);
16115 }
16116 }
16117 /*
16118 * "minExclusive valid restriction"
16119 */
16120 if (bfmininc) {
16121 /* minInclusive >= BASE minInclusive */
16122 res = xmlSchemaCompareValues(fmininc->val, bfmininc->val);
16123 if (res == -2)
16124 goto internal_error;
16125 if (res == -1) {
16126 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmininc, 1, 1, 1);
16127 }
16128 if ((res != 0) && (bfmininc->fixed)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016129 FACET_RESTR_FIXED_ERR(fmininc)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016130 }
16131 }
16132 if (bfmaxinc) {
16133 /* minInclusive <= BASE maxInclusive */
16134 res = xmlSchemaCompareValues(fmininc->val, bfmaxinc->val);
16135 if (res == -2)
16136 goto internal_error;
Daniel Veillard0a119eb2005-07-20 13:46:00 +000016137 if (res == 1) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016138 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmaxinc, -1, 1, 1);
16139 }
16140 }
16141 if (bfminexc) {
16142 /* minInclusive > BASE minExclusive */
16143 res = xmlSchemaCompareValues(fmininc->val, bfminexc->val);
16144 if (res == -2)
16145 goto internal_error;
16146 if (res != 1)
16147 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfminexc, 1, 0, 1);
16148 }
16149 if (bfmaxexc) {
16150 /* minInclusive < BASE maxExclusive */
16151 res = xmlSchemaCompareValues(fmininc->val, bfmaxexc->val);
16152 if (res == -2)
16153 goto internal_error;
16154 if (res != -1)
16155 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmaxexc, -1, 0, 1);
16156 }
16157 }
16158 if (ftotdig && bftotdig) {
16159 /*
16160 * SCC " totalDigits valid restriction"
16161 * totalDigits <= BASE totalDigits
16162 */
16163 res = xmlSchemaCompareValues(ftotdig->val, bftotdig->val);
16164 if (res == -2)
16165 goto internal_error;
16166 if (res == 1)
16167 xmlSchemaDeriveFacetErr(pctxt, ftotdig, bftotdig,
16168 -1, 1, 1);
16169 if ((res != 0) && (bftotdig->fixed)) {
16170 FACET_RESTR_FIXED_ERR(ftotdig)
16171 }
16172 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016173 if (ffracdig && bffracdig) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016174 /*
16175 * SCC "fractionDigits valid restriction"
16176 * fractionDigits <= BASE fractionDigits
16177 */
16178 res = xmlSchemaCompareValues(ffracdig->val, bffracdig->val);
16179 if (res == -2)
16180 goto internal_error;
16181 if (res == 1)
16182 xmlSchemaDeriveFacetErr(pctxt, ffracdig, bffracdig,
16183 -1, 1, 1);
16184 if ((res != 0) && (bffracdig->fixed)) {
16185 FACET_RESTR_FIXED_ERR(ffracdig)
16186 }
16187 }
16188 /*
16189 * SCC "fractionDigits less than or equal to totalDigits"
16190 */
16191 if (! ftotdig)
16192 ftotdig = bftotdig;
16193 if (! ffracdig)
16194 ffracdig = bffracdig;
16195 if (ftotdig && ffracdig) {
16196 res = xmlSchemaCompareValues(ffracdig->val, ftotdig->val);
16197 if (res == -2)
16198 goto internal_error;
16199 if (res == 1)
16200 xmlSchemaDeriveFacetErr(pctxt, ffracdig, ftotdig,
16201 -1, 1, 0);
16202 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016203 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016204 * *Enumerations* won' be added here, since only the first set
16205 * of enumerations in the ancestor-or-self axis is used
16206 * for validation, plus we need to use the base type of those
16207 * enumerations for whitespace.
16208 *
16209 * *Patterns*: won't be add here, since they are ORed at
16210 * type level and ANDed at ancestor level. This will
16211 * happed during validation by walking the base axis
16212 * of the type.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016213 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016214 for (cur = base->facetSet; cur != NULL; cur = cur->next) {
16215 bfacet = cur->facet;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016216 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016217 * Special handling of enumerations and patterns.
16218 * TODO: hmm, they should not appear in the set, so remove this.
16219 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016220 if ((bfacet->type == XML_SCHEMA_FACET_PATTERN) ||
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016221 (bfacet->type == XML_SCHEMA_FACET_ENUMERATION))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016222 continue;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016223 /*
16224 * Search for a duplicate facet in the current type.
16225 */
16226 link = type->facetSet;
16227 err = 0;
16228 fixedErr = 0;
16229 while (link != NULL) {
16230 facet = link->facet;
16231 if (facet->type == bfacet->type) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016232 switch (facet->type) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016233 case XML_SCHEMA_FACET_WHITESPACE:
16234 /*
16235 * The whitespace must be stronger.
16236 */
16237 if (facet->whitespace < bfacet->whitespace) {
16238 FACET_RESTR_ERR(flength,
16239 "The 'whitespace' value has to be equal to "
16240 "or stronger than the 'whitespace' value of "
16241 "the base type")
16242 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016243 if ((bfacet->fixed) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016244 (facet->whitespace != bfacet->whitespace)) {
16245 FACET_RESTR_FIXED_ERR(facet)
16246 }
16247 break;
16248 default:
16249 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016250 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016251 /* Duplicate found. */
16252 break;
16253 }
16254 link = link->next;
16255 }
16256 /*
16257 * If no duplicate was found: add the base types's facet
16258 * to the set.
16259 */
16260 if (link == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016261 link = (xmlSchemaFacetLinkPtr)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016262 xmlMalloc(sizeof(xmlSchemaFacetLink));
16263 if (link == NULL) {
16264 xmlSchemaPErrMemory(pctxt,
16265 "deriving facets, creating a facet link", NULL);
16266 return (-1);
16267 }
16268 link->facet = cur->facet;
16269 link->next = NULL;
16270 if (last == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016271 type->facetSet = link;
16272 else
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016273 last->next = link;
16274 last = link;
16275 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016276
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016277 }
16278
16279 return (0);
16280internal_error:
16281 xmlSchemaPCustomErr(pctxt,
16282 XML_SCHEMAP_INVALID_FACET_VALUE,
16283 NULL, type, NULL,
16284 "Internal error: xmlSchemaDeriveAndValidateFacets", NULL);
16285 return (-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016286}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016287
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016288static int
16289xmlSchemaFinishMemberTypeDefinitionsProperty(xmlSchemaParserCtxtPtr pctxt,
16290 xmlSchemaTypePtr type)
16291{
16292 xmlSchemaTypeLinkPtr link, lastLink, prevLink, subLink, newLink;
16293 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016294 * The actual value is then formed by replacing any union type
16295 * definition in the ·explicit members· with the members of their
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016296 * {member type definitions}, in order.
16297 */
16298 link = type->memberTypes;
16299 while (link != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016300
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016301 if (IS_NOT_TYPEFIXED(link->type))
16302 xmlSchemaTypeFixup(link->type, pctxt, NULL);
16303
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016304 if (VARIETY_UNION(link->type)) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016305 subLink = xmlSchemaGetUnionSimpleTypeMemberTypes(link->type);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016306 if (subLink != NULL) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016307 link->type = subLink->type;
16308 if (subLink->next != NULL) {
16309 lastLink = link->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016310 subLink = subLink->next;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016311 prevLink = link;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016312 while (subLink != NULL) {
16313 newLink = (xmlSchemaTypeLinkPtr)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016314 xmlMalloc(sizeof(xmlSchemaTypeLink));
16315 if (newLink == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016316 xmlSchemaPErrMemory(pctxt, "allocating a type link",
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016317 NULL);
16318 return (-1);
16319 }
16320 newLink->type = subLink->type;
16321 prevLink->next = newLink;
16322 prevLink = newLink;
16323 newLink->next = lastLink;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016324
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016325 subLink = subLink->next;
16326 }
16327 }
16328 }
16329 }
16330 link = link->next;
16331 }
16332 return (0);
16333}
16334
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016335static void
16336xmlSchemaTypeFixupOptimFacets(xmlSchemaTypePtr type)
16337{
16338 int has = 0, needVal = 0, normVal = 0;
16339
16340 has = (type->baseType->flags & XML_SCHEMAS_TYPE_HAS_FACETS) ? 1 : 0;
16341 if (has) {
16342 needVal = (type->baseType->flags &
16343 XML_SCHEMAS_TYPE_FACETSNEEDVALUE) ? 1 : 0;
16344 normVal = (type->baseType->flags &
16345 XML_SCHEMAS_TYPE_NORMVALUENEEDED) ? 1 : 0;
16346 }
16347 if (type->facets != NULL) {
16348 xmlSchemaFacetPtr fac;
16349
16350 for (fac = type->facets; fac != NULL; fac = fac->next) {
16351 switch (fac->type) {
16352 case XML_SCHEMA_FACET_WHITESPACE:
16353 break;
16354 case XML_SCHEMA_FACET_PATTERN:
16355 normVal = 1;
16356 has = 1;
16357 break;
16358 case XML_SCHEMA_FACET_ENUMERATION:
16359 needVal = 1;
16360 normVal = 1;
16361 has = 1;
16362 break;
16363 default:
16364 has = 1;
16365 break;
16366 }
16367 }
16368 }
16369 if (normVal)
16370 type->flags |= XML_SCHEMAS_TYPE_NORMVALUENEEDED;
16371 if (needVal)
16372 type->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
16373 if (has)
16374 type->flags |= XML_SCHEMAS_TYPE_HAS_FACETS;
16375
16376 if (has && (! needVal) && VARIETY_ATOMIC(type)) {
16377 xmlSchemaTypePtr prim = xmlSchemaGetPrimitiveType(type);
16378 /*
16379 * OPTIMIZE VAL TODO: Some facets need a computed value.
16380 */
16381 if ((prim->builtInType != XML_SCHEMAS_ANYSIMPLETYPE) &&
16382 (prim->builtInType != XML_SCHEMAS_STRING)) {
16383 type->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
16384 }
16385 }
16386}
16387
16388static int
16389xmlSchemaTypeFixupWhitespace(xmlSchemaTypePtr type)
16390{
16391
16392
16393 /*
16394 * Evaluate the whitespace-facet value.
16395 */
16396 if (VARIETY_LIST(type)) {
16397 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
16398 return (0);
16399 } else if (VARIETY_UNION(type))
16400 return (0);
16401
16402 if (type->facetSet != NULL) {
16403 xmlSchemaFacetLinkPtr lin;
16404
16405 for (lin = type->facetSet; lin != NULL; lin = lin->next) {
16406 if (lin->facet->type == XML_SCHEMA_FACET_WHITESPACE) {
16407 switch (lin->facet->whitespace) {
16408 case XML_SCHEMAS_FACET_PRESERVE:
16409 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE;
16410 break;
16411 case XML_SCHEMAS_FACET_REPLACE:
16412 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_REPLACE;
16413 break;
16414 case XML_SCHEMAS_FACET_COLLAPSE:
16415 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
16416 break;
16417 default:
16418 return (-1);
16419 }
16420 return (0);
16421 }
16422 }
16423 }
16424 /*
16425 * For all ·atomic· datatypes other than string (and types ·derived·
16426 * by ·restriction· from it) the value of whiteSpace is fixed to
16427 * collapse
16428 */
16429 {
16430 xmlSchemaTypePtr anc;
16431
16432 for (anc = type->baseType; anc != NULL &&
16433 anc->builtInType != XML_SCHEMAS_ANYTYPE;
16434 anc = anc->baseType) {
16435
16436 if (anc->type == XML_SCHEMA_TYPE_BASIC) {
16437 if (anc->builtInType == XML_SCHEMAS_NORMSTRING) {
16438 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_REPLACE;
16439
16440 } else if ((anc->builtInType == XML_SCHEMAS_STRING) ||
16441 (anc->builtInType == XML_SCHEMAS_ANYSIMPLETYPE)) {
16442 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE;
16443
16444 } else
16445 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
16446 break;
16447 }
16448 }
16449 return (0);
16450 }
16451 return (0);
16452}
16453
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016454/**
Daniel Veillard4255d502002-04-16 15:50:10 +000016455 * xmlSchemaTypeFixup:
16456 * @typeDecl: the schema type definition
16457 * @ctxt: the schema parser context
16458 *
16459 * Fixes the content model of the type.
16460 */
16461static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016462xmlSchemaTypeFixup(xmlSchemaTypePtr type,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016463 xmlSchemaParserCtxtPtr pctxt, const xmlChar * name)
Daniel Veillard4255d502002-04-16 15:50:10 +000016464{
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016465 if (type == NULL)
Daniel Veillard82bbbd42003-05-11 20:16:09 +000016466 return;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016467 if ((type->type != XML_SCHEMA_TYPE_COMPLEX) &&
16468 (type->type != XML_SCHEMA_TYPE_SIMPLE))
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000016469 return;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016470 if (! IS_NOT_TYPEFIXED(type))
16471 return;
16472 type->flags |= XML_SCHEMAS_TYPE_INTERNAL_RESOLVED;
Daniel Veillard4255d502002-04-16 15:50:10 +000016473 if (name == NULL)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016474 name = type->name;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016475
16476 if (type->baseType == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016477 xmlSchemaPCustomErr(pctxt,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016478 XML_SCHEMAP_INTERNAL,
16479 NULL, type, NULL,
16480 "Internal error: xmlSchemaTypeFixup, "
16481 "baseType is missing on '%s'", type->name);
16482 return;
16483 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016484
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016485 if (type->type == XML_SCHEMA_TYPE_COMPLEX) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016486 xmlSchemaTypePtr baseType = type->baseType;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016487
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016488 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016489 * Type-fix the base type.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016490 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016491 if (IS_NOT_TYPEFIXED(baseType))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016492 xmlSchemaTypeFixup(baseType, pctxt, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016493 if (baseType->flags & XML_SCHEMAS_TYPE_INTERNAL_INVALID) {
16494 /*
16495 * Skip fixup if the base type is invalid.
16496 * TODO: Generate a warning!
16497 */
16498 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016499 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016500 /*
16501 * This basically checks if the base type can be derived.
16502 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016503 if (xmlSchemaCheckSRCCT(pctxt, type) != 0) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016504 type->flags |= XML_SCHEMAS_TYPE_INTERNAL_INVALID;
16505 return;
16506 }
16507 /*
16508 * Fixup the content type.
16509 */
16510 if (type->contentType == XML_SCHEMA_CONTENT_SIMPLE) {
16511 /*
16512 * Corresponds to <complexType><simpleContent>...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016513 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016514 if ((IS_COMPLEX_TYPE(baseType)) &&
16515 (baseType->contentTypeDef != NULL) &&
16516 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016517 xmlSchemaTypePtr contentBase, content;
16518 char buf[30];
16519 const xmlChar *tmpname;
16520 /*
16521 * SPEC (1) If <restriction> + base type is <complexType>,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016522 * "whose own {content type} is a simple type..."
Daniel Veillard01fa6152004-06-29 17:04:39 +000016523 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016524 if (type->contentTypeDef != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016525 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016526 * SPEC (1.1) "the simple type definition corresponding to the
16527 * <simpleType> among the [children] of <restriction> if there
16528 * is one;"
16529 * Note that this "<simpleType> among the [children]" was put
16530 * into ->contentTypeDef during parsing.
Daniel Veillard01fa6152004-06-29 17:04:39 +000016531 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016532 contentBase = type->contentTypeDef;
16533 type->contentTypeDef = NULL;
16534 } else {
16535 /*
16536 * (1.2) "...otherwise (<restriction> has no <simpleType>
16537 * among its [children]), the simple type definition which
16538 * is the {content type} of the ... base type."
16539 */
16540 contentBase = baseType->contentTypeDef;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016541 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016542 /*
16543 * SPEC
16544 * "... a simple type definition which restricts the simple
16545 * type definition identified in clause 1.1 or clause 1.2
16546 * with a set of facet components"
16547 *
16548 * Create the anonymous simple type, which will be the content
16549 * type of the complex type.
16550 */
16551 snprintf(buf, 29, "#scST%d", ++(pctxt->counter));
16552 tmpname = xmlDictLookup(pctxt->dict, BAD_CAST buf, -1);
16553 content = xmlSchemaAddType(pctxt,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000016554 pctxt->schema, tmpname, tmpname, type->node, 0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016555 if (content == NULL)
16556 return;
16557 /*
16558 * We will use the same node as for the <complexType>
16559 * to have it somehow anchored in the schema doc.
16560 */
16561 content->node = type->node;
16562 content->type = XML_SCHEMA_TYPE_SIMPLE;
16563 content->contentType = XML_SCHEMA_CONTENT_SIMPLE;
16564 content->baseType = contentBase;
16565 /*
16566 * Move the facets, previously anchored on the complexType.
16567 */
16568 content->facets = type->facets;
16569 type->facets = NULL;
16570 content->facetSet = type->facetSet;
16571 type->facetSet = NULL;
16572
16573 type->contentTypeDef = content;
16574 if (IS_NOT_TYPEFIXED(contentBase))
16575 xmlSchemaTypeFixup(contentBase, pctxt, NULL);
16576 xmlSchemaTypeFixup(content, pctxt, NULL);
16577
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016578 } else if ((IS_COMPLEX_TYPE(baseType)) &&
16579 (baseType->contentType == XML_SCHEMA_CONTENT_MIXED) &&
16580 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION)) {
16581 /*
16582 * SPEC (2) If <restriction> + base is a mixed <complexType> with
16583 * an emptiable particle, then a simple type definition which
16584 * restricts the <restriction>'s <simpleType> child.
Daniel Veillard01fa6152004-06-29 17:04:39 +000016585 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016586 if ((type->contentTypeDef == NULL) ||
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016587 (type->contentTypeDef->baseType == NULL)) {
16588 /*
16589 * TODO: Check if this ever happens.
16590 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016591 xmlSchemaPCustomErr(pctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016592 XML_SCHEMAP_INTERNAL,
16593 NULL, type, NULL,
16594 "Internal error: xmlSchemaTypeFixup, "
16595 "complex type '%s': the <simpleContent><restriction> "
16596 "is missing a <simpleType> child, but was not catched "
16597 "by xmlSchemaCheckSRCCT()", type->name);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016598 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016599 } else if ((IS_COMPLEX_TYPE(baseType)) &&
16600 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION)) {
16601 /*
16602 * SPEC (3) If <extension> + base is <complexType> with
16603 * <simpleType> content, "...then the {content type} of that
16604 * complex type definition"
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016605 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016606 if (baseType->contentTypeDef == NULL) {
16607 /*
16608 * TODO: Check if this ever happens. xmlSchemaCheckSRCCT
16609 * should have catched this already.
16610 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016611 xmlSchemaPCustomErr(pctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016612 XML_SCHEMAP_INTERNAL,
16613 NULL, type, NULL,
16614 "Internal error: xmlSchemaTypeFixup, "
16615 "complex type '%s': the <extension>ed base type is "
16616 "a complex type with no simple content type",
16617 type->name);
16618 }
16619 type->contentTypeDef = baseType->contentTypeDef;
16620 } else if ((IS_SIMPLE_TYPE(baseType)) &&
16621 (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION)) {
16622 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016623 * SPEC (4) <extension> + base is <simpleType>
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016624 * "... then that simple type definition"
16625 */
16626 type->contentTypeDef = baseType;
16627 } else {
16628 /*
16629 * TODO: Check if this ever happens.
16630 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016631 xmlSchemaPCustomErr(pctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016632 XML_SCHEMAP_INTERNAL,
16633 NULL, type, NULL,
16634 "Internal error: xmlSchemaTypeFixup, "
16635 "complex type '%s' with <simpleContent>: unhandled "
16636 "derivation case", type->name);
16637 }
16638 } else {
16639 int dummySequence = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016640 xmlSchemaParticlePtr particle =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016641 (xmlSchemaParticlePtr) type->subtypes;
16642 /*
16643 * Corresponds to <complexType><complexContent>...
16644 *
16645 * NOTE that the effective mixed was already set during parsing of
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016646 * <complexType> and <complexContent>; its flag value is
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016647 * XML_SCHEMAS_TYPE_MIXED.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016648 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016649 * Compute the "effective content":
16650 * (2.1.1) + (2.1.2) + (2.1.3)
16651 */
16652 if ((particle == NULL) ||
16653 ((particle->type == XML_SCHEMA_TYPE_PARTICLE) &&
16654 ((particle->children->type == XML_SCHEMA_TYPE_ALL) ||
16655 (particle->children->type == XML_SCHEMA_TYPE_SEQUENCE) ||
16656 ((particle->children->type == XML_SCHEMA_TYPE_CHOICE) &&
16657 (particle->minOccurs == 0))) &&
16658 ( ((xmlSchemaTreeItemPtr) particle->children)->children == NULL))) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016659 if (type->flags & XML_SCHEMAS_TYPE_MIXED) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016660 /*
16661 * SPEC (2.1.4) "If the ·effective mixed· is true, then
16662 * a particle whose properties are as follows:..."
16663 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016664 * Empty sequence model group with
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016665 * minOccurs/maxOccurs = 1 (i.e. a "particle emptiable").
16666 * NOTE that we sill assign it the <complexType> node to
16667 * somehow anchor it in the doc.
16668 */
16669 if ((particle == NULL) ||
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016670 (particle->children->type != XML_SCHEMA_TYPE_SEQUENCE)) {
Daniel Veillard01fa6152004-06-29 17:04:39 +000016671 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016672 * Create the particle.
Daniel Veillard01fa6152004-06-29 17:04:39 +000016673 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016674 particle = xmlSchemaAddParticle(pctxt, pctxt->schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016675 type->node, 1, 1);
16676 if (particle == NULL)
16677 return;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016678 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016679 * Create the model group.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000016680 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016681 particle->children = (xmlSchemaTreeItemPtr)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016682 xmlSchemaAddModelGroup(pctxt, pctxt->schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016683 XML_SCHEMA_TYPE_SEQUENCE, NULL, type->node);
16684 if (particle->children == NULL)
16685 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016686
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016687 type->subtypes = (xmlSchemaTypePtr) particle;
Daniel Veillard01fa6152004-06-29 17:04:39 +000016688 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016689 dummySequence = 1;
16690 type->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
16691 } else {
16692 /*
16693 * SPEC (2.1.5) "otherwise empty"
16694 */
16695 type->contentType = XML_SCHEMA_CONTENT_EMPTY;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016696 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016697 } else {
Daniel Veillard01fa6152004-06-29 17:04:39 +000016698 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016699 * SPEC (2.2) "otherwise the particle corresponding to the
16700 * <all>, <choice>, <group> or <sequence> among the
16701 * [children]."
Daniel Veillard01fa6152004-06-29 17:04:39 +000016702 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016703 type->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
16704 }
16705 /*
16706 * Compute the "content type".
16707 */
16708 if (type->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) {
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016709 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016710 * SPEC (3.1) "If <restriction>..."
16711 * (3.1.1) + (3.1.2) */
16712 if (type->contentType != XML_SCHEMA_CONTENT_EMPTY) {
16713 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
16714 type->contentType = XML_SCHEMA_CONTENT_MIXED;
16715 }
16716 } else {
16717 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016718 * SPEC (3.2) "If <extension>..."
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000016719 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016720 if (type->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16721 /*
16722 * SPEC (3.2.1)
16723 */
16724 type->contentType = baseType->contentType;
16725 type->subtypes = baseType->subtypes;
16726 /*
16727 * NOTE that the effective mixed is ignored here.
16728 */
16729 } else if (baseType->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16730 /*
16731 * SPEC (3.2.2)
16732 */
16733 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
16734 type->contentType = XML_SCHEMA_CONTENT_MIXED;
16735 } else {
16736 /*
16737 * SPEC (3.2.3)
16738 */
16739 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
16740 type->contentType = XML_SCHEMA_CONTENT_MIXED;
16741 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016742 * "A model group whose {compositor} is sequence and whose
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016743 * {particles} are..."
16744 */
16745 if (! dummySequence) {
16746 xmlSchemaTreeItemPtr effectiveContent =
16747 (xmlSchemaTreeItemPtr) type->subtypes;
16748 /*
16749 * Create the particle.
16750 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016751 particle = xmlSchemaAddParticle(pctxt, pctxt->schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016752 type->node, 1, 1);
16753 if (particle == NULL)
16754 return;
16755 /*
16756 * Create the "sequence" model group.
16757 */
16758 particle->children = (xmlSchemaTreeItemPtr)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016759 xmlSchemaAddModelGroup(pctxt, pctxt->schema,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016760 XML_SCHEMA_TYPE_SEQUENCE, NULL, type->node);
16761 if (particle->children == NULL)
16762 return;
16763 type->subtypes = (xmlSchemaTypePtr) particle;
16764 /*
16765 * SPEC "the particle of the {content type} of
16766 * the ... base ..."
16767 * Create a duplicate of the base type's particle
16768 * and assign its "term" to it.
16769 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016770 particle->children->children =
16771 (xmlSchemaTreeItemPtr) xmlSchemaAddParticle(pctxt,
16772 pctxt->schema, type->node,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016773 ((xmlSchemaParticlePtr) type->subtypes)->minOccurs,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016774 ((xmlSchemaParticlePtr) type->subtypes)->maxOccurs);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016775 if (particle->children->children == NULL)
16776 return;
16777 particle = (xmlSchemaParticlePtr)
16778 particle->children->children;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016779 particle->children =
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016780 ((xmlSchemaParticlePtr) baseType->subtypes)->children;
16781 /*
16782 * SPEC "followed by the ·effective content·."
16783 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016784 particle->next = effectiveContent;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016785 } else {
16786 /*
16787 * This is the case when there is already an empty
16788 * <sequence> with minOccurs==maxOccurs==1.
16789 * Just add the base types's content type.
16790 * NOTE that, although we miss to add an intermediate
16791 * <sequence>, this should produce no difference to
16792 * neither the regex compilation of the content model,
16793 * nor to the complex type contraints.
16794 */
16795 particle->children->children =
16796 (xmlSchemaTreeItemPtr) baseType->subtypes;
16797 }
16798 }
16799 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016800 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016801 /*
16802 * Apply the complex type component constraints; this will not
16803 * check attributes, since this is done in
16804 * xmlSchemaBuildAttributeValidation().
16805 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016806 if (xmlSchemaCheckCTComponent(pctxt, type) != 0)
16807 return;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016808 /*
16809 * Inherit & check constraints for attributes.
16810 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016811 xmlSchemaBuildAttributeValidation(pctxt, type);
16812 } else if (type->type == XML_SCHEMA_TYPE_SIMPLE) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016813 /*
16814 * Simple Type Definition Schema Component
16815 */
16816 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016817 if (VARIETY_LIST(type)) {
16818 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016819 * Corresponds to <simpleType><list>...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016820 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016821 if (type->subtypes == NULL) {
16822 /*
16823 * This one is really needed, so get out.
16824 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016825 PERROR_INT("xmlSchemaTypeFixup",
16826 "list type has no item-type assigned");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016827 return;
16828 }
16829 if (IS_NOT_TYPEFIXED(type->subtypes))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016830 xmlSchemaTypeFixup(type->subtypes, pctxt, NULL);
16831 } else if (VARIETY_UNION(type)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016832 /*
16833 * Corresponds to <simpleType><union>...
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016834 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016835 if (type->memberTypes == NULL) {
16836 /*
16837 * This one is really needed, so get out.
16838 */
16839 return;
16840 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016841 if (xmlSchemaFinishMemberTypeDefinitionsProperty(pctxt, type) == -1)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016842 return;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016843 } else {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000016844 xmlSchemaTypePtr baseType = type->baseType;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016845 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016846 * Corresponds to <simpleType><restriction>...
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016847 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016848 if (IS_NOT_TYPEFIXED(baseType))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016849 xmlSchemaTypeFixup(baseType, pctxt, NULL);
16850 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016851 * Variety
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016852 * If the <restriction> alternative is chosen, then the
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016853 * {variety} of the {base type definition}.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016854 */
16855 if (VARIETY_ATOMIC(baseType))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016856 type->flags |= XML_SCHEMAS_TYPE_VARIETY_ATOMIC;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016857 else if (VARIETY_LIST(baseType)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016858 type->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
16859 /*
16860 * Inherit the itemType.
16861 */
16862 type->subtypes = baseType->subtypes;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016863 } else if (VARIETY_UNION(baseType)) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016864 type->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
16865 /*
16866 * NOTE that we won't assign the memberTypes of the base,
16867 * since this will make trouble when freeing them; we will
16868 * use a lookup function to access them instead.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016869 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016870 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016871 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016872 /*
16873 * Check constraints.
16874 *
16875 * TODO: Split this somehow, we need to know first if we can derive
16876 * from the base type at all!
16877 */
16878 if (type->baseType != NULL) {
16879 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016880 * Schema Component Constraint: Simple Type Restriction
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016881 * (Facets)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016882 * NOTE: Satisfaction of 1 and 2 arise from the fixup
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016883 * applied beforehand.
16884 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016885 xmlSchemaCheckSRCSimpleType(pctxt, type);
16886 xmlSchemaCheckFacetValues(type, pctxt);
16887 if ((type->facetSet != NULL) ||
16888 (type->baseType->facetSet != NULL))
16889 xmlSchemaDeriveAndValidateFacets(pctxt, type);
16890 /*
16891 * Whitespace value.
16892 */
16893 xmlSchemaTypeFixupWhitespace(type);
16894 xmlSchemaTypeFixupOptimFacets(type);
16895 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016896 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016897
Daniel Veillard8651f532002-04-17 09:06:27 +000016898#ifdef DEBUG_TYPE
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016899 if (type->node != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016900 xmlGenericError(xmlGenericErrorContext,
16901 "Type of %s : %s:%d :", name,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016902 type->node->doc->URL,
16903 xmlGetLineNo(type->node));
Daniel Veillarddecd64d2002-04-18 14:41:51 +000016904 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016905 xmlGenericError(xmlGenericErrorContext, "Type of %s :", name);
Daniel Veillarddecd64d2002-04-18 14:41:51 +000016906 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016907 if ((IS_SIMPLE_TYPE(type)) || (IS_COMPLEX_TYPE(type))) {
16908 switch (type->contentType) {
16909 case XML_SCHEMA_CONTENT_SIMPLE:
16910 xmlGenericError(xmlGenericErrorContext, "simple\n");
16911 break;
16912 case XML_SCHEMA_CONTENT_ELEMENTS:
16913 xmlGenericError(xmlGenericErrorContext, "elements\n");
16914 break;
16915 case XML_SCHEMA_CONTENT_UNKNOWN:
16916 xmlGenericError(xmlGenericErrorContext, "unknown !!!\n");
16917 break;
16918 case XML_SCHEMA_CONTENT_EMPTY:
16919 xmlGenericError(xmlGenericErrorContext, "empty\n");
16920 break;
16921 case XML_SCHEMA_CONTENT_MIXED:
16922 if (xmlSchemaIsParticleEmptiable((xmlSchemaParticlePtr)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016923 type->subtypes))
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000016924 xmlGenericError(xmlGenericErrorContext,
16925 "mixed as emptiable particle\n");
16926 else
16927 xmlGenericError(xmlGenericErrorContext, "mixed\n");
16928 break;
16929 /* Removed, since not used. */
16930 /*
16931 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
16932 xmlGenericError(xmlGenericErrorContext, "mixed or elems\n");
16933 break;
16934 */
16935 case XML_SCHEMA_CONTENT_BASIC:
16936 xmlGenericError(xmlGenericErrorContext, "basic\n");
16937 break;
16938 default:
16939 xmlGenericError(xmlGenericErrorContext,
16940 "not registered !!!\n");
16941 break;
16942 }
Daniel Veillard8651f532002-04-17 09:06:27 +000016943 }
16944#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000016945}
16946
16947/**
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016948 * xmlSchemaCheckFacet:
16949 * @facet: the facet
16950 * @typeDecl: the schema type definition
Daniel Veillard81562d22005-06-15 13:27:56 +000016951 * @pctxt: the schema parser context or NULL
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016952 * @name: the optional name of the type
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016953 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016954 * Checks and computes the values of facets.
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016955 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016956 * Returns 0 if valid, a positive error code if not valid and
16957 * -1 in case of an internal or API error.
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016958 */
16959int
16960xmlSchemaCheckFacet(xmlSchemaFacetPtr facet,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016961 xmlSchemaTypePtr typeDecl,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016962 xmlSchemaParserCtxtPtr pctxt,
16963 const xmlChar * name ATTRIBUTE_UNUSED)
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016964{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016965 int ret = 0, ctxtGiven;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016966
Daniel Veillardce682bc2004-11-05 17:22:25 +000016967 if ((facet == NULL) || (typeDecl == NULL))
16968 return(-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016969 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000016970 * TODO: will the parser context be given if used from
16971 * the relaxNG module?
16972 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016973 if (pctxt == NULL)
16974 ctxtGiven = 0;
16975 else
16976 ctxtGiven = 1;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016977
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000016978 switch (facet->type) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016979 case XML_SCHEMA_FACET_MININCLUSIVE:
16980 case XML_SCHEMA_FACET_MINEXCLUSIVE:
16981 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016982 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
16983 case XML_SCHEMA_FACET_ENUMERATION: {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000016984 /*
16985 * Okay we need to validate the value
16986 * at that point.
16987 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000016988 xmlSchemaTypePtr base;
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016989
16990 /* 4.3.5.5 Constraints on enumeration Schema Components
16991 * Schema Component Constraint: enumeration valid restriction
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016992 * It is an ·error· if any member of {value} is not in the
16993 * ·value space· of {base type definition}.
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016994 *
16995 * minInclusive, maxInclusive, minExclusive, maxExclusive:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000016996 * The value ·must· be in the
16997 * ·value space· of the ·base type·.
Daniel Veillardf4b05d02004-07-05 13:10:37 +000016998 */
16999 /*
17000 * This function is intended to deliver a compiled value
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000017001 * on the facet. In this implementation of XML Schemata the
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017002 * type holding a facet, won't be a built-in type.
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000017003 * Thus to ensure that other API
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017004 * calls (relaxng) do work, if the given type is a built-in
Daniel Veillardf4b05d02004-07-05 13:10:37 +000017005 * type, we will assume that the given built-in type *is
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017006 * already* the base type.
Daniel Veillardf4b05d02004-07-05 13:10:37 +000017007 */
17008 if (typeDecl->type != XML_SCHEMA_TYPE_BASIC) {
17009 base = typeDecl->baseType;
17010 if (base == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017011 PERROR_INT("xmlSchemaCheckFacet",
17012 "a type user derived type has no base type");
Daniel Veillardf4b05d02004-07-05 13:10:37 +000017013 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017014 }
Daniel Veillardf4b05d02004-07-05 13:10:37 +000017015 } else
17016 base = typeDecl;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017017
17018 if (! ctxtGiven) {
17019 /*
17020 * A context is needed if called from RelaxNG.
17021 */
17022 pctxt = xmlSchemaNewParserCtxt("*");
17023 if (pctxt == NULL)
17024 return (-1);
Daniel Veillard01fa6152004-06-29 17:04:39 +000017025 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017026 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017027 * NOTE: This call does not check the content nodes,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017028 * since they are not available:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017029 * facet->node is just the node holding the facet
17030 * definition, *not* the attribute holding the *value*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000017031 * of the facet.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017032 */
17033 ret = xmlSchemaVCheckCVCSimpleType(
17034 (xmlSchemaAbstractCtxtPtr) pctxt, facet->node, base,
17035 facet->value, &(facet->val), 1, 1, 0);
17036 if (ret != 0) {
17037 if (ret < 0) {
17038 /* No error message for RelaxNG. */
17039 if (ctxtGiven) {
17040 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) pctxt,
17041 XML_SCHEMAP_INTERNAL, facet->node, NULL,
17042 "Internal error: xmlSchemaCheckFacet, "
17043 "failed to validate the value '%s' of the "
17044 "facet '%s' against the base type",
17045 facet->value, xmlSchemaFacetTypeToString(facet->type));
17046 }
17047 goto internal_error;
17048 }
17049 ret = XML_SCHEMAP_INVALID_FACET_VALUE;
17050 /* No error message for RelaxNG. */
17051 if (ctxtGiven) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000017052 xmlChar *str = NULL;
17053
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017054 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) pctxt,
17055 ret, facet->node, (xmlSchemaTypePtr) facet,
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000017056 "The value '%s' of the facet does not validate "
17057 "against the base type '%s'",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017058 facet->value,
17059 xmlSchemaFormatQName(&str,
17060 base->targetNamespace, base->name));
17061 FREE_AND_NULL(str);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000017062 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017063 goto exit;
17064 } else if (facet->val == NULL) {
17065 if (ctxtGiven) {
17066 PERROR_INT("xmlSchemaCheckFacet",
17067 "value was not computed");
17068 }
17069 TODO
17070 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017071 break;
17072 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017073 case XML_SCHEMA_FACET_PATTERN:
17074 facet->regexp = xmlRegexpCompile(facet->value);
17075 if (facet->regexp == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017076 ret = XML_SCHEMAP_REGEXP_INVALID;
17077 /* No error message for RelaxNG. */
17078 if (ctxtGiven) {
17079 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) pctxt,
17080 ret, facet->node, typeDecl,
17081 "The value '%s' of the facet 'pattern' is not a "
17082 "valid regular expression",
17083 facet->value, NULL);
17084 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017085 }
17086 break;
17087 case XML_SCHEMA_FACET_TOTALDIGITS:
17088 case XML_SCHEMA_FACET_FRACTIONDIGITS:
17089 case XML_SCHEMA_FACET_LENGTH:
17090 case XML_SCHEMA_FACET_MAXLENGTH:
17091 case XML_SCHEMA_FACET_MINLENGTH:{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017092 ret = xmlSchemaValidatePredefinedType(
17093 xmlSchemaGetBuiltInType(XML_SCHEMAS_NNINTEGER),
17094 facet->value, &(facet->val));
17095 if (ret != 0) {
17096 if (ret < 0) {
17097 /* No error message for RelaxNG. */
17098 if (ctxtGiven) {
17099 PERROR_INT("xmlSchemaCheckFacet",
17100 "validating facet value");
17101 }
17102 goto internal_error;
17103 }
17104 ret = XML_SCHEMAP_INVALID_FACET_VALUE;
17105 /* No error message for RelaxNG. */
17106 if (ctxtGiven) {
17107 /* error code */
17108 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) pctxt,
17109 ret, facet->node, typeDecl,
17110 "The value '%s' of the facet '%s' is not a valid "
17111 "'nonNegativeInteger'",
17112 facet->value,
17113 xmlSchemaFacetTypeToString(facet->type));
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017114 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017115 }
17116 break;
17117 }
17118 case XML_SCHEMA_FACET_WHITESPACE:{
17119 if (xmlStrEqual(facet->value, BAD_CAST "preserve")) {
17120 facet->whitespace = XML_SCHEMAS_FACET_PRESERVE;
17121 } else if (xmlStrEqual(facet->value, BAD_CAST "replace")) {
17122 facet->whitespace = XML_SCHEMAS_FACET_REPLACE;
17123 } else if (xmlStrEqual(facet->value, BAD_CAST "collapse")) {
17124 facet->whitespace = XML_SCHEMAS_FACET_COLLAPSE;
17125 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017126 ret = XML_SCHEMAP_INVALID_FACET_VALUE;
17127 /* No error message for RelaxNG. */
17128 if (ctxtGiven) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000017129 /* error was previously: XML_SCHEMAP_INVALID_WHITE_SPACE */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017130 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) pctxt,
17131 ret, facet->node, typeDecl,
17132 "The value '%s' of the facet 'whitespace' is not "
17133 "valid", facet->value, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017134 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017135 }
17136 }
17137 default:
17138 break;
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000017139 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017140exit:
17141 if ((! ctxtGiven) && (pctxt != NULL))
17142 xmlSchemaFreeParserCtxt(pctxt);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017143 return (ret);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017144internal_error:
17145 if ((! ctxtGiven) && (pctxt != NULL))
17146 xmlSchemaFreeParserCtxt(pctxt);
17147 return (-1);
Daniel Veillard8bc6cf92003-02-27 17:42:22 +000017148}
17149
17150/**
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017151 * xmlSchemaCheckFacetValues:
Daniel Veillard4255d502002-04-16 15:50:10 +000017152 * @typeDecl: the schema type definition
17153 * @ctxt: the schema parser context
17154 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017155 * Checks the default values types, especially for facets
Daniel Veillard4255d502002-04-16 15:50:10 +000017156 */
17157static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017158xmlSchemaCheckFacetValues(xmlSchemaTypePtr typeDecl,
17159 xmlSchemaParserCtxtPtr ctxt)
Daniel Veillard4255d502002-04-16 15:50:10 +000017160{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017161 const xmlChar *name = typeDecl->name;
Daniel Veillard01fa6152004-06-29 17:04:39 +000017162 /*
17163 * NOTE: It is intended to use the facets list, instead
17164 * of facetSet.
17165 */
17166 if (typeDecl->facets != NULL) {
17167 xmlSchemaFacetPtr facet = typeDecl->facets;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017168
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017169 /*
17170 * Temporarily assign the "schema" to the validation context
17171 * of the parser context. This is needed for NOTATION validation.
17172 */
17173 if (ctxt->vctxt == NULL) {
17174 if (xmlSchemaCreateVCtxtOnPCtxt(ctxt) == -1)
17175 return;
17176 }
17177 ctxt->vctxt->schema = ctxt->schema;
17178
Daniel Veillard01fa6152004-06-29 17:04:39 +000017179 while (facet != NULL) {
17180 xmlSchemaCheckFacet(facet, typeDecl, ctxt, name);
17181 facet = facet->next;
17182 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000017183
17184 ctxt->vctxt->schema = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017185 }
Daniel Veillard4255d502002-04-16 15:50:10 +000017186}
17187
17188/**
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017189 * xmlSchemaGetCircModelGrDefRef:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017190 * @ctxtMGroup: the searched model group
17191 * @selfMGroup: the second searched model group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017192 * @particle: the first particle
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017193 *
17194 * This one is intended to be used by
17195 * xmlSchemaCheckGroupDefCircular only.
17196 *
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017197 * Returns the particle with the circular model group definition reference,
17198 * otherwise NULL.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017199 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017200static xmlSchemaTreeItemPtr
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017201xmlSchemaGetCircModelGrDefRef(xmlSchemaModelGroupDefPtr groupDef,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017202 xmlSchemaTreeItemPtr particle)
17203{
17204 xmlSchemaTreeItemPtr circ = NULL;
17205 xmlSchemaTreeItemPtr term;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017206 xmlSchemaModelGroupDefPtr gdef;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017207
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017208 for (; particle != NULL; particle = particle->next) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017209 term = particle->children;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017210 if (term == NULL)
17211 continue;
17212 switch (term->type) {
17213 case XML_SCHEMA_TYPE_GROUP:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017214 gdef = (xmlSchemaModelGroupDefPtr) term;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017215 if (gdef == groupDef)
17216 return (particle);
17217 /*
17218 * Mark this model group definition to avoid infinite
17219 * recursion on circular references not yet examined.
17220 */
17221 if (gdef->flags & XML_SCHEMA_MODEL_GROUP_DEF_MARKED)
17222 continue;
17223 if (gdef->children != NULL) {
17224 gdef->flags |= XML_SCHEMA_MODEL_GROUP_DEF_MARKED;
17225 circ = xmlSchemaGetCircModelGrDefRef(groupDef,
17226 gdef->children->children);
17227 gdef->flags ^= XML_SCHEMA_MODEL_GROUP_DEF_MARKED;
17228 if (circ != NULL)
17229 return (circ);
17230 }
17231 break;
17232 case XML_SCHEMA_TYPE_SEQUENCE:
17233 case XML_SCHEMA_TYPE_CHOICE:
17234 case XML_SCHEMA_TYPE_ALL:
17235 circ = xmlSchemaGetCircModelGrDefRef(groupDef, term->children);
17236 if (circ != NULL)
17237 return (circ);
17238 break;
17239 default:
17240 break;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017241 }
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017242 }
17243 return (NULL);
17244}
17245
17246/**
17247 * xmlSchemaCheckGroupDefCircular:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017248 * @item: the model group definition
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017249 * @ctxt: the parser context
17250 * @name: the name
17251 *
17252 * Checks for circular references to model group definitions.
17253 */
17254static void
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017255xmlSchemaCheckGroupDefCircular(xmlSchemaModelGroupDefPtr item,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017256 xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017257 const xmlChar * name ATTRIBUTE_UNUSED)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017258{
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017259 /*
17260 * Schema Component Constraint: Model Group Correct
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017261 * 2 Circular groups are disallowed. That is, within the {particles}
17262 * of a group there must not be at any depth a particle whose {term}
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017263 * is the group itself.
17264 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017265 if ((item == NULL) ||
17266 (item->type != XML_SCHEMA_TYPE_GROUP) ||
17267 (item->children == NULL))
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017268 return;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017269 {
17270 xmlSchemaTreeItemPtr circ;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017271
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017272 circ = xmlSchemaGetCircModelGrDefRef(item, item->children->children);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017273 if (circ != NULL) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017274 xmlChar *str = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017275 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017276 * TODO: The error report is not adequate: this constraint
17277 * is defined for model groups but not definitions, but since
17278 * there cannot be any circular model groups without a model group
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017279 * definition (if not using a construction API), we check those
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017280 * defintions only.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017281 */
17282 xmlSchemaPCustomErr(ctxt,
17283 XML_SCHEMAP_MG_PROPS_CORRECT_2,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017284 NULL, NULL, GET_NODE(circ),
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017285 "Circular reference to the model group definition '%s' "
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017286 "defined", xmlSchemaFormatQName(&str,
17287 item->targetNamespace, item->name));
17288 FREE_AND_NULL(str)
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017289 /*
17290 * NOTE: We will cut the reference to avoid further
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017291 * confusion of the processor. This is a fatal error.
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017292 */
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017293 circ->children = NULL;
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017294 }
17295 }
17296}
17297
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017298/**
17299 * xmlSchemaGroupDefTermFixup:
17300 * @item: the particle with a model group definition as term
17301 * @ctxt: the parser context
17302 * @name: the name
17303 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017304 * Checks cos-all-limited.
17305 *
17306 * Assigns the model group of model group definitions to the "term"
17307 * of the referencing particle.
17308 * In xmlSchemaMiscRefFixup the model group definitions was assigned
17309 * to the "term", since needed for the circularity check.
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017310 */
17311static void
17312xmlSchemaGroupDefTermFixup(xmlSchemaParticlePtr item,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017313 xmlSchemaParserCtxtPtr ctxt ATTRIBUTE_UNUSED,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017314 const xmlChar * name ATTRIBUTE_UNUSED)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017315{
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017316 if ((item == NULL) ||
17317 (item->type != XML_SCHEMA_TYPE_PARTICLE) ||
17318 (item->children == NULL) ||
17319 (item->children->type != XML_SCHEMA_TYPE_GROUP) ||
17320 (item->children->children == NULL))
17321 return;
17322 item->children = item->children->children;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017323 /*
17324 * TODO: Not nice, but we will anchor cos-all-limited here.
17325 */
17326 if ((item->children->type == XML_SCHEMA_TYPE_ALL) &&
17327 (item->maxOccurs != 1)) {
17328 /*
17329 * SPEC (1.2) "the {term} property of a particle with
17330 * {max occurs}=1which is part of a pair which constitutes the
17331 * {content type} of a complex type definition."
17332 */
17333 xmlSchemaPCustomErr(ctxt,
17334 XML_SCHEMAP_SRC_ATTRIBUTE_GROUP_3,
17335 NULL, (xmlSchemaTypePtr) item, item->node,
17336 "The particle's 'maxOccurs' must be 1, since an xs:all model "
17337 "group is its term", NULL);
17338 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017339}
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017340
17341/**
17342 * xmlSchemaGetCircAttrGrRef:
17343 * @ctxtGr: the searched attribute group
17344 * @attr: the current attribute list to be processed
17345 *
17346 * This one is intended to be used by
17347 * xmlSchemaCheckSRCAttributeGroupCircular only.
17348 *
17349 * Returns the circular attribute grou reference, otherwise NULL.
17350 */
17351static xmlSchemaAttributeGroupPtr
17352xmlSchemaGetCircAttrGrRef(xmlSchemaAttributeGroupPtr ctxtGr,
17353 xmlSchemaAttributePtr attr)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017354{
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017355 xmlSchemaAttributeGroupPtr circ = NULL, gr;
17356 int marked;
17357 /*
17358 * We will search for an attribute group reference which
17359 * references the context attribute group.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017360 */
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017361 while (attr != NULL) {
17362 marked = 0;
17363 if (attr->type == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
17364 gr = (xmlSchemaAttributeGroupPtr) attr;
17365 if (gr->refItem != NULL) {
17366 if (gr->refItem == ctxtGr)
17367 return (gr);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017368 else if (gr->refItem->flags &
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017369 XML_SCHEMAS_ATTRGROUP_MARKED) {
17370 attr = attr->next;
17371 continue;
17372 } else {
17373 /*
17374 * Mark as visited to avoid infinite recursion on
17375 * circular references not yet examined.
17376 */
17377 gr->refItem->flags |= XML_SCHEMAS_ATTRGROUP_MARKED;
17378 marked = 1;
17379 }
17380 }
17381 if (gr->attributes != NULL)
17382 circ = xmlSchemaGetCircAttrGrRef(ctxtGr, gr->attributes);
17383 /*
17384 * Unmark the visited group's attributes.
17385 */
17386 if (marked)
17387 gr->refItem->flags ^= XML_SCHEMAS_ATTRGROUP_MARKED;
17388 if (circ != NULL)
17389 return (circ);
17390 }
17391 attr = attr->next;
17392 }
17393 return (NULL);
17394}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017395
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017396/**
17397 * xmlSchemaCheckSRCAttributeGroupCircular:
17398 * attrGr: the attribute group definition
17399 * @ctxt: the parser context
17400 * @name: the name
17401 *
17402 * Checks for circular references of attribute groups.
17403 */
17404static void
17405xmlSchemaCheckAttributeGroupCircular(xmlSchemaAttributeGroupPtr attrGr,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017406 xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017407 const xmlChar * name ATTRIBUTE_UNUSED)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017408{
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017409 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017410 * Schema Representation Constraint:
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017411 * Attribute Group Definition Representation OK
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017412 * 3 Circular group reference is disallowed outside <redefine>.
17413 * That is, unless this element information item's parent is
17414 * <redefine>, then among the [children], if any, there must
17415 * not be an <attributeGroup> with ref [attribute] which resolves
17416 * to the component corresponding to this <attributeGroup>. Indirect
17417 * circularity is also ruled out. That is, when QName resolution
17418 * (Schema Document) (§3.15.3) is applied to a ·QName· arising from
17419 * any <attributeGroup>s with a ref [attribute] among the [children],
17420 * it must not be the case that a ·QName· is encountered at any depth
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017421 * which resolves to the component corresponding to this <attributeGroup>.
17422 */
17423 /*
17424 * Only global components can be referenced.
17425 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017426 if (((attrGr->flags & XML_SCHEMAS_ATTRGROUP_GLOBAL) == 0) ||
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017427 (attrGr->attributes == NULL))
17428 return;
17429 else {
17430 xmlSchemaAttributeGroupPtr circ;
17431
17432 circ = xmlSchemaGetCircAttrGrRef(attrGr, attrGr->attributes);
17433 if (circ != NULL) {
17434 /*
17435 * TODO: Report the referenced attr group as QName.
17436 */
17437 xmlSchemaPCustomErr(ctxt,
17438 XML_SCHEMAP_SRC_ATTRIBUTE_GROUP_3,
17439 NULL, NULL, circ->node,
17440 "Circular reference to the attribute group '%s' "
17441 "defined", attrGr->name);
17442 /*
17443 * NOTE: We will cut the reference to avoid further
17444 * confusion of the processor.
17445 * BADSPEC: The spec should define how to process in this case.
17446 */
17447 circ->attributes = NULL;
17448 circ->refItem = NULL;
17449 }
17450 }
17451}
17452
17453/**
Daniel Veillard13e04c62002-04-23 17:51:29 +000017454 * xmlSchemaAttrGrpFixup:
17455 * @attrgrpDecl: the schema attribute definition
17456 * @ctxt: the schema parser context
17457 * @name: the attribute name
17458 *
17459 * Fixes finish doing the computations on the attributes definitions
17460 */
17461static void
Daniel Veillard3646d642004-06-02 19:19:14 +000017462xmlSchemaAttrGrpFixup(xmlSchemaAttributeGroupPtr attrgrp,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017463 xmlSchemaParserCtxtPtr ctxt, const xmlChar * name)
Daniel Veillard13e04c62002-04-23 17:51:29 +000017464{
17465 if (name == NULL)
Daniel Veillard3646d642004-06-02 19:19:14 +000017466 name = attrgrp->name;
17467 if (attrgrp->attributes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017468 return;
Daniel Veillard3646d642004-06-02 19:19:14 +000017469 if (attrgrp->ref != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017470 xmlSchemaAttributeGroupPtr ref;
Daniel Veillard13e04c62002-04-23 17:51:29 +000017471
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017472 ref = xmlSchemaGetAttributeGroup(ctxt->schema, attrgrp->ref,
Daniel Veillardc0826a72004-08-10 14:17:33 +000017473 attrgrp->refNs);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017474 if (ref == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017475 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000017476 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017477 (xmlSchemaTypePtr) attrgrp, attrgrp->node,
17478 "ref", attrgrp->ref, attrgrp->refNs,
Daniel Veillardc0826a72004-08-10 14:17:33 +000017479 XML_SCHEMA_TYPE_ATTRIBUTEGROUP, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017480 return;
17481 }
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000017482 attrgrp->refItem = ref;
17483 /*
17484 * Check for self reference!
17485 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000017486 xmlSchemaAttrGrpFixup(ref, ctxt, NULL);
Daniel Veillard3646d642004-06-02 19:19:14 +000017487 attrgrp->attributes = ref->attributes;
17488 attrgrp->attributeWildcard = ref->attributeWildcard;
17489 }
Daniel Veillard13e04c62002-04-23 17:51:29 +000017490}
17491
17492/**
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017493 * xmlSchemaAttrCheckValConstr:
17494 * @item: an schema attribute declaration/use
17495 * @ctxt: a schema parser context
17496 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017497 *
17498 *
17499 * Schema Component Constraint: Attribute Declaration Properties Correct
17500 * (a-props-correct)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017501 * Validates the value constraints of an attribute declaration/use.
Daniel Veillard4255d502002-04-16 15:50:10 +000017502 *
17503 * Fixes finish doing the computations on the attributes definitions
17504 */
17505static void
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017506xmlSchemaCheckAttrValConstr(xmlSchemaAttributePtr item,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017507 xmlSchemaParserCtxtPtr pctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017508 const xmlChar * name ATTRIBUTE_UNUSED)
17509{
17510
17511 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017512 * 2 if there is a {value constraint}, the canonical lexical
17513 * representation of its value must be ·valid· with respect
17514 * to the {type definition} as defined in String Valid (§3.14.4).
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017515 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017516 if (item->defValue != NULL) {
17517 int ret;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017518
17519 if (item->subtypes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017520 PERROR_INT("xmlSchemaCheckAttrValConstr",
17521 "type is missing");
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017522 return;
17523 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017524 ret = xmlSchemaVCheckCVCSimpleType((xmlSchemaAbstractCtxtPtr) pctxt,
17525 item->node, item->subtypes, item->defValue, &(item->defVal),
17526 1, 1, 0);
17527 if (ret != 0) {
17528 if (ret < 0) {
17529 PERROR_INT("xmlSchemaAttrCheckValConstr",
17530 "calling xmlSchemaVCheckCVCSimpleType()");
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017531 return;
17532 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017533 ret = XML_SCHEMAP_A_PROPS_CORRECT_2;
17534 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) pctxt,
17535 ret, item->node, (xmlSchemaTypePtr) item,
17536 "The value of the value constraint is not valid", NULL, NULL);
17537 return;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017538 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017539 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017540}
17541
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017542static xmlSchemaElementPtr
17543xmlSchemaCheckSubstGroupCircular(xmlSchemaElementPtr elemDecl,
17544 xmlSchemaElementPtr ancestor)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017545{
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017546 xmlSchemaElementPtr ret;
17547
17548 if (SUBST_GROUP_AFF(ancestor) == NULL)
17549 return (NULL);
17550 if (SUBST_GROUP_AFF(ancestor) == elemDecl)
17551 return (ancestor);
17552
17553 if (SUBST_GROUP_AFF(ancestor)->flags & XML_SCHEMAS_ELEM_CIRCULAR)
17554 return (NULL);
17555 SUBST_GROUP_AFF(ancestor)->flags |= XML_SCHEMAS_ELEM_CIRCULAR;
17556 ret = xmlSchemaCheckSubstGroupCircular(elemDecl,
17557 SUBST_GROUP_AFF(ancestor));
17558 SUBST_GROUP_AFF(ancestor)->flags ^= XML_SCHEMAS_ELEM_CIRCULAR;
17559
17560 return (ret);
17561}
17562
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017563/**
17564 * xmlSchemaCheckElemPropsCorrect:
17565 * @ctxt: a schema parser context
17566 * @decl: the element declaration
17567 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017568 *
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017569 * Schema Component Constraint:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017570 * Element Declaration Properties Correct (e-props-correct)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017571 *
17572 * STATUS:
17573 * missing: (6)
17574 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017575static int
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017576xmlSchemaCheckElemPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
17577 xmlSchemaElementPtr elemDecl)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017578{
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017579 int ret = 0;
17580 xmlSchemaTypePtr typeDef = ELEM_TYPE(elemDecl);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017581 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017582 * SPEC (1) "The values of the properties of an element declaration
17583 * must be as described in the property tableau in The Element
17584 * Declaration Schema Component (§3.3.1), modulo the impact of Missing
17585 * Sub-components (§5.3)."
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017586 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017587 if (SUBST_GROUP_AFF(elemDecl) != NULL) {
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017588 xmlSchemaElementPtr head = SUBST_GROUP_AFF(elemDecl), circ;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017589
17590 xmlSchemaCheckElementDeclComponent(head, pctxt, NULL);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017591 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017592 * SPEC (3) "If there is a non-·absent· {substitution group
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017593 * affiliation}, then {scope} must be global."
17594 */
17595 if ((elemDecl->flags & XML_SCHEMAS_ELEM_GLOBAL) == 0) {
17596 xmlSchemaPCustomErr(pctxt,
17597 XML_SCHEMAP_E_PROPS_CORRECT_3,
17598 NULL, (xmlSchemaTypePtr) elemDecl, elemDecl->node,
17599 "Only global element declarations can have a "
17600 "substitution group affiliation", NULL);
17601 ret = XML_SCHEMAP_E_PROPS_CORRECT_3;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017602 }
17603 /*
17604 * TODO: SPEC (6) "Circular substitution groups are disallowed.
17605 * That is, it must not be possible to return to an element declaration
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017606 * by repeatedly following the {substitution group affiliation}
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017607 * property."
17608 */
17609 if (head == elemDecl)
17610 circ = head;
17611 else if (SUBST_GROUP_AFF(head) != NULL)
17612 circ = xmlSchemaCheckSubstGroupCircular(head, head);
17613 else
17614 circ = NULL;
17615 if (circ != NULL) {
17616 xmlChar *strA = NULL, *strB = NULL;
17617
17618 xmlSchemaPCustomErrExt(pctxt,
17619 XML_SCHEMAP_E_PROPS_CORRECT_6,
17620 NULL, (xmlSchemaTypePtr) circ, circ->node,
17621 "The element declaration '%s' defines a circular "
17622 "substitution group to element declaration '%s'",
17623 xmlSchemaGetComponentQName(&strA, circ),
17624 xmlSchemaGetComponentQName(&strB, head),
17625 NULL);
17626 FREE_AND_NULL(strA)
17627 FREE_AND_NULL(strB)
17628 ret = XML_SCHEMAP_E_PROPS_CORRECT_6;
17629 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017630 /*
17631 * SPEC (4) "If there is a {substitution group affiliation},
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017632 * the {type definition}
17633 * of the element declaration must be validly derived from the {type
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017634 * definition} of the {substitution group affiliation}, given the value
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017635 * of the {substitution group exclusions} of the {substitution group
17636 * affiliation}, as defined in Type Derivation OK (Complex) (§3.4.6)
17637 * (if the {type definition} is complex) or as defined in
17638 * Type Derivation OK (Simple) (§3.14.6) (if the {type definition} is
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017639 * simple)."
17640 *
17641 * NOTE: {substitution group exclusions} means the values of the
17642 * attribute "final".
17643 */
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017644
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017645 if (typeDef != ELEM_TYPE(SUBST_GROUP_AFF(elemDecl))) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017646 int set = 0;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017647
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017648 if (head->flags & XML_SCHEMAS_ELEM_FINAL_EXTENSION)
17649 set |= SUBSET_EXTENSION;
17650 if (head->flags & XML_SCHEMAS_ELEM_FINAL_RESTRICTION)
17651 set |= SUBSET_RESTRICTION;
17652
17653 if (xmlSchemaCheckCOSDerivedOK(typeDef,
17654 ELEM_TYPE(head), set) != 0) {
17655 xmlChar *strA = NULL, *strB = NULL, *strC = NULL;
17656
17657 ret = XML_SCHEMAP_E_PROPS_CORRECT_4;
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017658 xmlSchemaPCustomErrExt(pctxt,
17659 XML_SCHEMAP_E_PROPS_CORRECT_4,
17660 NULL, (xmlSchemaTypePtr) elemDecl, elemDecl->node,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017661 "The type definition '%s' was "
17662 "either rejected by the substitution group "
17663 "affiliation '%s', or not validly derived from its type "
17664 "definition '%s'",
17665 xmlSchemaGetComponentQName(&strA, typeDef),
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017666 xmlSchemaGetComponentQName(&strB, head),
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017667 xmlSchemaGetComponentQName(&strC, ELEM_TYPE(head)));
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017668 FREE_AND_NULL(strA)
17669 FREE_AND_NULL(strB)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017670 FREE_AND_NULL(strC)
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017671 }
17672 }
17673 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017674 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017675 * SPEC (5) "If the {type definition} or {type definition}'s
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017676 * {content type}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017677 * is or is derived from ID then there must not be a {value constraint}.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017678 * Note: The use of ID as a type definition for elements goes beyond
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017679 * XML 1.0, and should be avoided if backwards compatibility is desired"
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017680 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017681 if ((elemDecl->value != NULL) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017682 ((IS_SIMPLE_TYPE(typeDef) &&
17683 xmlSchemaIsDerivedFromBuiltInType(typeDef, XML_SCHEMAS_ID)) ||
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017684 (IS_COMPLEX_TYPE(typeDef) &&
17685 HAS_SIMPLE_CONTENT(typeDef) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017686 xmlSchemaIsDerivedFromBuiltInType(typeDef->contentTypeDef,
17687 XML_SCHEMAS_ID)))) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017688
17689 ret = XML_SCHEMAP_E_PROPS_CORRECT_5;
17690 xmlSchemaPCustomErr(pctxt,
17691 XML_SCHEMAP_E_PROPS_CORRECT_5,
17692 NULL, (xmlSchemaTypePtr) elemDecl, elemDecl->node,
17693 "The type definition (or type definition's content type) is or "
17694 "is derived from ID; value constraints are not allowed in "
17695 "conjunction with such a type definition", NULL);
17696 } else if (elemDecl->value != NULL) {
17697 int vcret;
17698 xmlNodePtr node = NULL;
17699
17700 /*
17701 * SPEC (2) "If there is a {value constraint}, the canonical lexical
17702 * representation of its value must be ·valid· with respect to the
17703 * {type definition} as defined in Element Default Valid (Immediate)
17704 * (§3.3.6)."
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017705 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017706 if (typeDef == NULL) {
17707 xmlSchemaPErr(pctxt, elemDecl->node,
17708 XML_SCHEMAP_INTERNAL,
17709 "Internal error: xmlSchemaCheckElemPropsCorrect, "
17710 "type is missing... skipping validation of "
17711 "the value constraint", NULL, NULL);
17712 return (-1);
17713 }
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017714 if (elemDecl->node != NULL) {
17715 if (elemDecl->flags & XML_SCHEMAS_ELEM_FIXED)
17716 node = (xmlNodePtr) xmlHasProp(elemDecl->node,
17717 BAD_CAST "fixed");
17718 else
17719 node = (xmlNodePtr) xmlHasProp(elemDecl->node,
17720 BAD_CAST "default");
17721 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017722 vcret = xmlSchemaParseCheckCOSValidDefault(pctxt, node,
17723 typeDef, elemDecl->value, &(elemDecl->defVal));
17724 if (vcret != 0) {
17725 if (vcret < 0) {
17726 PERROR_INT("xmlSchemaElemCheckValConstr",
17727 "failed to validate the value constraint of an "
17728 "element declaration");
17729 return (-1);
17730 }
17731 return (vcret);
17732 }
17733 }
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017734
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017735 return (ret);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017736}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017737
17738/**
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017739 * xmlSchemaCheckElemSubstGroup:
17740 * @ctxt: a schema parser context
17741 * @decl: the element declaration
17742 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017743 *
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017744 * Schema Component Constraint:
17745 * Substitution Group (cos-equiv-class)
17746 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017747 * In Libxml2 the subst. groups will be precomputed, in terms of that
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017748 * a list will be built for each subst. group head, holding all direct
17749 * referents to this head.
17750 * NOTE that this function needs:
17751 * 1. circular subst. groups to be checked beforehand
17752 * 2. the declaration's type to be derived from the head's type
17753 *
17754 * STATUS:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017755 *
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017756 */
17757static void
17758xmlSchemaCheckElemSubstGroup(xmlSchemaParserCtxtPtr ctxt,
17759 xmlSchemaElementPtr elemDecl)
17760{
17761 if ((SUBST_GROUP_AFF(elemDecl) == NULL) ||
17762 /* SPEC (1) "Its {abstract} is false." */
17763 (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT))
17764 return;
17765 {
17766 xmlSchemaElementPtr head;
17767 xmlSchemaTypePtr headType, type;
17768 int set, methSet;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017769 /*
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017770 * SPEC (2) "It is validly substitutable for HEAD subject to HEAD's
17771 * {disallowed substitutions} as the blocking constraint, as defined in
17772 * Substitution Group OK (Transitive) (§3.3.6)."
17773 */
17774 for (head = SUBST_GROUP_AFF(elemDecl); head != NULL;
17775 head = SUBST_GROUP_AFF(head)) {
17776 set = 0;
17777 methSet = 0;
17778 /*
17779 * The blocking constraints.
17780 */
17781 if (head->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION)
17782 continue;
17783 headType = head->subtypes;
17784 type = elemDecl->subtypes;
17785 if (headType == type)
17786 goto add_member;
17787 if (head->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION)
17788 set |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
17789 if (head->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION)
17790 set |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
17791 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017792 * SPEC: Substitution Group OK (Transitive) (2.3)
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017793 * "The set of all {derivation method}s involved in the
17794 * derivation of D's {type definition} from C's {type definition}
17795 * does not intersect with the union of the blocking constraint,
17796 * C's {prohibited substitutions} (if C is complex, otherwise the
17797 * empty set) and the {prohibited substitutions} (respectively the
17798 * empty set) of any intermediate {type definition}s in the
17799 * derivation of D's {type definition} from C's {type definition}."
17800 */
17801 /*
17802 * OPTIMIZE TODO: Optimize this a bit, since, if traversing the
17803 * subst.head axis, the methSet does not need to be computed for
17804 * the full depth over and over.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017805 */
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017806 /*
17807 * The set of all {derivation method}s involved in the derivation
17808 */
17809 while ((type != NULL) && (type != headType)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017810 if ((type->flags &
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017811 XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION) &&
17812 ((methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
17813 methSet |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017814
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017815 if ((type->flags &
17816 XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION) &&
17817 ((methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
17818 methSet |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
17819
17820 type = type->baseType;
17821 }
17822 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017823 * The {prohibited substitutions} of all intermediate types +
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017824 * the head's type.
17825 */
17826 type = elemDecl->subtypes->baseType;
17827 while (type != NULL) {
17828 if (IS_COMPLEX_TYPE(type)) {
17829 if ((type->flags &
17830 XML_SCHEMAS_TYPE_BLOCK_EXTENSION) &&
17831 ((set & XML_SCHEMAS_TYPE_BLOCK_EXTENSION) == 0))
17832 set |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
17833 if ((type->flags &
17834 XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) &&
17835 ((set & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
17836 set |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
17837 } else
17838 break;
17839 if (type == headType)
17840 break;
17841 type = type->baseType;
17842 }
17843 if ((set != 0) &&
17844 (((set & XML_SCHEMAS_TYPE_BLOCK_EXTENSION) &&
17845 (methSet & XML_SCHEMAS_TYPE_BLOCK_EXTENSION)) ||
17846 ((set & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) &&
17847 (methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION)))) {
17848 continue;
17849 }
17850add_member:
17851 xmlSchemaAddElementSubstitutionMember(ctxt, head, elemDecl);
17852 if ((head->flags & XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) == 0)
17853 head->flags |= XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD;
17854 }
17855 }
17856}
17857
17858/**
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017859 * xmlSchemaCheckElementDeclComponent
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017860 * @item: an schema element declaration/particle
17861 * @ctxt: a schema parser context
17862 * @name: the name of the attribute
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017863 *
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017864 * Validates the value constraints of an element declaration.
17865 *
17866 * Fixes finish doing the computations on the element declarations.
17867 */
17868static void
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017869xmlSchemaCheckElementDeclComponent(xmlSchemaElementPtr elemDecl,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017870 xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017871 const xmlChar * name ATTRIBUTE_UNUSED)
17872{
17873 if (elemDecl == NULL)
17874 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017875 if (elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_CHECKED)
17876 return;
17877 elemDecl->flags |= XML_SCHEMAS_ELEM_INTERNAL_CHECKED;
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000017878 if (xmlSchemaCheckElemPropsCorrect(ctxt, elemDecl) == 0)
17879 xmlSchemaCheckElemSubstGroup(ctxt, elemDecl);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017880}
17881
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017882/**
17883 * xmlSchemaMiscRefFixup:
17884 * @item: an schema component
17885 * @ctxt: a schema parser context
17886 * @name: the internal name of the component
17887 *
17888 * Resolves references of misc. schema components.
17889 */
17890static void
17891xmlSchemaMiscRefFixup(xmlSchemaTreeItemPtr item,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017892 xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017893 const xmlChar * name ATTRIBUTE_UNUSED)
17894{
17895 if (item->type == XML_SCHEMA_TYPE_PARTICLE) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017896 if ((item->children != NULL) &&
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017897 (item->children->type == XML_SCHEMA_EXTRA_QNAMEREF)) {
17898 xmlSchemaQNameRefPtr ref = (xmlSchemaQNameRefPtr) item->children;
17899 xmlSchemaTreeItemPtr refItem;
17900 /*
17901 * Resolve the reference.
17902 */
17903 item->children = NULL;
17904 refItem = xmlSchemaGetNamedComponent(ctxt->schema,
17905 ref->itemType, ref->name, ref->targetNamespace);
17906 if (refItem == NULL) {
17907 xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017908 NULL, GET_NODE(item), "ref", ref->name,
17909 ref->targetNamespace, ref->itemType, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017910 } else {
17911 if (refItem->type == XML_SCHEMA_TYPE_GROUP) {
17912 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017913 * NOTE that we will assign the model group definition
17914 * itself to the "term" of the particle. This will ease
17915 * the check for circular model group definitions. After
17916 * that the "term" will be assigned the model group of the
17917 * model group definition.
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017918 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000017919 item->children = refItem;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017920 } else
17921 item->children = refItem;
17922 }
17923 }
17924 }
17925}
17926
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017927static int
17928xmlSchemaAreValuesEqual(xmlSchemaValPtr x,
17929 xmlSchemaValPtr y)
17930{
17931 xmlSchemaTypePtr tx, ty, ptx, pty;
17932 int ret;
17933
17934 while (x != NULL) {
17935 /* Same types. */
17936 tx = xmlSchemaGetBuiltInType(xmlSchemaGetValType(x));
17937 ty = xmlSchemaGetBuiltInType(xmlSchemaGetValType(y));
17938 ptx = xmlSchemaGetPrimitiveType(tx);
17939 pty = xmlSchemaGetPrimitiveType(ty);
17940 /*
17941 * (1) if a datatype T' is ·derived· by ·restriction· from an
17942 * atomic datatype T then the ·value space· of T' is a subset of
17943 * the ·value space· of T. */
17944 /*
17945 * (2) if datatypes T' and T'' are ·derived· by ·restriction·
17946 * from a common atomic ancestor T then the ·value space·s of T'
17947 * and T'' may overlap.
17948 */
17949 if (ptx != pty)
17950 return(0);
17951 /*
17952 * We assume computed values to be normalized, so do a fast
17953 * string comparison for string based types.
17954 */
17955 if ((ptx->builtInType == XML_SCHEMAS_STRING) ||
17956 IS_ANY_SIMPLE_TYPE(ptx)) {
17957 if (! xmlStrEqual(
17958 xmlSchemaValueGetAsString(x),
17959 xmlSchemaValueGetAsString(y)))
17960 return (0);
17961 } else {
17962 ret = xmlSchemaCompareValuesWhtsp(
17963 x, XML_SCHEMA_WHITESPACE_PRESERVE,
17964 y, XML_SCHEMA_WHITESPACE_PRESERVE);
17965 if (ret == -2)
17966 return(-1);
17967 if (ret != 0)
17968 return(0);
17969 }
17970 /*
17971 * Lists.
17972 */
17973 x = xmlSchemaValueGetNext(x);
17974 if (x != NULL) {
17975 y = xmlSchemaValueGetNext(y);
17976 if (y == NULL)
17977 return (0);
17978 } else if (xmlSchemaValueGetNext(y) != NULL)
17979 return (0);
17980 else
17981 return (1);
17982 }
17983 return (0);
17984}
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000017985
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017986/**
17987 * xmlSchemaAttrFixup:
17988 * @item: an schema attribute declaration/use.
17989 * @ctxt: a schema parser context
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017990 * @name: the name of the attribute
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017991 *
17992 * Fixes finish doing the computations on attribute declarations/uses.
17993 */
17994static void
17995xmlSchemaAttrFixup(xmlSchemaAttributePtr item,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017996 xmlSchemaParserCtxtPtr ctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000017997 const xmlChar * name ATTRIBUTE_UNUSED)
Daniel Veillard4255d502002-04-16 15:50:10 +000017998{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000017999 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000018000 * TODO: If including this is done twice (!) for every attribute.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018001 * -> Hmm, check if this is still done.
Daniel Veillardc0826a72004-08-10 14:17:33 +000018002 */
Daniel Veillard01fa6152004-06-29 17:04:39 +000018003 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018004 * The simple type definition corresponding to the <simpleType> element
18005 * information item in the [children], if present, otherwise the simple
18006 * type definition ·resolved· to by the ·actual value· of the type
Daniel Veillard01fa6152004-06-29 17:04:39 +000018007 * [attribute], if present, otherwise the ·simple ur-type definition·.
18008 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018009 if (item->flags & XML_SCHEMAS_ATTR_INTERNAL_RESOLVED)
Daniel Veillardc0826a72004-08-10 14:17:33 +000018010 return;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018011 item->flags |= XML_SCHEMAS_ATTR_INTERNAL_RESOLVED;
18012 if (item->subtypes != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018013 return;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018014 if (item->typeName != NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018015 xmlSchemaTypePtr type;
Daniel Veillard4255d502002-04-16 15:50:10 +000018016
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018017 type = xmlSchemaGetType(ctxt->schema, item->typeName,
18018 item->typeNs);
18019 if ((type == NULL) || (! IS_SIMPLE_TYPE(type))) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000018020 xmlSchemaPResCompAttrErr(ctxt,
Daniel Veillard01fa6152004-06-29 17:04:39 +000018021 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018022 (xmlSchemaTypePtr) item, item->node,
18023 "type", item->typeName, item->typeNs,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018024 XML_SCHEMA_TYPE_SIMPLE, NULL);
18025 } else
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018026 item->subtypes = type;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018027
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018028 } else if (item->ref != NULL) {
18029 xmlSchemaAttributePtr decl;
Daniel Veillard4255d502002-04-16 15:50:10 +000018030
Daniel Veillardc0826a72004-08-10 14:17:33 +000018031 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018032 * We have an attribute use here; assign the referenced
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018033 * attribute declaration.
18034 */
18035 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000018036 * TODO: Evaluate, what errors could occur if the declaration is not
18037 * found. It might be possible that the "typefixup" might crash if
18038 * no ref declaration was found.
18039 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018040 decl = xmlSchemaGetAttributeDecl(ctxt->schema, item->ref, item->refNs);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018041 if (decl == NULL) {
Daniel Veillardc0826a72004-08-10 14:17:33 +000018042 xmlSchemaPResCompAttrErr(ctxt,
18043 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018044 (xmlSchemaTypePtr) item, item->node,
18045 "ref", item->ref, item->refNs,
Daniel Veillardc0826a72004-08-10 14:17:33 +000018046 XML_SCHEMA_TYPE_ATTRIBUTE, NULL);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018047 return;
18048 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018049 item->refDecl = decl;
18050 xmlSchemaAttrFixup(decl, ctxt, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018051 item->subtypes = decl->subtypes;
18052 /*
18053 * Attribute Use Correct
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018054 * au-props-correct.2: If the {attribute declaration} has a fixed
18055 * {value constraint}, then if the attribute use itself has a
18056 * {value constraint}, it must also be fixed and its value must match
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018057 * that of the {attribute declaration}'s {value constraint}.
18058 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018059 if ((decl->flags & XML_SCHEMAS_ATTR_FIXED) &&
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018060 (item->defValue != NULL)) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018061 if ((item->flags & XML_SCHEMAS_ATTR_FIXED) == 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018062 xmlSchemaPCustomErr(ctxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018063 XML_SCHEMAP_AU_PROPS_CORRECT_2,
18064 NULL, NULL, item->node,
18065 "The attribute declaration has a 'fixed' value constraint "
18066 ", thus it must be 'fixed' in attribute use as well",
18067 NULL);
18068 } else {
18069 if (! xmlSchemaAreValuesEqual(item->defVal, decl->defVal)) {
18070 xmlSchemaPCustomErr(ctxt,
18071 XML_SCHEMAP_AU_PROPS_CORRECT_2,
18072 NULL, NULL, item->node,
18073 "The 'fixed' value constraint of the attribute use "
18074 "must match the attribute declaration's value "
18075 "constraint '%s'",
18076 decl->defValue);
18077 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018078 }
18079 /*
18080 * FUTURE: One should change the values of the attr. use
18081 * if ever validation should be attempted even if the
18082 * schema itself was not fully valid.
18083 */
18084 }
Daniel Veillard3646d642004-06-02 19:19:14 +000018085 } else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018086 item->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
18087 }
Daniel Veillard4255d502002-04-16 15:50:10 +000018088}
18089
18090/**
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018091 * xmlSchemaResolveIDCKeyRef:
18092 * @idc: the identity-constraint definition
18093 * @ctxt: the schema parser context
18094 * @name: the attribute name
18095 *
18096 * Resolve keyRef references to key/unique IDCs.
18097 */
18098static void
18099xmlSchemaResolveIDCKeyRef(xmlSchemaIDCPtr idc,
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000018100 xmlSchemaParserCtxtPtr pctxt,
Kasimier T. Buchcik87250a92005-01-28 15:59:53 +000018101 const xmlChar * name ATTRIBUTE_UNUSED)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018102{
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018103 if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF)
18104 return;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018105 if (idc->ref->name != NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018106 idc->ref->item = (xmlSchemaBasicItemPtr) xmlHashLookup2(
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000018107 pctxt->schema->idcDef,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018108 idc->ref->name,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018109 idc->ref->targetNamespace);
18110 if (idc->ref->item == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018111 /*
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018112 * TODO: It is actually not an error to fail to resolve.
18113 */
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000018114 xmlSchemaPResCompAttrErr(pctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018115 XML_SCHEMAP_SRC_RESOLVE,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018116 (xmlSchemaTypePtr) idc, idc->node,
18117 "refer", idc->ref->name,
18118 idc->ref->targetNamespace,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018119 XML_SCHEMA_TYPE_IDC_KEYREF, NULL);
18120 return;
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000018121 } else {
18122 if (idc->nbFields !=
18123 ((xmlSchemaIDCPtr) idc->ref->item)->nbFields) {
18124 xmlChar *str = NULL;
18125 xmlSchemaIDCPtr refer;
18126
18127 refer = (xmlSchemaIDCPtr) idc->ref->item;
18128 /*
18129 * SPEC c-props-correct(2)
18130 * "If the {identity-constraint category} is keyref,
18131 * the cardinality of the {fields} must equal that of
18132 * the {fields} of the {referenced key}.
18133 */
18134 xmlSchemaPCustomErr(pctxt,
18135 XML_SCHEMAP_C_PROPS_CORRECT,
18136 NULL, (xmlSchemaTypePtr) idc, idc->node,
18137 "The cardinality of the keyref differs from the "
18138 "cardinality of the referenced key '%s'",
18139 xmlSchemaFormatQName(&str, refer->targetNamespace,
18140 refer->name)
18141 );
18142 FREE_AND_NULL(str)
18143 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018144 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018145 }
18146}
18147
18148/**
Daniel Veillard4255d502002-04-16 15:50:10 +000018149 * xmlSchemaParse:
18150 * @ctxt: a schema validation context
Daniel Veillard4255d502002-04-16 15:50:10 +000018151 *
Daniel Veillard01c13b52002-12-10 15:19:08 +000018152 * parse a schema definition resource and build an internal
Daniel Veillard4255d502002-04-16 15:50:10 +000018153 * XML Shema struture which can be used to validate instances.
18154 * *WARNING* this interface is highly subject to change
18155 *
18156 * Returns the internal XML Schema structure built from the resource or
18157 * NULL in case of error
18158 */
18159xmlSchemaPtr
18160xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt)
18161{
18162 xmlSchemaPtr ret = NULL;
18163 xmlDocPtr doc;
Daniel Veillardbd2904b2003-11-25 15:38:59 +000018164 xmlNodePtr root;
Daniel Veillarddda22c12004-01-24 08:31:30 +000018165 int preserve = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000018166
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018167 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018168 * This one is used if the schema to be parsed was specified via
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018169 * the API; i.e. not automatically by the validated instance document.
18170 */
18171
Daniel Veillard4255d502002-04-16 15:50:10 +000018172 xmlSchemaInitTypes();
18173
Daniel Veillard6045c902002-10-09 21:13:59 +000018174 if (ctxt == NULL)
Daniel Veillard4255d502002-04-16 15:50:10 +000018175 return (NULL);
18176
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000018177 ctxt->nberrors = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000018178 ctxt->counter = 0;
18179 ctxt->container = NULL;
18180
18181 /*
18182 * First step is to parse the input document into an DOM/Infoset
18183 */
Daniel Veillard6045c902002-10-09 21:13:59 +000018184 if (ctxt->URL != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018185 doc = xmlReadFile((const char *) ctxt->URL, NULL,
Daniel Veillardbd2904b2003-11-25 15:38:59 +000018186 SCHEMAS_PARSE_OPTIONS);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018187 if (doc == NULL) {
18188 xmlSchemaPErr(ctxt, NULL,
18189 XML_SCHEMAP_FAILED_LOAD,
Daniel Veillardc0826a72004-08-10 14:17:33 +000018190 "xmlSchemaParse: could not load '%s'.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018191 ctxt->URL, NULL);
18192 return (NULL);
18193 }
Daniel Veillard6045c902002-10-09 21:13:59 +000018194 } else if (ctxt->buffer != NULL) {
Daniel Veillardbd2904b2003-11-25 15:38:59 +000018195 doc = xmlReadMemory(ctxt->buffer, ctxt->size, NULL, NULL,
18196 SCHEMAS_PARSE_OPTIONS);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018197 if (doc == NULL) {
18198 xmlSchemaPErr(ctxt, NULL,
18199 XML_SCHEMAP_FAILED_PARSE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000018200 "xmlSchemaParse: could not parse.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018201 NULL, NULL);
18202 return (NULL);
18203 }
18204 doc->URL = xmlStrdup(BAD_CAST "in_memory_buffer");
Daniel Veillard65765282004-01-08 16:59:30 +000018205 ctxt->URL = xmlDictLookup(ctxt->dict, BAD_CAST "in_memory_buffer", -1);
Daniel Veillard9d751502003-10-29 13:21:47 +000018206 } else if (ctxt->doc != NULL) {
18207 doc = ctxt->doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +000018208 preserve = 1;
Daniel Veillard6045c902002-10-09 21:13:59 +000018209 } else {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018210 xmlSchemaPErr(ctxt, NULL,
18211 XML_SCHEMAP_NOTHING_TO_PARSE,
Daniel Veillardc0826a72004-08-10 14:17:33 +000018212 "xmlSchemaParse: could not parse.\n",
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018213 NULL, NULL);
18214 return (NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000018215 }
18216
18217 /*
18218 * Then extract the root and Schema parse it
18219 */
18220 root = xmlDocGetRootElement(doc);
18221 if (root == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018222 xmlSchemaPErr(ctxt, (xmlNodePtr) doc,
18223 XML_SCHEMAP_NOROOT,
Daniel Veillardc0826a72004-08-10 14:17:33 +000018224 "The schema has no document element.\n", NULL, NULL);
Daniel Veillarddda22c12004-01-24 08:31:30 +000018225 if (!preserve) {
18226 xmlFreeDoc(doc);
18227 }
Daniel Veillard4255d502002-04-16 15:50:10 +000018228 return (NULL);
18229 }
18230
18231 /*
18232 * Remove all the blank text nodes
18233 */
Daniel Veillardbd2904b2003-11-25 15:38:59 +000018234 xmlSchemaCleanupDoc(ctxt, root);
Daniel Veillard4255d502002-04-16 15:50:10 +000018235
18236 /*
18237 * Then do the parsing for good
18238 */
18239 ret = xmlSchemaParseSchema(ctxt, root);
Daniel Veillard1d913862003-11-21 00:28:39 +000018240 if (ret == NULL) {
Daniel Veillarddda22c12004-01-24 08:31:30 +000018241 if (!preserve) {
18242 xmlFreeDoc(doc);
18243 }
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018244 return (NULL);
Daniel Veillard1d913862003-11-21 00:28:39 +000018245 }
Daniel Veillard4255d502002-04-16 15:50:10 +000018246 ret->doc = doc;
Daniel Veillarddda22c12004-01-24 08:31:30 +000018247 ret->preserve = preserve;
Daniel Veillard4255d502002-04-16 15:50:10 +000018248 ctxt->schema = ret;
Daniel Veillardc0826a72004-08-10 14:17:33 +000018249 ctxt->ctxtType = NULL;
18250 ctxt->parentItem = NULL;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018251
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018252 /*
18253 * Resolve base types of simple/complex types.
18254 */
18255 xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaResolveTypeDefs, ctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018256
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018257 if (ctxt->nberrors != 0)
18258 goto exit;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018259
18260 if (ret->volatiles != NULL) {
18261 xmlSchemaItemListPtr list = (xmlSchemaItemListPtr) ret->volatiles;
18262 int i;
18263 xmlSchemaTreeItemPtr item;
18264
18265 for (i = 0; i < list->nbItems; i++) {
18266 item = (xmlSchemaTreeItemPtr) list->items[i];
18267 if (item->type == XML_SCHEMA_TYPE_PARTICLE)
18268 xmlSchemaMiscRefFixup(item, ctxt, NULL);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018269 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018270 }
Daniel Veillard4255d502002-04-16 15:50:10 +000018271 /*
Daniel Veillardf2a12832003-11-24 13:04:35 +000018272 * Then fixup all attributes declarations
18273 */
18274 xmlHashScan(ret->attrDecl, (xmlHashScanner) xmlSchemaAttrFixup, ctxt);
Daniel Veillardf2a12832003-11-24 13:04:35 +000018275 /*
18276 * Then fixup all attributes group declarations
18277 */
18278 xmlHashScan(ret->attrgrpDecl, (xmlHashScanner) xmlSchemaAttrGrpFixup,
18279 ctxt);
Daniel Veillardf2a12832003-11-24 13:04:35 +000018280 /*
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018281 * Resolve identity-constraint keyRefs.
18282 */
18283 xmlHashScan(ret->idcDef, (xmlHashScanner) xmlSchemaResolveIDCKeyRef, ctxt);
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018284 /*
18285 * Check type defnitions for circular references.
18286 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018287 xmlHashScan(ret->typeDecl, (xmlHashScanner)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018288 xmlSchemaCheckTypeDefCircular, ctxt);
18289 /*
18290 * Check model groups defnitions for circular references.
18291 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018292 xmlHashScan(ret->groupDecl, (xmlHashScanner)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018293 xmlSchemaCheckGroupDefCircular, ctxt);
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018294 /*
18295 * Set the "term" of particles pointing to model group definitions
18296 * to the contained model group.
18297 */
18298 if (ret->volatiles != NULL) {
18299 xmlSchemaItemListPtr list = (xmlSchemaItemListPtr) ret->volatiles;
18300 int i;
18301 xmlSchemaParticlePtr item;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018302
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018303 for (i = 0; i < list->nbItems; i++) {
18304 item = (xmlSchemaParticlePtr) list->items[i];
18305 if (item->type == XML_SCHEMA_TYPE_PARTICLE)
18306 xmlSchemaGroupDefTermFixup(item, ctxt, NULL);
18307 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018308 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000018309 /*
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018310 * Check attribute groups for circular references.
18311 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018312 xmlHashScan(ret->attrgrpDecl, (xmlHashScanner)
18313 xmlSchemaCheckAttributeGroupCircular, ctxt);
Kasimier T. Buchcik383434b2004-09-03 18:55:35 +000018314 /*
Daniel Veillardc0826a72004-08-10 14:17:33 +000018315 * Then fix references of element declaration; apply constraints.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018316 */
Daniel Veillardc0826a72004-08-10 14:17:33 +000018317 xmlHashScanFull(ret->elemDecl,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018318 (xmlHashScannerFull) xmlSchemaElementFixup, ctxt);
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000018319 /*
18320 * We will stop here if the schema was not valid to avoid internal errors
18321 * on missing sub-components. This is not conforming to the spec, since it
18322 * allows missing components, but it might make further processing crash.
18323 * So see it as a very strict handling, which might be made more lax in the
18324 * future.
18325 */
18326 if (ctxt->nberrors != 0)
18327 goto exit;
18328 /*
18329 * Then fixup all types properties
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018330 */
18331 xmlHashScan(ret->typeDecl, (xmlHashScanner) xmlSchemaTypeFixup, ctxt);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018332 /*
18333 * Validate the value constraint of attribute declarations/uses.
18334 */
18335 xmlHashScan(ret->attrDecl, (xmlHashScanner) xmlSchemaCheckAttrValConstr, ctxt);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018336 /*
18337 * Validate the value constraint of element declarations.
18338 */
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018339 xmlHashScan(ret->elemDecl, (xmlHashScanner) xmlSchemaCheckElementDeclComponent, ctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018340
18341 if (ctxt->nberrors != 0)
18342 goto exit;
18343
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018344 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018345 * TODO: cos-element-consistent, cos-all-limited
18346 *
18347 * Then build the content model for all complex types
18348 */
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018349 xmlHashScan(ret->typeDecl,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018350 (xmlHashScanner) xmlSchemaBuildContentModel, ctxt);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018351
Kasimier T. Buchcikb474fa42005-03-11 12:34:42 +000018352exit:
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000018353 if (ctxt->nberrors != 0) {
18354 xmlSchemaFree(ret);
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018355 ret = NULL;
Daniel Veillard75bb3bb2003-05-12 15:25:56 +000018356 }
Daniel Veillard4255d502002-04-16 15:50:10 +000018357 return (ret);
18358}
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018359
Daniel Veillard4255d502002-04-16 15:50:10 +000018360/**
Daniel Veillard01c13b52002-12-10 15:19:08 +000018361 * xmlSchemaSetParserErrors:
Daniel Veillard4255d502002-04-16 15:50:10 +000018362 * @ctxt: a schema validation context
Daniel Veillard01c13b52002-12-10 15:19:08 +000018363 * @err: the error callback
18364 * @warn: the warning callback
18365 * @ctx: contextual data for the callbacks
Daniel Veillard4255d502002-04-16 15:50:10 +000018366 *
Daniel Veillard01c13b52002-12-10 15:19:08 +000018367 * Set the callback functions used to handle errors for a validation context
Daniel Veillard4255d502002-04-16 15:50:10 +000018368 */
18369void
18370xmlSchemaSetParserErrors(xmlSchemaParserCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018371 xmlSchemaValidityErrorFunc err,
18372 xmlSchemaValidityWarningFunc warn, void *ctx)
18373{
Daniel Veillard4255d502002-04-16 15:50:10 +000018374 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018375 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000018376 ctxt->error = err;
18377 ctxt->warning = warn;
18378 ctxt->userData = ctx;
18379}
18380
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000018381/**
Daniel Veillard259f0df2004-08-18 09:13:18 +000018382 * xmlSchemaGetParserErrors:
18383 * @ctxt: a XMl-Schema parser context
18384 * @err: the error callback result
18385 * @warn: the warning callback result
18386 * @ctx: contextual data for the callbacks result
18387 *
18388 * Get the callback information used to handle errors for a parser context
18389 *
18390 * Returns -1 in case of failure, 0 otherwise
18391 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018392int
Daniel Veillard259f0df2004-08-18 09:13:18 +000018393xmlSchemaGetParserErrors(xmlSchemaParserCtxtPtr ctxt,
18394 xmlSchemaValidityErrorFunc * err,
18395 xmlSchemaValidityWarningFunc * warn, void **ctx)
18396{
18397 if (ctxt == NULL)
18398 return(-1);
18399 if (err != NULL)
18400 *err = ctxt->error;
18401 if (warn != NULL)
18402 *warn = ctxt->warning;
18403 if (ctx != NULL)
18404 *ctx = ctxt->userData;
18405 return(0);
18406}
18407
18408/**
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000018409 * xmlSchemaFacetTypeToString:
18410 * @type: the facet type
18411 *
18412 * Convert the xmlSchemaTypeType to a char string.
18413 *
18414 * Returns the char string representation of the facet type if the
18415 * type is a facet and an "Internal Error" string otherwise.
18416 */
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018417static const xmlChar *
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000018418xmlSchemaFacetTypeToString(xmlSchemaTypeType type)
18419{
18420 switch (type) {
18421 case XML_SCHEMA_FACET_PATTERN:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018422 return (BAD_CAST "pattern");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018423 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018424 return (BAD_CAST "maxExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018425 case XML_SCHEMA_FACET_MAXINCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018426 return (BAD_CAST "maxInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018427 case XML_SCHEMA_FACET_MINEXCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018428 return (BAD_CAST "minExclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018429 case XML_SCHEMA_FACET_MININCLUSIVE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018430 return (BAD_CAST "minInclusive");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018431 case XML_SCHEMA_FACET_WHITESPACE:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018432 return (BAD_CAST "whiteSpace");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018433 case XML_SCHEMA_FACET_ENUMERATION:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018434 return (BAD_CAST "enumeration");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018435 case XML_SCHEMA_FACET_LENGTH:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018436 return (BAD_CAST "length");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018437 case XML_SCHEMA_FACET_MAXLENGTH:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018438 return (BAD_CAST "maxLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018439 case XML_SCHEMA_FACET_MINLENGTH:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018440 return (BAD_CAST "minLength");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018441 case XML_SCHEMA_FACET_TOTALDIGITS:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018442 return (BAD_CAST "totalDigits");
Daniel Veillardd0c9c322003-10-10 00:49:42 +000018443 case XML_SCHEMA_FACET_FRACTIONDIGITS:
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018444 return (BAD_CAST "fractionDigits");
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000018445 default:
18446 break;
18447 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018448 return (BAD_CAST "Internal Error");
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000018449}
18450
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018451static xmlSchemaWhitespaceValueType
Daniel Veillardc0826a72004-08-10 14:17:33 +000018452xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type)
18453{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018454 /*
18455 * The normalization type can be changed only for types which are derived
Daniel Veillardc0826a72004-08-10 14:17:33 +000018456 * from xsd:string.
18457 */
18458 if (type->type == XML_SCHEMA_TYPE_BASIC) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018459 /*
18460 * Note that we assume a whitespace of preserve for anySimpleType.
18461 */
18462 if ((type->builtInType == XML_SCHEMAS_STRING) ||
18463 (type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE))
18464 return(XML_SCHEMA_WHITESPACE_PRESERVE);
Kasimier T. Buchcik91feaf82004-11-12 14:04:58 +000018465 else if (type->builtInType == XML_SCHEMAS_NORMSTRING)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018466 return(XML_SCHEMA_WHITESPACE_REPLACE);
Daniel Veillardc0826a72004-08-10 14:17:33 +000018467 else {
18468 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018469 * For all ·atomic· datatypes other than string (and types ·derived·
18470 * by ·restriction· from it) the value of whiteSpace is fixed to
Daniel Veillardc0826a72004-08-10 14:17:33 +000018471 * collapse
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018472 * Note that this includes built-in list datatypes.
Daniel Veillardc0826a72004-08-10 14:17:33 +000018473 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018474 return(XML_SCHEMA_WHITESPACE_COLLAPSE);
Daniel Veillardc0826a72004-08-10 14:17:33 +000018475 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018476 } else if (VARIETY_LIST(type)) {
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018477 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018478 * For list types the facet "whiteSpace" is fixed to "collapse".
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018479 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018480 return (XML_SCHEMA_WHITESPACE_COLLAPSE);
18481 } else if (VARIETY_UNION(type)) {
18482 return (XML_SCHEMA_WHITESPACE_UNKNOWN);
18483 } else if (VARIETY_ATOMIC(type)) {
18484 if (type->flags & XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE)
18485 return (XML_SCHEMA_WHITESPACE_PRESERVE);
18486 else if (type->flags & XML_SCHEMAS_TYPE_WHITESPACE_REPLACE)
18487 return (XML_SCHEMA_WHITESPACE_REPLACE);
18488 else
18489 return (XML_SCHEMA_WHITESPACE_COLLAPSE);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000018490 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018491 return (-1);
Daniel Veillardd3b9cd82003-04-09 11:24:17 +000018492}
18493
Daniel Veillard4255d502002-04-16 15:50:10 +000018494/************************************************************************
18495 * *
18496 * Simple type validation *
18497 * *
18498 ************************************************************************/
Daniel Veillard377e1a92004-04-16 16:30:05 +000018499
Daniel Veillard4255d502002-04-16 15:50:10 +000018500
18501/************************************************************************
18502 * *
18503 * DOM Validation code *
18504 * *
18505 ************************************************************************/
18506
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018507static void
18508xmlSchemaPostSchemaAssembleFixup(xmlSchemaParserCtxtPtr ctxt)
18509{
18510 int i, nbItems;
18511 xmlSchemaTypePtr item, *items;
18512
18513
18514 /*
18515 * During the Assemble of the schema ctxt->curItems has
18516 * been filled with the relevant new items. Fix those up.
18517 */
18518 nbItems = ctxt->assemble->nbItems;
18519 items = (xmlSchemaTypePtr *) ctxt->assemble->items;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018520
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018521 for (i = 0; i < nbItems; i++) {
18522 item = items[i];
18523 switch (item->type) {
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018524 case XML_SCHEMA_TYPE_COMPLEX:
18525 case XML_SCHEMA_TYPE_SIMPLE:
18526 xmlSchemaResolveTypeDefs(item, ctxt, NULL);
18527 break;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018528 case XML_SCHEMA_TYPE_ATTRIBUTE:
18529 xmlSchemaAttrFixup((xmlSchemaAttributePtr) item, ctxt, NULL);
18530 break;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018531 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018532 xmlSchemaAttrGrpFixup((xmlSchemaAttributeGroupPtr) item,
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018533 ctxt, NULL);
18534 break;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018535 case XML_SCHEMA_TYPE_PARTICLE:
18536 xmlSchemaMiscRefFixup((xmlSchemaTreeItemPtr) item, ctxt, NULL);
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000018537 break;
18538 case XML_SCHEMA_TYPE_IDC_KEY:
18539 case XML_SCHEMA_TYPE_IDC_UNIQUE:
18540 case XML_SCHEMA_TYPE_IDC_KEYREF:
18541 xmlSchemaResolveIDCKeyRef((xmlSchemaIDCPtr) item, ctxt, NULL);
18542 break;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018543 default:
18544 break;
18545 }
18546 }
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018547 if (ctxt->nberrors != 0)
18548 return;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018549 /*
18550 * Circularity checks.
18551 */
18552 for (i = 0; i < nbItems; i++) {
18553 item = items[i];
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018554 switch (item->type) {
18555 case XML_SCHEMA_TYPE_COMPLEX:
18556 case XML_SCHEMA_TYPE_SIMPLE:
18557 xmlSchemaCheckTypeDefCircular(
18558 (xmlSchemaTypePtr) item, ctxt, NULL);
18559 break;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018560 case XML_SCHEMA_TYPE_GROUP:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018561 xmlSchemaCheckGroupDefCircular(
18562 (xmlSchemaModelGroupDefPtr) item, ctxt, NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018563 break;
18564 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
18565 xmlSchemaCheckAttributeGroupCircular(
18566 (xmlSchemaAttributeGroupPtr) item, ctxt, NULL);
18567 break;
18568 default:
18569 break;
18570 }
18571 }
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018572 if (ctxt->nberrors != 0)
18573 return;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018574 /*
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018575 * Set the "term" of particles pointing to model group definitions
18576 * to the contained model group.
18577 */
18578 for (i = 0; i < nbItems; i++) {
18579 item = items[i];
18580 if ((item->type == XML_SCHEMA_TYPE_PARTICLE) &&
18581 (((xmlSchemaParticlePtr) item)->children != NULL) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018582 (((xmlSchemaParticlePtr) item)->children->type ==
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018583 XML_SCHEMA_TYPE_GROUP)) {
18584 xmlSchemaGroupDefTermFixup((xmlSchemaParticlePtr) item,
18585 ctxt, NULL);
18586 }
18587 }
Kasimier T. Buchcikc306d902005-07-08 21:37:44 +000018588 if (ctxt->nberrors != 0)
18589 return;
18590 for (i = 0; i < nbItems; i++) {
18591 item = items[i];
18592 switch (item->type) {
18593 case XML_SCHEMA_TYPE_ELEMENT:
18594 xmlSchemaElementFixup((xmlSchemaElementPtr) item, ctxt,
18595 NULL, NULL, NULL);
18596 break;
18597 default:
18598 break;
18599 }
18600 }
18601 if (ctxt->nberrors != 0)
18602 return;
18603
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018604 /*
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018605 * Fixup for simple/complex types.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018606 */
18607 for (i = 0; i < nbItems; i++) {
18608 item = items[i];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018609 switch (item->type) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018610 case XML_SCHEMA_TYPE_SIMPLE:
18611 case XML_SCHEMA_TYPE_COMPLEX:
18612 xmlSchemaTypeFixup(item, ctxt, NULL);
18613 break;
18614 default:
18615 break;
18616 }
18617 }
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018618 if (ctxt->nberrors != 0)
18619 return;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018620 /*
18621 * Validate value contraint values.
18622 */
18623 for (i = 0; i < nbItems; i++) {
18624 item = items[i];
18625 switch (item->type) {
18626 case XML_SCHEMA_TYPE_ATTRIBUTE:
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018627 xmlSchemaCheckAttrValConstr((xmlSchemaAttributePtr) item,
18628 ctxt, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018629 break;
18630 case XML_SCHEMA_TYPE_ELEMENT:
Kasimier T. Buchcik1a99a392005-04-08 11:23:56 +000018631 xmlSchemaCheckElementDeclComponent((xmlSchemaElementPtr) item,
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000018632 ctxt, NULL);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018633 break;
18634 default:
18635 break;
18636 }
18637 }
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018638 if (ctxt->nberrors != 0)
18639 return;
18640 /*
18641 * Build the content model for complex types.
18642 */
18643 for (i = 0; i < nbItems; i++) {
18644 item = items[i];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018645 switch (item->type) {
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018646 case XML_SCHEMA_TYPE_COMPLEX:
18647 xmlSchemaBuildContentModel(item, ctxt, NULL);
18648 break;
18649 default:
18650 break;
18651 }
18652 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018653}
18654
18655/**
18656 * xmlSchemaAssembleByLocation:
18657 * @pctxt: a schema parser context
18658 * @vctxt: a schema validation context
18659 * @schema: the existing schema
18660 * @node: the node that fired the assembling
18661 * @nsName: the namespace name of the new schema
18662 * @location: the location of the schema
18663 *
18664 * Expands an existing schema by an additional schema.
18665 *
18666 * Returns 0 if the new schema is correct, a positive error code
18667 * number otherwise and -1 in case of an internal or API error.
18668 */
18669static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018670xmlSchemaAssembleByLocation(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018671 xmlSchemaPtr schema,
18672 xmlNodePtr node,
18673 const xmlChar *nsName,
18674 const xmlChar *location)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018675{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018676 const xmlChar *targetNs, *oldtns;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018677 xmlDocPtr doc, olddoc;
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000018678 int oldflags, ret = 0, oldIsS4S;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018679 xmlNodePtr docElem;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018680 xmlSchemaParserCtxtPtr pctxt;
18681
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018682 /*
18683 * This should be used:
18684 * 1. on <import>(s)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018685 * 2. if requested by the validated instance
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018686 * 3. if requested via the API
18687 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018688 if ((vctxt == NULL) || (schema == NULL))
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018689 return (-1);
18690 /*
18691 * Create a temporary parser context.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018692 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018693 if ((vctxt->pctxt == NULL) &&
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018694 (xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1))
18695 return (-1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018696 pctxt = vctxt->pctxt;
18697 /*
18698 * Set the counter to produce unique names for anonymous items.
18699 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018700 pctxt->counter = schema->counter;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018701 /*
18702 * Acquire the schema document.
18703 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018704 ret = xmlSchemaAcquireSchemaDoc((xmlSchemaAbstractCtxtPtr) vctxt, schema,
18705 node, nsName, location, &doc, &targetNs, 0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018706 if (ret != 0) {
18707 if (doc != NULL)
18708 xmlFreeDoc(doc);
18709 } else if (doc != NULL) {
18710 docElem = xmlDocGetRootElement(doc);
18711 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018712 * Create new assemble info.
18713 */
18714 if (pctxt->assemble == NULL) {
18715 pctxt->assemble = xmlSchemaNewAssemble();
18716 if (pctxt->assemble == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018717 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018718 "Memory error: xmlSchemaAssembleByLocation, "
18719 "allocating assemble info", NULL);
18720 xmlFreeDoc(doc);
18721 return (-1);
18722 }
18723 }
18724 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018725 * Save and reset the context & schema.
18726 */
18727 oldflags = schema->flags;
18728 oldtns = schema->targetNamespace;
18729 olddoc = schema->doc;
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000018730 oldIsS4S = vctxt->pctxt->isS4S;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018731
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018732 xmlSchemaClearSchemaDefaults(schema);
18733 schema->targetNamespace = targetNs;
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000018734 if ((targetNs != NULL) &&
18735 xmlStrEqual(targetNs, xmlSchemaNs)) {
18736 /*
18737 * We are parsing the schema for schema!
18738 */
18739 vctxt->pctxt->isS4S = 1;
18740 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018741 /* schema->nbCurItems = 0; */
18742 pctxt->schema = schema;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018743 pctxt->ctxtType = NULL;
18744 pctxt->parentItem = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018745
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018746 xmlSchemaParseSchemaDefaults(pctxt, schema, docElem);
18747 if (pctxt->nberrors != 0) {
18748 vctxt->nberrors += pctxt->nberrors;
18749 goto finally;
18750 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018751 xmlSchemaParseSchemaTopLevel(pctxt, schema, docElem->children);
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018752 if (pctxt->nberrors != 0) {
18753 vctxt->nberrors += pctxt->nberrors;
18754 goto finally;
18755 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018756 xmlSchemaPostSchemaAssembleFixup(pctxt);
Kasimier T. Buchcik016d92e2005-04-08 20:08:40 +000018757 if (pctxt->nberrors != 0)
18758 vctxt->nberrors += pctxt->nberrors;
18759finally:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018760 /*
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018761 * Set the counter of items.
18762 */
18763 schema->counter = pctxt->counter;
18764 /*
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018765 * Free the list of assembled components.
18766 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018767 pctxt->assemble->nbItems = 0;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018768 /*
18769 * Restore the context & schema.
18770 */
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000018771 vctxt->pctxt->isS4S = oldIsS4S;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018772 schema->flags = oldflags;
18773 schema->targetNamespace = oldtns;
18774 schema->doc = olddoc;
18775 ret = pctxt->err;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018776 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018777 return (ret);
18778}
18779
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018780static xmlSchemaAttrInfoPtr
18781xmlSchemaGetMetaAttrInfo(xmlSchemaValidCtxtPtr vctxt,
18782 int metaType)
18783{
18784 if (vctxt->nbAttrInfos == 0)
18785 return (NULL);
18786 {
18787 int i;
18788 xmlSchemaAttrInfoPtr iattr;
18789
18790 for (i = 0; i < vctxt->nbAttrInfos; i++) {
18791 iattr = vctxt->attrInfos[i];
18792 if (iattr->metaType == metaType)
18793 return (iattr);
18794 }
18795
18796 }
18797 return (NULL);
18798}
18799
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018800/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018801 * xmlSchemaAssembleByXSI:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018802 * @vctxt: a schema validation context
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018803 *
18804 * Expands an existing schema by an additional schema using
18805 * the xsi:schemaLocation or xsi:noNamespaceSchemaLocation attribute
18806 * of an instance. If xsi:noNamespaceSchemaLocation is used, @noNamespace
18807 * must be set to 1.
18808 *
18809 * Returns 0 if the new schema is correct, a positive error code
18810 * number otherwise and -1 in case of an internal or API error.
18811 */
18812static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018813xmlSchemaAssembleByXSI(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018814{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018815 const xmlChar *cur, *end;
18816 const xmlChar *nsname = NULL, *location;
18817 int count = 0;
18818 int ret = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018819 xmlSchemaAttrInfoPtr iattr;
18820
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018821 /*
18822 * Parse the value; we will assume an even number of values
18823 * to be given (this is how Xerces and XSV work).
18824 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018825 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
18826 XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC);
18827 if (iattr == NULL)
18828 xmlSchemaGetMetaAttrInfo(vctxt,
18829 XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC);
18830 if (iattr == NULL)
18831 return (0);
18832 cur = iattr->value;
18833 do {
18834 if (iattr->metaType == XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC) {
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018835 /*
18836 * Get the namespace name.
18837 */
18838 while (IS_BLANK_CH(*cur))
18839 cur++;
18840 end = cur;
18841 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
18842 end++;
18843 if (end == cur)
18844 break;
18845 count++;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018846 nsname = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018847 cur = end;
18848 }
18849 /*
18850 * Get the URI.
18851 */
18852 while (IS_BLANK_CH(*cur))
18853 cur++;
18854 end = cur;
18855 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
18856 end++;
18857 if (end == cur)
18858 break;
18859 count++;
18860 location = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018861 cur = end;
18862 ret = xmlSchemaAssembleByLocation(vctxt, vctxt->schema,
18863 iattr->node, nsname, location);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018864 if (ret == -1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018865 VERROR_INT("xmlSchemaAssembleByXSI",
18866 "assembling schemata");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018867 return (-1);
18868 }
18869 } while (*cur != 0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018870 return (ret);
18871}
18872
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018873static const xmlChar *
18874xmlSchemaLookupNamespace(xmlSchemaValidCtxtPtr vctxt,
18875 const xmlChar *prefix)
18876{
18877 if (vctxt->sax != NULL) {
18878 int i, j;
18879 xmlSchemaNodeInfoPtr inode;
18880
18881 for (i = vctxt->depth; i >= 0; i--) {
18882 if (vctxt->elemInfos[i]->nbNsBindings != 0) {
18883 inode = vctxt->elemInfos[i];
18884 for (j = 0; j < inode->nbNsBindings * 2; j += 2) {
18885 if (((prefix == NULL) &&
18886 (inode->nsBindings[j] == NULL)) ||
18887 ((prefix != NULL) && xmlStrEqual(prefix,
18888 inode->nsBindings[j]))) {
18889
18890 /*
18891 * Note that the namespace bindings are already
18892 * in a string dict.
18893 */
18894 return (inode->nsBindings[j+1]);
18895 }
18896 }
18897 }
18898 }
18899 return (NULL);
Daniel Veillard39e5c892005-07-03 22:48:50 +000018900#ifdef LIBXML_WRITER_ENABLED
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018901 } else if (vctxt->reader != NULL) {
18902 xmlChar *nsName;
18903
18904 nsName = xmlTextReaderLookupNamespace(vctxt->reader, prefix);
18905 if (nsName != NULL) {
18906 const xmlChar *ret;
18907
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018908 ret = xmlDictLookup(vctxt->dict, nsName, -1);
18909 xmlFree(nsName);
18910 return (ret);
18911 } else
18912 return (NULL);
Daniel Veillard39e5c892005-07-03 22:48:50 +000018913#endif
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018914 } else {
18915 xmlNsPtr ns;
18916
18917 if ((vctxt->inode->node == NULL) ||
18918 (vctxt->inode->node->doc == NULL)) {
18919 VERROR_INT("xmlSchemaLookupNamespace",
18920 "no node or node's doc avaliable");
18921 return (NULL);
18922 }
18923 ns = xmlSearchNs(vctxt->inode->node->doc,
18924 vctxt->inode->node, prefix);
18925 if (ns != NULL)
18926 return (ns->href);
18927 return (NULL);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018928 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000018929}
18930
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018931/*
18932* This one works on the schema of the validation context.
18933*/
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018934static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018935xmlSchemaValidateNotation(xmlSchemaValidCtxtPtr vctxt,
18936 xmlSchemaPtr schema,
18937 xmlNodePtr node,
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018938 const xmlChar *value,
18939 xmlSchemaValPtr *val,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018940 int valNeeded)
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018941{
18942 int ret;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018943
18944 if (vctxt && (vctxt->schema == NULL)) {
18945 VERROR_INT("xmlSchemaValidateNotation",
18946 "a schema is needed on the validation context");
18947 return (-1);
18948 }
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018949 ret = xmlValidateQName(value, 1);
18950 if (ret != 0)
18951 return (ret);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018952 {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018953 xmlChar *localName = NULL;
18954 xmlChar *prefix = NULL;
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018955
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018956 localName = xmlSplitQName2(value, &prefix);
18957 if (prefix != NULL) {
18958 const xmlChar *nsName = NULL;
18959
18960 if (vctxt != NULL)
18961 nsName = xmlSchemaLookupNamespace(vctxt, BAD_CAST prefix);
18962 else if (node != NULL) {
18963 xmlNsPtr ns = xmlSearchNs(node->doc, node, prefix);
18964 if (ns != NULL)
18965 nsName = ns->href;
18966 } else {
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018967 xmlFree(prefix);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018968 xmlFree(localName);
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018969 return (1);
18970 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018971 if (nsName == NULL) {
18972 xmlFree(prefix);
18973 xmlFree(localName);
18974 return (1);
18975 }
18976 if (xmlHashLookup2(schema->notaDecl, localName,
18977 nsName) != NULL) {
18978 if (valNeeded && (val != NULL)) {
18979 (*val) = xmlSchemaNewNOTATIONValue(BAD_CAST localName,
18980 BAD_CAST xmlStrdup(nsName));
18981 if (*val == NULL)
18982 ret = -1;
18983 }
18984 } else
Kasimier T. Buchcikb06b4de2005-02-17 19:00:23 +000018985 ret = 1;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000018986 xmlFree(prefix);
18987 xmlFree(localName);
18988 } else {
18989 if (xmlHashLookup2(schema->notaDecl, value, NULL) != NULL) {
18990 if (valNeeded && (val != NULL)) {
18991 (*val) = xmlSchemaNewNOTATIONValue(
18992 BAD_CAST xmlStrdup(value), NULL);
18993 if (*val == NULL)
18994 ret = -1;
18995 }
18996 } else
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018997 return (1);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018998 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000018999 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019000 return (ret);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000019001}
19002
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000019003static int
19004xmlSchemaVAddNodeQName(xmlSchemaValidCtxtPtr vctxt,
19005 const xmlChar* lname,
19006 const xmlChar* nsname)
19007{
19008 int i;
19009
19010 lname = xmlDictLookup(vctxt->dict, lname, -1);
19011 if (lname == NULL)
19012 return(-1);
19013 if (nsname != NULL) {
19014 nsname = xmlDictLookup(vctxt->dict, nsname, -1);
19015 if (nsname == NULL)
19016 return(-1);
19017 }
19018 for (i = 0; i < vctxt->nodeQNames->nbItems; i += 2) {
19019 if ((vctxt->nodeQNames->items [i] == lname) &&
19020 (vctxt->nodeQNames->items[i +1] == nsname))
19021 /* Already there */
19022 return(i);
19023 }
19024 /* Add new entry. */
19025 i = vctxt->nodeQNames->nbItems;
19026 xmlSchemaItemListAdd(vctxt->nodeQNames, (void *) lname);
19027 xmlSchemaItemListAdd(vctxt->nodeQNames, (void *) nsname);
19028 return(i);
19029}
19030
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019031/************************************************************************
19032 * *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019033 * Validation of identity-constraints (IDC) *
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019034 * *
19035 ************************************************************************/
19036
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019037/**
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019038 * xmlSchemaAugmentIDC:
19039 * @idcDef: the IDC definition
19040 *
19041 * Creates an augmented IDC definition item.
19042 *
19043 * Returns the item, or NULL on internal errors.
19044 */
19045static void
19046xmlSchemaAugmentIDC(xmlSchemaIDCPtr idcDef,
19047 xmlSchemaValidCtxtPtr vctxt)
19048{
19049 xmlSchemaIDCAugPtr aidc;
19050
19051 aidc = (xmlSchemaIDCAugPtr) xmlMalloc(sizeof(xmlSchemaIDCAug));
19052 if (aidc == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019053 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019054 "xmlSchemaAugmentIDC: allocating an augmented IDC definition",
19055 NULL);
19056 return;
19057 }
19058 aidc->bubbleDepth = -1;
19059 aidc->def = idcDef;
19060 aidc->next = NULL;
19061 if (vctxt->aidcs == NULL)
19062 vctxt->aidcs = aidc;
19063 else {
19064 aidc->next = vctxt->aidcs;
19065 vctxt->aidcs = aidc;
19066 }
19067}
19068
19069/**
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019070 * xmlSchemaIDCNewBinding:
19071 * @idcDef: the IDC definition of this binding
19072 *
19073 * Creates a new IDC binding.
19074 *
19075 * Returns the new binding in case of succeeded, NULL on internal errors.
19076 */
19077static xmlSchemaPSVIIDCBindingPtr
19078xmlSchemaIDCNewBinding(xmlSchemaIDCPtr idcDef)
19079{
19080 xmlSchemaPSVIIDCBindingPtr ret;
19081
19082 ret = (xmlSchemaPSVIIDCBindingPtr) xmlMalloc(
19083 sizeof(xmlSchemaPSVIIDCBinding));
19084 if (ret == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019085 xmlSchemaVErrMemory(NULL,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019086 "allocating a PSVI IDC binding item", NULL);
19087 return (NULL);
19088 }
19089 memset(ret, 0, sizeof(xmlSchemaPSVIIDCBinding));
19090 ret->definition = idcDef;
19091 return (ret);
19092}
19093
19094/**
19095 * xmlSchemaIDCStoreNodeTableItem:
19096 * @vctxt: the WXS validation context
19097 * @item: the IDC node table item
19098 *
19099 * The validation context is used to store an IDC node table items.
19100 * They are stored to avoid copying them if IDC node-tables are merged
19101 * with corresponding parent IDC node-tables (bubbling).
19102 *
19103 * Returns 0 if succeeded, -1 on internal errors.
19104 */
19105static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019106xmlSchemaIDCStoreNodeTableItem(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019107 xmlSchemaPSVIIDCNodePtr item)
19108{
19109 /*
19110 * Add to gobal list.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019111 */
19112 if (vctxt->idcNodes == NULL) {
19113 vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019114 xmlMalloc(20 * sizeof(xmlSchemaPSVIIDCNodePtr));
19115 if (vctxt->idcNodes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019116 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019117 "allocating the IDC node table item list", NULL);
19118 return (-1);
19119 }
19120 vctxt->sizeIdcNodes = 20;
19121 } else if (vctxt->sizeIdcNodes <= vctxt->nbIdcNodes) {
19122 vctxt->sizeIdcNodes *= 2;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019123 vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
19124 xmlRealloc(vctxt->idcNodes, vctxt->sizeIdcNodes *
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019125 sizeof(xmlSchemaPSVIIDCNodePtr));
19126 if (vctxt->idcNodes == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019127 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019128 "re-allocating the IDC node table item list", NULL);
19129 return (-1);
19130 }
19131 }
19132 vctxt->idcNodes[vctxt->nbIdcNodes++] = item;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019133
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019134 return (0);
19135}
19136
19137/**
19138 * xmlSchemaIDCStoreKey:
19139 * @vctxt: the WXS validation context
19140 * @item: the IDC key
19141 *
19142 * The validation context is used to store an IDC key.
19143 *
19144 * Returns 0 if succeeded, -1 on internal errors.
19145 */
19146static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019147xmlSchemaIDCStoreKey(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019148 xmlSchemaPSVIIDCKeyPtr key)
19149{
19150 /*
19151 * Add to gobal list.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019152 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019153 if (vctxt->idcKeys == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019154 vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019155 xmlMalloc(40 * sizeof(xmlSchemaPSVIIDCKeyPtr));
19156 if (vctxt->idcKeys == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019157 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019158 "allocating the IDC key storage list", NULL);
19159 return (-1);
19160 }
19161 vctxt->sizeIdcKeys = 40;
19162 } else if (vctxt->sizeIdcKeys <= vctxt->nbIdcKeys) {
19163 vctxt->sizeIdcKeys *= 2;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019164 vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
19165 xmlRealloc(vctxt->idcKeys, vctxt->sizeIdcKeys *
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019166 sizeof(xmlSchemaPSVIIDCKeyPtr));
19167 if (vctxt->idcKeys == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019168 xmlSchemaVErrMemory(vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019169 "re-allocating the IDC key storage list", NULL);
19170 return (-1);
19171 }
19172 }
19173 vctxt->idcKeys[vctxt->nbIdcKeys++] = key;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019174
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019175 return (0);
19176}
19177
19178/**
19179 * xmlSchemaIDCAppendNodeTableItem:
19180 * @bind: the IDC binding
19181 * @ntItem: the node-table item
19182 *
19183 * Appends the IDC node-table item to the binding.
19184 *
19185 * Returns 0 on success and -1 on internal errors.
19186 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019187static int
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019188xmlSchemaIDCAppendNodeTableItem(xmlSchemaPSVIIDCBindingPtr bind,
19189 xmlSchemaPSVIIDCNodePtr ntItem)
19190{
19191 if (bind->nodeTable == NULL) {
19192 bind->sizeNodes = 10;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019193 bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019194 xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr));
19195 if (bind->nodeTable == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019196 xmlSchemaVErrMemory(NULL,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019197 "allocating an array of IDC node-table items", NULL);
19198 return(-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019199 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019200 } else if (bind->sizeNodes <= bind->nbNodes) {
19201 bind->sizeNodes *= 2;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019202 bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
19203 xmlRealloc(bind->nodeTable, bind->sizeNodes *
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019204 sizeof(xmlSchemaPSVIIDCNodePtr));
19205 if (bind->nodeTable == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019206 xmlSchemaVErrMemory(NULL,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019207 "re-allocating an array of IDC node-table items", NULL);
19208 return(-1);
19209 }
19210 }
19211 bind->nodeTable[bind->nbNodes++] = ntItem;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019212 return(0);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019213}
19214
19215/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019216 * xmlSchemaIDCAquireBinding:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019217 * @vctxt: the WXS validation context
19218 * @matcher: the IDC matcher
19219 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019220 * Looks up an PSVI IDC binding, for the IDC definition and
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019221 * of the given matcher. If none found, a new one is created
19222 * and added to the IDC table.
19223 *
19224 * Returns an IDC binding or NULL on internal errors.
19225 */
19226static xmlSchemaPSVIIDCBindingPtr
19227xmlSchemaIDCAquireBinding(xmlSchemaValidCtxtPtr vctxt,
19228 xmlSchemaIDCMatcherPtr matcher)
19229{
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019230 xmlSchemaNodeInfoPtr info;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019231
19232 info = vctxt->elemInfos[matcher->depth];
19233
19234 if (info->idcTable == NULL) {
19235 info->idcTable = xmlSchemaIDCNewBinding(matcher->aidc->def);
19236 if (info->idcTable == NULL)
19237 return (NULL);
19238 return(info->idcTable);
19239 } else {
19240 xmlSchemaPSVIIDCBindingPtr bind = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019241
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019242 bind = info->idcTable;
19243 do {
19244 if (bind->definition == matcher->aidc->def)
19245 return(bind);
19246 if (bind->next == NULL) {
19247 bind->next = xmlSchemaIDCNewBinding(matcher->aidc->def);
19248 if (bind->next == NULL)
19249 return (NULL);
19250 return(bind->next);
19251 }
19252 bind = bind->next;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019253 } while (bind != NULL);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019254 }
19255 return (NULL);
19256}
19257
19258/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019259 * xmlSchemaIDCFreeKey:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019260 * @key: the IDC key
19261 *
19262 * Frees an IDC key together with its compiled value.
19263 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019264static void
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019265xmlSchemaIDCFreeKey(xmlSchemaPSVIIDCKeyPtr key)
19266{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019267 if (key->val != NULL)
19268 xmlSchemaFreeValue(key->val);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019269 xmlFree(key);
19270}
19271
19272/**
19273 * xmlSchemaIDCFreeBinding:
19274 *
19275 * Frees an IDC binding. Note that the node table-items
19276 * are not freed.
19277 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019278static void
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019279xmlSchemaIDCFreeBinding(xmlSchemaPSVIIDCBindingPtr bind)
19280{
19281 if (bind->nodeTable != NULL) {
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019282 if (bind->definition->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
19283 int i;
19284 /*
19285 * Node-table items for keyrefs are not stored globally
19286 * to the validation context, since they are not bubbled.
19287 * We need to free them here.
19288 */
19289 for (i = 0; i < bind->nbNodes; i++) {
19290 xmlFree(bind->nodeTable[i]->keys);
19291 xmlFree(bind->nodeTable[i]);
19292 }
19293 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019294 xmlFree(bind->nodeTable);
19295 }
19296 xmlFree(bind);
19297}
19298
19299/**
19300 * xmlSchemaIDCFreeIDCTable:
19301 * @bind: the first IDC binding in the list
19302 *
19303 * Frees an IDC table, i.e. all the IDC bindings in the list.
19304 */
19305static void
19306xmlSchemaIDCFreeIDCTable(xmlSchemaPSVIIDCBindingPtr bind)
19307{
19308 xmlSchemaPSVIIDCBindingPtr prev;
19309
19310 while (bind != NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019311 prev = bind;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019312 bind = bind->next;
19313 xmlSchemaIDCFreeBinding(prev);
19314 }
19315}
19316
19317/**
19318 * xmlSchemaIDCFreeMatcherList:
19319 * @matcher: the first IDC matcher in the list
19320 *
19321 * Frees a list of IDC matchers.
19322 */
19323static void
19324xmlSchemaIDCFreeMatcherList(xmlSchemaIDCMatcherPtr matcher)
19325{
19326 xmlSchemaIDCMatcherPtr next;
19327
19328 while (matcher != NULL) {
19329 next = matcher->next;
19330 if (matcher->keySeqs != NULL) {
19331 int i;
19332 for (i = 0; i < matcher->sizeKeySeqs; i++)
19333 if (matcher->keySeqs[i] != NULL)
19334 xmlFree(matcher->keySeqs[i]);
19335 xmlFree(matcher->keySeqs);
19336 }
19337 xmlFree(matcher);
19338 matcher = next;
19339 }
19340}
19341
19342/**
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019343 * xmlSchemaIDCAddStateObject:
19344 * @vctxt: the WXS validation context
19345 * @matcher: the IDC matcher
19346 * @sel: the XPath information
19347 * @parent: the parent "selector" state object if any
19348 * @type: "selector" or "field"
19349 *
19350 * Creates/reuses and activates state objects for the given
19351 * XPath information; if the XPath expression consists of unions,
19352 * multiple state objects are created for every unioned expression.
19353 *
19354 * Returns 0 on success and -1 on internal errors.
19355 */
19356static int
19357xmlSchemaIDCAddStateObject(xmlSchemaValidCtxtPtr vctxt,
19358 xmlSchemaIDCMatcherPtr matcher,
19359 xmlSchemaIDCSelectPtr sel,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019360 int type)
19361{
19362 xmlSchemaIDCStateObjPtr sto;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019363
19364 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019365 * Reuse the state objects from the pool.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019366 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019367 if (vctxt->xpathStatePool != NULL) {
19368 sto = vctxt->xpathStatePool;
19369 vctxt->xpathStatePool = sto->next;
19370 sto->next = NULL;
19371 } else {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019372 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019373 * Create a new state object.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019374 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019375 sto = (xmlSchemaIDCStateObjPtr) xmlMalloc(sizeof(xmlSchemaIDCStateObj));
19376 if (sto == NULL) {
19377 xmlSchemaVErrMemory(NULL,
19378 "allocating an IDC state object", NULL);
19379 return (-1);
19380 }
19381 memset(sto, 0, sizeof(xmlSchemaIDCStateObj));
19382 }
19383 /*
19384 * Add to global list.
19385 */
19386 if (vctxt->xpathStates != NULL)
19387 sto->next = vctxt->xpathStates;
19388 vctxt->xpathStates = sto;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019389
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019390 /*
19391 * Free the old xpath validation context.
19392 */
19393 if (sto->xpathCtxt != NULL)
19394 xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
19395
19396 /*
19397 * Create a new XPath (pattern) validation context.
19398 */
19399 sto->xpathCtxt = (void *) xmlPatternGetStreamCtxt(
19400 (xmlPatternPtr) sel->xpathComp);
19401 if (sto->xpathCtxt == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019402 VERROR_INT("xmlSchemaIDCAddStateObject",
19403 "failed to create an XPath validation context");
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019404 return (-1);
19405 }
19406 sto->type = type;
19407 sto->depth = vctxt->depth;
19408 sto->matcher = matcher;
19409 sto->sel = sel;
19410 sto->nbHistory = 0;
19411
19412#if DEBUG_IDC
19413 xmlGenericError(xmlGenericErrorContext, "IDC: STO push '%s'\n",
19414 sto->sel->xpath);
19415#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019416 return (0);
19417}
19418
19419/**
19420 * xmlSchemaXPathEvaluate:
19421 * @vctxt: the WXS validation context
19422 * @nodeType: the nodeType of the current node
19423 *
19424 * Evaluates all active XPath state objects.
19425 *
19426 * Returns the number of IC "field" state objects which resolved to
19427 * this node, 0 if none resolved and -1 on internal errors.
19428 */
19429static int
19430xmlSchemaXPathEvaluate(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019431 xmlElementType nodeType)
19432{
19433 xmlSchemaIDCStateObjPtr sto, head = NULL, first;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019434 int res, resolved = 0, depth = vctxt->depth;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019435
19436 if (vctxt->xpathStates == NULL)
19437 return (0);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019438
19439 if (nodeType == XML_ATTRIBUTE_NODE)
19440 depth++;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019441#if DEBUG_IDC
19442 {
19443 xmlChar *str = NULL;
19444 xmlGenericError(xmlGenericErrorContext,
19445 "IDC: EVAL on %s, depth %d, type %d\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019446 xmlSchemaFormatQName(&str, vctxt->inode->nsName,
19447 vctxt->inode->localName), depth, nodeType);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019448 FREE_AND_NULL(str)
19449 }
19450#endif
19451 /*
19452 * Process all active XPath state objects.
19453 */
19454 first = vctxt->xpathStates;
19455 sto = first;
19456 while (sto != head) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019457#if DEBUG_IDC
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019458 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019459 xmlGenericError(xmlGenericErrorContext, "IDC: ['%s'] selector '%s'\n",
19460 sto->matcher->aidc->def->name, sto->sel->xpath);
19461 else
19462 xmlGenericError(xmlGenericErrorContext, "IDC: ['%s'] field '%s'\n",
19463 sto->matcher->aidc->def->name, sto->sel->xpath);
19464#endif
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019465 if (nodeType == XML_ELEMENT_NODE)
19466 res = xmlStreamPush((xmlStreamCtxtPtr) sto->xpathCtxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019467 vctxt->inode->localName, vctxt->inode->nsName);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019468 else
19469 res = xmlStreamPushAttr((xmlStreamCtxtPtr) sto->xpathCtxt,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019470 vctxt->inode->localName, vctxt->inode->nsName);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019471
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019472 if (res == -1) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019473 VERROR_INT("xmlSchemaXPathEvaluate",
19474 "calling xmlStreamPush()");
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019475 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019476 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019477 if (res == 0)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019478 goto next_sto;
19479 /*
19480 * Full match.
19481 */
19482#if DEBUG_IDC
19483 xmlGenericError(xmlGenericErrorContext, "IDC: "
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019484 "MATCH\n");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019485#endif
19486 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019487 * Register a match in the state object history.
19488 */
19489 if (sto->history == NULL) {
19490 sto->history = (int *) xmlMalloc(5 * sizeof(int));
19491 if (sto->history == NULL) {
19492 xmlSchemaVErrMemory(NULL,
19493 "allocating the state object history", NULL);
19494 return(-1);
19495 }
19496 sto->sizeHistory = 10;
19497 } else if (sto->sizeHistory <= sto->nbHistory) {
19498 sto->sizeHistory *= 2;
19499 sto->history = (int *) xmlRealloc(sto->history,
19500 sto->sizeHistory * sizeof(int));
19501 if (sto->history == NULL) {
19502 xmlSchemaVErrMemory(NULL,
19503 "re-allocating the state object history", NULL);
19504 return(-1);
19505 }
19506 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019507 sto->history[sto->nbHistory++] = depth;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019508
19509#ifdef DEBUG_IDC
19510 xmlGenericError(xmlGenericErrorContext, "IDC: push match '%d'\n",
19511 vctxt->depth);
19512#endif
19513
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019514 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
19515 xmlSchemaIDCSelectPtr sel;
19516 /*
19517 * Activate state objects for the IDC fields of
19518 * the IDC selector.
19519 */
19520#if DEBUG_IDC
19521 xmlGenericError(xmlGenericErrorContext, "IDC: "
19522 "activating field states\n");
19523#endif
19524 sel = sto->matcher->aidc->def->fields;
19525 while (sel != NULL) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019526 if (xmlSchemaIDCAddStateObject(vctxt, sto->matcher,
19527 sel, XPATH_STATE_OBJ_TYPE_IDC_FIELD) == -1)
19528 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019529 sel = sel->next;
19530 }
19531 } else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
19532 /*
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000019533 * An IDC key node was found by the IDC field.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019534 */
19535#if DEBUG_IDC
19536 xmlGenericError(xmlGenericErrorContext,
19537 "IDC: key found\n");
19538#endif
19539 /*
19540 * Notify that the character value of this node is
19541 * needed.
19542 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019543 if (resolved == 0) {
19544 if ((vctxt->inode->flags &
19545 XML_SCHEMA_NODE_INFO_VALUE_NEEDED) == 0)
19546 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_VALUE_NEEDED;
19547 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019548 resolved++;
19549 }
19550next_sto:
19551 if (sto->next == NULL) {
19552 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019553 * Evaluate field state objects created on this node as well.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019554 */
19555 head = first;
19556 sto = vctxt->xpathStates;
19557 } else
19558 sto = sto->next;
19559 }
19560 return (resolved);
19561}
19562
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000019563static const xmlChar *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019564xmlSchemaFormatIDCKeySequence(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000019565 xmlChar **buf,
19566 xmlSchemaPSVIIDCKeyPtr *seq,
19567 int count)
19568{
19569 int i, res;
19570 const xmlChar *value = NULL;
19571
19572 *buf = xmlStrdup(BAD_CAST "[");
19573 for (i = 0; i < count; i++) {
19574 *buf = xmlStrcat(*buf, BAD_CAST "'");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019575 res = xmlSchemaGetCanonValueWhtsp(seq[i]->val, &value,
19576 xmlSchemaGetWhiteSpaceFacetValue(seq[i]->type));
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000019577 if (res == 0)
19578 *buf = xmlStrcat(*buf, value);
19579 else {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019580 VERROR_INT("xmlSchemaFormatIDCKeySequence",
19581 "failed to compute a canonical value");
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000019582 *buf = xmlStrcat(*buf, BAD_CAST "???");
19583 }
19584 if (i < count -1)
19585 *buf = xmlStrcat(*buf, BAD_CAST "', ");
19586 else
19587 *buf = xmlStrcat(*buf, BAD_CAST "'");
19588 if (value != NULL) {
19589 xmlFree((xmlChar *) value);
19590 value = NULL;
19591 }
19592 }
19593 *buf = xmlStrcat(*buf, BAD_CAST "]");
19594
19595 return (BAD_CAST *buf);
19596}
19597
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019598/**
Kasimier T. Buchcik800cbac2005-08-09 12:31:55 +000019599 * xmlSchemaXPathPop:
19600 * @vctxt: the WXS validation context
19601 *
19602 * Pops all XPath states.
19603 *
19604 * Returns 0 on success and -1 on internal errors.
19605 */
19606static int
19607xmlSchemaXPathPop(xmlSchemaValidCtxtPtr vctxt)
19608{
19609 xmlSchemaIDCStateObjPtr sto;
19610 int res;
19611
19612 if (vctxt->xpathStates == NULL)
19613 return(0);
19614 sto = vctxt->xpathStates;
19615 do {
19616 res = xmlStreamPop((xmlStreamCtxtPtr) sto->xpathCtxt);
19617 if (res == -1)
19618 return (-1);
19619 sto = sto->next;
19620 } while (sto != NULL);
19621 return(0);
19622}
19623
19624/**
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019625 * xmlSchemaXPathProcessHistory:
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019626 * @vctxt: the WXS validation context
19627 * @type: the simple/complex type of the current node if any at all
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019628 * @val: the precompiled value
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019629 *
19630 * Processes and pops the history items of the IDC state objects.
19631 * IDC key-sequences are validated/created on IDC bindings.
19632 *
19633 * Returns 0 on success and -1 on internal errors.
19634 */
19635static int
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019636xmlSchemaXPathProcessHistory(xmlSchemaValidCtxtPtr vctxt,
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019637 int depth)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019638{
19639 xmlSchemaIDCStateObjPtr sto, nextsto;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019640 int res, matchDepth;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019641 xmlSchemaPSVIIDCKeyPtr key = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019642 xmlSchemaTypePtr type = vctxt->inode->typeDef;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019643
19644 if (vctxt->xpathStates == NULL)
19645 return (0);
19646 sto = vctxt->xpathStates;
19647
19648#if DEBUG_IDC
19649 {
19650 xmlChar *str = NULL;
19651 xmlGenericError(xmlGenericErrorContext,
19652 "IDC: BACK on %s, depth %d\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019653 xmlSchemaFormatQName(&str, vctxt->inode->nsName,
19654 vctxt->inode->localName), vctxt->depth);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019655 FREE_AND_NULL(str)
19656 }
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019657#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019658 /*
19659 * Evaluate the state objects.
19660 */
19661 while (sto != NULL) {
Kasimier T. Buchcikc63fbbf2005-06-15 12:54:05 +000019662 res = xmlStreamPop((xmlStreamCtxtPtr) sto->xpathCtxt);
19663 if (res == -1) {
19664 VERROR_INT("xmlSchemaXPathProcessHistory",
19665 "calling xmlStreamPop()");
19666 return (-1);
19667 }
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000019668#if DEBUG_IDC
19669 xmlGenericError(xmlGenericErrorContext, "IDC: stream pop '%s'\n",
19670 sto->sel->xpath);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000019671#endif
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019672 if (sto->nbHistory == 0)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019673 goto deregister_check;
19674
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019675 matchDepth = sto->history[sto->nbHistory -1];
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019676
19677 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019678 * Only matches at the current depth are of interest.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019679 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019680 if (matchDepth != depth) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019681 sto = sto->next;
19682 continue;
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019683 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019684 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
19685 if (! IS_SIMPLE_TYPE(type)) {
19686 /*
19687 * Not qualified if the field resolves to a node of non
19688 * simple type.
19689 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019690 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
19691 XML_SCHEMAV_CVC_IDC, NULL,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019692 (xmlSchemaTypePtr) sto->matcher->aidc->def,
19693 "The field '%s' does evaluate to a node of "
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019694 "non-simple type", sto->sel->xpath, NULL);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019695
19696 sto->nbHistory--;
19697 goto deregister_check;
19698 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019699 if ((key == NULL) && (vctxt->inode->val == NULL)) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019700 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019701 * Failed to provide the normalized value; maybe
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019702 * the value was invalid.
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019703 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019704 VERROR(XML_SCHEMAV_CVC_IDC,
Kasimier T. Buchcik6e224f12005-02-17 11:10:44 +000019705 (xmlSchemaTypePtr) sto->matcher->aidc->def,
19706 "Warning: No precomputed value available, the value "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019707 "was either invalid or something strange happend");
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019708 sto->nbHistory--;
19709 goto deregister_check;
19710 } else {
19711 xmlSchemaIDCMatcherPtr matcher = sto->matcher;
19712 xmlSchemaPSVIIDCKeyPtr *keySeq;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019713 int pos, idx;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019714
19715 /*
19716 * The key will be anchored on the matcher's list of
19717 * key-sequences. The position in this list is determined
19718 * by the target node's depth relative to the matcher's
19719 * depth of creation (i.e. the depth of the scope element).
19720 */
19721 pos = sto->depth - matcher->depth;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019722 idx = sto->sel->index;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019723
19724 /*
19725 * Create/grow the array of key-sequences.
19726 */
19727 if (matcher->keySeqs == NULL) {
19728 if (pos > 9)
19729 matcher->sizeKeySeqs = pos * 2;
19730 else
19731 matcher->sizeKeySeqs = 10;
19732 matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
19733 xmlMalloc(matcher->sizeKeySeqs *
19734 sizeof(xmlSchemaPSVIIDCKeyPtr *));
19735 if (matcher->keySeqs == NULL) {
19736 xmlSchemaVErrMemory(NULL,
19737 "allocating an array of key-sequences",
19738 NULL);
19739 return(-1);
19740 }
19741 memset(matcher->keySeqs, 0,
19742 matcher->sizeKeySeqs *
19743 sizeof(xmlSchemaPSVIIDCKeyPtr *));
19744 } else if (pos >= matcher->sizeKeySeqs) {
19745 int i = matcher->sizeKeySeqs;
19746
19747 matcher->sizeKeySeqs *= 2;
19748 matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
19749 xmlRealloc(matcher->keySeqs,
19750 matcher->sizeKeySeqs *
19751 sizeof(xmlSchemaPSVIIDCKeyPtr *));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019752 if (matcher->keySeqs == NULL) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019753 xmlSchemaVErrMemory(NULL,
19754 "reallocating an array of key-sequences",
19755 NULL);
19756 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019757 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019758 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019759 * The array needs to be NULLed.
19760 * TODO: Use memset?
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019761 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019762 for (; i < matcher->sizeKeySeqs; i++)
19763 matcher->keySeqs[i] = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019764 }
19765
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019766 /*
19767 * Get/create the key-sequence.
19768 */
19769 keySeq = matcher->keySeqs[pos];
19770 if (keySeq == NULL) {
19771 goto create_sequence;
19772 } else {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019773 if (keySeq[idx] != NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019774 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019775 * cvc-identity-constraint:
19776 * 3 For each node in the ·target node set· all
19777 * of the {fields}, with that node as the context
19778 * node, evaluate to either an empty node-set or
19779 * a node-set with exactly one member, which must
19780 * have a simple type.
19781 *
19782 * The key was already set; report an error.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019783 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019784 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
19785 XML_SCHEMAV_CVC_IDC, NULL,
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019786 (xmlSchemaTypePtr) matcher->aidc->def,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019787 "The field '%s' evaluates to a node-set "
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000019788 "with more than one member",
19789 sto->sel->xpath, NULL);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019790 sto->nbHistory--;
19791 goto deregister_check;
19792 } else {
19793 goto create_key;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019794 }
19795 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019796
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019797create_sequence:
19798 /*
19799 * Create a key-sequence.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019800 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019801 keySeq = (xmlSchemaPSVIIDCKeyPtr *) xmlMalloc(
19802 matcher->aidc->def->nbFields *
19803 sizeof(xmlSchemaPSVIIDCKeyPtr));
19804 if (keySeq == NULL) {
19805 xmlSchemaVErrMemory(NULL,
19806 "allocating an IDC key-sequence", NULL);
19807 return(-1);
19808 }
19809 memset(keySeq, 0, matcher->aidc->def->nbFields *
19810 sizeof(xmlSchemaPSVIIDCKeyPtr));
19811 matcher->keySeqs[pos] = keySeq;
19812create_key:
19813 /*
19814 * Created a key once per node only.
19815 */
19816 if (key == NULL) {
19817 key = (xmlSchemaPSVIIDCKeyPtr) xmlMalloc(
19818 sizeof(xmlSchemaPSVIIDCKey));
19819 if (key == NULL) {
19820 xmlSchemaVErrMemory(NULL,
19821 "allocating a IDC key", NULL);
19822 xmlFree(keySeq);
19823 matcher->keySeqs[pos] = NULL;
19824 return(-1);
19825 }
19826 /*
19827 * Consume the compiled value.
19828 */
19829 key->type = type;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019830 key->val = vctxt->inode->val;
19831 vctxt->inode->val = NULL;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019832 /*
19833 * Store the key in a global list.
19834 */
19835 if (xmlSchemaIDCStoreKey(vctxt, key) == -1) {
19836 xmlSchemaIDCFreeKey(key);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019837 return (-1);
19838 }
19839 }
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019840 keySeq[idx] = key;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019841 }
19842 } else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019843
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019844 xmlSchemaPSVIIDCKeyPtr **keySeq = NULL;
19845 xmlSchemaPSVIIDCBindingPtr bind;
19846 xmlSchemaPSVIIDCNodePtr ntItem;
19847 xmlSchemaIDCMatcherPtr matcher;
19848 xmlSchemaIDCPtr idc;
19849 int pos, i, j, nbKeys;
19850 /*
19851 * Here we have the following scenario:
19852 * An IDC 'selector' state object resolved to a target node,
19853 * during the time this target node was in the
19854 * ancestor-or-self axis, the 'field' state object(s) looked
19855 * out for matching nodes to create a key-sequence for this
19856 * target node. Now we are back to this target node and need
19857 * to put the key-sequence, together with the target node
19858 * itself, into the node-table of the corresponding IDC
19859 * binding.
19860 */
19861 matcher = sto->matcher;
19862 idc = matcher->aidc->def;
19863 nbKeys = idc->nbFields;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019864 pos = depth - matcher->depth;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019865 /*
19866 * Check if the matcher has any key-sequences at all, plus
19867 * if it has a key-sequence for the current target node.
19868 */
19869 if ((matcher->keySeqs == NULL) ||
19870 (matcher->sizeKeySeqs <= pos)) {
19871 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
19872 goto selector_key_error;
19873 else
19874 goto selector_leave;
19875 }
19876
19877 keySeq = &(matcher->keySeqs[pos]);
19878 if (*keySeq == NULL) {
19879 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
19880 goto selector_key_error;
19881 else
19882 goto selector_leave;
19883 }
19884
19885 for (i = 0; i < nbKeys; i++) {
19886 if ((*keySeq)[i] == NULL) {
19887 /*
19888 * Not qualified, if not all fields did resolve.
19889 */
19890 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY) {
19891 /*
19892 * All fields of a "key" IDC must resolve.
19893 */
19894 goto selector_key_error;
19895 }
19896 goto selector_leave;
19897 }
19898 }
19899 /*
19900 * All fields did resolve.
19901 */
19902
19903 /*
19904 * 4.1 If the {identity-constraint category} is unique(/key),
19905 * then no two members of the ·qualified node set· have
19906 * ·key-sequences· whose members are pairwise equal, as
19907 * defined by Equal in [XML Schemas: Datatypes].
19908 *
19909 * Get the IDC binding from the matcher and check for
19910 * duplicate key-sequences.
19911 */
19912 bind = xmlSchemaIDCAquireBinding(vctxt, matcher);
19913 if ((idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) &&
19914 (bind->nbNodes != 0)) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019915 xmlSchemaPSVIIDCKeyPtr ckey, bkey, *bkeySeq;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019916
19917 i = 0;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019918 res = 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019919 /*
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019920 * Compare the key-sequences, key by key.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019921 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019922 do {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019923 bkeySeq = bind->nodeTable[i]->keys;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019924 for (j = 0; j < nbKeys; j++) {
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000019925 ckey = (*keySeq)[j];
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019926 bkey = bkeySeq[j];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019927 res = xmlSchemaAreValuesEqual(ckey->val, bkey->val);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019928 if (res == -1) {
19929 return (-1);
19930 } else if (res == 0)
19931 break;
19932 }
19933 if (res == 1) {
19934 /*
19935 * Duplicate found.
19936 */
19937 break;
19938 }
19939 i++;
19940 } while (i < bind->nbNodes);
19941 if (i != bind->nbNodes) {
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000019942 xmlChar *str = NULL;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019943 /*
19944 * TODO: Try to report the key-sequence.
19945 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000019946 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
19947 XML_SCHEMAV_CVC_IDC, NULL,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019948 (xmlSchemaTypePtr) idc,
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000019949 "Duplicate key-sequence %s",
19950 xmlSchemaFormatIDCKeySequence(vctxt, &str,
19951 (*keySeq), nbKeys), NULL);
19952 FREE_AND_NULL(str)
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019953 goto selector_leave;
19954 }
19955 }
19956 /*
19957 * Add a node-table item to the IDC binding.
19958 */
19959 ntItem = (xmlSchemaPSVIIDCNodePtr) xmlMalloc(
19960 sizeof(xmlSchemaPSVIIDCNode));
19961 if (ntItem == NULL) {
19962 xmlSchemaVErrMemory(NULL,
19963 "allocating an IDC node-table item", NULL);
19964 xmlFree(*keySeq);
19965 *keySeq = NULL;
19966 return(-1);
19967 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000019968 memset(ntItem, 0, sizeof(xmlSchemaPSVIIDCNode));
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019969
19970 /*
19971 * Store the node-table item on global list.
19972 */
19973 if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) {
19974 if (xmlSchemaIDCStoreNodeTableItem(vctxt, ntItem) == -1) {
19975 xmlFree(ntItem);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019976 xmlFree(*keySeq);
19977 *keySeq = NULL;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019978 return (-1);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000019979 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000019980 ntItem->nodeQNameID = -1;
19981 } else {
19982 /*
19983 * Save a cached QName for this node on the IDC node, to be
19984 * able to report it, even if the node is not saved.
19985 */
19986 ntItem->nodeQNameID = xmlSchemaVAddNodeQName(vctxt,
19987 vctxt->inode->localName, vctxt->inode->nsName);
19988 if (ntItem->nodeQNameID == -1) {
19989 xmlFree(ntItem);
19990 xmlFree(*keySeq);
19991 *keySeq = NULL;
19992 return (-1);
19993 }
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019994 }
19995 /*
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000019996 * Init the node-table item: Save the node, position and
19997 * consume the key-sequence.
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000019998 */
19999 ntItem->node = vctxt->node;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000020000 ntItem->nodeLine = vctxt->inode->nodeLine;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020001 ntItem->keys = *keySeq;
20002 *keySeq = NULL;
20003 if (xmlSchemaIDCAppendNodeTableItem(bind, ntItem) == -1) {
20004 if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
20005 /*
20006 * Free the item, since keyref items won't be
20007 * put on a global list.
20008 */
20009 xmlFree(ntItem->keys);
20010 xmlFree(ntItem);
20011 }
20012 return (-1);
20013 }
20014
20015 goto selector_leave;
20016selector_key_error:
20017 /*
20018 * 4.2.1 (KEY) The ·target node set· and the
20019 * ·qualified node set· are equal, that is, every
20020 * member of the ·target node set· is also a member
20021 * of the ·qualified node set· and vice versa.
20022 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020023 VERROR(XML_SCHEMAV_CVC_IDC, (xmlSchemaTypePtr) idc,
20024 "All 'key' fields must evaluate to a node");
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020025selector_leave:
20026 /*
20027 * Free the key-sequence if not added to the IDC table.
20028 */
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000020029 if ((keySeq != NULL) && (*keySeq != NULL)) {
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020030 xmlFree(*keySeq);
20031 *keySeq = NULL;
20032 }
20033 } /* if selector */
20034
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020035 sto->nbHistory--;
20036
20037deregister_check:
20038 /*
20039 * Deregister state objects if they reach the depth of creation.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020040 */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020041 if ((sto->nbHistory == 0) && (sto->depth == depth)) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020042#if DEBUG_IDC
20043 xmlGenericError(xmlGenericErrorContext, "IDC: STO pop '%s'\n",
20044 sto->sel->xpath);
20045#endif
20046 if (vctxt->xpathStates != sto) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020047 VERROR_INT("xmlSchemaXPathProcessHistory",
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020048 "The state object to be removed is not the first "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020049 "in the list");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020050 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020051 nextsto = sto->next;
20052 /*
20053 * Unlink from the list of active XPath state objects.
20054 */
20055 vctxt->xpathStates = sto->next;
20056 sto->next = vctxt->xpathStatePool;
20057 /*
20058 * Link it to the pool of reusable state objects.
20059 */
20060 vctxt->xpathStatePool = sto;
20061 sto = nextsto;
20062 } else
20063 sto = sto->next;
20064 } /* while (sto != NULL) */
20065 return (0);
20066}
20067
20068/**
20069 * xmlSchemaIDCRegisterMatchers:
20070 * @vctxt: the WXS validation context
20071 * @elemDecl: the element declaration
20072 *
20073 * Creates helper objects to evaluate IDC selectors/fields
20074 * successively.
20075 *
20076 * Returns 0 if OK and -1 on internal errors.
20077 */
20078static int
20079xmlSchemaIDCRegisterMatchers(xmlSchemaValidCtxtPtr vctxt,
20080 xmlSchemaElementPtr elemDecl)
20081{
20082 xmlSchemaIDCMatcherPtr matcher, last = NULL;
20083 xmlSchemaIDCPtr idc, refIdc;
20084 xmlSchemaIDCAugPtr aidc;
20085
20086 idc = (xmlSchemaIDCPtr) elemDecl->idcs;
20087 if (idc == NULL)
20088 return (0);
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000020089
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020090#if DEBUG_IDC
20091 {
20092 xmlChar *str = NULL;
20093 xmlGenericError(xmlGenericErrorContext,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020094 "IDC: REGISTER on %s, depth %d\n",
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020095 (char *) xmlSchemaFormatQName(&str, vctxt->inode->nsName,
20096 vctxt->inode->localName), vctxt->depth);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020097 FREE_AND_NULL(str)
20098 }
20099#endif
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020100 if (vctxt->inode->idcMatchers != NULL) {
20101 VERROR_INT("xmlSchemaIDCRegisterMatchers",
20102 "The chain of IDC matchers is expected to be empty");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020103 return (-1);
20104 }
20105 do {
20106 if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
20107 /*
20108 * Since IDCs bubbles are expensive we need to know the
20109 * depth at which the bubbles should stop; this will be
20110 * the depth of the top-most keyref IDC. If no keyref
20111 * references a key/unique IDC, the bubbleDepth will
20112 * be -1, indicating that no bubbles are needed.
20113 */
20114 refIdc = (xmlSchemaIDCPtr) idc->ref->item;
20115 if (refIdc != NULL) {
20116 /*
20117 * Lookup the augmented IDC.
20118 */
20119 aidc = vctxt->aidcs;
20120 while (aidc != NULL) {
20121 if (aidc->def == refIdc)
20122 break;
20123 aidc = aidc->next;
20124 }
20125 if (aidc == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020126 VERROR_INT("xmlSchemaIDCRegisterMatchers",
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020127 "Could not find an augmented IDC item for an IDC "
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020128 "definition");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020129 return (-1);
20130 }
20131 if ((aidc->bubbleDepth == -1) ||
20132 (vctxt->depth < aidc->bubbleDepth))
20133 aidc->bubbleDepth = vctxt->depth;
20134 }
20135 }
20136 /*
20137 * Lookup the augmented IDC item for the IDC definition.
20138 */
20139 aidc = vctxt->aidcs;
20140 while (aidc != NULL) {
20141 if (aidc->def == idc)
20142 break;
20143 aidc = aidc->next;
20144 }
20145 if (aidc == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020146 VERROR_INT("xmlSchemaIDCRegisterMatchers",
20147 "Could not find an augmented IDC item for an IDC definition");
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020148 return (-1);
20149 }
20150 /*
20151 * Create an IDC matcher for every IDC definition.
20152 */
20153 matcher = (xmlSchemaIDCMatcherPtr)
20154 xmlMalloc(sizeof(xmlSchemaIDCMatcher));
20155 if (matcher == NULL) {
20156 xmlSchemaVErrMemory(vctxt,
20157 "allocating an IDC matcher", NULL);
20158 return (-1);
20159 }
20160 memset(matcher, 0, sizeof(xmlSchemaIDCMatcher));
20161 if (last == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020162 vctxt->inode->idcMatchers = matcher;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020163 else
20164 last->next = matcher;
20165 last = matcher;
20166
20167 matcher->type = IDC_MATCHER;
20168 matcher->depth = vctxt->depth;
20169 matcher->aidc = aidc;
20170#if DEBUG_IDC
20171 xmlGenericError(xmlGenericErrorContext, "IDC: register matcher\n");
20172#endif
20173 /*
20174 * Init the automaton state object.
20175 */
20176 if (xmlSchemaIDCAddStateObject(vctxt, matcher,
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020177 idc->selector, XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) == -1)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020178 return (-1);
20179
20180 idc = idc->next;
20181 } while (idc != NULL);
20182 return (0);
20183}
20184
20185/**
20186 * xmlSchemaBubbleIDCNodeTables:
20187 * @depth: the current tree depth
20188 *
20189 * Merges IDC bindings of an element at @depth into the corresponding IDC
20190 * bindings of its parent element. If a duplicate note-table entry is found,
20191 * both, the parent node-table entry and child entry are discarded from the
20192 * node-table of the parent.
20193 *
20194 * Returns 0 if OK and -1 on internal errors.
20195 */
20196static int
20197xmlSchemaBubbleIDCNodeTables(xmlSchemaValidCtxtPtr vctxt)
20198{
20199 xmlSchemaPSVIIDCBindingPtr bind; /* IDC bindings of the current node. */
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020200 xmlSchemaPSVIIDCBindingPtr *parTable, parBind = NULL, lastParBind = NULL; /* parent IDC bindings. */
20201 xmlSchemaPSVIIDCNodePtr node, parNode = NULL; /* node-table entries. */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020202 xmlSchemaPSVIIDCKeyPtr key, parKey; /* keys of in a key-sequence. */
20203 xmlSchemaIDCAugPtr aidc;
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000020204 int i, j, k, ret = 0, oldNum, newDupls;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020205 int duplTop;
20206
20207 /*
20208 * The node table has the following sections:
20209 *
20210 * O --> old node-table entries (first)
20211 * O
20212 * + --> new node-table entries
20213 * +
20214 * % --> new duplicate node-table entries
20215 * %
20216 * # --> old duplicate node-table entries
20217 * # (last)
20218 *
20219 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020220 bind = vctxt->inode->idcTable;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020221 if (bind == NULL) {
20222 /* Fine, no table, no bubbles. */
20223 return (0);
20224 }
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000020225
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020226 parTable = &(vctxt->elemInfos[vctxt->depth -1]->idcTable);
20227 /*
20228 * Walk all bindings; create new or add to existing bindings.
20229 * Remove duplicate key-sequences.
20230 */
20231start_binding:
20232 while (bind != NULL) {
20233 /*
20234 * Skip keyref IDCs.
20235 */
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020236 if (bind->definition->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
20237 bind = bind->next;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020238 continue;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020239 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020240 /*
20241 * Check if the key/unique IDC table needs to be bubbled.
20242 */
20243 aidc = vctxt->aidcs;
20244 do {
20245 if (aidc->def == bind->definition) {
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000020246 if ((aidc->bubbleDepth == -1) ||
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000020247 (aidc->bubbleDepth >= vctxt->depth)) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020248 bind = bind->next;
20249 goto start_binding;
20250 }
20251 break;
20252 }
20253 aidc = aidc->next;
20254 } while (aidc != NULL);
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020255
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020256 if (parTable != NULL)
20257 parBind = *parTable;
20258 while (parBind != NULL) {
20259 /*
20260 * Search a matching parent binding for the
20261 * IDC definition.
20262 */
20263 if (parBind->definition == bind->definition) {
20264
20265 /*
20266 * Compare every node-table entry of the child node,
20267 * i.e. the key-sequence within, ...
20268 */
20269 oldNum = parBind->nbNodes; /* Skip newly added items. */
20270 duplTop = oldNum + parBind->nbDupls;
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000020271 newDupls = 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020272
20273 for (i = 0; i < bind->nbNodes; i++) {
20274 node = bind->nodeTable[i];
20275 if (node == NULL)
20276 continue;
20277 /*
20278 * ...with every key-sequence of the parent node, already
20279 * evaluated to be a duplicate key-sequence.
20280 */
20281 if (parBind->nbDupls != 0) {
20282 j = bind->nbNodes + newDupls;
20283 while (j < duplTop) {
20284 parNode = parBind->nodeTable[j];
20285 for (k = 0; k < bind->definition->nbFields; k++) {
20286 key = node->keys[k];
20287 parKey = parNode->keys[k];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020288 ret = xmlSchemaAreValuesEqual(key->val,
20289 parKey->val);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020290 if (ret == -1) {
20291 /* TODO: Internal error */
20292 return(-1);
20293 } else if (ret == 0)
20294 break;
20295
20296 }
20297 if (ret == 1)
20298 /* Duplicate found. */
20299 break;
20300 j++;
20301 }
20302 if (j != duplTop) {
20303 /* Duplicate found. */
20304 continue;
20305 }
20306 }
20307 /*
20308 * ... and with every key-sequence of the parent node.
20309 */
20310 j = 0;
20311 while (j < oldNum) {
20312 parNode = parBind->nodeTable[j];
20313 /*
20314 * Compare key by key.
20315 */
20316 for (k = 0; k < parBind->definition->nbFields; k++) {
20317 key = node->keys[k];
20318 parKey = parNode->keys[k];
20319
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020320 ret = xmlSchemaAreValuesEqual(key->val,
20321 parKey->val);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020322 if (ret == -1) {
20323 /* TODO: Internal error */
20324 } else if (ret == 0)
20325 break;
20326
20327 }
20328 if (ret == 1)
20329 /*
20330 * The key-sequences are equal.
20331 */
20332 break;
20333 j++;
20334 }
20335 if (j != oldNum) {
20336 /*
20337 * Handle duplicates.
20338 */
20339 newDupls++;
20340 oldNum--;
20341 parBind->nbNodes--;
20342 /*
20343 * Move last old item to pos of duplicate.
20344 */
20345 parBind->nodeTable[j] =
20346 parBind->nodeTable[oldNum];
20347
20348 if (parBind->nbNodes != oldNum) {
20349 /*
20350 * If new items exist, move last new item to
20351 * last of old items.
20352 */
20353 parBind->nodeTable[oldNum] =
20354 parBind->nodeTable[parBind->nbNodes];
20355 }
20356 /*
20357 * Move duplicate to last pos of new/old items.
20358 */
20359 parBind->nodeTable[parBind->nbNodes] = parNode;
20360
20361 } else {
20362 /*
20363 * Add the node-table entry (node and key-sequence) of
20364 * the child node to the node table of the parent node.
20365 */
20366 if (parBind->nodeTable == NULL) {
20367 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000020368 xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020369 if (parBind->nodeTable == NULL) {
20370 xmlSchemaVErrMemory(NULL,
20371 "allocating IDC list of node-table items", NULL);
20372 return(-1);
20373 }
20374 parBind->sizeNodes = 1;
20375 } else if (duplTop >= parBind->sizeNodes) {
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000020376 parBind->sizeNodes *= 2;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020377 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
20378 xmlRealloc(parBind->nodeTable, parBind->sizeNodes *
20379 sizeof(xmlSchemaPSVIIDCNodePtr));
20380 if (parBind->nodeTable == NULL) {
20381 xmlSchemaVErrMemory(NULL,
20382 "re-allocating IDC list of node-table items", NULL);
20383 return(-1);
20384 }
20385 }
20386
20387 /*
20388 * Move first old duplicate to last position
20389 * of old duplicates +1.
20390 */
20391 if (parBind->nbDupls != 0) {
20392 parBind->nodeTable[duplTop] =
20393 parBind->nodeTable[parBind->nbNodes + newDupls];
20394 }
20395 /*
20396 * Move first new duplicate to last position of
20397 * new duplicates +1.
20398 */
20399 if (newDupls != 0) {
20400 parBind->nodeTable[parBind->nbNodes + newDupls] =
20401 parBind->nodeTable[parBind->nbNodes];
20402 }
20403 /*
20404 * Append the new node-table entry to the 'new node-table
20405 * entries' section.
20406 */
20407 parBind->nodeTable[parBind->nbNodes] = node;
20408 parBind->nbNodes++;
20409 duplTop++;
20410 }
20411 }
20412 parBind->nbDupls += newDupls;
20413 break;
20414 }
20415 if (parBind->next == NULL)
20416 lastParBind = parBind;
20417 parBind = parBind->next;
20418 }
Kasimier T. Buchcikb34ad1b2005-03-21 20:10:31 +000020419 if ((parBind == NULL) && (bind->nbNodes != 0)) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020420 /*
20421 * No binding for the IDC was found: create a new one and
20422 * copy all node-tables.
20423 */
20424 parBind = xmlSchemaIDCNewBinding(bind->definition);
20425 if (parBind == NULL)
20426 return(-1);
20427
20428 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
20429 xmlMalloc(bind->nbNodes * sizeof(xmlSchemaPSVIIDCNodePtr));
20430 if (parBind->nodeTable == NULL) {
20431 xmlSchemaVErrMemory(NULL,
20432 "allocating an array of IDC node-table items", NULL);
20433 xmlSchemaIDCFreeBinding(parBind);
20434 return(-1);
20435 }
20436 parBind->sizeNodes = bind->nbNodes;
Kasimier T. Buchcik0a598522005-01-31 17:02:07 +000020437 parBind->nbNodes = bind->nbNodes;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020438 memcpy(parBind->nodeTable, bind->nodeTable,
20439 bind->nbNodes * sizeof(xmlSchemaPSVIIDCNodePtr));
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020440 if (*parTable == NULL)
20441 *parTable = parBind;
20442 else
20443 lastParBind->next = parBind;
20444 }
20445 bind = bind->next;
20446 }
20447 return (0);
20448}
20449
20450/**
20451 * xmlSchemaCheckCVCIDCKeyRef:
20452 * @vctxt: the WXS validation context
20453 * @elemDecl: the element declaration
20454 *
20455 * Check the cvc-idc-keyref constraints.
20456 */
20457static int
20458xmlSchemaCheckCVCIDCKeyRef(xmlSchemaValidCtxtPtr vctxt)
20459{
20460 xmlSchemaPSVIIDCBindingPtr refbind, bind;
20461
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020462 refbind = vctxt->inode->idcTable;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020463 /*
20464 * Find a keyref.
20465 */
20466 while (refbind != NULL) {
20467 if (refbind->definition->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
20468 int i, j, k, res;
20469 xmlSchemaPSVIIDCKeyPtr *refKeys, *keys;
20470 xmlSchemaPSVIIDCKeyPtr refKey, key;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000020471 xmlSchemaPSVIIDCNodePtr refNode = NULL;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020472
20473 /*
20474 * Find the referred key/unique.
20475 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020476 bind = vctxt->inode->idcTable;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020477 do {
20478 if ((xmlSchemaIDCPtr) refbind->definition->ref->item ==
20479 bind->definition)
20480 break;
20481 bind = bind->next;
20482 } while (bind != NULL);
20483
20484 /*
20485 * Search for a matching key-sequences.
20486 */
20487 for (i = 0; i < refbind->nbNodes; i++) {
20488 res = 0;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000020489 refNode = refbind->nodeTable[i];
20490 if (bind != NULL) {
20491 refKeys = refNode->keys;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020492 for (j = 0; j < bind->nbNodes; j++) {
20493 keys = bind->nodeTable[j]->keys;
20494 for (k = 0; k < bind->definition->nbFields; k++) {
20495 refKey = refKeys[k];
20496 key = keys[k];
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020497 res = xmlSchemaAreValuesEqual(key->val,
20498 refKey->val);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020499 if (res == 0)
20500 break;
20501 else if (res == -1) {
20502 return (-1);
20503 }
20504 }
20505 if (res == 1) {
20506 /*
20507 * Match found.
20508 */
20509 break;
20510 }
20511 }
20512 }
20513 if (res == 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020514 xmlChar *str = NULL, *strB = NULL;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000020515 xmlSchemaKeyrefErr(vctxt,
20516 XML_SCHEMAV_CVC_IDC, refNode,
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020517 (xmlSchemaTypePtr) refbind->definition,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020518 "No match found for key-sequence %s of key "
20519 "reference '%s'",
Kasimier T. Buchcikc872afb2005-04-18 10:57:04 +000020520 xmlSchemaFormatIDCKeySequence(vctxt, &str,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020521 refbind->nodeTable[i]->keys,
20522 refbind->definition->nbFields),
20523 xmlSchemaFormatQName(&strB,
20524 refbind->definition->targetNamespace,
20525 refbind->definition->name));
20526 FREE_AND_NULL(str);
20527 FREE_AND_NULL(strB);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020528 }
20529 }
20530 }
20531 refbind = refbind->next;
20532 }
20533 return (0);
20534}
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020535
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020536/************************************************************************
20537 * *
20538 * XML Reader validation code *
20539 * *
20540 ************************************************************************/
20541
20542static xmlSchemaAttrInfoPtr
20543xmlSchemaGetFreshAttrInfo(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020544{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020545 xmlSchemaAttrInfoPtr iattr;
20546 /*
20547 * Grow/create list of attribute infos.
20548 */
20549 if (vctxt->attrInfos == NULL) {
20550 vctxt->attrInfos = (xmlSchemaAttrInfoPtr *)
20551 xmlMalloc(sizeof(xmlSchemaAttrInfoPtr));
20552 vctxt->sizeAttrInfos = 1;
20553 if (vctxt->attrInfos == NULL) {
20554 xmlSchemaVErrMemory(vctxt,
20555 "allocating attribute info list", NULL);
20556 return (NULL);
20557 }
20558 } else if (vctxt->sizeAttrInfos <= vctxt->nbAttrInfos) {
20559 vctxt->sizeAttrInfos++;
20560 vctxt->attrInfos = (xmlSchemaAttrInfoPtr *)
20561 xmlRealloc(vctxt->attrInfos,
20562 vctxt->sizeAttrInfos * sizeof(xmlSchemaAttrInfoPtr));
20563 if (vctxt->attrInfos == NULL) {
20564 xmlSchemaVErrMemory(vctxt,
20565 "re-allocating attribute info list", NULL);
20566 return (NULL);
20567 }
20568 } else {
20569 iattr = vctxt->attrInfos[vctxt->nbAttrInfos++];
20570 if (iattr->localName != NULL) {
20571 VERROR_INT("xmlSchemaGetFreshAttrInfo",
20572 "attr info not cleared");
20573 return (NULL);
20574 }
20575 iattr->nodeType = XML_ATTRIBUTE_NODE;
20576 return (iattr);
20577 }
20578 /*
20579 * Create an attribute info.
20580 */
20581 iattr = (xmlSchemaAttrInfoPtr)
20582 xmlMalloc(sizeof(xmlSchemaAttrInfo));
20583 if (iattr == NULL) {
20584 xmlSchemaVErrMemory(vctxt, "creating new attribute info", NULL);
20585 return (NULL);
20586 }
20587 memset(iattr, 0, sizeof(xmlSchemaAttrInfo));
20588 iattr->nodeType = XML_ATTRIBUTE_NODE;
20589 vctxt->attrInfos[vctxt->nbAttrInfos++] = iattr;
20590
20591 return (iattr);
20592}
20593
20594static int
20595xmlSchemaValidatorPushAttribute(xmlSchemaValidCtxtPtr vctxt,
20596 xmlNodePtr attrNode,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000020597 int nodeLine,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020598 const xmlChar *localName,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000020599 const xmlChar *nsName,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020600 int ownedNames,
20601 xmlChar *value,
20602 int ownedValue)
20603{
20604 xmlSchemaAttrInfoPtr attr;
20605
20606 attr = xmlSchemaGetFreshAttrInfo(vctxt);
20607 if (attr == NULL) {
20608 VERROR_INT("xmlSchemaPushAttribute",
20609 "calling xmlSchemaGetFreshAttrInfo()");
20610 return (-1);
20611 }
20612 attr->node = attrNode;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000020613 attr->nodeLine = nodeLine;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020614 attr->state = XML_SCHEMAS_ATTR_UNKNOWN;
20615 attr->localName = localName;
20616 attr->nsName = nsName;
20617 if (ownedNames)
20618 attr->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES;
20619 /*
20620 * Evaluate if it's an XSI attribute.
20621 */
20622 if (nsName != NULL) {
20623 if (xmlStrEqual(localName, BAD_CAST "nil")) {
20624 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
20625 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_NIL;
20626 }
20627 } else if (xmlStrEqual(localName, BAD_CAST "type")) {
20628 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
20629 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_TYPE;
20630 }
20631 } else if (xmlStrEqual(localName, BAD_CAST "schemaLocation")) {
20632 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
20633 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC;
20634 }
20635 } else if (xmlStrEqual(localName, BAD_CAST "noNamespaceSchemaLocation")) {
20636 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
20637 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC;
20638 }
20639 } else if (xmlStrEqual(attr->nsName, xmlNamespaceNs)) {
20640 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XMLNS;
20641 }
20642 }
20643 attr->value = value;
20644 if (ownedValue)
20645 attr->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
20646 if (attr->metaType != 0)
20647 attr->state = XML_SCHEMAS_ATTR_META;
20648 return (0);
20649}
20650
20651static void
20652xmlSchemaClearElemInfo(xmlSchemaNodeInfoPtr ielem)
20653{
20654 if (ielem->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES) {
20655 FREE_AND_NULL(ielem->localName);
20656 FREE_AND_NULL(ielem->nsName);
20657 } else {
20658 ielem->localName = NULL;
20659 ielem->nsName = NULL;
20660 }
20661 if (ielem->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
20662 FREE_AND_NULL(ielem->value);
20663 } else {
20664 ielem->value = NULL;
20665 }
20666 if (ielem->val != NULL) {
20667 xmlSchemaFreeValue(ielem->val);
20668 ielem->val = NULL;
20669 }
20670 if (ielem->idcMatchers != NULL) {
20671 xmlSchemaIDCFreeMatcherList(ielem->idcMatchers);
20672 ielem->idcMatchers = NULL;
20673 }
20674 if (ielem->idcTable != NULL) {
20675 xmlSchemaIDCFreeIDCTable(ielem->idcTable);
20676 ielem->idcTable = NULL;
20677 }
20678 if (ielem->regexCtxt != NULL) {
20679 xmlRegFreeExecCtxt(ielem->regexCtxt);
20680 ielem->regexCtxt = NULL;
20681 }
20682 if (ielem->nsBindings != NULL) {
20683 xmlFree((xmlChar **)ielem->nsBindings);
20684 ielem->nsBindings = NULL;
20685 ielem->nbNsBindings = 0;
20686 ielem->sizeNsBindings = 0;
20687 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020688}
20689
20690/**
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020691 * xmlSchemaGetFreshElemInfo:
20692 * @vctxt: the schema validation context
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020693 *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020694 * Creates/reuses and initializes the element info item for
20695 * the currect tree depth.
20696 *
20697 * Returns the element info item or NULL on API or internal errors.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020698 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020699static xmlSchemaNodeInfoPtr
20700xmlSchemaGetFreshElemInfo(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020701{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020702 xmlSchemaNodeInfoPtr info = NULL;
20703
20704 if (vctxt->depth > vctxt->sizeElemInfos) {
20705 VERROR_INT("xmlSchemaGetFreshElemInfo",
20706 "inconsistent depth encountered");
20707 return (NULL);
20708 }
20709 if (vctxt->elemInfos == NULL) {
20710 vctxt->elemInfos = (xmlSchemaNodeInfoPtr *)
20711 xmlMalloc(10 * sizeof(xmlSchemaNodeInfoPtr));
20712 if (vctxt->elemInfos == NULL) {
20713 xmlSchemaVErrMemory(vctxt,
20714 "allocating the element info array", NULL);
20715 return (NULL);
20716 }
20717 memset(vctxt->elemInfos, 0, 10 * sizeof(xmlSchemaNodeInfoPtr));
20718 vctxt->sizeElemInfos = 10;
20719 } else if (vctxt->sizeElemInfos <= vctxt->depth) {
20720 int i = vctxt->sizeElemInfos;
20721
20722 vctxt->sizeElemInfos *= 2;
20723 vctxt->elemInfos = (xmlSchemaNodeInfoPtr *)
20724 xmlRealloc(vctxt->elemInfos, vctxt->sizeElemInfos *
20725 sizeof(xmlSchemaNodeInfoPtr));
20726 if (vctxt->elemInfos == NULL) {
20727 xmlSchemaVErrMemory(vctxt,
20728 "re-allocating the element info array", NULL);
20729 return (NULL);
20730 }
20731 /*
20732 * We need the new memory to be NULLed.
20733 * TODO: Use memset instead?
20734 */
20735 for (; i < vctxt->sizeElemInfos; i++)
20736 vctxt->elemInfos[i] = NULL;
20737 } else
20738 info = vctxt->elemInfos[vctxt->depth];
20739
20740 if (info == NULL) {
20741 info = (xmlSchemaNodeInfoPtr)
20742 xmlMalloc(sizeof(xmlSchemaNodeInfo));
20743 if (info == NULL) {
20744 xmlSchemaVErrMemory(vctxt,
20745 "allocating an element info", NULL);
20746 return (NULL);
20747 }
20748 vctxt->elemInfos[vctxt->depth] = info;
20749 } else {
20750 if (info->localName != NULL) {
20751 VERROR_INT("xmlSchemaGetFreshElemInfo",
20752 "elem info has not been cleared");
20753 return (NULL);
20754 }
20755 }
20756 memset(info, 0, sizeof(xmlSchemaNodeInfo));
20757 info->nodeType = XML_ELEMENT_NODE;
20758 info->depth = vctxt->depth;
20759
20760 return (info);
20761}
20762
20763#define ACTIVATE_ATTRIBUTE(item) vctxt->inode = (xmlSchemaNodeInfoPtr) item;
20764#define ACTIVATE_ELEM vctxt->inode = vctxt->elemInfos[vctxt->depth];
20765#define ACTIVATE_PARENT_ELEM vctxt->inode = vctxt->elemInfos[vctxt->depth -1];
20766
20767static int
20768xmlSchemaValidateFacets(xmlSchemaAbstractCtxtPtr actxt,
20769 xmlNodePtr node,
20770 xmlSchemaTypePtr type,
20771 xmlSchemaValType valType,
20772 const xmlChar * value,
20773 xmlSchemaValPtr val,
20774 unsigned long length,
20775 int fireErrors)
20776{
20777 int ret, error = 0;
20778
20779 xmlSchemaTypePtr tmpType;
20780 xmlSchemaFacetLinkPtr facetLink;
20781 xmlSchemaFacetPtr facet;
20782 unsigned long len = 0;
20783 xmlSchemaWhitespaceValueType ws;
20784
20785 /*
20786 * In Libxml2, derived built-in types have currently no explicit facets.
20787 */
20788 if (type->type == XML_SCHEMA_TYPE_BASIC)
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000020789 return (0);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020790
20791 /*
20792 * NOTE: Do not jump away, if the facetSet of the given type is
20793 * empty: until now, "pattern" and "enumeration" facets of the
20794 * *base types* need to be checked as well.
20795 */
20796 if (type->facetSet == NULL)
20797 goto pattern_and_enum;
20798
20799 if (! VARIETY_ATOMIC(type)) {
20800 if (VARIETY_LIST(type))
20801 goto variety_list;
20802 else
20803 goto pattern_and_enum;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020804 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020805 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020806 * Whitespace handling is only of importance for string-based
20807 * types.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020808 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020809 tmpType = xmlSchemaGetPrimitiveType(type);
20810 if ((tmpType->builtInType == XML_SCHEMAS_STRING) ||
20811 IS_ANY_SIMPLE_TYPE(tmpType)) {
20812 ws = xmlSchemaGetWhiteSpaceFacetValue(type);
20813 } else
20814 ws = XML_SCHEMA_WHITESPACE_COLLAPSE;
20815 /*
20816 * If the value was not computed (for string or
20817 * anySimpleType based types), then use the provided
20818 * type.
20819 */
20820 if (val == NULL)
20821 valType = valType;
20822 else
20823 valType = xmlSchemaGetValType(val);
20824
20825 ret = 0;
20826 for (facetLink = type->facetSet; facetLink != NULL;
20827 facetLink = facetLink->next) {
20828 /*
20829 * Skip the pattern "whiteSpace": it is used to
20830 * format the character content beforehand.
20831 */
20832 switch (facetLink->facet->type) {
20833 case XML_SCHEMA_FACET_WHITESPACE:
20834 case XML_SCHEMA_FACET_PATTERN:
20835 case XML_SCHEMA_FACET_ENUMERATION:
20836 continue;
20837 case XML_SCHEMA_FACET_LENGTH:
20838 case XML_SCHEMA_FACET_MINLENGTH:
20839 case XML_SCHEMA_FACET_MAXLENGTH:
20840 ret = xmlSchemaValidateLengthFacetWhtsp(facetLink->facet,
20841 valType, value, val, &len, ws);
20842 break;
20843 default:
20844 ret = xmlSchemaValidateFacetWhtsp(facetLink->facet, ws,
20845 valType, value, val, ws);
20846 break;
20847 }
20848 if (ret < 0) {
20849 AERROR_INT("xmlSchemaValidateFacets",
20850 "validating against a atomic type facet");
20851 return (-1);
20852 } else if (ret > 0) {
20853 if (fireErrors)
20854 xmlSchemaFacetErr(actxt, ret, node,
20855 value, len, type, facetLink->facet, NULL, NULL, NULL);
20856 else
20857 return (ret);
20858 if (error == 0)
20859 error = ret;
20860 }
20861 ret = 0;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000020862 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000020863
20864variety_list:
20865 if (! VARIETY_LIST(type))
20866 goto pattern_and_enum;
20867 /*
20868 * "length", "minLength" and "maxLength" of list types.
20869 */
20870 ret = 0;
20871 for (facetLink = type->facetSet; facetLink != NULL;
20872 facetLink = facetLink->next) {
20873
20874 switch (facetLink->facet->type) {
20875 case XML_SCHEMA_FACET_LENGTH:
20876 case XML_SCHEMA_FACET_MINLENGTH:
20877 case XML_SCHEMA_FACET_MAXLENGTH:
20878 ret = xmlSchemaValidateListSimpleTypeFacet(facetLink->facet,
20879 value, length, NULL);
20880 break;
20881 default:
20882 continue;
20883 }
20884 if (ret < 0) {
20885 AERROR_INT("xmlSchemaValidateFacets",
20886 "validating against a list type facet");
20887 return (-1);
20888 } else if (ret > 0) {
20889 if (fireErrors)
20890 xmlSchemaFacetErr(actxt, ret, node,
20891 value, length, type, facetLink->facet, NULL, NULL, NULL);
20892 else
20893 return (ret);
20894 if (error == 0)
20895 error = ret;
20896 }
20897 ret = 0;
20898 }
20899
20900pattern_and_enum:
20901 if (error >= 0) {
20902 int found = 0;
20903 /*
20904 * Process enumerations. Facet values are in the value space
20905 * of the defining type's base type. This seems to be a bug in the
20906 * XML Schema 1.0 spec. Use the whitespace type of the base type.
20907 * Only the first set of enumerations in the ancestor-or-self axis
20908 * is used for validation.
20909 */
20910 ret = 0;
20911 tmpType = type;
20912 do {
20913 for (facet = tmpType->facets; facet != NULL; facet = facet->next) {
20914 if (facet->type != XML_SCHEMA_FACET_ENUMERATION)
20915 continue;
20916 found = 1;
20917 ret = xmlSchemaAreValuesEqual(facet->val, val);
20918 if (ret == 1)
20919 break;
20920 else if (ret < 0) {
20921 AERROR_INT("xmlSchemaValidateFacets",
20922 "validating against an enumeration facet");
20923 return (-1);
20924 }
20925 }
20926 if (ret != 0)
20927 break;
20928 tmpType = tmpType->baseType;
20929 } while ((tmpType != NULL) &&
20930 (tmpType->type != XML_SCHEMA_TYPE_BASIC));
20931 if (found && (ret == 0)) {
20932 ret = XML_SCHEMAV_CVC_ENUMERATION_VALID;
20933 if (fireErrors) {
20934 xmlSchemaFacetErr(actxt, ret, node,
20935 value, 0, type, NULL, NULL, NULL, NULL);
20936 } else
20937 return (ret);
20938 if (error == 0)
20939 error = ret;
20940 }
20941 }
20942
20943 if (error >= 0) {
20944 int found;
20945 /*
20946 * Process patters. Pattern facets are ORed at type level
20947 * and ANDed if derived. Walk the base type axis.
20948 */
20949 tmpType = type;
20950 facet = NULL;
20951 do {
20952 found = 0;
20953 for (facetLink = tmpType->facetSet; facetLink != NULL;
20954 facetLink = facetLink->next) {
20955 if (facetLink->facet->type != XML_SCHEMA_FACET_PATTERN)
20956 continue;
20957 found = 1;
20958 /*
20959 * NOTE that for patterns, @value needs to be the
20960 * normalized vaule.
20961 */
20962 ret = xmlRegexpExec(facetLink->facet->regexp, value);
20963 if (ret == 1)
20964 break;
20965 else if (ret < 0) {
20966 AERROR_INT("xmlSchemaValidateFacets",
20967 "validating against a pattern facet");
20968 return (-1);
20969 } else {
20970 /*
20971 * Save the last non-validating facet.
20972 */
20973 facet = facetLink->facet;
20974 }
20975 }
20976 if (found && (ret != 1)) {
20977 ret = XML_SCHEMAV_CVC_PATTERN_VALID;
20978 if (fireErrors) {
20979 xmlSchemaFacetErr(actxt, ret, node,
20980 value, 0, type, facet, NULL, NULL, NULL);
20981 } else
20982 return (ret);
20983 if (error == 0)
20984 error = ret;
20985 break;
20986 }
20987 tmpType = tmpType->baseType;
20988 } while ((tmpType != NULL) && (tmpType->type != XML_SCHEMA_TYPE_BASIC));
20989 }
20990
20991 return (error);
20992}
20993
20994static xmlChar *
20995xmlSchemaNormalizeValue(xmlSchemaTypePtr type,
20996 const xmlChar *value)
20997{
20998 switch (xmlSchemaGetWhiteSpaceFacetValue(type)) {
20999 case XML_SCHEMA_WHITESPACE_COLLAPSE:
21000 return (xmlSchemaCollapseString(value));
21001 case XML_SCHEMA_WHITESPACE_REPLACE:
21002 return (xmlSchemaWhiteSpaceReplace(value));
21003 default:
21004 return (NULL);
21005 }
21006}
21007
21008static int
21009xmlSchemaValidateQName(xmlSchemaValidCtxtPtr vctxt,
21010 const xmlChar *value,
21011 xmlSchemaValPtr *val,
21012 int valNeeded)
21013{
21014 int ret;
21015 const xmlChar *nsName;
21016 xmlChar *local, *prefix = NULL;
21017
21018 ret = xmlValidateQName(value, 1);
21019 if (ret != 0) {
21020 if (ret == -1) {
21021 VERROR_INT("xmlSchemaValidateQName",
21022 "calling xmlValidateQName()");
21023 return (-1);
21024 }
21025 return( XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1);
21026 }
21027 /*
21028 * NOTE: xmlSplitQName2 will always return a duplicated
21029 * strings.
21030 */
21031 local = xmlSplitQName2(value, &prefix);
21032 if (local == NULL)
21033 local = xmlStrdup(value);
21034 /*
21035 * OPTIMIZE TODO: Use flags for:
21036 * - is there any namespace binding?
21037 * - is there a default namespace?
21038 */
21039 nsName = xmlSchemaLookupNamespace(vctxt, prefix);
21040
21041 if (prefix != NULL) {
21042 xmlFree(prefix);
21043 /*
21044 * A namespace must be found if the prefix is
21045 * NOT NULL.
21046 */
21047 if (nsName == NULL) {
21048 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
21049 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt, ret, NULL,
21050 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
21051 "The QName value '%s' has no "
21052 "corresponding namespace declaration in "
21053 "scope", value, NULL);
21054 if (local != NULL)
21055 xmlFree(local);
21056 return (ret);
21057 }
21058 }
21059 if (valNeeded && val) {
21060 if (nsName != NULL)
21061 *val = xmlSchemaNewQNameValue(
21062 BAD_CAST xmlStrdup(nsName), BAD_CAST local);
21063 else
21064 *val = xmlSchemaNewQNameValue(NULL,
21065 BAD_CAST local);
21066 } else
21067 xmlFree(local);
21068 return (0);
21069}
21070
21071/*
21072* cvc-simple-type
21073*/
21074static int
21075xmlSchemaVCheckCVCSimpleType(xmlSchemaAbstractCtxtPtr actxt,
21076 xmlNodePtr node,
21077 xmlSchemaTypePtr type,
21078 const xmlChar *value,
21079 xmlSchemaValPtr *retVal,
21080 int fireErrors,
21081 int normalize,
21082 int isNormalized)
21083{
21084 int ret = 0, valNeeded = (retVal) ? 1 : 0;
21085 xmlSchemaValPtr val = NULL;
21086 xmlSchemaWhitespaceValueType ws;
21087 xmlChar *normValue = NULL;
21088
21089#define NORMALIZE(atype) \
21090 if ((! isNormalized) && \
21091 (normalize || (type->flags & XML_SCHEMAS_TYPE_NORMVALUENEEDED))) { \
21092 normValue = xmlSchemaNormalizeValue(atype, value); \
21093 if (normValue != NULL) \
21094 value = normValue; \
21095 isNormalized = 1; \
21096 }
21097
21098 if ((retVal != NULL) && (*retVal != NULL)) {
21099 xmlSchemaFreeValue(*retVal);
21100 *retVal = NULL;
21101 }
21102 /*
21103 * 3.14.4 Simple Type Definition Validation Rules
21104 * Validation Rule: String Valid
21105 */
21106 /*
21107 * 1 It is schema-valid with respect to that definition as defined
21108 * by Datatype Valid in [XML Schemas: Datatypes].
21109 */
21110 /*
21111 * 2.1 If The definition is ENTITY or is validly derived from ENTITY given
21112 * the empty set, as defined in Type Derivation OK (Simple) (§3.14.6), then
21113 * the string must be a ·declared entity name·.
21114 */
21115 /*
21116 * 2.2 If The definition is ENTITIES or is validly derived from ENTITIES
21117 * given the empty set, as defined in Type Derivation OK (Simple) (§3.14.6),
21118 * then every whitespace-delimited substring of the string must be a ·declared
21119 * entity name·.
21120 */
21121 /*
21122 * 2.3 otherwise no further condition applies.
21123 */
21124 if ((! valNeeded) && (type->flags & XML_SCHEMAS_TYPE_FACETSNEEDVALUE))
21125 valNeeded = 1;
Kasimier T. Buchcik9c215eb2005-06-21 08:38:49 +000021126 if (value == NULL)
21127 value = BAD_CAST "";
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021128 if (IS_ANY_SIMPLE_TYPE(type) || VARIETY_ATOMIC(type)) {
21129 xmlSchemaTypePtr biType; /* The built-in type. */
21130 /*
21131 * SPEC (1.2.1) "if {variety} is ·atomic· then the string must ·match·
21132 * a literal in the ·lexical space· of {base type definition}"
21133 */
21134 /*
21135 * Whitespace-normalize.
21136 */
21137 NORMALIZE(type);
21138 if (type->type != XML_SCHEMA_TYPE_BASIC) {
21139 /*
21140 * Get the built-in type.
21141 */
21142 biType = type->baseType;
21143 while ((biType != NULL) &&
21144 (biType->type != XML_SCHEMA_TYPE_BASIC))
21145 biType = biType->baseType;
21146
21147 if (biType == NULL) {
21148 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
21149 "could not get the built-in type");
21150 goto internal_error;
21151 }
21152 } else
21153 biType = type;
21154 /*
21155 * NOTATIONs need to be processed here, since they need
21156 * to lookup in the hashtable of NOTATION declarations of the schema.
21157 */
21158 if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
21159 switch (biType->builtInType) {
21160 case XML_SCHEMAS_NOTATION:
21161 ret = xmlSchemaValidateNotation(
21162 (xmlSchemaValidCtxtPtr) actxt,
21163 ((xmlSchemaValidCtxtPtr) actxt)->schema,
21164 NULL, value, &val, valNeeded);
21165 break;
21166 case XML_SCHEMAS_QNAME:
21167 ret = xmlSchemaValidateQName((xmlSchemaValidCtxtPtr) actxt,
21168 value, &val, valNeeded);
21169 break;
21170 default:
21171 ws = xmlSchemaGetWhiteSpaceFacetValue(type);
21172 if (valNeeded)
21173 ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
21174 value, &val, NULL);
21175 else
21176 ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
21177 value, NULL, NULL);
21178 break;
21179 }
21180 } else if (actxt->type == XML_SCHEMA_CTXT_PARSER) {
21181 switch (biType->builtInType) {
21182 case XML_SCHEMAS_NOTATION:
21183 ret = xmlSchemaValidateNotation(NULL,
21184 ((xmlSchemaParserCtxtPtr) actxt)->schema, node,
21185 value, &val, valNeeded);
21186 break;
21187 default:
21188 ws = xmlSchemaGetWhiteSpaceFacetValue(type);
21189 if (valNeeded)
21190 ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
21191 value, &val, node);
21192 else
21193 ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
21194 value, NULL, node);
21195 break;
21196 }
21197 } else {
21198 /*
21199 * Validation via a public API is not implemented yet.
21200 */
21201 TODO
21202 goto internal_error;
21203 }
21204 if (ret != 0) {
21205 if (ret < 0) {
21206 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
21207 "validating against a built-in type");
21208 goto internal_error;
21209 }
21210 if (VARIETY_LIST(type))
21211 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
21212 else
21213 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
21214 }
21215 if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
21216 /*
21217 * Check facets.
21218 */
21219 ret = xmlSchemaValidateFacets(actxt, node, type,
21220 (xmlSchemaValType) biType->builtInType, value, val,
21221 0, fireErrors);
21222 if (ret != 0) {
21223 if (ret < 0) {
21224 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
21225 "validating facets of atomic simple type");
21226 goto internal_error;
21227 }
21228 if (VARIETY_LIST(type))
21229 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
21230 else
21231 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
21232 }
21233 }
21234 if (fireErrors && (ret > 0))
21235 xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
21236 } else if (VARIETY_LIST(type)) {
21237
21238 xmlSchemaTypePtr itemType;
21239 const xmlChar *cur, *end;
21240 xmlChar *tmpValue = NULL;
21241 unsigned long len = 0;
21242 xmlSchemaValPtr prevVal = NULL, curVal = NULL;
21243 /* 1.2.2 if {variety} is ·list· then the string must be a sequence
21244 * of white space separated tokens, each of which ·match·es a literal
21245 * in the ·lexical space· of {item type definition}
21246 */
21247 /*
21248 * Note that XML_SCHEMAS_TYPE_NORMVALUENEEDED will be set if
21249 * the list type has an enum or pattern facet.
21250 */
21251 NORMALIZE(type);
21252 /*
21253 * VAL TODO: Optimize validation of empty values.
21254 * VAL TODO: We do not have computed values for lists.
21255 */
Kasimier T. Buchcik9c215eb2005-06-21 08:38:49 +000021256 itemType = GET_LIST_ITEM_TYPE(type);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021257 cur = value;
21258 do {
21259 while (IS_BLANK_CH(*cur))
21260 cur++;
21261 end = cur;
21262 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
21263 end++;
21264 if (end == cur)
21265 break;
21266 tmpValue = xmlStrndup(cur, end - cur);
21267 len++;
21268
21269 if (valNeeded)
21270 ret = xmlSchemaVCheckCVCSimpleType(actxt, node, itemType,
21271 tmpValue, &curVal, fireErrors, 0, 1);
21272 else
21273 ret = xmlSchemaVCheckCVCSimpleType(actxt, node, itemType,
21274 tmpValue, NULL, fireErrors, 0, 1);
21275 FREE_AND_NULL(tmpValue);
21276 if (curVal != NULL) {
21277 /*
21278 * Add to list of computed values.
21279 */
21280 if (val == NULL)
21281 val = curVal;
21282 else
21283 xmlSchemaValueAppend(prevVal, curVal);
21284 prevVal = curVal;
21285 curVal = NULL;
21286 }
21287 if (ret != 0) {
21288 if (ret < 0) {
21289 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
21290 "validating an item of list simple type");
21291 goto internal_error;
21292 }
21293 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
21294 break;
21295 }
21296 cur = end;
21297 } while (*cur != 0);
21298 FREE_AND_NULL(tmpValue);
21299 if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
21300 /*
21301 * Apply facets (pattern, enumeration).
21302 */
21303 ret = xmlSchemaValidateFacets(actxt, node, type,
21304 XML_SCHEMAS_UNKNOWN, value, val,
21305 len, fireErrors);
21306 if (ret != 0) {
21307 if (ret < 0) {
21308 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
21309 "validating facets of list simple type");
21310 goto internal_error;
21311 }
21312 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
21313 }
21314 }
21315 if (fireErrors && (ret > 0)) {
21316 /*
21317 * Report the normalized value.
21318 */
21319 normalize = 1;
21320 NORMALIZE(type);
21321 xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
21322 }
21323 } else if (VARIETY_UNION(type)) {
21324 xmlSchemaTypeLinkPtr memberLink;
21325 /*
21326 * TODO: For all datatypes ·derived· by ·union· whiteSpace does
21327 * not apply directly; however, the normalization behavior of ·union·
21328 * types is controlled by the value of whiteSpace on that one of the
21329 * ·memberTypes· against which the ·union· is successfully validated.
21330 *
21331 * This means that the value is normalized by the first validating
21332 * member type, then the facets of the union type are applied. This
21333 * needs changing of the value!
21334 */
21335
21336 /*
21337 * 1.2.3 if {variety} is ·union· then the string must ·match· a
21338 * literal in the ·lexical space· of at least one member of
21339 * {member type definitions}
21340 */
21341 memberLink = xmlSchemaGetUnionSimpleTypeMemberTypes(type);
21342 if (memberLink == NULL) {
21343 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
21344 "union simple type has no member types");
21345 goto internal_error;
21346 }
21347 /*
21348 * Always normalize union type values, since we currently
21349 * cannot store the whitespace information with the value
21350 * itself; otherwise a later value-comparison would be
21351 * not possible.
21352 */
21353 while (memberLink != NULL) {
21354 if (valNeeded)
21355 ret = xmlSchemaVCheckCVCSimpleType(actxt, node,
21356 memberLink->type, value, &val, 0, 1, 0);
21357 else
21358 ret = xmlSchemaVCheckCVCSimpleType(actxt, node,
21359 memberLink->type, value, NULL, 0, 1, 0);
21360 if (ret <= 0)
21361 break;
21362 memberLink = memberLink->next;
21363 }
21364 if (ret != 0) {
21365 if (ret < 0) {
21366 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
21367 "validating members of union simple type");
21368 goto internal_error;
21369 }
21370 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
21371 }
21372 /*
21373 * Apply facets (pattern, enumeration).
21374 */
21375 if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
21376 /*
21377 * The normalization behavior of ·union· types is controlled by
21378 * the value of whiteSpace on that one of the ·memberTypes·
21379 * against which the ·union· is successfully validated.
21380 */
21381 NORMALIZE(memberLink->type);
21382 ret = xmlSchemaValidateFacets(actxt, node, type,
21383 XML_SCHEMAS_UNKNOWN, value, val,
21384 0, fireErrors);
21385 if (ret != 0) {
21386 if (ret < 0) {
21387 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
21388 "validating facets of union simple type");
21389 goto internal_error;
21390 }
21391 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
21392 }
21393 }
21394 if (fireErrors && (ret > 0))
21395 xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
21396 }
21397
21398 if (normValue != NULL)
21399 xmlFree(normValue);
21400 if (ret == 0) {
21401 if (retVal != NULL)
21402 *retVal = val;
21403 else if (val != NULL)
21404 xmlSchemaFreeValue(val);
21405 } else if (val != NULL)
21406 xmlSchemaFreeValue(val);
21407 return (ret);
21408internal_error:
21409 if (normValue != NULL)
21410 xmlFree(normValue);
21411 if (val != NULL)
21412 xmlSchemaFreeValue(val);
21413 return (-1);
21414}
21415
21416static int
21417xmlSchemaVExpandQName(xmlSchemaValidCtxtPtr vctxt,
21418 const xmlChar *value,
21419 const xmlChar **nsName,
21420 const xmlChar **localName)
21421{
21422 int ret = 0;
21423
21424 if ((nsName == NULL) || (localName == NULL))
21425 return (-1);
21426 *nsName = NULL;
21427 *localName = NULL;
21428
21429 ret = xmlValidateQName(value, 1);
21430 if (ret == -1)
21431 return (-1);
21432 if (ret > 0) {
21433 xmlSchemaSimpleTypeErr((xmlSchemaAbstractCtxtPtr) vctxt,
21434 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1, NULL,
21435 value, xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), 1);
21436 return (1);
21437 }
21438 {
21439 xmlChar *local = NULL;
21440 xmlChar *prefix;
21441
21442 /*
21443 * NOTE: xmlSplitQName2 will return a duplicated
21444 * string.
21445 */
21446 local = xmlSplitQName2(value, &prefix);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000021447 if (local == NULL)
21448 *localName = xmlDictLookup(vctxt->dict, value, -1);
21449 else {
21450 *localName = xmlDictLookup(vctxt->dict, local, -1);
21451 xmlFree(local);
21452 }
21453
21454 *nsName = xmlSchemaLookupNamespace(vctxt, prefix);
21455
21456 if (prefix != NULL) {
21457 xmlFree(prefix);
21458 /*
21459 * A namespace must be found if the prefix is NOT NULL.
21460 */
21461 if (*nsName == NULL) {
21462 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
21463 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1, NULL,
21464 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
21465 "The QName value '%s' has no "
21466 "corresponding namespace declaration in scope",
21467 value, NULL);
21468 return (2);
21469 }
21470 }
21471 }
21472 return (0);
21473}
21474
21475static int
21476xmlSchemaProcessXSIType(xmlSchemaValidCtxtPtr vctxt,
21477 xmlSchemaAttrInfoPtr iattr,
21478 xmlSchemaTypePtr *localType,
21479 xmlSchemaElementPtr elemDecl)
21480{
21481 int ret = 0;
21482 /*
21483 * cvc-elt (3.3.4) : (4)
21484 * AND
21485 * Schema-Validity Assessment (Element) (cvc-assess-elt)
21486 * (1.2.1.2.1) - (1.2.1.2.4)
21487 * Handle 'xsi:type'.
21488 */
21489 if (localType == NULL)
21490 return (-1);
21491 *localType = NULL;
21492 if (iattr == NULL)
21493 return (0);
21494 else {
21495 const xmlChar *nsName = NULL, *local = NULL;
21496 /*
21497 * TODO: We should report a *warning* that the type was overriden
21498 * by the instance.
21499 */
21500 ACTIVATE_ATTRIBUTE(iattr);
21501 /*
21502 * (cvc-elt) (3.3.4) : (4.1)
21503 * (cvc-assess-elt) (1.2.1.2.2)
21504 */
21505 ret = xmlSchemaVExpandQName(vctxt, iattr->value,
21506 &nsName, &local);
21507 if (ret != 0) {
21508 if (ret < 0) {
21509 VERROR_INT("xmlSchemaValidateElementByDeclaration",
21510 "calling xmlSchemaQNameExpand() to validate the "
21511 "attribute 'xsi:type'");
21512 goto internal_error;
21513 }
21514 goto exit;
21515 }
21516 /*
21517 * (cvc-elt) (3.3.4) : (4.2)
21518 * (cvc-assess-elt) (1.2.1.2.3)
21519 */
21520 *localType = xmlSchemaGetType(vctxt->schema, local, nsName);
21521 if (*localType == NULL) {
21522 xmlChar *str = NULL;
21523
21524 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
21525 XML_SCHEMAV_CVC_ELT_4_2, NULL,
21526 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
21527 "The QName value '%s' of the xsi:type attribute does not "
21528 "resolve to a type definition",
21529 xmlSchemaFormatQName(&str, nsName, local), NULL);
21530 FREE_AND_NULL(str);
21531 ret = vctxt->err;
21532 goto exit;
21533 }
21534 if (elemDecl != NULL) {
21535 int set = 0;
21536
21537 /*
21538 * SPEC cvc-elt (3.3.4) : (4.3) (Type Derivation OK)
21539 * "The ·local type definition· must be validly
21540 * derived from the {type definition} given the union of
21541 * the {disallowed substitutions} and the {type definition}'s
21542 * {prohibited substitutions}, as defined in
21543 * Type Derivation OK (Complex) (§3.4.6)
21544 * (if it is a complex type definition),
21545 * or given {disallowed substitutions} as defined in Type
21546 * Derivation OK (Simple) (§3.14.6) (if it is a simple type
21547 * definition)."
21548 *
21549 * {disallowed substitutions}: the "block" on the element decl.
21550 * {prohibited substitutions}: the "block" on the type def.
21551 */
21552 if ((elemDecl->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) ||
21553 (elemDecl->subtypes->flags &
21554 XML_SCHEMAS_TYPE_BLOCK_EXTENSION))
21555 set |= SUBSET_EXTENSION;
21556
21557 if ((elemDecl->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) ||
21558 (elemDecl->subtypes->flags &
21559 XML_SCHEMAS_TYPE_BLOCK_RESTRICTION))
21560 set |= SUBSET_RESTRICTION;
21561
21562 if (xmlSchemaCheckCOSDerivedOK(*localType,
21563 elemDecl->subtypes, set) != 0) {
21564 xmlChar *str = NULL;
21565
21566 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
21567 XML_SCHEMAV_CVC_ELT_4_3, NULL, NULL,
21568 "The type definition '%s', specified by xsi:type, is "
21569 "blocked or not validly derived from the type definition "
21570 "of the element declaration",
21571 xmlSchemaFormatQName(&str,
21572 (*localType)->targetNamespace,
21573 (*localType)->name),
21574 NULL);
21575 FREE_AND_NULL(str);
21576 ret = vctxt->err;
21577 *localType = NULL;
21578 }
21579 }
21580 }
21581exit:
21582 ACTIVATE_ELEM;
21583 return (ret);
21584internal_error:
21585 ACTIVATE_ELEM;
21586 return (-1);
21587}
21588
21589static int
21590xmlSchemaValidateElemDecl(xmlSchemaValidCtxtPtr vctxt)
21591{
21592 xmlSchemaElementPtr elemDecl = vctxt->inode->decl;
21593 xmlSchemaTypePtr actualType = ELEM_TYPE(elemDecl);
21594
21595 /*
21596 * cvc-elt (3.3.4) : 1
21597 */
21598 if (elemDecl == NULL) {
21599 VERROR(XML_SCHEMAV_CVC_ELT_1, NULL,
21600 "No matching declaration available");
21601 return (vctxt->err);
21602 }
21603 /*
21604 * cvc-elt (3.3.4) : 2
21605 */
21606 if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT) {
21607 VERROR(XML_SCHEMAV_CVC_ELT_2, NULL,
21608 "The element declaration is abstract");
21609 return (vctxt->err);
21610 }
21611 if (actualType == NULL) {
21612 VERROR(XML_SCHEMAV_CVC_TYPE_1, NULL,
21613 "The type definition is absent");
21614 return (XML_SCHEMAV_CVC_TYPE_1);
21615 }
21616 if (vctxt->nbAttrInfos != 0) {
21617 int ret;
21618 xmlSchemaAttrInfoPtr iattr;
21619 /*
21620 * cvc-elt (3.3.4) : 3
21621 * Handle 'xsi:nil'.
21622 */
21623 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
21624 XML_SCHEMA_ATTR_INFO_META_XSI_NIL);
21625 if (iattr) {
21626 ACTIVATE_ATTRIBUTE(iattr);
21627 /*
21628 * Validate the value.
21629 */
21630 ret = xmlSchemaVCheckCVCSimpleType(
21631 (xmlSchemaAbstractCtxtPtr) vctxt, NULL,
21632 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
21633 iattr->value, &(iattr->val), 1, 0, 0);
21634 ACTIVATE_ELEM;
21635 if (ret < 0) {
21636 VERROR_INT("xmlSchemaValidateElemDecl",
21637 "calling xmlSchemaVCheckCVCSimpleType() to "
21638 "validate the attribute 'xsi:nil'");
21639 return (-1);
21640 }
21641 if (ret == 0) {
21642 if ((elemDecl->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) {
21643 /*
21644 * cvc-elt (3.3.4) : 3.1
21645 */
21646 VERROR(XML_SCHEMAV_CVC_ELT_3_1, NULL,
21647 "The element is not 'nillable'");
21648 /* Does not return an error on purpose. */
21649 } else {
21650 if (xmlSchemaValueGetAsBoolean(iattr->val)) {
21651 /*
21652 * cvc-elt (3.3.4) : 3.2.2
21653 */
21654 if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) &&
21655 (elemDecl->value != NULL)) {
21656 VERROR(XML_SCHEMAV_CVC_ELT_3_2_2, NULL,
21657 "The element cannot be 'nilled' because "
21658 "there is a fixed value constraint defined "
21659 "for it");
21660 /* Does not return an error on purpose. */
21661 } else
21662 vctxt->inode->flags |=
21663 XML_SCHEMA_ELEM_INFO_NILLED;
21664 }
21665 }
21666 }
21667 }
21668 /*
21669 * cvc-elt (3.3.4) : 4
21670 * Handle 'xsi:type'.
21671 */
21672 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
21673 XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
21674 if (iattr) {
21675 xmlSchemaTypePtr localType = NULL;
21676
21677 ret = xmlSchemaProcessXSIType(vctxt, iattr, &localType,
21678 elemDecl);
21679 if (ret != 0) {
21680 if (ret == -1) {
21681 VERROR_INT("xmlSchemaValidateElemDecl",
21682 "calling xmlSchemaProcessXSIType() to "
21683 "process the attribute 'xsi:type'");
21684 return (-1);
21685 }
21686 /* Does not return an error on purpose. */
21687 }
21688 if (localType != NULL) {
21689 vctxt->inode->flags |= XML_SCHEMA_ELEM_INFO_LOCAL_TYPE;
21690 actualType = localType;
21691 }
21692 }
21693 }
21694 /*
21695 * IDC: Register identity-constraint XPath matchers.
21696 */
21697 if ((elemDecl->idcs != NULL) &&
21698 (xmlSchemaIDCRegisterMatchers(vctxt, elemDecl) == -1))
21699 return (-1);
21700 /*
21701 * No actual type definition.
21702 */
21703 if (actualType == NULL) {
21704 VERROR(XML_SCHEMAV_CVC_TYPE_1, NULL,
21705 "The type definition is absent");
21706 return (XML_SCHEMAV_CVC_TYPE_1);
21707 }
21708 /*
21709 * Remember the actual type definition.
21710 */
21711 vctxt->inode->typeDef = actualType;
21712
21713 return (0);
21714}
21715
21716static int
21717xmlSchemaVAttributesSimple(xmlSchemaValidCtxtPtr vctxt)
21718{
21719 xmlSchemaAttrInfoPtr iattr;
21720 int ret = 0, i;
21721
21722 /*
21723 * SPEC cvc-type (3.1.1)
21724 * "The attributes of must be empty, excepting those whose namespace
21725 * name is identical to http://www.w3.org/2001/XMLSchema-instance and
21726 * whose local name is one of type, nil, schemaLocation or
21727 * noNamespaceSchemaLocation."
21728 */
21729 if (vctxt->nbAttrInfos == 0)
21730 return (0);
21731 for (i = 0; i < vctxt->nbAttrInfos; i++) {
21732 iattr = vctxt->attrInfos[i];
21733 if (! iattr->metaType) {
21734 ACTIVATE_ATTRIBUTE(iattr)
21735 xmlSchemaIllegalAttrErr((xmlSchemaAbstractCtxtPtr) vctxt,
21736 XML_SCHEMAV_CVC_TYPE_3_1_1, iattr, NULL);
21737 ret = XML_SCHEMAV_CVC_TYPE_3_1_1;
21738 }
21739 }
21740 ACTIVATE_ELEM
21741 return (ret);
21742}
21743
21744/*
21745* Cleanup currently used attribute infos.
21746*/
21747static void
21748xmlSchemaClearAttrInfos(xmlSchemaValidCtxtPtr vctxt)
21749{
21750 int i;
21751 xmlSchemaAttrInfoPtr attr;
21752
21753 if (vctxt->nbAttrInfos == 0)
21754 return;
21755 for (i = 0; i < vctxt->nbAttrInfos; i++) {
21756 attr = vctxt->attrInfos[i];
21757 if (attr->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES) {
21758 if (attr->localName != NULL)
21759 xmlFree((xmlChar *) attr->localName);
21760 if (attr->nsName != NULL)
21761 xmlFree((xmlChar *) attr->nsName);
21762 }
21763 if (attr->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
21764 if (attr->value != NULL)
21765 xmlFree((xmlChar *) attr->value);
21766 }
21767 if (attr->val != NULL) {
21768 xmlSchemaFreeValue(attr->val);
21769 attr->val = NULL;
21770 }
21771 memset(attr, 0, sizeof(xmlSchemaAttrInfo));
21772 }
21773 vctxt->nbAttrInfos = 0;
21774}
21775
21776/*
21777* 3.4.4 Complex Type Definition Validation Rules
21778* Element Locally Valid (Complex Type) (cvc-complex-type)
21779* 3.2.4 Attribute Declaration Validation Rules
21780* Validation Rule: Attribute Locally Valid (cvc-attribute)
21781* Attribute Locally Valid (Use) (cvc-au)
21782*
21783* Only "assessed" attribute information items will be visible to
21784* IDCs. I.e. not "lax" (without declaration) and "skip" wild attributes.
21785*/
21786static int
21787xmlSchemaVAttributesComplex(xmlSchemaValidCtxtPtr vctxt)
21788{
21789 xmlSchemaTypePtr type = vctxt->inode->typeDef;
21790 xmlSchemaAttributeLinkPtr attrUseLink;
21791 xmlSchemaAttributePtr attrUse = NULL, attrDecl = NULL;
21792 xmlSchemaAttrInfoPtr attr, tmpAttr;
21793 int i, found, nbAttrs;
21794 int xpathRes = 0, res, wildIDs = 0, fixed;
21795
21796 /*
21797 * SPEC (cvc-attribute)
21798 * (1) "The declaration must not be ·absent· (see Missing
21799 * Sub-components (§5.3) for how this can fail to be
21800 * the case)."
21801 * (2) "Its {type definition} must not be absent."
21802 *
21803 * NOTE (1) + (2): This is not handled here, since we currently do not
21804 * allow validation against schemas which have missing sub-components.
21805 *
21806 * SPEC (cvc-complex-type)
21807 * (3) "For each attribute information item in the element information
21808 * item's [attributes] excepting those whose [namespace name] is
21809 * identical to http://www.w3.org/2001/XMLSchema-instance and whose
21810 * [local name] is one of type, nil, schemaLocation or
21811 * noNamespaceSchemaLocation, the appropriate case among the following
21812 * must be true:
21813 *
21814 */
21815 nbAttrs = vctxt->nbAttrInfos;
21816 for (attrUseLink = type->attributeUses; attrUseLink != NULL;
21817 attrUseLink = attrUseLink->next) {
21818
21819 found = 0;
21820 attrUse = attrUseLink->attr;
21821 /*
21822 * VAL TODO: Implement a real "attribute use" component.
21823 */
21824 if (attrUse->refDecl != NULL)
21825 attrDecl = attrUse->refDecl;
21826 else
21827 attrDecl = attrUse;
21828 for (i = 0; i < nbAttrs; i++) {
21829 attr = vctxt->attrInfos[i];
21830 /*
21831 * SPEC (cvc-complex-type) (3)
21832 * Skip meta attributes.
21833 */
21834 if (attr->metaType)
21835 continue;
21836 if (attr->localName[0] != attrDecl->name[0])
21837 continue;
21838 if (!xmlStrEqual(attr->localName, attrDecl->name))
21839 continue;
21840 if (!xmlStrEqual(attr->nsName, attrDecl->targetNamespace))
21841 continue;
21842 found = 1;
21843 /*
21844 * SPEC (cvc-complex-type)
21845 * (3.1) "If there is among the {attribute uses} an attribute
21846 * use with an {attribute declaration} whose {name} matches
21847 * the attribute information item's [local name] and whose
21848 * {target namespace} is identical to the attribute information
21849 * item's [namespace name] (where an ·absent· {target namespace}
21850 * is taken to be identical to a [namespace name] with no value),
21851 * then the attribute information must be ·valid· with respect
21852 * to that attribute use as per Attribute Locally Valid (Use)
21853 * (§3.5.4). In this case the {attribute declaration} of that
21854 * attribute use is the ·context-determined declaration· for the
21855 * attribute information item with respect to Schema-Validity
21856 * Assessment (Attribute) (§3.2.4) and
21857 * Assessment Outcome (Attribute) (§3.2.5).
21858 */
21859 attr->state = XML_SCHEMAS_ATTR_ASSESSED;
21860 attr->use = attrUse;
21861 /*
21862 * Context-determined declaration.
21863 */
21864 attr->decl = attrDecl;
21865 attr->typeDef = attrDecl->subtypes;
21866 break;
21867 }
21868
21869 if (found)
21870 continue;
21871
21872 if (attrUse->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED) {
21873 /*
21874 * Handle non-existent, required attributes.
21875 *
21876 * SPEC (cvc-complex-type)
21877 * (4) "The {attribute declaration} of each attribute use in
21878 * the {attribute uses} whose {required} is true matches one
21879 * of the attribute information items in the element information
21880 * item's [attributes] as per clause 3.1 above."
21881 */
21882 tmpAttr = xmlSchemaGetFreshAttrInfo(vctxt);
21883 if (tmpAttr == NULL) {
21884 VERROR_INT(
21885 "xmlSchemaVAttributesComplex",
21886 "calling xmlSchemaGetFreshAttrInfo()");
21887 return (-1);
21888 }
21889 tmpAttr->state = XML_SCHEMAS_ATTR_ERR_MISSING;
21890 tmpAttr->use = attrUse;
21891 tmpAttr->decl = attrDecl;
21892 } else if ((attrUse->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
21893 ((attrUse->defValue != NULL) ||
21894 (attrDecl->defValue != NULL))) {
21895 /*
21896 * Handle non-existent, optional, default/fixed attributes.
21897 */
21898 tmpAttr = xmlSchemaGetFreshAttrInfo(vctxt);
21899 if (tmpAttr == NULL) {
21900 VERROR_INT(
21901 "xmlSchemaVAttributesComplex",
21902 "calling xmlSchemaGetFreshAttrInfo()");
21903 return (-1);
21904 }
21905 tmpAttr->state = XML_SCHEMAS_ATTR_DEFAULT;
21906 tmpAttr->use = attrUse;
21907 tmpAttr->decl = attrDecl;
21908 tmpAttr->typeDef = attrDecl->subtypes;
21909 tmpAttr->localName = attrDecl->name;
21910 tmpAttr->nsName = attrDecl->targetNamespace;
21911 }
21912 }
21913 if (vctxt->nbAttrInfos == 0)
21914 return (0);
21915 /*
21916 * Validate against the wildcard.
21917 */
21918 if (type->attributeWildcard != NULL) {
21919 /*
21920 * SPEC (cvc-complex-type)
21921 * (3.2.1) "There must be an {attribute wildcard}."
21922 */
21923 for (i = 0; i < nbAttrs; i++) {
21924 attr = vctxt->attrInfos[i];
21925 /*
21926 * SPEC (cvc-complex-type) (3)
21927 * Skip meta attributes.
21928 */
21929 if (attr->state != XML_SCHEMAS_ATTR_UNKNOWN)
21930 continue;
21931 /*
21932 * SPEC (cvc-complex-type)
21933 * (3.2.2) "The attribute information item must be ·valid· with
21934 * respect to it as defined in Item Valid (Wildcard) (§3.10.4)."
21935 *
21936 * SPEC Item Valid (Wildcard) (cvc-wildcard)
21937 * "... its [namespace name] must be ·valid· with respect to
21938 * the wildcard constraint, as defined in Wildcard allows
21939 * Namespace Name (§3.10.4)."
21940 */
21941 if (xmlSchemaCheckCVCWildcardNamespace(type->attributeWildcard,
21942 attr->nsName)) {
21943 /*
21944 * Handle processContents.
21945 *
21946 * SPEC (cvc-wildcard):
21947 * processContents | context-determined declaration:
21948 * "strict" "mustFind"
21949 * "lax" "none"
21950 * "skip" "skip"
21951 */
21952 if (type->attributeWildcard->processContents ==
21953 XML_SCHEMAS_ANY_SKIP) {
21954 /*
21955 * context-determined declaration = "skip"
21956 *
21957 * SPEC PSVI Assessment Outcome (Attribute)
21958 * [validity] = "notKnown"
21959 * [validation attempted] = "none"
21960 */
21961 attr->state = XML_SCHEMAS_ATTR_WILD_SKIP;
21962 continue;
21963 }
21964 /*
21965 * Find an attribute declaration.
21966 */
21967 attr->decl = xmlSchemaGetAttributeDecl(vctxt->schema,
21968 attr->localName, attr->nsName);
21969 if (attr->decl != NULL) {
21970 attr->state = XML_SCHEMAS_ATTR_ASSESSED;
21971 /*
21972 * SPEC (cvc-complex-type)
21973 * (5) "Let [Definition:] the wild IDs be the set of
21974 * all attribute information item to which clause 3.2
21975 * applied and whose ·validation· resulted in a
21976 * ·context-determined declaration· of mustFind or no
21977 * ·context-determined declaration· at all, and whose
21978 * [local name] and [namespace name] resolve (as
21979 * defined by QName resolution (Instance) (§3.15.4)) to
21980 * an attribute declaration whose {type definition} is
21981 * or is derived from ID. Then all of the following
21982 * must be true:"
21983 */
21984 attr->typeDef = attr->decl->subtypes;
21985 if (xmlSchemaIsDerivedFromBuiltInType(
21986 attr->typeDef, XML_SCHEMAS_ID)) {
21987 /*
21988 * SPEC (5.1) "There must be no more than one
21989 * item in ·wild IDs·."
21990 */
21991 if (wildIDs != 0) {
21992 /* VAL TODO */
21993 attr->state = XML_SCHEMAS_ATTR_ERR_WILD_DUPLICATE_ID;
21994 TODO
21995 continue;
21996 }
21997 wildIDs++;
21998 /*
21999 * SPEC (cvc-complex-type)
22000 * (5.2) "If ·wild IDs· is non-empty, there must not
22001 * be any attribute uses among the {attribute uses}
22002 * whose {attribute declaration}'s {type definition}
22003 * is or is derived from ID."
22004 */
22005 for (attrUseLink = type->attributeUses;
22006 attrUseLink != NULL;
22007 attrUseLink = attrUseLink->next) {
22008 if (xmlSchemaIsDerivedFromBuiltInType(
22009 attrUseLink->attr->subtypes,
22010 XML_SCHEMAS_ID)) {
22011 /* VAL TODO */
22012 attr->state = XML_SCHEMAS_ATTR_ERR_WILD_AND_USE_ID;
22013 TODO
22014 }
22015 }
22016 }
22017 } else if (type->attributeWildcard->processContents ==
22018 XML_SCHEMAS_ANY_LAX) {
22019 attr->state = XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL;
22020 /*
22021 * SPEC PSVI Assessment Outcome (Attribute)
22022 * [validity] = "notKnown"
22023 * [validation attempted] = "none"
22024 */
22025 } else {
22026 attr->state = XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL;
22027 }
22028 }
22029 }
22030 }
22031
22032
22033 if (vctxt->nbAttrInfos == 0)
22034 return (0);
22035
22036 /*
22037 * Validate values, create default attributes, evaluate IDCs.
22038 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022039 for (i = 0; i < vctxt->nbAttrInfos; i++) {
22040 attr = vctxt->attrInfos[i];
22041 /*
22042 * VAL TODO: Note that we won't try to resolve IDCs to
22043 * "lax" and "skip" validated attributes. Check what to
22044 * do in this case.
22045 */
22046 if ((attr->state != XML_SCHEMAS_ATTR_ASSESSED) &&
22047 (attr->state != XML_SCHEMAS_ATTR_DEFAULT))
22048 continue;
22049 /*
22050 * VAL TODO: What to do if the type definition is missing?
22051 */
22052 if (attr->typeDef == NULL) {
22053 attr->state = XML_SCHEMAS_ATTR_ERR_NO_TYPE;
22054 continue;
22055 }
22056
22057 ACTIVATE_ATTRIBUTE(attr);
Kasimier T. Buchcik828f6542005-06-09 11:23:39 +000022058 fixed = 0;
22059 xpathRes = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022060
22061 if (vctxt->xpathStates != NULL) {
22062 /*
22063 * Evaluate IDCs.
22064 */
22065 xpathRes = xmlSchemaXPathEvaluate(vctxt,
22066 XML_ATTRIBUTE_NODE);
22067 if (xpathRes == -1) {
22068 VERROR_INT("xmlSchemaVAttributesComplex",
22069 "calling xmlSchemaXPathEvaluate()");
22070 goto internal_error;
22071 }
22072 }
22073
22074 if (attr->state == XML_SCHEMAS_ATTR_DEFAULT) {
22075 /*
22076 * Default/fixed attributes.
22077 */
22078 if (xpathRes) {
22079 if (attr->use->defValue == NULL) {
22080 attr->value = (xmlChar *) attr->use->defValue;
22081 attr->val = attr->use->defVal;
22082 } else {
22083 attr->value = (xmlChar *) attr->decl->defValue;
22084 attr->val = attr->decl->defVal;
22085 }
22086 /*
22087 * IDCs will consume the precomputed default value,
22088 * so we need to clone it.
22089 */
22090 if (attr->val == NULL) {
22091 VERROR_INT("xmlSchemaVAttributesComplex",
22092 "default/fixed value on an attribute use was "
22093 "not precomputed");
22094 goto internal_error;
22095 }
22096 attr->val = xmlSchemaCopyValue(attr->val);
22097 if (attr->val == NULL) {
22098 VERROR_INT("xmlSchemaVAttributesComplex",
22099 "calling xmlSchemaCopyValue()");
22100 goto internal_error;
22101 }
22102 }
22103 /*
22104 * PSVI: Add the default attribute to the current element.
22105 * VAL TODO: Should we use the *normalized* value? This currently
22106 * uses the *initial* value.
22107 */
22108 if ((vctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) &&
22109 (attr->node != NULL) && (attr->node->doc != NULL)) {
22110 xmlChar *normValue;
22111 const xmlChar *value;
22112
22113 value = attr->value;
22114 /*
22115 * Normalize the value.
22116 */
22117 normValue = xmlSchemaNormalizeValue(attr->typeDef,
22118 attr->value);
22119 if (normValue != NULL)
22120 value = BAD_CAST normValue;
22121
22122 if (attr->nsName == NULL) {
22123 if (xmlNewProp(attr->node->parent,
22124 attr->localName, value) == NULL) {
22125 VERROR_INT("xmlSchemaVAttributesComplex",
22126 "callling xmlNewProp()");
22127 if (normValue != NULL)
22128 xmlFree(normValue);
22129 goto internal_error;
22130 }
22131 } else {
22132 xmlNsPtr ns;
22133
22134 ns = xmlSearchNsByHref(attr->node->doc,
22135 attr->node->parent, attr->nsName);
22136 if (ns == NULL) {
22137 xmlChar prefix[12];
22138 int counter = 0;
22139
22140 /*
22141 * Create a namespace declaration on the validation
22142 * root node if no namespace declaration is in scope.
22143 */
22144 do {
22145 snprintf((char *) prefix, 12, "p%d", counter++);
22146 ns = xmlSearchNs(attr->node->doc,
22147 attr->node->parent, BAD_CAST prefix);
22148 if (counter > 1000) {
22149 VERROR_INT(
22150 "xmlSchemaVAttributesComplex",
22151 "could not compute a ns prefix for a "
22152 "default/fixed attribute");
22153 if (normValue != NULL)
22154 xmlFree(normValue);
22155 goto internal_error;
22156 }
22157 } while (ns != NULL);
22158 ns = xmlNewNs(vctxt->validationRoot,
22159 attr->nsName, BAD_CAST prefix);
22160 }
22161 xmlNewNsProp(attr->node->parent, ns,
22162 attr->localName, value);
22163 }
22164 if (normValue != NULL)
22165 xmlFree(normValue);
22166 }
22167 /*
22168 * Go directly to IDC evaluation.
22169 */
22170 goto eval_idcs;
22171 }
22172 /*
22173 * Validate the value.
22174 */
22175 if (vctxt->value != NULL) {
22176 /*
22177 * Free last computed value; just for safety reasons.
22178 */
22179 xmlSchemaFreeValue(vctxt->value);
22180 vctxt->value = NULL;
22181 }
22182 /*
22183 * Note that the attribute *use* can be unavailable, if
22184 * the attribute was a wild attribute.
22185 */
22186 if ((attr->decl->flags & XML_SCHEMAS_ATTR_FIXED) ||
22187 ((attr->use != NULL) &&
22188 (attr->use->flags & XML_SCHEMAS_ATTR_FIXED)))
22189 fixed = 1;
22190 else
22191 fixed = 0;
22192 /*
22193 * SPEC (cvc-attribute)
22194 * (3) "The item's ·normalized value· must be locally ·valid·
22195 * with respect to that {type definition} as per
22196 * String Valid (§3.14.4)."
22197 *
22198 * VAL TODO: Do we already have the
22199 * "normalized attribute value" here?
22200 */
22201 if (xpathRes || fixed) {
22202 attr->flags |= XML_SCHEMA_NODE_INFO_VALUE_NEEDED;
22203 /*
22204 * Request a computed value.
22205 */
22206 res = xmlSchemaVCheckCVCSimpleType(
22207 (xmlSchemaAbstractCtxtPtr) vctxt,
22208 attr->node, attr->typeDef, attr->value, &(attr->val),
22209 1, 1, 0);
22210 } else {
22211 res = xmlSchemaVCheckCVCSimpleType(
22212 (xmlSchemaAbstractCtxtPtr) vctxt,
22213 attr->node, attr->typeDef, attr->value, NULL,
22214 1, 0, 0);
22215 }
22216
22217 if (res != 0) {
22218 if (res == -1) {
22219 VERROR_INT("xmlSchemaVAttributesComplex",
22220 "calling xmlSchemaStreamValidateSimpleTypeValue()");
22221 goto internal_error;
22222 }
22223 attr->state = XML_SCHEMAS_ATTR_INVALID_VALUE;
22224 /*
22225 * SPEC PSVI Assessment Outcome (Attribute)
22226 * [validity] = "invalid"
22227 */
22228 goto eval_idcs;
22229 }
22230
22231 if (fixed) {
22232 int ws;
22233 /*
22234 * SPEC Attribute Locally Valid (Use) (cvc-au)
22235 * "For an attribute information item to be·valid·
22236 * with respect to an attribute use its *normalized*
22237 * value· must match the *canonical* lexical
22238 * representation of the attribute use's {value
22239 * constraint}value, if it is present and fixed."
22240 *
22241 * VAL TODO: The requirement for the *canonical* value
22242 * will be removed in XML Schema 1.1.
22243 */
22244 /*
22245 * SPEC Attribute Locally Valid (cvc-attribute)
22246 * (4) "The item's *actual* value· must match the *value* of
22247 * the {value constraint}, if it is present and fixed."
22248 */
22249 ws = xmlSchemaGetWhiteSpaceFacetValue(attr->typeDef);
22250 if (attr->val == NULL) {
22251 /* VAL TODO: A value was not precomputed. */
22252 TODO
22253 goto eval_idcs;
22254 }
22255 if ((attr->use != NULL) &&
22256 (attr->use->defValue != NULL)) {
22257 if (attr->use->defVal == NULL) {
22258 /* VAL TODO: A default value was not precomputed. */
22259 TODO
22260 goto eval_idcs;
22261 }
22262 attr->vcValue = attr->use->defValue;
22263 /*
22264 if (xmlSchemaCompareValuesWhtsp(attr->val,
22265 (xmlSchemaWhitespaceValueType) ws,
22266 attr->use->defVal,
22267 (xmlSchemaWhitespaceValueType) ws) != 0) {
22268 */
22269 if (! xmlSchemaAreValuesEqual(attr->val, attr->use->defVal))
22270 attr->state = XML_SCHEMAS_ATTR_ERR_FIXED_VALUE;
22271 } else {
Kasimier T. Buchcik828f6542005-06-09 11:23:39 +000022272 if (attr->decl->defVal == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022273 /* VAL TODO: A default value was not precomputed. */
22274 TODO
22275 goto eval_idcs;
22276 }
Kasimier T. Buchcik828f6542005-06-09 11:23:39 +000022277 attr->vcValue = attr->decl->defValue;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022278 /*
22279 if (xmlSchemaCompareValuesWhtsp(attr->val,
22280 (xmlSchemaWhitespaceValueType) ws,
22281 attrDecl->defVal,
22282 (xmlSchemaWhitespaceValueType) ws) != 0) {
22283 */
Kasimier T. Buchcik828f6542005-06-09 11:23:39 +000022284 if (! xmlSchemaAreValuesEqual(attr->val, attr->decl->defVal))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022285 attr->state = XML_SCHEMAS_ATTR_ERR_FIXED_VALUE;
22286 }
22287 /*
22288 * [validity] = "valid"
22289 */
22290 }
22291eval_idcs:
22292 /*
22293 * Evaluate IDCs.
22294 */
22295 if (xpathRes) {
22296 if (xmlSchemaXPathProcessHistory(vctxt,
22297 vctxt->depth +1) == -1) {
22298 VERROR_INT("xmlSchemaVAttributesComplex",
22299 "calling xmlSchemaXPathEvaluate()");
22300 goto internal_error;
22301 }
Kasimier T. Buchcik800cbac2005-08-09 12:31:55 +000022302 } else if (vctxt->xpathStates != NULL)
22303 xmlSchemaXPathPop(vctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022304 }
22305
22306 /*
22307 * Report errors.
22308 */
22309 for (i = 0; i < vctxt->nbAttrInfos; i++) {
22310 attr = vctxt->attrInfos[i];
22311 if ((attr->state == XML_SCHEMAS_ATTR_META) ||
22312 (attr->state == XML_SCHEMAS_ATTR_ASSESSED) ||
22313 (attr->state == XML_SCHEMAS_ATTR_WILD_SKIP) ||
22314 (attr->state == XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL))
22315 continue;
22316 ACTIVATE_ATTRIBUTE(attr);
22317 switch (attr->state) {
22318 case XML_SCHEMAS_ATTR_ERR_MISSING: {
22319 xmlChar *str = NULL;
22320 ACTIVATE_ELEM;
22321 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
22322 XML_SCHEMAV_CVC_COMPLEX_TYPE_4, NULL, NULL,
22323 "The attribute '%s' is required but missing",
22324 xmlSchemaFormatQName(&str,
22325 attr->decl->targetNamespace,
22326 attr->decl->name),
22327 NULL);
22328 FREE_AND_NULL(str)
22329 break;
22330 }
22331 case XML_SCHEMAS_ATTR_ERR_NO_TYPE:
22332 VERROR(XML_SCHEMAV_CVC_ATTRIBUTE_2, NULL,
22333 "The type definition is absent");
22334 break;
22335 case XML_SCHEMAS_ATTR_ERR_FIXED_VALUE:
22336 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
22337 XML_SCHEMAV_CVC_AU, NULL, NULL,
22338 "The value '%s' does not match the fixed "
22339 "value constraint '%s'",
22340 attr->value, attr->vcValue);
22341 break;
22342 case XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL:
22343 VERROR(XML_SCHEMAV_CVC_WILDCARD, NULL,
22344 "No matching global attribute declaration available, but "
22345 "demanded by the strict wildcard");
22346 break;
22347 case XML_SCHEMAS_ATTR_UNKNOWN:
22348 if (attr->metaType)
22349 break;
22350 /*
22351 * MAYBE VAL TODO: One might report different error messages
22352 * for the following errors.
22353 */
22354 if (type->attributeWildcard == NULL) {
22355 xmlSchemaIllegalAttrErr((xmlSchemaAbstractCtxtPtr) vctxt,
22356 XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_1, attr, NULL);
22357 } else {
22358 xmlSchemaIllegalAttrErr((xmlSchemaAbstractCtxtPtr) vctxt,
22359 XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_2, attr, NULL);
22360 }
22361 break;
22362 default:
22363 break;
22364 }
22365 }
22366
22367 ACTIVATE_ELEM;
22368 return (0);
22369internal_error:
22370 ACTIVATE_ELEM;
22371 return (-1);
22372}
22373
22374static int
22375xmlSchemaValidateElemWildcard(xmlSchemaValidCtxtPtr vctxt,
22376 int *skip)
22377{
22378 xmlSchemaWildcardPtr wild = (xmlSchemaWildcardPtr) vctxt->inode->decl;
22379 /*
22380 * The namespace of the element was already identified to be
22381 * matching the wildcard.
22382 */
22383 if ((skip == NULL) || (wild == NULL) ||
22384 (wild->type != XML_SCHEMA_TYPE_ANY)) {
22385 VERROR_INT("xmlSchemaValidateElemWildcard",
22386 "bad arguments");
22387 return (-1);
22388 }
22389 *skip = 0;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022390 if (wild->processContents == XML_SCHEMAS_ANY_SKIP) {
22391 /*
22392 * URGENT VAL TODO: Either we need to position the stream to the
22393 * next sibling, or walk the whole subtree.
22394 */
22395 *skip = 1;
22396 return (0);
22397 }
22398 {
22399 xmlSchemaElementPtr decl = NULL;
22400
22401 decl = xmlHashLookup3(vctxt->schema->elemDecl,
22402 vctxt->inode->localName, vctxt->inode->nsName,
22403 NULL);
22404 if (decl != NULL) {
22405 vctxt->inode->decl = decl;
22406 return (0);
22407 }
22408 }
22409 if (wild->processContents == XML_SCHEMAS_ANY_STRICT) {
22410 /* VAL TODO: Change to proper error code. */
22411 VERROR(XML_SCHEMAV_CVC_ELT_1, (xmlSchemaTypePtr) wild,
22412 "No matching global element declaration available, but "
22413 "demanded by the strict wildcard");
22414 return (vctxt->err);
22415 }
22416 if (vctxt->nbAttrInfos != 0) {
22417 xmlSchemaAttrInfoPtr iattr;
22418 /*
22419 * SPEC Validation Rule: Schema-Validity Assessment (Element)
22420 * (1.2.1.2.1) - (1.2.1.2.3 )
22421 *
22422 * Use the xsi:type attribute for the type definition.
22423 */
22424 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
22425 XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
22426 if (iattr != NULL) {
22427 if (xmlSchemaProcessXSIType(vctxt, iattr,
22428 &(vctxt->inode->typeDef), NULL) == -1) {
22429 VERROR_INT("xmlSchemaValidateElemWildcard",
22430 "calling xmlSchemaProcessXSIType() to "
22431 "process the attribute 'xsi:nil'");
22432 return (-1);
22433 }
22434 /*
22435 * Don't return an error on purpose.
22436 */
22437 return (0);
22438 }
22439 }
22440 /*
22441 * SPEC Validation Rule: Schema-Validity Assessment (Element)
22442 *
22443 * Fallback to "anyType".
22444 */
22445 vctxt->inode->typeDef =
22446 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
22447 return (0);
22448}
22449
22450/*
22451* xmlSchemaCheckCOSValidDefault:
22452*
22453* This will be called if: not nilled, no content and a default/fixed
22454* value is provided.
22455*/
22456
22457static int
22458xmlSchemaCheckCOSValidDefault(xmlSchemaValidCtxtPtr vctxt,
22459 const xmlChar *value,
22460 xmlSchemaValPtr *val)
22461{
22462 int ret = 0;
22463 xmlSchemaNodeInfoPtr inode = vctxt->inode;
22464
22465 /*
22466 * cos-valid-default:
22467 * Schema Component Constraint: Element Default Valid (Immediate)
22468 * For a string to be a valid default with respect to a type
22469 * definition the appropriate case among the following must be true:
22470 */
22471 if IS_COMPLEX_TYPE(inode->typeDef) {
22472 /*
22473 * Complex type.
22474 *
22475 * SPEC (2.1) "its {content type} must be a simple type definition
22476 * or mixed."
22477 * SPEC (2.2.2) "If the {content type} is mixed, then the {content
22478 * type}'s particle must be ·emptiable· as defined by
22479 * Particle Emptiable (§3.9.6)."
22480 */
22481 if ((! HAS_SIMPLE_CONTENT(inode->typeDef)) &&
22482 ((! HAS_MIXED_CONTENT(inode->typeDef)) ||
22483 (! IS_PARTICLE_EMPTIABLE(inode->typeDef)))) {
22484 ret = XML_SCHEMAP_COS_VALID_DEFAULT_2_1;
22485 /* NOTE that this covers (2.2.2) as well. */
22486 VERROR(ret, NULL,
22487 "For a string to be a valid default, the type definition "
22488 "must be a simple type or a complex type with simple content "
22489 "or mixed content and a particle emptiable");
22490 return(ret);
22491 }
22492 }
22493 /*
22494 * 1 If the type definition is a simple type definition, then the string
22495 * must be ·valid· with respect to that definition as defined by String
22496 * Valid (§3.14.4).
22497 *
22498 * AND
22499 *
22500 * 2.2.1 If the {content type} is a simple type definition, then the
22501 * string must be ·valid· with respect to that simple type definition
22502 * as defined by String Valid (§3.14.4).
22503 */
22504 if (IS_SIMPLE_TYPE(inode->typeDef)) {
22505
22506 ret = xmlSchemaVCheckCVCSimpleType((xmlSchemaAbstractCtxtPtr) vctxt,
22507 NULL, inode->typeDef, value, val, 1, 1, 0);
22508
22509 } else if (HAS_SIMPLE_CONTENT(inode->typeDef)) {
22510
22511 ret = xmlSchemaVCheckCVCSimpleType((xmlSchemaAbstractCtxtPtr) vctxt,
22512 NULL, inode->typeDef->contentTypeDef, value, val, 1, 1, 0);
22513 }
22514 if (ret < 0) {
22515 VERROR_INT("xmlSchemaCheckCOSValidDefault",
22516 "calling xmlSchemaVCheckCVCSimpleType()");
22517 }
22518 return (ret);
22519}
22520
22521static void
22522xmlSchemaVContentModelCallback(xmlSchemaValidCtxtPtr vctxt ATTRIBUTE_UNUSED,
22523 const xmlChar * name ATTRIBUTE_UNUSED,
22524 xmlSchemaElementPtr item,
22525 xmlSchemaNodeInfoPtr inode)
22526{
22527 inode->decl = item;
22528#ifdef DEBUG_CONTENT
22529 {
22530 xmlChar *str = NULL;
22531
22532 if (item->type == XML_SCHEMA_TYPE_ELEMENT) {
22533 xmlGenericError(xmlGenericErrorContext,
22534 "AUTOMATON callback for '%s' [declaration]\n",
22535 xmlSchemaFormatQName(&str,
22536 inode->localName, inode->nsName));
22537 } else {
22538 xmlGenericError(xmlGenericErrorContext,
22539 "AUTOMATON callback for '%s' [wildcard]\n",
22540 xmlSchemaFormatQName(&str,
22541 inode->localName, inode->nsName));
22542
22543 }
22544 FREE_AND_NULL(str)
22545 }
22546#endif
22547}
22548
22549static int
22550xmlSchemaValidatorPushElem(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000022551{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022552 vctxt->inode = xmlSchemaGetFreshElemInfo(vctxt);
22553 if (vctxt->inode == NULL) {
22554 VERROR_INT("xmlSchemaValidatorPushElem",
22555 "calling xmlSchemaGetFreshElemInfo()");
22556 return (-1);
22557 }
22558 vctxt->nbAttrInfos = 0;
22559 return (0);
22560}
22561
22562static int
22563xmlSchemaVCheckINodeDataType(xmlSchemaValidCtxtPtr vctxt,
22564 xmlSchemaNodeInfoPtr inode,
22565 xmlSchemaTypePtr type,
22566 const xmlChar *value)
22567{
22568 if (inode->flags & XML_SCHEMA_NODE_INFO_VALUE_NEEDED)
22569 return (xmlSchemaVCheckCVCSimpleType(
22570 (xmlSchemaAbstractCtxtPtr) vctxt, NULL,
22571 type, value, &(inode->val), 1, 1, 0));
22572 else
22573 return (xmlSchemaVCheckCVCSimpleType(
22574 (xmlSchemaAbstractCtxtPtr) vctxt, NULL,
22575 type, value, NULL, 1, 0, 0));
22576}
22577
22578
22579
22580/*
22581* Process END of element.
22582*/
22583static int
22584xmlSchemaValidatorPopElem(xmlSchemaValidCtxtPtr vctxt)
22585{
22586 int ret = 0;
22587 xmlSchemaNodeInfoPtr inode = vctxt->inode;
22588
22589 if (vctxt->nbAttrInfos != 0)
22590 xmlSchemaClearAttrInfos(vctxt);
22591 if (inode->flags & XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED) {
22592 /*
22593 * This element was not expected;
22594 * we will not validate child elements of broken parents.
22595 * Skip validation of all content of the parent.
22596 */
22597 vctxt->skipDepth = vctxt->depth -1;
22598 goto end_elem;
22599 }
22600 if ((inode->typeDef == NULL) ||
22601 (inode->flags & XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE)) {
22602 /*
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000022603 * 1. the type definition might be missing if the element was
22604 * error prone
22605 * 2. it might be abstract.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022606 */
22607 goto end_elem;
22608 }
22609 /*
22610 * Check the content model.
22611 */
22612 if ((inode->typeDef->contentType == XML_SCHEMA_CONTENT_MIXED) ||
22613 (inode->typeDef->contentType == XML_SCHEMA_CONTENT_ELEMENTS)) {
22614
22615 /*
22616 * Workaround for "anyType".
22617 */
22618 if (inode->typeDef->builtInType == XML_SCHEMAS_ANYTYPE)
22619 goto character_content;
22620
22621 if ((inode->flags & XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT) == 0) {
22622 xmlChar *values[10];
22623 int terminal, nbval = 10, nbneg;
22624
22625 if (inode->regexCtxt == NULL) {
22626 /*
22627 * Create the regex context.
22628 */
22629 inode->regexCtxt =
22630 xmlRegNewExecCtxt(inode->typeDef->contModel,
22631 (xmlRegExecCallbacks) xmlSchemaVContentModelCallback,
22632 vctxt);
22633 if (inode->regexCtxt == NULL) {
22634 VERROR_INT("xmlSchemaValidatorPopElem",
22635 "failed to create a regex context");
22636 goto internal_error;
22637 }
22638#ifdef DEBUG_AUTOMATA
22639 xmlGenericError(xmlGenericErrorContext,
22640 "AUTOMATON create on '%s'\n", inode->localName);
22641#endif
22642 }
22643 /*
22644 * Get hold of the still expected content, since a further
22645 * call to xmlRegExecPushString() will loose this information.
22646 */
22647 xmlRegExecNextValues(inode->regexCtxt,
22648 &nbval, &nbneg, &values[0], &terminal);
22649 ret = xmlRegExecPushString(inode->regexCtxt, NULL, NULL);
22650 if (ret <= 0) {
22651 /*
22652 * Still missing something.
22653 */
22654 ret = 1;
22655 inode->flags |=
22656 XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT;
22657 xmlSchemaComplexTypeErr((xmlSchemaAbstractCtxtPtr) vctxt,
22658 XML_SCHEMAV_ELEMENT_CONTENT, NULL, NULL,
22659 "Missing child element(s)",
22660 nbval, nbneg, values);
22661#ifdef DEBUG_AUTOMATA
22662 xmlGenericError(xmlGenericErrorContext,
22663 "AUTOMATON missing ERROR on '%s'\n",
22664 inode->localName);
22665#endif
22666 } else {
22667 /*
22668 * Content model is satisfied.
22669 */
22670 ret = 0;
22671#ifdef DEBUG_AUTOMATA
22672 xmlGenericError(xmlGenericErrorContext,
22673 "AUTOMATON succeeded on '%s'\n",
22674 inode->localName);
22675#endif
22676 }
22677
22678 }
22679 }
22680 if (inode->typeDef->contentType == XML_SCHEMA_CONTENT_ELEMENTS)
22681 goto end_elem;
22682
22683character_content:
22684
22685 if (vctxt->value != NULL) {
22686 xmlSchemaFreeValue(vctxt->value);
22687 vctxt->value = NULL;
22688 }
22689 /*
22690 * Check character content.
22691 */
22692 if (inode->decl == NULL) {
22693 /*
22694 * Speedup if no declaration exists.
22695 */
22696 if (IS_SIMPLE_TYPE(inode->typeDef)) {
22697 ret = xmlSchemaVCheckINodeDataType(vctxt,
22698 inode, inode->typeDef, inode->value);
22699 } else if (HAS_SIMPLE_CONTENT(inode->typeDef)) {
22700 ret = xmlSchemaVCheckINodeDataType(vctxt,
22701 inode, inode->typeDef->contentTypeDef,
22702 inode->value);
22703 }
22704 if (ret < 0) {
22705 VERROR_INT("xmlSchemaValidatorPopElem",
22706 "calling xmlSchemaVCheckCVCSimpleType()");
22707 goto internal_error;
22708 }
22709 goto end_elem;
22710 }
22711 /*
22712 * cvc-elt (3.3.4) : 5
22713 * The appropriate case among the following must be true:
22714 */
22715 /*
22716 * cvc-elt (3.3.4) : 5.1
22717 * If the declaration has a {value constraint},
22718 * the item has neither element nor character [children] and
22719 * clause 3.2 has not applied, then all of the following must be true:
22720 */
22721 if ((inode->decl->value != NULL) &&
22722 (inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY) &&
22723 (! INODE_NILLED(inode))) {
22724 /*
22725 * cvc-elt (3.3.4) : 5.1.1
22726 * If the ·actual type definition· is a ·local type definition·
22727 * then the canonical lexical representation of the {value constraint}
22728 * value must be a valid default for the ·actual type definition· as
22729 * defined in Element Default Valid (Immediate) (§3.3.6).
22730 */
22731 /*
22732 * NOTE: 'local' above means types aquired by xsi:type.
22733 * NOTE: Although the *canonical* value is stated, it is not
22734 * relevant if canonical or not. Additionally XML Schema 1.1
22735 * will removed this requirement as well.
22736 */
22737 if (inode->flags & XML_SCHEMA_ELEM_INFO_LOCAL_TYPE) {
22738
22739 ret = xmlSchemaCheckCOSValidDefault(vctxt,
22740 inode->decl->value, &(inode->val));
22741 if (ret != 0) {
22742 if (ret < 0) {
22743 VERROR_INT("xmlSchemaValidatorPopElem",
22744 "calling xmlSchemaCheckCOSValidDefault()");
22745 goto internal_error;
22746 }
22747 goto end_elem;
22748 }
22749 /*
22750 * Stop here, to avoid redundant validation of the value
22751 * (see following).
22752 */
22753 goto default_psvi;
22754 }
22755 /*
22756 * cvc-elt (3.3.4) : 5.1.2
22757 * The element information item with the canonical lexical
22758 * representation of the {value constraint} value used as its
22759 * ·normalized value· must be ·valid· with respect to the
22760 * ·actual type definition· as defined by Element Locally Valid (Type)
22761 * (§3.3.4).
22762 */
22763 if (IS_SIMPLE_TYPE(inode->typeDef)) {
22764 ret = xmlSchemaVCheckINodeDataType(vctxt,
22765 inode, inode->typeDef, inode->decl->value);
22766 } else if (HAS_SIMPLE_CONTENT(inode->typeDef)) {
22767 ret = xmlSchemaVCheckINodeDataType(vctxt,
22768 inode, inode->typeDef->contentTypeDef,
22769 inode->decl->value);
22770 }
22771 if (ret != 0) {
22772 if (ret < 0) {
22773 VERROR_INT("xmlSchemaValidatorPopElem",
22774 "calling xmlSchemaVCheckCVCSimpleType()");
22775 goto internal_error;
22776 }
22777 goto end_elem;
22778 }
22779
22780default_psvi:
22781 /*
22782 * PSVI: Create a text node on the instance element.
22783 */
22784 if ((vctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) &&
22785 (inode->node != NULL)) {
22786 xmlNodePtr textChild;
22787 xmlChar *normValue;
22788 /*
22789 * VAL TODO: Normalize the value.
22790 */
22791 normValue = xmlSchemaNormalizeValue(inode->typeDef,
22792 inode->decl->value);
22793 if (normValue != NULL) {
22794 textChild = xmlNewText(BAD_CAST normValue);
22795 xmlFree(normValue);
22796 } else
22797 textChild = xmlNewText(inode->decl->value);
22798 if (textChild == NULL) {
22799 VERROR_INT("xmlSchemaValidatorPopElem",
22800 "calling xmlNewText()");
22801 goto internal_error;
22802 } else
22803 xmlAddChild(inode->node, textChild);
22804 }
22805
22806 } else if (! INODE_NILLED(inode)) {
22807 /*
22808 * 5.2.1 The element information item must be ·valid· with respect
22809 * to the ·actual type definition· as defined by Element Locally
22810 * Valid (Type) (§3.3.4).
22811 */
22812 if (IS_SIMPLE_TYPE(inode->typeDef)) {
22813 /*
22814 * SPEC (cvc-type) (3.1)
22815 * "If the type definition is a simple type definition, ..."
22816 * (3.1.3) "If clause 3.2 of Element Locally Valid
22817 * (Element) (§3.3.4) did not apply, then the ·normalized value·
22818 * must be ·valid· with respect to the type definition as defined
22819 * by String Valid (§3.14.4).
22820 */
22821 ret = xmlSchemaVCheckINodeDataType(vctxt,
22822 inode, inode->typeDef, inode->value);
22823 } else if (HAS_SIMPLE_CONTENT(inode->typeDef)) {
22824 /*
22825 * SPEC (cvc-type) (3.2) "If the type definition is a complex type
22826 * definition, then the element information item must be
22827 * ·valid· with respect to the type definition as per
22828 * Element Locally Valid (Complex Type) (§3.4.4);"
22829 *
22830 * SPEC (cvc-complex-type) (2.2)
22831 * "If the {content type} is a simple type definition, ...
22832 * the ·normalized value· of the element information item is
22833 * ·valid· with respect to that simple type definition as
22834 * defined by String Valid (§3.14.4)."
22835 */
22836 ret = xmlSchemaVCheckINodeDataType(vctxt,
22837 inode, inode->typeDef->contentTypeDef, inode->value);
22838 }
22839 if (ret != 0) {
22840 if (ret < 0) {
22841 VERROR_INT("xmlSchemaValidatorPopElem",
22842 "calling xmlSchemaVCheckCVCSimpleType()");
22843 goto internal_error;
22844 }
22845 goto end_elem;
22846 }
22847 /*
22848 * 5.2.2 If there is a fixed {value constraint} and clause 3.2 has
22849 * not applied, all of the following must be true:
22850 */
22851 if ((inode->decl->value != NULL) &&
22852 (inode->decl->flags & XML_SCHEMAS_ELEM_FIXED)) {
22853
22854 /*
22855 * TODO: We will need a computed value, when comparison is
22856 * done on computed values.
22857 */
22858 /*
22859 * 5.2.2.1 The element information item must have no element
22860 * information item [children].
22861 */
22862 if (inode->flags &
22863 XML_SCHEMA_ELEM_INFO_HAS_ELEM_CONTENT) {
22864 ret = XML_SCHEMAV_CVC_ELT_5_2_2_1;
22865 VERROR(ret, NULL,
22866 "The content must not containt element nodes since "
22867 "there is a fixed value constraint");
22868 goto end_elem;
22869 } else {
22870 /*
22871 * 5.2.2.2 The appropriate case among the following must
22872 * be true:
22873 */
22874 if (HAS_MIXED_CONTENT(inode->typeDef)) {
22875 /*
22876 * 5.2.2.2.1 If the {content type} of the ·actual type
22877 * definition· is mixed, then the *initial value* of the
22878 * item must match the canonical lexical representation
22879 * of the {value constraint} value.
22880 *
22881 * ... the *initial value* of an element information
22882 * item is the string composed of, in order, the
22883 * [character code] of each character information item in
22884 * the [children] of that element information item.
22885 */
22886 if (! xmlStrEqual(inode->value, inode->decl->value)){
22887 /*
22888 * VAL TODO: Report invalid & expected values as well.
22889 * VAL TODO: Implement the canonical stuff.
22890 */
22891 ret = XML_SCHEMAV_CVC_ELT_5_2_2_2_1;
22892 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
22893 ret, NULL, NULL,
22894 "The initial value '%s' does not match the fixed "
22895 "value constraint '%s'",
22896 inode->value, inode->decl->value);
22897 goto end_elem;
22898 }
22899 } else if (HAS_SIMPLE_CONTENT(inode->typeDef)) {
22900 /*
22901 * 5.2.2.2.2 If the {content type} of the ·actual type
22902 * definition· is a simple type definition, then the
22903 * *actual value* of the item must match the canonical
22904 * lexical representation of the {value constraint} value.
22905 */
22906 /*
22907 * VAL TODO: *actual value* is the normalized value, impl.
22908 * this.
22909 * VAL TODO: Report invalid & expected values as well.
22910 * VAL TODO: Implement a comparison with the computed values.
22911 */
22912 if (! xmlStrEqual(inode->value,
22913 inode->decl->value)) {
22914 ret = XML_SCHEMAV_CVC_ELT_5_2_2_2_2;
22915 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) vctxt,
22916 ret, NULL, NULL,
22917 "The actual value '%s' does not match the fixed "
22918 "value constraint '%s'",
22919 inode->value,
22920 inode->decl->value);
22921 goto end_elem;
22922 }
22923 }
22924 }
22925 }
22926 }
22927
22928end_elem:
22929 if (vctxt->depth < 0) {
22930 /* TODO: raise error? */
22931 return (0);
22932 }
22933 if (vctxt->depth == vctxt->skipDepth)
22934 vctxt->skipDepth = -1;
22935 /*
22936 * Evaluate the history of XPath state objects.
22937 */
22938 if (xmlSchemaXPathProcessHistory(vctxt, vctxt->depth) == -1)
22939 goto internal_error;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022940 /*
22941 * TODO: 6 The element information item must be ·valid· with respect to each of
22942 * the {identity-constraint definitions} as per Identity-constraint
22943 * Satisfied (§3.11.4).
22944 */
22945 /*
22946 * Validate IDC keyrefs.
22947 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022948 if (xmlSchemaCheckCVCIDCKeyRef(vctxt) == -1)
22949 goto internal_error;
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022950 /*
22951 * Merge/free the IDC table.
22952 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022953 if (inode->idcTable != NULL) {
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022954#ifdef DEBUG_IDC
22955 xmlSchemaDebugDumpIDCTable(stdout,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022956 inode->nsName,
22957 inode->localName,
22958 inode->idcTable);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022959#endif
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022960 if (vctxt->depth > 0) {
22961 /*
22962 * Merge the IDC node table with the table of the parent node.
22963 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022964 if (xmlSchemaBubbleIDCNodeTables(vctxt) == -1)
22965 goto internal_error;
22966 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022967 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022968 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022969 * Clear the current ielem.
22970 * VAL TODO: Don't free the PSVI IDC tables if they are
22971 * requested for the PSVI.
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022972 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022973 xmlSchemaClearElemInfo(inode);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022974 /*
22975 * Skip further processing if we are on the validation root.
22976 */
22977 if (vctxt->depth == 0) {
22978 vctxt->depth--;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022979 vctxt->inode = NULL;
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000022980 return (0);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022981 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022982 /*
22983 * Reset the bubbleDepth if needed.
22984 */
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000022985 if (vctxt->aidcs != NULL) {
22986 xmlSchemaIDCAugPtr aidc = vctxt->aidcs;
22987 do {
22988 if (aidc->bubbleDepth == vctxt->depth) {
22989 /*
22990 * A bubbleDepth of a key/unique IDC matches the current
22991 * depth, this means that we are leaving the scope of the
22992 * top-most keyref IDC.
22993 */
22994 aidc->bubbleDepth = -1;
22995 }
22996 aidc = aidc->next;
22997 } while (aidc != NULL);
22998 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000022999 vctxt->depth--;
23000 vctxt->inode = vctxt->elemInfos[vctxt->depth];
Kasimier T. Buchcik25799ce2005-02-15 14:39:48 +000023001 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023002 * VAL TODO: 7 If the element information item is the ·validation root·, it must be
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023003 * ·valid· per Validation Root Valid (ID/IDREF) (§3.3.4).
23004 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023005 return (ret);
23006
23007internal_error:
23008 vctxt->err = -1;
23009 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000023010}
23011
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023012/*
23013* 3.4.4 Complex Type Definition Validation Rules
23014* Validation Rule: Element Locally Valid (Complex Type) (cvc-complex-type)
23015*/
Daniel Veillardc0826a72004-08-10 14:17:33 +000023016static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023017xmlSchemaValidateChildElem(xmlSchemaValidCtxtPtr vctxt)
William M. Brack2f2a6632004-08-20 23:09:47 +000023018{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023019 xmlSchemaNodeInfoPtr pielem;
23020 xmlSchemaTypePtr ptype;
Daniel Veillard01fa6152004-06-29 17:04:39 +000023021 int ret = 0;
Daniel Veillard3646d642004-06-02 19:19:14 +000023022
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023023 if (vctxt->depth <= 0) {
23024 VERROR_INT("xmlSchemaValidateChildElem",
23025 "not intended for the validation root");
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023026 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023027 }
23028 pielem = vctxt->elemInfos[vctxt->depth -1];
23029 if (pielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
23030 pielem->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023031 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023032 * Handle 'nilled' elements.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023033 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023034 if (INODE_NILLED(pielem)) {
23035 /*
23036 * SPEC (cvc-elt) (3.3.4) : (3.2.1)
23037 */
23038 ACTIVATE_PARENT_ELEM;
23039 ret = XML_SCHEMAV_CVC_ELT_3_2_1;
23040 VERROR(ret, NULL,
23041 "Neither character nor element content is allowed, "
23042 "because the element was 'nilled'");
23043 ACTIVATE_ELEM;
23044 goto unexpected_elem;
23045 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023046
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023047 ptype = pielem->typeDef;
23048
23049 if (ptype->builtInType == XML_SCHEMAS_ANYTYPE) {
23050 /*
23051 * Workaround for "anyType": we have currently no content model
23052 * assigned for "anyType", so handle it explicitely.
23053 * "anyType" has an unbounded, lax "any" wildcard.
23054 */
23055 vctxt->inode->decl = xmlSchemaGetElem(vctxt->schema,
23056 vctxt->inode->localName,
23057 vctxt->inode->nsName);
23058
23059 if (vctxt->inode->decl == NULL) {
23060 xmlSchemaAttrInfoPtr iattr;
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000023061 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023062 * Process "xsi:type".
23063 * SPEC (cvc-assess-elt) (1.2.1.2.1) - (1.2.1.2.3)
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000023064 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023065 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
23066 XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
23067 if (iattr != NULL) {
23068 ret = xmlSchemaProcessXSIType(vctxt, iattr,
23069 &(vctxt->inode->typeDef), NULL);
23070 if (ret != 0) {
23071 if (ret == -1) {
23072 VERROR_INT("xmlSchemaValidateChildElem",
23073 "calling xmlSchemaProcessXSIType() to "
23074 "process the attribute 'xsi:nil'");
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000023075 return (-1);
Kasimier T. Buchcik187ea5f2005-04-19 11:25:43 +000023076 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023077 return (ret);
Daniel Veillard01fa6152004-06-29 17:04:39 +000023078 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023079 } else {
23080 /*
23081 * Fallback to "anyType".
23082 *
23083 * SPEC (cvc-assess-elt)
23084 * "If the item cannot be ·strictly assessed·, [...]
23085 * an element information item's schema validity may be laxly
23086 * assessed if its ·context-determined declaration· is not
23087 * skip by ·validating· with respect to the ·ur-type
23088 * definition· as per Element Locally Valid (Type) (§3.3.4)."
23089 */
23090 vctxt->inode->typeDef =
23091 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023092 }
23093 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023094 return (0);
23095 }
23096
23097 switch (ptype->contentType) {
23098 case XML_SCHEMA_CONTENT_EMPTY:
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023099 /*
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023100 * SPEC (2.1) "If the {content type} is empty, then the
23101 * element information item has no character or element
23102 * information item [children]."
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023103 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023104 ACTIVATE_PARENT_ELEM
23105 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1;
23106 VERROR(ret, NULL,
23107 "Element content is not allowed, "
23108 "because the content type is empty");
23109 ACTIVATE_ELEM
23110 goto unexpected_elem;
23111 break;
23112
23113 case XML_SCHEMA_CONTENT_MIXED:
23114 case XML_SCHEMA_CONTENT_ELEMENTS: {
23115 xmlRegExecCtxtPtr regexCtxt;
23116 xmlChar *values[10];
23117 int terminal, nbval = 10, nbneg;
23118
23119 /* VAL TODO: Optimized "anyType" validation.*/
23120
23121 if (ptype->contModel == NULL) {
23122 VERROR_INT("xmlSchemaValidateChildElem",
23123 "type has elem content but no content model");
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000023124 return (-1);
Kasimier T. Buchcik478d6932005-03-16 16:29:18 +000023125 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023126 /*
23127 * Safety belf for evaluation if the cont. model was already
23128 * examined to be invalid.
23129 */
23130 if (pielem->flags & XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT) {
23131 VERROR_INT("xmlSchemaValidateChildElem",
23132 "validating elem, but elem content is already invalid");
23133 return (-1);
23134 }
Kasimier T. Buchcikc3af19d2005-01-13 12:10:11 +000023135
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023136 regexCtxt = pielem->regexCtxt;
23137 if (regexCtxt == NULL) {
23138 /*
23139 * Create the regex context.
23140 */
23141 regexCtxt = xmlRegNewExecCtxt(ptype->contModel,
23142 (xmlRegExecCallbacks) xmlSchemaVContentModelCallback,
23143 vctxt);
23144 if (regexCtxt == NULL) {
23145 VERROR_INT("xmlSchemaValidateChildElem",
23146 "failed to create a regex context");
23147 return (-1);
23148 }
23149 pielem->regexCtxt = regexCtxt;
23150#ifdef DEBUG_AUTOMATA
23151 xmlGenericError(xmlGenericErrorContext, "AUTOMATA create on '%s'\n",
23152 pielem->localName);
23153#endif
23154 }
23155
23156 /*
23157 * SPEC (2.4) "If the {content type} is element-only or mixed,
23158 * then the sequence of the element information item's
23159 * element information item [children], if any, taken in
23160 * order, is ·valid· with respect to the {content type}'s
23161 * particle, as defined in Element Sequence Locally Valid
23162 * (Particle) (§3.9.4)."
23163 */
23164 ret = xmlRegExecPushString2(regexCtxt,
23165 vctxt->inode->localName,
23166 vctxt->inode->nsName,
23167 vctxt->inode);
23168#ifdef DEBUG_AUTOMATA
23169 if (ret < 0)
23170 xmlGenericError(xmlGenericErrorContext,
23171 "AUTOMATON push ERROR for '%s' on '%s'\n",
23172 vctxt->inode->localName, pielem->localName);
23173 else
23174 xmlGenericError(xmlGenericErrorContext,
23175 "AUTOMATON push OK for '%s' on '%s'\n",
23176 vctxt->inode->localName, pielem->localName);
23177#endif
23178 if (vctxt->err == XML_SCHEMAV_INTERNAL) {
23179 VERROR_INT("xmlSchemaValidateChildElem",
23180 "calling xmlRegExecPushString2()");
23181 return (-1);
23182 }
23183 if (ret < 0) {
23184 xmlRegExecErrInfo(regexCtxt, NULL, &nbval, &nbneg,
23185 &values[0], &terminal);
23186 xmlSchemaComplexTypeErr((xmlSchemaAbstractCtxtPtr) vctxt,
23187 XML_SCHEMAV_ELEMENT_CONTENT, NULL,NULL,
23188 "This element is not expected",
23189 nbval, nbneg, values);
23190 ret = vctxt->err;
23191 goto unexpected_elem;
23192 } else
23193 ret = 0;
Daniel Veillard01fa6152004-06-29 17:04:39 +000023194 }
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023195 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023196 case XML_SCHEMA_CONTENT_SIMPLE:
23197 case XML_SCHEMA_CONTENT_BASIC:
23198 ACTIVATE_PARENT_ELEM
23199 if (IS_COMPLEX_TYPE(ptype)) {
23200 /*
23201 * SPEC (cvc-complex-type) (2.2)
23202 * "If the {content type} is a simple type definition, then
23203 * the element information item has no element information
23204 * item [children], ..."
23205 */
23206 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
23207 VERROR(ret, NULL, "Element content is not allowed, "
23208 "because the content type is a simple type definition");
23209 } else {
23210 /*
23211 * SPEC (cvc-type) (3.1.2) "The element information item must
23212 * have no element information item [children]."
23213 */
23214 ret = XML_SCHEMAV_CVC_TYPE_3_1_2;
23215 VERROR(ret, NULL, "Element content is not allowed, "
23216 "because the type definition is simple");
23217 }
23218 ACTIVATE_ELEM
23219 ret = vctxt->err;
23220 goto unexpected_elem;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023221 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023222
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023223 default:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023224 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023225 }
23226 return (ret);
23227unexpected_elem:
23228 /*
23229 * Pop this element and set the skipDepth to skip
23230 * all further content of the parent element.
23231 */
23232 vctxt->skipDepth = vctxt->depth;
23233 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED;
23234 pielem->flags |= XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT;
23235 return (ret);
23236}
23237
23238#define XML_SCHEMA_PUSH_TEXT_PERSIST 1
23239#define XML_SCHEMA_PUSH_TEXT_CREATED 2
23240#define XML_SCHEMA_PUSH_TEXT_VOLATILE 3
23241
23242static int
23243xmlSchemaVPushText(xmlSchemaValidCtxtPtr vctxt,
23244 int nodeType, const xmlChar *value, int len,
23245 int mode, int *consumed)
23246{
23247 /*
23248 * Unfortunately we have to duplicate the text sometimes.
23249 * OPTIMIZE: Maybe we could skip it, if:
23250 * 1. content type is simple
23251 * 2. whitespace is "collapse"
23252 * 3. it consists of whitespace only
23253 *
23254 * Process character content.
23255 */
23256 if (consumed != NULL)
23257 *consumed = 0;
23258 if (INODE_NILLED(vctxt->inode)) {
23259 /*
23260 * SPEC cvc-elt (3.3.4 - 3.2.1)
23261 * "The element information item must have no character or
23262 * element information item [children]."
23263 */
23264 VERROR(XML_SCHEMAV_CVC_ELT_3_2_1, NULL,
23265 "Neither character nor element content is allowed "
23266 "because the element is 'nilled'");
23267 return (vctxt->err);
23268 }
23269 /*
23270 * SPEC (2.1) "If the {content type} is empty, then the
23271 * element information item has no character or element
23272 * information item [children]."
23273 */
23274 if (vctxt->inode->typeDef->contentType ==
23275 XML_SCHEMA_CONTENT_EMPTY) {
23276 VERROR(XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1, NULL,
23277 "Character content is not allowed, "
23278 "because the content type is empty");
23279 return (vctxt->err);
23280 }
23281
23282 if (vctxt->inode->typeDef->contentType ==
23283 XML_SCHEMA_CONTENT_ELEMENTS) {
23284 if ((nodeType != XML_TEXT_NODE) ||
23285 (! xmlSchemaIsBlank((xmlChar *) value, len))) {
23286 /*
23287 * SPEC cvc-complex-type (2.3)
23288 * "If the {content type} is element-only, then the
23289 * element information item has no character information
23290 * item [children] other than those whose [character
23291 * code] is defined as a white space in [XML 1.0 (Second
23292 * Edition)]."
23293 */
23294 VERROR(XML_SCHEMAV_CVC_COMPLEX_TYPE_2_3, NULL,
23295 "Character content other than whitespace is not allowed "
23296 "because the content type is 'element-only'");
23297 return (vctxt->err);
23298 }
23299 return (0);
23300 }
23301
23302 if ((value == NULL) || (value[0] == 0))
23303 return (0);
23304 /*
23305 * Save the value.
23306 * NOTE that even if the content type is *mixed*, we need the
23307 * *initial value* for default/fixed value constraints.
23308 */
23309 if ((vctxt->inode->typeDef->contentType == XML_SCHEMA_CONTENT_MIXED) &&
23310 ((vctxt->inode->decl == NULL) ||
23311 (vctxt->inode->decl->value == NULL)))
23312 return (0);
23313
23314 if (vctxt->inode->value == NULL) {
23315 /*
23316 * Set the value.
23317 */
23318 switch (mode) {
23319 case XML_SCHEMA_PUSH_TEXT_PERSIST:
23320 /*
23321 * When working on a tree.
23322 */
23323 vctxt->inode->value = value;
23324 break;
23325 case XML_SCHEMA_PUSH_TEXT_CREATED:
23326 /*
23327 * When working with the reader.
23328 * The value will be freed by the element info.
23329 */
23330 vctxt->inode->value = value;
23331 if (consumed != NULL)
23332 *consumed = 1;
23333 vctxt->inode->flags |=
23334 XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
23335 break;
23336 case XML_SCHEMA_PUSH_TEXT_VOLATILE:
23337 /*
23338 * When working with SAX.
23339 * The value will be freed by the element info.
23340 */
23341 if (len != -1)
23342 vctxt->inode->value = BAD_CAST xmlStrndup(value, len);
23343 else
23344 vctxt->inode->value = BAD_CAST xmlStrdup(value);
23345 vctxt->inode->flags |=
23346 XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
23347 break;
23348 default:
23349 break;
23350 }
23351 } else {
23352 /*
23353 * Concat the value.
23354 */
23355 if (vctxt->inode->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
Kasimier T. Buchcik9c215eb2005-06-21 08:38:49 +000023356 vctxt->inode->value = BAD_CAST xmlStrncat(
23357 (xmlChar *) vctxt->inode->value, value, len);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023358 } else {
23359 vctxt->inode->value =
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000023360 BAD_CAST xmlStrncatNew(vctxt->inode->value, value, len);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023361 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
23362 }
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023363 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023364
23365 return (0);
Daniel Veillard4255d502002-04-16 15:50:10 +000023366}
23367
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023368static int
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023369xmlSchemaValidateElem(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcik9b77aa02005-03-04 22:04:16 +000023370{
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023371 int ret = 0;
Daniel Veillard4255d502002-04-16 15:50:10 +000023372
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023373 if ((vctxt->skipDepth != -1) &&
23374 (vctxt->depth >= vctxt->skipDepth)) {
23375 VERROR_INT("xmlSchemaValidateElem",
23376 "in skip-state");
23377 goto internal_error;
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000023378 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023379 if (vctxt->xsiAssemble) {
23380 if (xmlSchemaAssembleByXSI(vctxt) == -1)
23381 goto internal_error;
23382 }
23383 if (vctxt->depth > 0) {
23384 /*
23385 * Validate this element against the content model
23386 * of the parent.
23387 */
23388 ret = xmlSchemaValidateChildElem(vctxt);
23389 if (ret != 0) {
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023390 if (ret < 0) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023391 VERROR_INT("xmlSchemaValidateElem",
23392 "calling xmlSchemaStreamValidateChildElement()");
23393 goto internal_error;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023394 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023395 goto exit;
23396 }
23397 if (vctxt->depth == vctxt->skipDepth)
23398 goto exit;
23399 if ((vctxt->inode->decl == NULL) &&
23400 (vctxt->inode->typeDef == NULL)) {
23401 VERROR_INT("xmlSchemaValidateElem",
23402 "the child element was valid but neither the "
23403 "declaration nor the type was set");
23404 goto internal_error;
23405 }
23406 } else {
23407 /*
23408 * Get the declaration of the validation root.
23409 */
23410 vctxt->inode->decl = xmlSchemaGetElem(vctxt->schema,
23411 vctxt->inode->localName,
23412 vctxt->inode->nsName);
23413 if (vctxt->inode->decl == NULL) {
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000023414 ret = XML_SCHEMAV_CVC_ELT_1;
23415 VERROR(ret, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023416 "No matching global declaration available "
23417 "for the validation root");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023418 goto exit;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023419 }
23420 }
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023421
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023422 if (vctxt->inode->decl == NULL)
23423 goto type_validation;
23424
23425 if (vctxt->inode->decl->type == XML_SCHEMA_TYPE_ANY) {
23426 int skip;
23427 /*
23428 * Wildcards.
23429 */
23430 ret = xmlSchemaValidateElemWildcard(vctxt, &skip);
23431 if (ret != 0) {
23432 if (ret < 0) {
23433 VERROR_INT("xmlSchemaValidateElem",
23434 "calling xmlSchemaValidateElemWildcard()");
23435 goto internal_error;
23436 }
23437 goto exit;
23438 }
23439 if (skip) {
23440 vctxt->skipDepth = vctxt->depth;
23441 goto exit;
23442 }
23443 /*
23444 * The declaration might be set by the wildcard validation,
23445 * when the processContents is "lax" or "strict".
23446 */
23447 if (vctxt->inode->decl->type != XML_SCHEMA_TYPE_ELEMENT) {
23448 /*
23449 * Clear the "decl" field to not confuse further processing.
23450 */
23451 vctxt->inode->decl = NULL;
23452 goto type_validation;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023453 }
Daniel Veillard4255d502002-04-16 15:50:10 +000023454 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023455 /*
23456 * Validate against the declaration.
23457 */
23458 ret = xmlSchemaValidateElemDecl(vctxt);
23459 if (ret != 0) {
23460 if (ret < 0) {
23461 VERROR_INT("xmlSchemaValidateElem",
23462 "calling xmlSchemaValidateElemDecl()");
23463 goto internal_error;
23464 }
23465 goto exit;
23466 }
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000023467 /*
23468 * Validate against the type definition.
23469 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023470type_validation:
23471
23472 if (vctxt->inode->typeDef == NULL) {
23473 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE;
23474 ret = XML_SCHEMAV_CVC_TYPE_1;
23475 VERROR(ret, NULL,
23476 "The type definition is absent");
23477 goto exit;
23478 }
23479 if (vctxt->inode->typeDef->flags & XML_SCHEMAS_TYPE_ABSTRACT) {
23480 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE;
23481 ret = XML_SCHEMAV_CVC_TYPE_2;
23482 VERROR(ret, NULL,
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000023483 "The type definition is abstract");
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023484 goto exit;
23485 }
23486 /*
Kasimier T. Buchcik9ca11bf2005-06-14 19:24:47 +000023487 * Evaluate IDCs. Do it here, since new IDC matchers are registered
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023488 * during validation against the declaration. This must be done
23489 * _before_ attribute validation.
23490 */
23491 ret = xmlSchemaXPathEvaluate(vctxt, XML_ELEMENT_NODE);
23492 if (ret == -1) {
23493 VERROR_INT("xmlSchemaValidateElem",
23494 "calling xmlSchemaXPathEvaluate()");
23495 goto internal_error;
23496 }
23497 /*
23498 * Validate attributes.
23499 */
23500 if (IS_COMPLEX_TYPE(vctxt->inode->typeDef)) {
23501 if ((vctxt->nbAttrInfos != 0) ||
23502 (vctxt->inode->typeDef->attributeUses != NULL)) {
23503
23504 ret = xmlSchemaVAttributesComplex(vctxt);
23505 }
23506 } else if (vctxt->nbAttrInfos != 0) {
23507
23508 ret = xmlSchemaVAttributesSimple(vctxt);
23509 }
23510 /*
23511 * Clear registered attributes.
23512 */
23513 if (vctxt->nbAttrInfos != 0)
23514 xmlSchemaClearAttrInfos(vctxt);
23515 if (ret == -1) {
23516 VERROR_INT("xmlSchemaValidateElem",
23517 "calling attributes validation");
23518 goto internal_error;
23519 }
23520 /*
23521 * Don't return an error if attributes are invalid on purpose.
23522 */
23523 ret = 0;
23524
23525exit:
23526 if (ret != 0)
23527 vctxt->skipDepth = vctxt->depth;
23528 return (ret);
23529internal_error:
23530 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000023531}
23532
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023533#ifdef XML_SCHEMA_READER_ENABLED
23534static int
23535xmlSchemaVReaderWalk(xmlSchemaValidCtxtPtr vctxt)
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000023536{
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023537 const int WHTSP = 13, SIGN_WHTSP = 14, END_ELEM = 15;
23538 int depth, nodeType, ret = 0, consumed;
23539 xmlSchemaNodeInfoPtr ielem;
Kasimier T. Buchcik5eba91f2004-09-08 09:17:27 +000023540
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023541 vctxt->depth = -1;
23542 ret = xmlTextReaderRead(vctxt->reader);
23543 /*
23544 * Move to the document element.
23545 */
23546 while (ret == 1) {
23547 nodeType = xmlTextReaderNodeType(vctxt->reader);
23548 if (nodeType == XML_ELEMENT_NODE)
23549 goto root_found;
23550 ret = xmlTextReaderRead(vctxt->reader);
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023551 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023552 goto exit;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000023553
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023554root_found:
23555
23556 do {
23557 depth = xmlTextReaderDepth(vctxt->reader);
23558 nodeType = xmlTextReaderNodeType(vctxt->reader);
23559
23560 if (nodeType == XML_ELEMENT_NODE) {
23561
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000023562 vctxt->depth++;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023563 if (xmlSchemaValidatorPushElem(vctxt) == -1) {
23564 VERROR_INT("xmlSchemaVReaderWalk",
23565 "calling xmlSchemaValidatorPushElem()");
23566 goto internal_error;
23567 }
23568 ielem = vctxt->inode;
23569 ielem->localName = xmlTextReaderLocalName(vctxt->reader);
23570 ielem->nsName = xmlTextReaderNamespaceUri(vctxt->reader);
23571 ielem->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES;
23572 /*
23573 * Is the element empty?
23574 */
23575 ret = xmlTextReaderIsEmptyElement(vctxt->reader);
23576 if (ret == -1) {
23577 VERROR_INT("xmlSchemaVReaderWalk",
23578 "calling xmlTextReaderIsEmptyElement()");
23579 goto internal_error;
23580 }
23581 if (ret) {
23582 ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
23583 }
23584 /*
23585 * Register attributes.
23586 */
23587 vctxt->nbAttrInfos = 0;
23588 ret = xmlTextReaderMoveToFirstAttribute(vctxt->reader);
23589 if (ret == -1) {
23590 VERROR_INT("xmlSchemaVReaderWalk",
23591 "calling xmlTextReaderMoveToFirstAttribute()");
23592 goto internal_error;
23593 }
23594 if (ret == 1) {
23595 do {
23596 /*
23597 * VAL TODO: How do we know that the reader works on a
23598 * node tree, to be able to pass a node here?
23599 */
23600 if (xmlSchemaValidatorPushAttribute(vctxt, NULL,
23601 (const xmlChar *) xmlTextReaderLocalName(vctxt->reader),
23602 xmlTextReaderNamespaceUri(vctxt->reader), 1,
23603 xmlTextReaderValue(vctxt->reader), 1) == -1) {
23604
23605 VERROR_INT("xmlSchemaVReaderWalk",
23606 "calling xmlSchemaValidatorPushAttribute()");
23607 goto internal_error;
23608 }
23609 ret = xmlTextReaderMoveToNextAttribute(vctxt->reader);
23610 if (ret == -1) {
23611 VERROR_INT("xmlSchemaVReaderWalk",
23612 "calling xmlTextReaderMoveToFirstAttribute()");
23613 goto internal_error;
23614 }
23615 } while (ret == 1);
23616 /*
23617 * Back to element position.
23618 */
23619 ret = xmlTextReaderMoveToElement(vctxt->reader);
23620 if (ret == -1) {
23621 VERROR_INT("xmlSchemaVReaderWalk",
23622 "calling xmlTextReaderMoveToElement()");
23623 goto internal_error;
23624 }
23625 }
23626 /*
23627 * Validate the element.
23628 */
23629 ret= xmlSchemaValidateElem(vctxt);
23630 if (ret != 0) {
23631 if (ret == -1) {
23632 VERROR_INT("xmlSchemaVReaderWalk",
23633 "calling xmlSchemaValidateElem()");
23634 goto internal_error;
23635 }
23636 goto exit;
23637 }
23638 if (vctxt->depth == vctxt->skipDepth) {
23639 int curDepth;
23640 /*
23641 * Skip all content.
23642 */
23643 if ((ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY) == 0) {
23644 ret = xmlTextReaderRead(vctxt->reader);
23645 curDepth = xmlTextReaderDepth(vctxt->reader);
23646 while ((ret == 1) && (curDepth != depth)) {
23647 ret = xmlTextReaderRead(vctxt->reader);
23648 curDepth = xmlTextReaderDepth(vctxt->reader);
23649 }
23650 if (ret < 0) {
23651 /*
23652 * VAL TODO: A reader error occured; what to do here?
23653 */
23654 ret = 1;
23655 goto exit;
23656 }
23657 }
23658 goto leave_elem;
23659 }
23660 /*
23661 * READER VAL TODO: Is an END_ELEM really never called
23662 * if the elem is empty?
23663 */
23664 if (ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
23665 goto leave_elem;
23666 } else if (nodeType == END_ELEM) {
23667 /*
23668 * Process END of element.
23669 */
23670leave_elem:
23671 ret = xmlSchemaValidatorPopElem(vctxt);
23672 if (ret != 0) {
23673 if (ret < 0) {
23674 VERROR_INT("xmlSchemaVReaderWalk",
23675 "calling xmlSchemaValidatorPopElem()");
23676 goto internal_error;
23677 }
23678 goto exit;
23679 }
23680 if (vctxt->depth >= 0)
23681 ielem = vctxt->inode;
23682 else
23683 ielem = NULL;
23684 } else if ((nodeType == XML_TEXT_NODE) ||
23685 (nodeType == XML_CDATA_SECTION_NODE) ||
23686 (nodeType == WHTSP) ||
23687 (nodeType == SIGN_WHTSP)) {
23688 /*
23689 * Process character content.
23690 */
23691 xmlChar *value;
23692
23693 if ((nodeType == WHTSP) || (nodeType == SIGN_WHTSP))
23694 nodeType = XML_TEXT_NODE;
23695
23696 value = xmlTextReaderValue(vctxt->reader);
23697 ret = xmlSchemaVPushText(vctxt, nodeType, BAD_CAST value,
23698 -1, XML_SCHEMA_PUSH_TEXT_CREATED, &consumed);
23699 if (! consumed)
23700 xmlFree(value);
23701 if (ret == -1) {
23702 VERROR_INT("xmlSchemaVReaderWalk",
23703 "calling xmlSchemaVPushText()");
23704 goto internal_error;
23705 }
23706 } else if ((nodeType == XML_ENTITY_NODE) ||
23707 (nodeType == XML_ENTITY_REF_NODE)) {
23708 /*
23709 * VAL TODO: What to do with entities?
23710 */
23711 TODO
23712 }
23713 /*
23714 * Read next node.
23715 */
23716 ret = xmlTextReaderRead(vctxt->reader);
23717 } while (ret == 1);
23718
23719exit:
23720 return (ret);
23721internal_error:
23722 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000023723}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023724#endif
Daniel Veillard4255d502002-04-16 15:50:10 +000023725
23726/************************************************************************
23727 * *
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023728 * SAX validation handlers *
Daniel Veillard4255d502002-04-16 15:50:10 +000023729 * *
23730 ************************************************************************/
23731
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023732/*
23733* Process text content.
23734*/
23735static void
23736xmlSchemaSAXHandleText(void *ctx,
23737 const xmlChar * ch,
23738 int len)
23739{
23740 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
23741
23742 if (vctxt->depth < 0)
23743 return;
23744 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
23745 return;
23746 if (vctxt->inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
23747 vctxt->inode->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
23748 if (xmlSchemaVPushText(vctxt, XML_TEXT_NODE, ch, len,
23749 XML_SCHEMA_PUSH_TEXT_VOLATILE, NULL) == -1) {
23750 VERROR_INT("xmlSchemaSAXHandleCDataSection",
23751 "calling xmlSchemaVPushText()");
23752 vctxt->err = -1;
23753 xmlStopParser(vctxt->parserCtxt);
23754 }
23755}
23756
23757/*
23758* Process CDATA content.
23759*/
23760static void
23761xmlSchemaSAXHandleCDataSection(void *ctx,
23762 const xmlChar * ch,
23763 int len)
23764{
23765 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
23766
23767 if (vctxt->depth < 0)
23768 return;
23769 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
23770 return;
23771 if (vctxt->inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
23772 vctxt->inode->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
23773 if (xmlSchemaVPushText(vctxt, XML_CDATA_SECTION_NODE, ch, len,
23774 XML_SCHEMA_PUSH_TEXT_VOLATILE, NULL) == -1) {
23775 VERROR_INT("xmlSchemaSAXHandleCDataSection",
23776 "calling xmlSchemaVPushText()");
23777 vctxt->err = -1;
23778 xmlStopParser(vctxt->parserCtxt);
23779 }
23780}
23781
23782static void
23783xmlSchemaSAXHandleReference(void *ctx ATTRIBUTE_UNUSED,
23784 const xmlChar * name ATTRIBUTE_UNUSED)
23785{
23786 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
23787
23788 if (vctxt->depth < 0)
23789 return;
23790 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
23791 return;
23792 /* SAX VAL TODO: What to do here? */
23793 TODO
23794}
23795
23796static void
23797xmlSchemaSAXHandleStartElementNs(void *ctx,
23798 const xmlChar * localname,
23799 const xmlChar * prefix ATTRIBUTE_UNUSED,
23800 const xmlChar * URI,
23801 int nb_namespaces,
23802 const xmlChar ** namespaces,
23803 int nb_attributes,
23804 int nb_defaulted ATTRIBUTE_UNUSED,
23805 const xmlChar ** attributes)
23806{
23807 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
23808 int ret;
23809 xmlSchemaNodeInfoPtr ielem;
23810 int i, j;
23811
23812 /*
23813 * SAX VAL TODO: What to do with nb_defaulted?
23814 */
23815 /*
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000023816 * Skip elements if inside a "skip" wildcard or invalid.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023817 */
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000023818 vctxt->depth++;
23819 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023820 return;
23821 /*
23822 * Push the element.
23823 */
23824 if (xmlSchemaValidatorPushElem(vctxt) == -1) {
23825 VERROR_INT("xmlSchemaSAXHandleStartElementNs",
23826 "calling xmlSchemaValidatorPushElem()");
23827 goto internal_error;
23828 }
23829 ielem = vctxt->inode;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000023830 /*
23831 * TODO: Is this OK?
23832 */
23833 ielem->nodeLine = xmlSAX2GetLineNumber(vctxt->parserCtxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023834 ielem->localName = localname;
23835 ielem->nsName = URI;
23836 ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
23837 /*
23838 * Register namespaces on the elem info.
23839 */
23840 if (nb_namespaces != 0) {
23841 /*
23842 * Although the parser builds its own namespace list,
23843 * we have no access to it, so we'll use an own one.
23844 */
23845 for (i = 0, j = 0; i < nb_namespaces; i++, j += 2) {
23846 /*
23847 * Store prefix and namespace name.
23848 */
23849 if (ielem->nsBindings == NULL) {
23850 ielem->nsBindings =
23851 (const xmlChar **) xmlMalloc(10 *
23852 sizeof(const xmlChar *));
23853 if (ielem->nsBindings == NULL) {
23854 xmlSchemaVErrMemory(vctxt,
23855 "allocating namespace bindings for SAX validation",
23856 NULL);
23857 goto internal_error;
23858 }
23859 ielem->nbNsBindings = 0;
23860 ielem->sizeNsBindings = 5;
23861 } else if (ielem->sizeNsBindings <= ielem->nbNsBindings) {
23862 ielem->sizeNsBindings *= 2;
23863 ielem->nsBindings =
23864 (const xmlChar **) xmlRealloc(
23865 (void *) ielem->nsBindings,
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000023866 ielem->sizeNsBindings * 2 * sizeof(const xmlChar *));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023867 if (ielem->nsBindings == NULL) {
23868 xmlSchemaVErrMemory(vctxt,
23869 "re-allocating namespace bindings for SAX validation",
23870 NULL);
23871 goto internal_error;
23872 }
23873 }
23874
23875 ielem->nsBindings[ielem->nbNsBindings * 2] = namespaces[j];
23876 if (namespaces[j+1][0] == 0) {
23877 /*
23878 * Handle xmlns="".
23879 */
23880 ielem->nsBindings[ielem->nbNsBindings * 2 + 1] = NULL;
23881 } else
23882 ielem->nsBindings[ielem->nbNsBindings * 2 + 1] =
23883 namespaces[j+1];
23884 ielem->nbNsBindings++;
23885 }
23886 }
23887 /*
23888 * Register attributes.
23889 * SAX VAL TODO: We are not adding namespace declaration
23890 * attributes yet.
23891 */
23892 if (nb_attributes != 0) {
23893 xmlChar *value;
23894
23895 for (j = 0, i = 0; i < nb_attributes; i++, j += 5) {
23896 /*
23897 * Duplicate the value.
23898 */
23899 value = xmlStrndup(attributes[j+3],
23900 attributes[j+4] - attributes[j+3]);
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000023901 /*
23902 * TODO: Set the node line.
23903 */
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023904 ret = xmlSchemaValidatorPushAttribute(vctxt,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000023905 NULL, ielem->nodeLine, attributes[j], attributes[j+2], 0,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023906 value, 1);
23907 if (ret == -1) {
23908 VERROR_INT("xmlSchemaSAXHandleStartElementNs",
23909 "calling xmlSchemaValidatorPushAttribute()");
23910 goto internal_error;
23911 }
23912 }
23913 }
23914 /*
23915 * Validate the element.
23916 */
23917 ret = xmlSchemaValidateElem(vctxt);
23918 if (ret != 0) {
23919 if (ret == -1) {
23920 VERROR_INT("xmlSchemaSAXHandleStartElementNs",
23921 "calling xmlSchemaValidateElem()");
23922 goto internal_error;
23923 }
23924 goto exit;
23925 }
23926
23927exit:
23928 return;
23929internal_error:
23930 vctxt->err = -1;
23931 xmlStopParser(vctxt->parserCtxt);
23932 return;
23933}
23934
23935static void
23936xmlSchemaSAXHandleEndElementNs(void *ctx,
23937 const xmlChar * localname ATTRIBUTE_UNUSED,
23938 const xmlChar * prefix ATTRIBUTE_UNUSED,
23939 const xmlChar * URI ATTRIBUTE_UNUSED)
23940{
23941 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
23942 int res;
23943
23944 /*
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000023945 * Skip elements if inside a "skip" wildcard or if invalid.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023946 */
23947 if (vctxt->skipDepth != -1) {
23948 if (vctxt->depth > vctxt->skipDepth) {
23949 vctxt->depth--;
23950 return;
23951 } else
23952 vctxt->skipDepth = -1;
23953 }
23954 /*
23955 * SAX VAL TODO: Just a temporary check.
23956 */
23957 if ((!xmlStrEqual(vctxt->inode->localName, localname)) ||
23958 (!xmlStrEqual(vctxt->inode->nsName, URI))) {
23959 VERROR_INT("xmlSchemaSAXHandleEndElementNs",
23960 "elem pop mismatch");
23961 }
23962 res = xmlSchemaValidatorPopElem(vctxt);
23963 if (res != 0) {
23964 if (res < 0) {
23965 VERROR_INT("xmlSchemaSAXHandleEndElementNs",
23966 "calling xmlSchemaValidatorPopElem()");
23967 goto internal_error;
23968 }
23969 goto exit;
23970 }
23971exit:
23972 return;
23973internal_error:
23974 vctxt->err = -1;
23975 xmlStopParser(vctxt->parserCtxt);
23976 return;
23977}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000023978
Daniel Veillard4255d502002-04-16 15:50:10 +000023979/************************************************************************
23980 * *
23981 * Validation interfaces *
23982 * *
23983 ************************************************************************/
23984
23985/**
23986 * xmlSchemaNewValidCtxt:
23987 * @schema: a precompiled XML Schemas
23988 *
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000023989 * Create an XML Schemas validation context based on the given schema.
Daniel Veillard4255d502002-04-16 15:50:10 +000023990 *
23991 * Returns the validation context or NULL in case of error
23992 */
23993xmlSchemaValidCtxtPtr
Daniel Veillardd0c9c322003-10-10 00:49:42 +000023994xmlSchemaNewValidCtxt(xmlSchemaPtr schema)
23995{
Daniel Veillard4255d502002-04-16 15:50:10 +000023996 xmlSchemaValidCtxtPtr ret;
23997
23998 ret = (xmlSchemaValidCtxtPtr) xmlMalloc(sizeof(xmlSchemaValidCtxt));
23999 if (ret == NULL) {
Daniel Veillardd0c9c322003-10-10 00:49:42 +000024000 xmlSchemaVErrMemory(NULL, "allocating validation context", NULL);
Daniel Veillard4255d502002-04-16 15:50:10 +000024001 return (NULL);
24002 }
24003 memset(ret, 0, sizeof(xmlSchemaValidCtxt));
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024004 ret->type = XML_SCHEMA_CTXT_VALIDATOR;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000024005 ret->dict = xmlDictCreate();
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000024006 ret->nodeQNames = xmlSchemaItemListCreate();
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024007 ret->schema = schema;
Daniel Veillard4255d502002-04-16 15:50:10 +000024008 return (ret);
24009}
24010
24011/**
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000024012 * xmlSchemaClearValidCtxt:
24013 * @ctxt: the schema validation context
24014 *
24015 * Free the resources associated to the schema validation context;
24016 * leaves some fields alive intended for reuse of the context.
24017 */
24018static void
24019xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt)
24020{
24021 if (vctxt == NULL)
24022 return;
24023
Kasimier T. Buchcikaba15f72005-04-01 15:17:27 +000024024 vctxt->flags = 0;
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000024025 vctxt->validationRoot = NULL;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024026 vctxt->doc = NULL;
Daniel Veillard39e5c892005-07-03 22:48:50 +000024027#ifdef LIBXML_READER_ENABLED
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024028 vctxt->reader = NULL;
Daniel Veillard39e5c892005-07-03 22:48:50 +000024029#endif
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000024030 if (vctxt->value != NULL) {
24031 xmlSchemaFreeValue(vctxt->value);
24032 vctxt->value = NULL;
24033 }
24034 /*
24035 * Augmented IDC information.
24036 */
24037 if (vctxt->aidcs != NULL) {
24038 xmlSchemaIDCAugPtr cur = vctxt->aidcs, next;
24039 do {
24040 next = cur->next;
24041 xmlFree(cur);
24042 cur = next;
24043 } while (cur != NULL);
24044 vctxt->aidcs = NULL;
24045 }
24046 if (vctxt->idcNodes != NULL) {
24047 int i;
24048 xmlSchemaPSVIIDCNodePtr item;
24049
24050 for (i = 0; i < vctxt->nbIdcNodes; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024051 item = vctxt->idcNodes[i];
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000024052 xmlFree(item->keys);
24053 xmlFree(item);
24054 }
24055 xmlFree(vctxt->idcNodes);
24056 vctxt->idcNodes = NULL;
24057 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024058 /*
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000024059 * Note that we won't delete the XPath state pool here.
24060 */
24061 if (vctxt->xpathStates != NULL) {
24062 xmlSchemaFreeIDCStateObjList(vctxt->xpathStates);
24063 vctxt->xpathStates = NULL;
24064 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024065 /*
24066 * Attribute info.
24067 */
24068 if (vctxt->nbAttrInfos != 0) {
24069 xmlSchemaClearAttrInfos(vctxt);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000024070 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024071 /*
24072 * Element info.
24073 */
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000024074 if (vctxt->elemInfos != NULL) {
24075 int i;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024076 xmlSchemaNodeInfoPtr ei;
24077
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000024078 for (i = 0; i < vctxt->sizeElemInfos; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024079 ei = vctxt->elemInfos[i];
24080 if (ei == NULL)
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000024081 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024082 xmlSchemaClearElemInfo(ei);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000024083 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000024084 }
24085 xmlSchemaItemListClear(vctxt->nodeQNames);
24086 /* Recreate the dict. */
24087 xmlDictFree(vctxt->dict);
24088 vctxt->dict = xmlDictCreate();
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000024089}
24090
24091/**
Daniel Veillard4255d502002-04-16 15:50:10 +000024092 * xmlSchemaFreeValidCtxt:
24093 * @ctxt: the schema validation context
24094 *
24095 * Free the resources associated to the schema validation context
24096 */
24097void
Daniel Veillardd0c9c322003-10-10 00:49:42 +000024098xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt)
24099{
Daniel Veillard4255d502002-04-16 15:50:10 +000024100 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000024101 return;
Daniel Veillard88c58912002-04-23 07:12:20 +000024102 if (ctxt->value != NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000024103 xmlSchemaFreeValue(ctxt->value);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000024104 if (ctxt->pctxt != NULL)
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000024105 xmlSchemaFreeParserCtxt(ctxt->pctxt);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000024106 if (ctxt->idcNodes != NULL) {
24107 int i;
24108 xmlSchemaPSVIIDCNodePtr item;
24109
24110 for (i = 0; i < ctxt->nbIdcNodes; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024111 item = ctxt->idcNodes[i];
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000024112 xmlFree(item->keys);
24113 xmlFree(item);
24114 }
24115 xmlFree(ctxt->idcNodes);
24116 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000024117 if (ctxt->idcKeys != NULL) {
24118 int i;
24119 for (i = 0; i < ctxt->nbIdcKeys; i++)
24120 xmlSchemaIDCFreeKey(ctxt->idcKeys[i]);
24121 xmlFree(ctxt->idcKeys);
24122 }
24123
24124 if (ctxt->xpathStates != NULL)
24125 xmlSchemaFreeIDCStateObjList(ctxt->xpathStates);
24126 if (ctxt->xpathStatePool != NULL)
24127 xmlSchemaFreeIDCStateObjList(ctxt->xpathStatePool);
24128
24129 /*
24130 * Augmented IDC information.
24131 */
24132 if (ctxt->aidcs != NULL) {
24133 xmlSchemaIDCAugPtr cur = ctxt->aidcs, next;
24134 do {
24135 next = cur->next;
24136 xmlFree(cur);
24137 cur = next;
24138 } while (cur != NULL);
24139 }
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024140 if (ctxt->attrInfos != NULL) {
24141 int i;
24142 xmlSchemaAttrInfoPtr attr;
24143
24144 /* Just a paranoid call to the cleanup. */
24145 if (ctxt->nbAttrInfos != 0)
24146 xmlSchemaClearAttrInfos(ctxt);
24147 for (i = 0; i < ctxt->sizeAttrInfos; i++) {
24148 attr = ctxt->attrInfos[i];
24149 xmlFree(attr);
24150 }
24151 xmlFree(ctxt->attrInfos);
Kasimier T. Buchcikbd2a7d12005-02-16 12:27:25 +000024152 }
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000024153 if (ctxt->elemInfos != NULL) {
24154 int i;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024155 xmlSchemaNodeInfoPtr ei;
24156
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000024157 for (i = 0; i < ctxt->sizeElemInfos; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024158 ei = ctxt->elemInfos[i];
24159 if (ei == NULL)
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000024160 break;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024161 xmlSchemaClearElemInfo(ei);
24162 xmlFree(ei);
Kasimier T. Buchcike8a550b2005-01-27 12:49:31 +000024163 }
24164 xmlFree(ctxt->elemInfos);
24165 }
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000024166 if (ctxt->nodeQNames != NULL)
Kasimier T. Buchcik630215b2005-08-22 10:15:39 +000024167 xmlSchemaItemListFree(ctxt->nodeQNames);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024168 if (ctxt->dict != NULL)
24169 xmlDictFree(ctxt->dict);
Daniel Veillard4255d502002-04-16 15:50:10 +000024170 xmlFree(ctxt);
24171}
24172
24173/**
Daniel Veillardf10ae122005-07-10 19:03:16 +000024174 * xmlSchemaIsValid:
24175 * @ctxt: the schema validation context
24176 *
24177 * Check if any error was detected during validation.
24178 *
24179 * Returns 1 if valid so far, 0 if errors were detected, and -1 in case
24180 * of internal error.
24181 */
24182int
24183xmlSchemaIsValid(xmlSchemaValidCtxtPtr ctxt)
24184{
24185 if (ctxt == NULL)
24186 return(-1);
24187 return(ctxt->err == 0);
24188}
24189
24190/**
Daniel Veillard4255d502002-04-16 15:50:10 +000024191 * xmlSchemaSetValidErrors:
24192 * @ctxt: a schema validation context
24193 * @err: the error function
24194 * @warn: the warning function
Daniel Veillarda9b66d02002-12-11 14:23:49 +000024195 * @ctx: the functions context
Daniel Veillard4255d502002-04-16 15:50:10 +000024196 *
William M. Brack2f2a6632004-08-20 23:09:47 +000024197 * Set the error and warning callback informations
Daniel Veillard4255d502002-04-16 15:50:10 +000024198 */
24199void
24200xmlSchemaSetValidErrors(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000024201 xmlSchemaValidityErrorFunc err,
24202 xmlSchemaValidityWarningFunc warn, void *ctx)
24203{
Daniel Veillard4255d502002-04-16 15:50:10 +000024204 if (ctxt == NULL)
Daniel Veillardd0c9c322003-10-10 00:49:42 +000024205 return;
Daniel Veillard4255d502002-04-16 15:50:10 +000024206 ctxt->error = err;
24207 ctxt->warning = warn;
24208 ctxt->userData = ctx;
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000024209 if (ctxt->pctxt != NULL)
24210 xmlSchemaSetParserErrors(ctxt->pctxt, err, warn, ctx);
Daniel Veillard4255d502002-04-16 15:50:10 +000024211}
24212
24213/**
Daniel Veillardda0aa4c2005-07-13 23:07:49 +000024214 * xmlSchemaSetValidStructuredErrors:
24215 * @ctxt: a schema validation context
24216 * @serror: the structured error function
24217 * @ctx: the functions context
24218 *
24219 * Set the structured error callback
24220 */
24221void
24222xmlSchemaSetValidStructuredErrors(xmlSchemaValidCtxtPtr ctxt,
24223 xmlStructuredErrorFunc serror, void *ctx)
24224{
24225 if (ctxt == NULL)
24226 return;
24227 ctxt->serror = serror;
24228 ctxt->error = NULL;
24229 ctxt->warning = NULL;
24230 ctxt->userData = ctx;
24231}
24232
24233/**
Daniel Veillard259f0df2004-08-18 09:13:18 +000024234 * xmlSchemaGetValidErrors:
24235 * @ctxt: a XML-Schema validation context
24236 * @err: the error function result
24237 * @warn: the warning function result
24238 * @ctx: the functions context result
24239 *
24240 * Get the error and warning callback informations
24241 *
24242 * Returns -1 in case of error and 0 otherwise
24243 */
24244int
24245xmlSchemaGetValidErrors(xmlSchemaValidCtxtPtr ctxt,
24246 xmlSchemaValidityErrorFunc * err,
24247 xmlSchemaValidityWarningFunc * warn, void **ctx)
24248{
24249 if (ctxt == NULL)
24250 return (-1);
24251 if (err != NULL)
24252 *err = ctxt->error;
24253 if (warn != NULL)
24254 *warn = ctxt->warning;
24255 if (ctx != NULL)
24256 *ctx = ctxt->userData;
24257 return (0);
24258}
24259
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000024260
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000024261/**
Daniel Veillard6927b102004-10-27 17:29:04 +000024262 * xmlSchemaSetValidOptions:
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000024263 * @ctxt: a schema validation context
24264 * @options: a combination of xmlSchemaValidOption
24265 *
24266 * Sets the options to be used during the validation.
24267 *
24268 * Returns 0 in case of success, -1 in case of an
24269 * API error.
24270 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000024271int
24272xmlSchemaSetValidOptions(xmlSchemaValidCtxtPtr ctxt,
24273 int options)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024274
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000024275{
24276 int i;
24277
24278 if (ctxt == NULL)
24279 return (-1);
24280 /*
24281 * WARNING: Change the start value if adding to the
24282 * xmlSchemaValidOption.
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000024283 * TODO: Is there an other, more easy to maintain,
24284 * way?
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000024285 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000024286 for (i = 1; i < (int) sizeof(int) * 8; i++) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024287 if (options & 1<<i)
24288 return (-1);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000024289 }
24290 ctxt->options = options;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024291 return (0);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000024292}
24293
24294/**
Daniel Veillard6927b102004-10-27 17:29:04 +000024295 * xmlSchemaValidCtxtGetOptions:
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024296 * @ctxt: a schema validation context
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000024297 *
William M. Brack21e4ef22005-01-02 09:53:13 +000024298 * Get the validation context options.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024299 *
William M. Brack21e4ef22005-01-02 09:53:13 +000024300 * Returns the option combination or -1 on error.
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000024301 */
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000024302int
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000024303xmlSchemaValidCtxtGetOptions(xmlSchemaValidCtxtPtr ctxt)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024304
24305{
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000024306 if (ctxt == NULL)
24307 return (-1);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024308 else
24309 return (ctxt->options);
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000024310}
Kasimier T. Buchcik87876402004-09-29 13:29:03 +000024311
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024312static int
24313xmlSchemaVDocWalk(xmlSchemaValidCtxtPtr vctxt)
24314{
24315 xmlAttrPtr attr;
24316 int ret = 0;
24317 xmlSchemaNodeInfoPtr ielem = NULL;
24318 xmlNodePtr node, valRoot;
24319 const xmlChar *nsName;
24320
24321 /* DOC VAL TODO: Move this to the start function. */
24322 valRoot = xmlDocGetRootElement(vctxt->doc);
24323 if (valRoot == NULL) {
24324 /* VAL TODO: Error code? */
24325 VERROR(1, NULL, "The document has no document element");
24326 return (1);
24327 }
24328 vctxt->depth = -1;
24329 vctxt->validationRoot = valRoot;
24330 node = valRoot;
24331 while (node != NULL) {
24332 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
24333 goto next_sibling;
24334 if (node->type == XML_ELEMENT_NODE) {
24335
24336 /*
24337 * Init the node-info.
24338 */
Kasimier T. Buchcik84a56e32005-06-16 12:44:35 +000024339 vctxt->depth++;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024340 if (xmlSchemaValidatorPushElem(vctxt) == -1)
24341 goto internal_error;
24342 ielem = vctxt->inode;
24343 ielem->node = node;
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000024344 ielem->nodeLine = node->line;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024345 ielem->localName = node->name;
24346 if (node->ns != NULL)
24347 ielem->nsName = node->ns->href;
24348 ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
24349 /*
24350 * Register attributes.
24351 * DOC VAL TODO: We do not register namespace declaration
24352 * attributes yet.
24353 */
24354 vctxt->nbAttrInfos = 0;
24355 if (node->properties != NULL) {
24356 attr = node->properties;
24357 do {
24358 if (attr->ns != NULL)
24359 nsName = attr->ns->href;
24360 else
24361 nsName = NULL;
24362 ret = xmlSchemaValidatorPushAttribute(vctxt,
24363 (xmlNodePtr) attr,
Kasimier T. Buchcik764b3d62005-08-12 12:25:23 +000024364 /*
24365 * Note that we give it the line number of the
24366 * parent element.
24367 */
24368 ielem->nodeLine,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024369 attr->name, nsName, 0,
24370 xmlNodeListGetString(attr->doc, attr->children, 1), 1);
24371 if (ret == -1) {
24372 VERROR_INT("xmlSchemaDocWalk",
24373 "calling xmlSchemaValidatorPushAttribute()");
24374 goto internal_error;
24375 }
24376 attr = attr->next;
24377 } while (attr);
24378 }
24379 /*
24380 * Validate the element.
24381 */
24382 ret = xmlSchemaValidateElem(vctxt);
24383 if (ret != 0) {
24384 if (ret == -1) {
24385 VERROR_INT("xmlSchemaDocWalk",
24386 "calling xmlSchemaValidateElem()");
24387 goto internal_error;
24388 }
24389 /*
24390 * Don't stop validation; just skip the content
24391 * of this element.
24392 */
24393 goto leave_node;
24394 }
24395 if ((vctxt->skipDepth != -1) &&
24396 (vctxt->depth >= vctxt->skipDepth))
24397 goto leave_node;
24398 } else if ((node->type == XML_TEXT_NODE) ||
24399 (node->type == XML_CDATA_SECTION_NODE)) {
24400 /*
24401 * Process character content.
24402 */
24403 if (ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
24404 ielem->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
24405 ret = xmlSchemaVPushText(vctxt, node->type, node->content,
24406 -1, XML_SCHEMA_PUSH_TEXT_PERSIST, NULL);
24407 if (ret < 0) {
24408 VERROR_INT("xmlSchemaVDocWalk",
24409 "calling xmlSchemaVPushText()");
24410 goto internal_error;
24411 }
24412 /*
24413 * DOC VAL TODO: Should we skip further validation of the
24414 * element content here?
24415 */
24416 } else if ((node->type == XML_ENTITY_NODE) ||
24417 (node->type == XML_ENTITY_REF_NODE)) {
24418 /*
24419 * DOC VAL TODO: What to do with entities?
24420 */
24421 TODO
24422 } else {
24423 goto leave_node;
24424 /*
24425 * DOC VAL TODO: XInclude nodes, etc.
24426 */
24427 }
24428 /*
24429 * Walk the doc.
24430 */
24431 if (node->children != NULL) {
24432 node = node->children;
24433 continue;
24434 }
24435leave_node:
24436 if (node->type == XML_ELEMENT_NODE) {
24437 /*
24438 * Leaving the scope of an element.
24439 */
24440 if (node != vctxt->inode->node) {
24441 VERROR_INT("xmlSchemaVDocWalk",
24442 "element position mismatch");
24443 goto internal_error;
24444 }
24445 ret = xmlSchemaValidatorPopElem(vctxt);
24446 if (ret != 0) {
24447 if (ret < 0) {
24448 VERROR_INT("xmlSchemaVDocWalk",
24449 "calling xmlSchemaValidatorPopElem()");
24450 goto internal_error;
24451 }
24452 }
24453 if (node == valRoot)
24454 goto exit;
24455 }
24456next_sibling:
24457 if (node->next != NULL)
24458 node = node->next;
24459 else {
24460 node = node->parent;
24461 goto leave_node;
24462 }
24463 }
24464
24465exit:
24466 return (ret);
24467internal_error:
24468 return (-1);
24469}
24470
24471static int
Daniel Veillardf10ae122005-07-10 19:03:16 +000024472xmlSchemaPreRun(xmlSchemaValidCtxtPtr vctxt) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024473 /*
24474 * Some initialization.
24475 */
24476 vctxt->err = 0;
24477 vctxt->nberrors = 0;
24478 vctxt->depth = -1;
24479 vctxt->skipDepth = -1;
24480 /*
24481 * Create a schema + parser if necessary.
24482 */
24483 if (vctxt->schema == NULL) {
24484
24485 if ((vctxt->pctxt == NULL) &&
24486 (xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1))
24487 return (-1);
24488
24489 vctxt->schema = xmlSchemaNewSchema(vctxt->pctxt);
24490 if (vctxt->schema == NULL) {
24491 VERROR_INT("xmlSchemaVStartValidation",
24492 "creating a schema");
24493 return (-1);
24494 }
24495 vctxt->xsiAssemble = 1;
24496 } else
24497 vctxt->xsiAssemble = 0;
24498 /*
24499 * Augment the IDC definitions.
24500 */
24501 if (vctxt->schema->idcDef != NULL) {
24502 xmlHashScan(vctxt->schema->idcDef,
24503 (xmlHashScanner) xmlSchemaAugmentIDC, vctxt);
24504 }
Daniel Veillardf10ae122005-07-10 19:03:16 +000024505 return(0);
24506}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024507
Daniel Veillardf10ae122005-07-10 19:03:16 +000024508static void
24509xmlSchemaPostRun(xmlSchemaValidCtxtPtr vctxt) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024510 if (vctxt->xsiAssemble) {
24511 if (vctxt->schema != NULL) {
24512 xmlSchemaFree(vctxt->schema);
24513 vctxt->schema = NULL;
24514 }
24515 }
24516 xmlSchemaClearValidCtxt(vctxt);
Daniel Veillardf10ae122005-07-10 19:03:16 +000024517}
24518
24519static int
24520xmlSchemaVStart(xmlSchemaValidCtxtPtr vctxt)
24521{
24522 int ret = 0;
24523
24524 if (xmlSchemaPreRun(vctxt) < 0)
24525 return(-1);
24526
24527 if (vctxt->doc != NULL) {
24528 /*
24529 * Tree validation.
24530 */
24531 ret = xmlSchemaVDocWalk(vctxt);
24532#ifdef LIBXML_READER_ENABLED
24533 } else if (vctxt->reader != NULL) {
24534 /*
24535 * XML Reader validation.
24536 */
24537#ifdef XML_SCHEMA_READER_ENABLED
24538 ret = xmlSchemaVReaderWalk(vctxt);
24539#endif
24540#endif
24541 } else if ((vctxt->sax != NULL) && (vctxt->parserCtxt != NULL)) {
24542 /*
24543 * SAX validation.
24544 */
24545 ret = xmlParseDocument(vctxt->parserCtxt);
24546 } else {
24547 VERROR_INT("xmlSchemaVStartValidation",
24548 "no instance to validate");
24549 ret = -1;
24550 }
24551
24552 xmlSchemaPostRun(vctxt);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024553 if (ret == 0)
24554 ret = vctxt->err;
24555 return (ret);
24556}
24557
24558/**
24559 * xmlSchemaValidateOneElement:
24560 * @ctxt: a schema validation context
24561 * @elem: an element node
24562 *
24563 * Validate a branch of a tree, starting with the given @elem.
24564 *
24565 * Returns 0 if the element and its subtree is valid, a positive error
24566 * code number otherwise and -1 in case of an internal or API error.
24567 */
24568int
24569xmlSchemaValidateOneElement(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem)
24570{
24571 if ((ctxt == NULL) || (elem == NULL) || (elem->type != XML_ELEMENT_NODE))
24572 return (-1);
24573
24574 if (ctxt->schema == NULL)
24575 return (-1);
24576
24577 ctxt->doc = elem->doc;
24578 ctxt->node = elem;
24579 ctxt->validationRoot = elem;
24580 return(xmlSchemaVStart(ctxt));
24581}
Kasimier T. Buchcik876a6db2004-09-16 11:31:52 +000024582
Daniel Veillard259f0df2004-08-18 09:13:18 +000024583/**
Daniel Veillard4255d502002-04-16 15:50:10 +000024584 * xmlSchemaValidateDoc:
24585 * @ctxt: a schema validation context
24586 * @doc: a parsed document tree
24587 *
24588 * Validate a document tree in memory.
24589 *
24590 * Returns 0 if the document is schemas valid, a positive error code
24591 * number otherwise and -1 in case of internal or API error.
24592 */
24593int
Daniel Veillardd0c9c322003-10-10 00:49:42 +000024594xmlSchemaValidateDoc(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
24595{
Daniel Veillard4255d502002-04-16 15:50:10 +000024596 if ((ctxt == NULL) || (doc == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000024597 return (-1);
Daniel Veillard4255d502002-04-16 15:50:10 +000024598
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024599 ctxt->doc = doc;
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000024600 ctxt->node = xmlDocGetRootElement(doc);
24601 if (ctxt->node == NULL) {
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024602 xmlSchemaCustomErr((xmlSchemaAbstractCtxtPtr) ctxt,
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000024603 XML_SCHEMAV_DOCUMENT_ELEMENT_MISSING,
24604 (xmlNodePtr) doc, NULL,
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024605 "The document has no document element", NULL, NULL);
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000024606 return (ctxt->err);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024607 }
Kasimier T. Buchcik7f3efa92005-03-07 17:41:58 +000024608 ctxt->validationRoot = ctxt->node;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000024609 return (xmlSchemaVStart(ctxt));
Daniel Veillard4255d502002-04-16 15:50:10 +000024610}
24611
Daniel Veillardcdc82732005-07-08 15:04:06 +000024612
24613/************************************************************************
24614 * *
24615 * Function and data for SAX streaming API *
24616 * *
24617 ************************************************************************/
24618typedef struct _xmlSchemaSplitSAXData xmlSchemaSplitSAXData;
24619typedef xmlSchemaSplitSAXData *xmlSchemaSplitSAXDataPtr;
24620
24621struct _xmlSchemaSplitSAXData {
24622 xmlSAXHandlerPtr user_sax;
24623 void *user_data;
24624 xmlSchemaValidCtxtPtr ctxt;
24625 xmlSAXHandlerPtr schemas_sax;
24626};
24627
Daniel Veillard971771e2005-07-09 17:32:57 +000024628#define XML_SAX_PLUG_MAGIC 0xdc43ba21
24629
24630struct _xmlSchemaSAXPlug {
24631 unsigned int magic;
24632
24633 /* the original callbacks informations */
24634 xmlSAXHandlerPtr *user_sax_ptr;
24635 xmlSAXHandlerPtr user_sax;
24636 void **user_data_ptr;
24637 void *user_data;
24638
24639 /* the block plugged back and validation informations */
24640 xmlSAXHandler schemas_sax;
24641 xmlSchemaValidCtxtPtr ctxt;
24642};
24643
Daniel Veillardcdc82732005-07-08 15:04:06 +000024644/* All those functions just bounces to the user provided SAX handlers */
24645static void
24646internalSubsetSplit(void *ctx, const xmlChar *name,
24647 const xmlChar *ExternalID, const xmlChar *SystemID)
24648{
Daniel Veillard971771e2005-07-09 17:32:57 +000024649 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024650 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24651 (ctxt->user_sax->internalSubset != NULL))
24652 ctxt->user_sax->internalSubset(ctxt->user_data, name, ExternalID,
24653 SystemID);
24654}
24655
24656static int
24657isStandaloneSplit(void *ctx)
24658{
Daniel Veillard971771e2005-07-09 17:32:57 +000024659 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024660 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24661 (ctxt->user_sax->isStandalone != NULL))
24662 return(ctxt->user_sax->isStandalone(ctxt->user_data));
24663 return(0);
24664}
24665
24666static int
24667hasInternalSubsetSplit(void *ctx)
24668{
Daniel Veillard971771e2005-07-09 17:32:57 +000024669 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024670 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24671 (ctxt->user_sax->hasInternalSubset != NULL))
24672 return(ctxt->user_sax->hasInternalSubset(ctxt->user_data));
24673 return(0);
24674}
24675
24676static int
24677hasExternalSubsetSplit(void *ctx)
24678{
Daniel Veillard971771e2005-07-09 17:32:57 +000024679 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024680 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24681 (ctxt->user_sax->hasExternalSubset != NULL))
24682 return(ctxt->user_sax->hasExternalSubset(ctxt->user_data));
24683 return(0);
24684}
24685
24686static void
24687externalSubsetSplit(void *ctx, const xmlChar *name,
24688 const xmlChar *ExternalID, const xmlChar *SystemID)
24689{
Daniel Veillard971771e2005-07-09 17:32:57 +000024690 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024691 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24692 (ctxt->user_sax->internalSubset != NULL))
24693 ctxt->user_sax->internalSubset(ctxt->user_data, name, ExternalID,
24694 SystemID);
24695}
24696
24697static xmlParserInputPtr
24698resolveEntitySplit(void *ctx, const xmlChar *publicId, const xmlChar *systemId)
24699{
Daniel Veillard971771e2005-07-09 17:32:57 +000024700 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024701 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24702 (ctxt->user_sax->resolveEntity != NULL))
24703 return(ctxt->user_sax->resolveEntity(ctxt->user_data, publicId,
24704 systemId));
24705 return(NULL);
24706}
24707
24708static xmlEntityPtr
24709getEntitySplit(void *ctx, const xmlChar *name)
24710{
Daniel Veillard971771e2005-07-09 17:32:57 +000024711 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024712 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24713 (ctxt->user_sax->getEntity != NULL))
24714 return(ctxt->user_sax->getEntity(ctxt->user_data, name));
24715 return(NULL);
24716}
24717
24718static xmlEntityPtr
24719getParameterEntitySplit(void *ctx, const xmlChar *name)
24720{
Daniel Veillard971771e2005-07-09 17:32:57 +000024721 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024722 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24723 (ctxt->user_sax->getParameterEntity != NULL))
24724 return(ctxt->user_sax->getParameterEntity(ctxt->user_data, name));
24725 return(NULL);
24726}
24727
24728
24729static void
24730entityDeclSplit(void *ctx, const xmlChar *name, int type,
24731 const xmlChar *publicId, const xmlChar *systemId, xmlChar *content)
24732{
Daniel Veillard971771e2005-07-09 17:32:57 +000024733 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024734 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24735 (ctxt->user_sax->entityDecl != NULL))
24736 ctxt->user_sax->entityDecl(ctxt->user_data, name, type, publicId,
24737 systemId, content);
24738}
24739
24740static void
24741attributeDeclSplit(void *ctx, const xmlChar * elem,
24742 const xmlChar * name, int type, int def,
24743 const xmlChar * defaultValue, xmlEnumerationPtr tree)
24744{
Daniel Veillard971771e2005-07-09 17:32:57 +000024745 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024746 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24747 (ctxt->user_sax->attributeDecl != NULL)) {
24748 ctxt->user_sax->attributeDecl(ctxt->user_data, elem, name, type,
24749 def, defaultValue, tree);
24750 } else {
24751 xmlFreeEnumeration(tree);
24752 }
24753}
24754
24755static void
24756elementDeclSplit(void *ctx, const xmlChar *name, int type,
24757 xmlElementContentPtr content)
24758{
Daniel Veillard971771e2005-07-09 17:32:57 +000024759 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024760 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24761 (ctxt->user_sax->elementDecl != NULL))
24762 ctxt->user_sax->elementDecl(ctxt->user_data, name, type, content);
24763}
24764
24765static void
24766notationDeclSplit(void *ctx, const xmlChar *name,
24767 const xmlChar *publicId, const xmlChar *systemId)
24768{
Daniel Veillard971771e2005-07-09 17:32:57 +000024769 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024770 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24771 (ctxt->user_sax->notationDecl != NULL))
24772 ctxt->user_sax->notationDecl(ctxt->user_data, name, publicId,
24773 systemId);
24774}
24775
24776static void
24777unparsedEntityDeclSplit(void *ctx, const xmlChar *name,
24778 const xmlChar *publicId, const xmlChar *systemId,
24779 const xmlChar *notationName)
24780{
Daniel Veillard971771e2005-07-09 17:32:57 +000024781 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024782 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24783 (ctxt->user_sax->unparsedEntityDecl != NULL))
24784 ctxt->user_sax->unparsedEntityDecl(ctxt->user_data, name, publicId,
24785 systemId, notationName);
24786}
24787
24788static void
24789setDocumentLocatorSplit(void *ctx, xmlSAXLocatorPtr loc)
24790{
Daniel Veillard971771e2005-07-09 17:32:57 +000024791 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024792 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24793 (ctxt->user_sax->setDocumentLocator != NULL))
24794 ctxt->user_sax->setDocumentLocator(ctxt->user_data, loc);
24795}
24796
24797static void
24798startDocumentSplit(void *ctx)
24799{
Daniel Veillard971771e2005-07-09 17:32:57 +000024800 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024801 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24802 (ctxt->user_sax->startDocument != NULL))
24803 ctxt->user_sax->startDocument(ctxt->user_data);
24804}
24805
24806static void
24807endDocumentSplit(void *ctx)
24808{
Daniel Veillard971771e2005-07-09 17:32:57 +000024809 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024810 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24811 (ctxt->user_sax->endDocument != NULL))
24812 ctxt->user_sax->endDocument(ctxt->user_data);
24813}
24814
24815static void
24816processingInstructionSplit(void *ctx, const xmlChar *target,
24817 const xmlChar *data)
24818{
Daniel Veillard971771e2005-07-09 17:32:57 +000024819 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024820 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24821 (ctxt->user_sax->processingInstruction != NULL))
24822 ctxt->user_sax->processingInstruction(ctxt->user_data, target, data);
24823}
24824
24825static void
24826commentSplit(void *ctx, const xmlChar *value)
24827{
Daniel Veillard971771e2005-07-09 17:32:57 +000024828 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024829 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24830 (ctxt->user_sax->comment != NULL))
24831 ctxt->user_sax->comment(ctxt->user_data, value);
24832}
24833
24834/*
24835 * Varargs error callbacks to the user application, harder ...
24836 */
24837
Daniel Veillardffa3c742005-07-21 13:24:09 +000024838static void XMLCDECL
Daniel Veillardafc05b62005-07-17 06:11:19 +000024839warningSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
Daniel Veillard971771e2005-07-09 17:32:57 +000024840 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024841 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24842 (ctxt->user_sax->warning != NULL)) {
24843 TODO
24844 }
24845}
Daniel Veillardffa3c742005-07-21 13:24:09 +000024846static void XMLCDECL
Daniel Veillardafc05b62005-07-17 06:11:19 +000024847errorSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
Daniel Veillard971771e2005-07-09 17:32:57 +000024848 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024849 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24850 (ctxt->user_sax->error != NULL)) {
24851 TODO
24852 }
24853}
Daniel Veillardffa3c742005-07-21 13:24:09 +000024854static void XMLCDECL
Daniel Veillardafc05b62005-07-17 06:11:19 +000024855fatalErrorSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
Daniel Veillard971771e2005-07-09 17:32:57 +000024856 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024857 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24858 (ctxt->user_sax->fatalError != NULL)) {
24859 TODO
24860 }
24861}
24862
24863/*
24864 * Those are function where both the user handler and the schemas handler
24865 * need to be called.
24866 */
24867static void
24868charactersSplit(void *ctx, const xmlChar *ch, int len)
24869{
Daniel Veillard971771e2005-07-09 17:32:57 +000024870 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024871 if (ctxt == NULL)
24872 return;
24873 if ((ctxt->user_sax != NULL) && (ctxt->user_sax->characters != NULL))
24874 ctxt->user_sax->characters(ctxt->user_data, ch, len);
24875 if (ctxt->ctxt != NULL)
24876 xmlSchemaSAXHandleText(ctxt->ctxt, ch, len);
24877}
24878
24879static void
24880ignorableWhitespaceSplit(void *ctx, const xmlChar *ch, int len)
24881{
Daniel Veillard971771e2005-07-09 17:32:57 +000024882 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024883 if (ctxt == NULL)
24884 return;
24885 if ((ctxt->user_sax != NULL) &&
24886 (ctxt->user_sax->ignorableWhitespace != NULL))
24887 ctxt->user_sax->ignorableWhitespace(ctxt->user_data, ch, len);
24888 if (ctxt->ctxt != NULL)
24889 xmlSchemaSAXHandleText(ctxt->ctxt, ch, len);
24890}
24891
24892static void
24893cdataBlockSplit(void *ctx, const xmlChar *value, int len)
24894{
Daniel Veillard971771e2005-07-09 17:32:57 +000024895 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024896 if (ctxt == NULL)
24897 return;
24898 if ((ctxt->user_sax != NULL) &&
24899 (ctxt->user_sax->ignorableWhitespace != NULL))
24900 ctxt->user_sax->ignorableWhitespace(ctxt->user_data, value, len);
24901 if (ctxt->ctxt != NULL)
24902 xmlSchemaSAXHandleCDataSection(ctxt->ctxt, value, len);
24903}
24904
24905static void
24906referenceSplit(void *ctx, const xmlChar *name)
24907{
Daniel Veillard971771e2005-07-09 17:32:57 +000024908 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024909 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
24910 (ctxt->user_sax->reference != NULL))
24911 ctxt->user_sax->reference(ctxt->user_data, name);
24912 if (ctxt->ctxt != NULL)
24913 xmlSchemaSAXHandleReference(ctxt->user_data, name);
24914}
24915
24916static void
24917startElementNsSplit(void *ctx, const xmlChar * localname,
24918 const xmlChar * prefix, const xmlChar * URI,
24919 int nb_namespaces, const xmlChar ** namespaces,
24920 int nb_attributes, int nb_defaulted,
24921 const xmlChar ** attributes) {
Daniel Veillard971771e2005-07-09 17:32:57 +000024922 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024923 if (ctxt == NULL)
24924 return;
24925 if ((ctxt->user_sax != NULL) &&
24926 (ctxt->user_sax->startElementNs != NULL))
24927 ctxt->user_sax->startElementNs(ctxt->user_data, localname, prefix,
24928 URI, nb_namespaces, namespaces,
24929 nb_attributes, nb_defaulted,
24930 attributes);
24931 if (ctxt->ctxt != NULL)
24932 xmlSchemaSAXHandleStartElementNs(ctxt->ctxt, localname, prefix,
24933 URI, nb_namespaces, namespaces,
24934 nb_attributes, nb_defaulted,
24935 attributes);
24936}
24937
24938static void
24939endElementNsSplit(void *ctx, const xmlChar * localname,
24940 const xmlChar * prefix, const xmlChar * URI) {
Daniel Veillard971771e2005-07-09 17:32:57 +000024941 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
Daniel Veillardcdc82732005-07-08 15:04:06 +000024942 if (ctxt == NULL)
24943 return;
24944 if ((ctxt->user_sax != NULL) &&
24945 (ctxt->user_sax->endElementNs != NULL))
24946 ctxt->user_sax->endElementNs(ctxt->user_data, localname, prefix, URI);
24947 if (ctxt->ctxt != NULL)
24948 xmlSchemaSAXHandleEndElementNs(ctxt->ctxt, localname, prefix, URI);
24949}
24950
Daniel Veillard4255d502002-04-16 15:50:10 +000024951/**
Daniel Veillard971771e2005-07-09 17:32:57 +000024952 * xmlSchemaSAXPlug:
24953 * @ctxt: a schema validation context
Daniel Veillard1f33c4d2005-07-10 21:38:31 +000024954 * @sax: a pointer to the original xmlSAXHandlerPtr
24955 * @user_data: a pointer to the original SAX user data pointer
Daniel Veillard971771e2005-07-09 17:32:57 +000024956 *
24957 * Plug a SAX based validation layer in a SAX parsing event flow.
24958 * The original @saxptr and @dataptr data are replaced by new pointers
24959 * but the calls to the original will be maintained.
24960 *
24961 * Returns a pointer to a data structure needed to unplug the validation layer
24962 * or NULL in case of errors.
24963 */
24964xmlSchemaSAXPlugPtr
24965xmlSchemaSAXPlug(xmlSchemaValidCtxtPtr ctxt,
24966 xmlSAXHandlerPtr *sax, void **user_data)
24967{
24968 xmlSchemaSAXPlugPtr ret;
24969 xmlSAXHandlerPtr old_sax;
24970
24971 if ((ctxt == NULL) || (sax == NULL) || (user_data == NULL))
24972 return(NULL);
24973
24974 /*
24975 * We only allow to plug into SAX2 event streams
24976 */
24977 old_sax = *sax;
24978 if ((old_sax != NULL) && (old_sax->initialized != XML_SAX2_MAGIC))
24979 return(NULL);
24980 if ((old_sax != NULL) &&
24981 (old_sax->startElementNs == NULL) && (old_sax->endElementNs == NULL) &&
24982 ((old_sax->startElement != NULL) || (old_sax->endElement != NULL)))
24983 return(NULL);
24984
24985 /*
24986 * everything seems right allocate the local data needed for that layer
24987 */
24988 ret = (xmlSchemaSAXPlugPtr) xmlMalloc(sizeof(xmlSchemaSAXPlugStruct));
24989 if (ret == NULL) {
24990 return(NULL);
24991 }
24992 memset(ret, 0, sizeof(xmlSchemaSAXPlugStruct));
24993 ret->magic = XML_SAX_PLUG_MAGIC;
24994 ret->schemas_sax.initialized = XML_SAX2_MAGIC;
24995 ret->ctxt = ctxt;
24996 ret->user_sax_ptr = sax;
24997 ret->user_sax = old_sax;
24998 if (old_sax == NULL) {
24999 /*
25000 * go direct, no need for the split block and functions.
25001 */
25002 ret->schemas_sax.startElementNs = xmlSchemaSAXHandleStartElementNs;
25003 ret->schemas_sax.endElementNs = xmlSchemaSAXHandleEndElementNs;
25004 /*
25005 * Note that we use the same text-function for both, to prevent
25006 * the parser from testing for ignorable whitespace.
25007 */
25008 ret->schemas_sax.ignorableWhitespace = xmlSchemaSAXHandleText;
25009 ret->schemas_sax.characters = xmlSchemaSAXHandleText;
25010
25011 ret->schemas_sax.cdataBlock = xmlSchemaSAXHandleCDataSection;
25012 ret->schemas_sax.reference = xmlSchemaSAXHandleReference;
25013
25014 ret->user_data = ctxt;
25015 *user_data = ctxt;
25016 } else {
25017 /*
25018 * for each callback unused by Schemas initialize it to the Split
25019 * routine only if non NULL in the user block, this can speed up
25020 * things at the SAX level.
25021 */
25022 if (old_sax->internalSubset != NULL)
25023 ret->schemas_sax.internalSubset = internalSubsetSplit;
25024 if (old_sax->isStandalone != NULL)
25025 ret->schemas_sax.isStandalone = isStandaloneSplit;
25026 if (old_sax->hasInternalSubset != NULL)
25027 ret->schemas_sax.hasInternalSubset = hasInternalSubsetSplit;
25028 if (old_sax->hasExternalSubset != NULL)
25029 ret->schemas_sax.hasExternalSubset = hasExternalSubsetSplit;
25030 if (old_sax->resolveEntity != NULL)
25031 ret->schemas_sax.resolveEntity = resolveEntitySplit;
25032 if (old_sax->getEntity != NULL)
25033 ret->schemas_sax.getEntity = getEntitySplit;
25034 if (old_sax->entityDecl != NULL)
25035 ret->schemas_sax.entityDecl = entityDeclSplit;
25036 if (old_sax->notationDecl != NULL)
25037 ret->schemas_sax.notationDecl = notationDeclSplit;
25038 if (old_sax->attributeDecl != NULL)
25039 ret->schemas_sax.attributeDecl = attributeDeclSplit;
25040 if (old_sax->elementDecl != NULL)
25041 ret->schemas_sax.elementDecl = elementDeclSplit;
25042 if (old_sax->unparsedEntityDecl != NULL)
25043 ret->schemas_sax.unparsedEntityDecl = unparsedEntityDeclSplit;
25044 if (old_sax->setDocumentLocator != NULL)
25045 ret->schemas_sax.setDocumentLocator = setDocumentLocatorSplit;
25046 if (old_sax->startDocument != NULL)
25047 ret->schemas_sax.startDocument = startDocumentSplit;
25048 if (old_sax->endDocument != NULL)
25049 ret->schemas_sax.endDocument = endDocumentSplit;
25050 if (old_sax->processingInstruction != NULL)
25051 ret->schemas_sax.processingInstruction = processingInstructionSplit;
25052 if (old_sax->comment != NULL)
25053 ret->schemas_sax.comment = commentSplit;
25054 if (old_sax->warning != NULL)
25055 ret->schemas_sax.warning = warningSplit;
25056 if (old_sax->error != NULL)
25057 ret->schemas_sax.error = errorSplit;
25058 if (old_sax->fatalError != NULL)
25059 ret->schemas_sax.fatalError = fatalErrorSplit;
25060 if (old_sax->getParameterEntity != NULL)
25061 ret->schemas_sax.getParameterEntity = getParameterEntitySplit;
25062 if (old_sax->externalSubset != NULL)
25063 ret->schemas_sax.externalSubset = externalSubsetSplit;
25064
25065 /*
25066 * the 6 schemas callback have to go to the splitter functions
25067 * Note that we use the same text-function for ignorableWhitespace
25068 * if possible, to prevent the parser from testing for ignorable
25069 * whitespace.
25070 */
25071 ret->schemas_sax.characters = charactersSplit;
25072 if ((old_sax->ignorableWhitespace != NULL) &&
25073 (old_sax->ignorableWhitespace != old_sax->characters))
25074 ret->schemas_sax.ignorableWhitespace = ignorableWhitespaceSplit;
25075 else
25076 ret->schemas_sax.ignorableWhitespace = charactersSplit;
25077 ret->schemas_sax.cdataBlock = cdataBlockSplit;
25078 ret->schemas_sax.reference = referenceSplit;
25079 ret->schemas_sax.startElementNs = startElementNsSplit;
25080 ret->schemas_sax.endElementNs = endElementNsSplit;
25081
25082 ret->user_data_ptr = user_data;
25083 ret->user_data = *user_data;
25084 *user_data = ret;
25085 }
25086
25087 /*
25088 * plug the pointers back.
25089 */
25090 *sax = &(ret->schemas_sax);
Daniel Veillardf10ae122005-07-10 19:03:16 +000025091 ctxt->sax = *sax;
25092 ctxt->flags |= XML_SCHEMA_VALID_CTXT_FLAG_STREAM;
25093 xmlSchemaPreRun(ctxt);
Daniel Veillard971771e2005-07-09 17:32:57 +000025094 return(ret);
25095}
25096
25097/**
25098 * xmlSchemaSAXUnplug:
25099 * @plug: a data structure returned by xmlSchemaSAXPlug
25100 *
25101 * Unplug a SAX based validation layer in a SAX parsing event flow.
25102 * The original pointers used in the call are restored.
25103 *
25104 * Returns 0 in case of success and -1 in case of failure.
25105 */
25106int
25107xmlSchemaSAXUnplug(xmlSchemaSAXPlugPtr plug)
25108{
25109 xmlSAXHandlerPtr *sax;
25110 void **user_data;
25111
25112 if ((plug == NULL) || (plug->magic != XML_SAX_PLUG_MAGIC))
25113 return(-1);
25114 plug->magic = 0;
25115
Daniel Veillardf10ae122005-07-10 19:03:16 +000025116 xmlSchemaPostRun(plug->ctxt);
Daniel Veillard971771e2005-07-09 17:32:57 +000025117 /* restore the data */
25118 sax = plug->user_sax_ptr;
25119 *sax = plug->user_sax;
25120 if (plug->user_sax != NULL) {
25121 user_data = plug->user_data_ptr;
25122 *user_data = plug->user_data;
25123 }
25124
25125 /* free and return */
25126 xmlFree(plug);
25127 return(0);
25128}
25129
25130/**
Daniel Veillard4255d502002-04-16 15:50:10 +000025131 * xmlSchemaValidateStream:
25132 * @ctxt: a schema validation context
25133 * @input: the input to use for reading the data
25134 * @enc: an optional encoding information
25135 * @sax: a SAX handler for the resulting events
25136 * @user_data: the context to provide to the SAX handler.
25137 *
Daniel Veillardcdc82732005-07-08 15:04:06 +000025138 * Validate an input based on a flow of SAX event from the parser
25139 * and forward the events to the @sax handler with the provided @user_data
25140 * the user provided @sax handler must be a SAX2 one.
Daniel Veillard4255d502002-04-16 15:50:10 +000025141 *
25142 * Returns 0 if the document is schemas valid, a positive error code
25143 * number otherwise and -1 in case of internal or API error.
25144 */
Daniel Veillardd0c9c322003-10-10 00:49:42 +000025145int
Daniel Veillard4255d502002-04-16 15:50:10 +000025146xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt,
Daniel Veillardd0c9c322003-10-10 00:49:42 +000025147 xmlParserInputBufferPtr input, xmlCharEncoding enc,
25148 xmlSAXHandlerPtr sax, void *user_data)
25149{
Daniel Veillard971771e2005-07-09 17:32:57 +000025150 xmlSchemaSAXPlugPtr plug = NULL;
25151 xmlSAXHandlerPtr old_sax = NULL;
25152 xmlParserCtxtPtr pctxt = NULL;
25153 xmlParserInputPtr inputStream = NULL;
Daniel Veillardcdc82732005-07-08 15:04:06 +000025154 int ret;
25155
Daniel Veillard4255d502002-04-16 15:50:10 +000025156 if ((ctxt == NULL) || (input == NULL))
Daniel Veillardd0c9c322003-10-10 00:49:42 +000025157 return (-1);
Daniel Veillardcdc82732005-07-08 15:04:06 +000025158
Daniel Veillardcdc82732005-07-08 15:04:06 +000025159 /*
25160 * prepare the parser
25161 */
25162 pctxt = xmlNewParserCtxt();
25163 if (pctxt == NULL)
25164 return (-1);
25165 old_sax = pctxt->sax;
Daniel Veillard971771e2005-07-09 17:32:57 +000025166 pctxt->sax = sax;
25167 pctxt->userData = user_data;
Daniel Veillardcdc82732005-07-08 15:04:06 +000025168#if 0
25169 if (options)
25170 xmlCtxtUseOptions(pctxt, options);
25171#endif
Kasimier T. Buchcik85aed6d2005-07-08 18:06:18 +000025172 pctxt->linenumbers = 1;
Daniel Veillardcdc82732005-07-08 15:04:06 +000025173
Daniel Veillardf0af8ec2005-07-08 17:27:33 +000025174 inputStream = xmlNewIOInputStream(pctxt, input, enc);;
Daniel Veillardcdc82732005-07-08 15:04:06 +000025175 if (inputStream == NULL) {
25176 ret = -1;
25177 goto done;
25178 }
25179 inputPush(pctxt, inputStream);
25180 ctxt->parserCtxt = pctxt;
25181 ctxt->input = input;
25182
25183 /*
Daniel Veillard971771e2005-07-09 17:32:57 +000025184 * Plug the validation and launch the parsing
Daniel Veillardcdc82732005-07-08 15:04:06 +000025185 */
Daniel Veillard971771e2005-07-09 17:32:57 +000025186 plug = xmlSchemaSAXPlug(ctxt, &(pctxt->sax), &(pctxt->userData));
25187 if (plug == NULL) {
25188 ret = -1;
25189 goto done;
25190 }
25191 ctxt->input = input;
25192 ctxt->enc = enc;
25193 ctxt->sax = pctxt->sax;
Daniel Veillardcdc82732005-07-08 15:04:06 +000025194 ctxt->flags |= XML_SCHEMA_VALID_CTXT_FLAG_STREAM;
25195 ret = xmlSchemaVStart(ctxt);
25196
25197 if ((ret == 0) && (! ctxt->parserCtxt->wellFormed)) {
25198 ret = ctxt->parserCtxt->errNo;
25199 if (ret == 0)
25200 ret = 1;
25201 }
Daniel Veillardcdc82732005-07-08 15:04:06 +000025202
25203done:
Daniel Veillard971771e2005-07-09 17:32:57 +000025204 ctxt->parserCtxt = NULL;
25205 ctxt->sax = NULL;
25206 ctxt->input = NULL;
25207 if (plug != NULL) {
25208 xmlSchemaSAXUnplug(plug);
25209 }
Daniel Veillardcdc82732005-07-08 15:04:06 +000025210 /* cleanup */
Daniel Veillard971771e2005-07-09 17:32:57 +000025211 if (pctxt != NULL) {
25212 pctxt->sax = old_sax;
25213 xmlFreeParserCtxt(pctxt);
25214 }
Daniel Veillardcdc82732005-07-08 15:04:06 +000025215 return (ret);
Daniel Veillard4255d502002-04-16 15:50:10 +000025216}
25217
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025218/**
25219 * xmlSchemaValidateFile:
25220 * @ctxt: a schema validation context
Daniel Veillard81562d22005-06-15 13:27:56 +000025221 * @filename: the URI of the instance
25222 * @options: a future set of options, currently unused
25223 *
25224 * Do a schemas validation of the given resource, it will use the
25225 * SAX streamable validation internally.
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025226 *
25227 * Returns 0 if the document is valid, a positive error code
25228 * number otherwise and -1 in case of an internal or API error.
25229 */
25230int
25231xmlSchemaValidateFile(xmlSchemaValidCtxtPtr ctxt,
Kasimier T. Buchcikc63fbbf2005-06-15 12:54:05 +000025232 const char * filename,
25233 int options ATTRIBUTE_UNUSED)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025234{
25235 int ret;
Kasimier T. Buchcik72d3adc2005-07-08 16:43:37 +000025236 xmlParserInputBufferPtr input;
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025237
25238 if ((ctxt == NULL) || (filename == NULL))
25239 return (-1);
25240
Kasimier T. Buchcik72d3adc2005-07-08 16:43:37 +000025241 input = xmlParserInputBufferCreateFilename(filename,
25242 XML_CHAR_ENCODING_NONE);
25243 if (input == NULL)
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025244 return (-1);
Kasimier T. Buchcik72d3adc2005-07-08 16:43:37 +000025245 ret = xmlSchemaValidateStream(ctxt, input, XML_CHAR_ENCODING_NONE,
25246 NULL, NULL);
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025247 return (ret);
Daniel Veillard81562d22005-06-15 13:27:56 +000025248}
Kasimier T. Buchcik4efd90d2005-06-09 10:32:53 +000025249
Daniel Veillard5d4644e2005-04-01 13:11:58 +000025250#define bottom_xmlschemas
25251#include "elfgcchack.h"
Daniel Veillard4255d502002-04-16 15:50:10 +000025252#endif /* LIBXML_SCHEMAS_ENABLED */