ReactOS 0.4.16-dev-2169-g4e7a64b
xmlschemas.c
Go to the documentation of this file.
1/*
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
10/*
11 * TODO:
12 * - when types are redefined in includes, check that all
13 * types in the redef list are equal
14 * -> need a type equality operation.
15 * - if we don't intend to use the schema for schemas, we
16 * need to validate all schema attributes (ref, type, name)
17 * against their types.
18 * - Eliminate item creation for: ??
19 *
20 * URGENT TODO:
21 * - For xsi-driven schema acquisition, augment the IDCs after every
22 * acquisition episode (xmlSchemaAugmentIDC).
23 *
24 * NOTES:
25 * - Eliminated item creation for: <restriction>, <extension>,
26 * <simpleContent>, <complexContent>, <list>, <union>
27 *
28 * PROBLEMS:
29 * - http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005JulSep/0337.html
30 * IDC XPath expression and chameleon includes: the targetNamespace is changed, so
31 * XPath will have trouble to resolve to this namespace, since not known.
32 *
33 *
34 * CONSTRAINTS:
35 *
36 * Schema Component Constraint:
37 * All Group Limited (cos-all-limited)
38 * Status: complete
39 * (1.2)
40 * In xmlSchemaGroupDefReferenceTermFixup() and
41 * (2)
42 * In xmlSchemaParseModelGroup()
43 * TODO: Actually this should go to component-level checks,
44 * but is done here due to performance. Move it to an other layer
45 * is schema construction via an API is implemented.
46 */
47
48/* To avoid EBCDIC trouble when parsing on zOS */
49#if defined(__MVS__)
50#pragma convert("ISO8859-1")
51#endif
52
53#define IN_LIBXML
54#include "libxml.h"
55
56#ifdef LIBXML_SCHEMAS_ENABLED
57
58#include <string.h>
59#include <libxml/xmlmemory.h>
60#include <libxml/parser.h>
62#include <libxml/hash.h>
63#include <libxml/uri.h>
64#include <libxml/xmlschemas.h>
67#include <libxml/xmlautomata.h>
68#include <libxml/xmlregexp.h>
69#include <libxml/dict.h>
70#include <libxml/encoding.h>
71#include <libxml/xmlIO.h>
72#ifdef LIBXML_PATTERN_ENABLED
73#include <libxml/pattern.h>
74#endif
75#ifdef LIBXML_READER_ENABLED
76#include <libxml/xmlreader.h>
77#endif
78
79#include "private/error.h"
80#include "private/string.h"
81
82/* #define WXS_ELEM_DECL_CONS_ENABLED */
83
84/* #define ENABLE_PARTICLE_RESTRICTION 1 */
85
86#define ENABLE_REDEFINE
87
88/* #define ENABLE_NAMED_LOCALS */
89
90/* #define ENABLE_IDC_NODE_TABLES_TEST */
91
92#define DUMP_CONTENT_MODEL
93
94#ifdef LIBXML_READER_ENABLED
95/* #define XML_SCHEMA_READER_ENABLED */
96#endif
97
98#define UNBOUNDED (1 << 30)
99#define TODO \
100 xmlGenericError(xmlGenericErrorContext, \
101 "Unimplemented block at %s:%d\n", \
102 __FILE__, __LINE__);
103
104#define XML_SCHEMAS_NO_NAMESPACE (const xmlChar *) "##"
105
106/*
107 * The XML Schemas namespaces
108 */
109static const xmlChar *xmlSchemaNs = (const xmlChar *)
110 "http://www.w3.org/2001/XMLSchema";
111
112static const xmlChar *xmlSchemaInstanceNs = (const xmlChar *)
113 "http://www.w3.org/2001/XMLSchema-instance";
114
115static const xmlChar *xmlNamespaceNs = (const xmlChar *)
116 "http://www.w3.org/2000/xmlns/";
117
118/*
119* Come casting macros.
120*/
121#define ACTXT_CAST (xmlSchemaAbstractCtxtPtr)
122#define PCTXT_CAST (xmlSchemaParserCtxtPtr)
123#define VCTXT_CAST (xmlSchemaValidCtxtPtr)
124#define WXS_BASIC_CAST (xmlSchemaBasicItemPtr)
125#define WXS_TREE_CAST (xmlSchemaTreeItemPtr)
126#define WXS_PTC_CAST (xmlSchemaParticlePtr)
127#define WXS_TYPE_CAST (xmlSchemaTypePtr)
128#define WXS_ELEM_CAST (xmlSchemaElementPtr)
129#define WXS_ATTR_GROUP_CAST (xmlSchemaAttributeGroupPtr)
130#define WXS_ATTR_CAST (xmlSchemaAttributePtr)
131#define WXS_ATTR_USE_CAST (xmlSchemaAttributeUsePtr)
132#define WXS_ATTR_PROHIB_CAST (xmlSchemaAttributeUseProhibPtr)
133#define WXS_MODEL_GROUPDEF_CAST (xmlSchemaModelGroupDefPtr)
134#define WXS_MODEL_GROUP_CAST (xmlSchemaModelGroupPtr)
135#define WXS_IDC_CAST (xmlSchemaIDCPtr)
136#define WXS_QNAME_CAST (xmlSchemaQNameRefPtr)
137#define WXS_LIST_CAST (xmlSchemaItemListPtr)
138
139/*
140* Macros to query common properties of components.
141*/
142#define WXS_ITEM_NODE(i) xmlSchemaGetComponentNode(WXS_BASIC_CAST (i))
143
144#define WXS_ITEM_TYPE_NAME(i) xmlSchemaGetComponentTypeStr(WXS_BASIC_CAST (i))
145/*
146* Macros for element declarations.
147*/
148#define WXS_ELEM_TYPEDEF(e) (e)->subtypes
149
150#define WXS_SUBST_HEAD(item) (item)->refDecl
151/*
152* Macros for attribute declarations.
153*/
154#define WXS_ATTR_TYPEDEF(a) (a)->subtypes
155/*
156* Macros for attribute uses.
157*/
158#define WXS_ATTRUSE_DECL(au) (WXS_ATTR_USE_CAST (au))->attrDecl
159
160#define WXS_ATTRUSE_TYPEDEF(au) WXS_ATTR_TYPEDEF(WXS_ATTRUSE_DECL( WXS_ATTR_USE_CAST au))
161
162#define WXS_ATTRUSE_DECL_NAME(au) (WXS_ATTRUSE_DECL(au))->name
163
164#define WXS_ATTRUSE_DECL_TNS(au) (WXS_ATTRUSE_DECL(au))->targetNamespace
165/*
166* Macros for attribute groups.
167*/
168#define WXS_ATTR_GROUP_HAS_REFS(ag) ((WXS_ATTR_GROUP_CAST (ag))->flags & XML_SCHEMAS_ATTRGROUP_HAS_REFS)
169#define WXS_ATTR_GROUP_EXPANDED(ag) ((WXS_ATTR_GROUP_CAST (ag))->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED)
170/*
171* Macros for particles.
172*/
173#define WXS_PARTICLE(p) WXS_PTC_CAST (p)
174
175#define WXS_PARTICLE_TERM(p) (WXS_PARTICLE(p))->children
176
177#define WXS_PARTICLE_TERM_AS_ELEM(p) (WXS_ELEM_CAST WXS_PARTICLE_TERM(p))
178
179#define WXS_PARTICLE_MODEL(p) WXS_MODEL_GROUP_CAST WXS_PARTICLE(p)->children
180/*
181* Macros for model groups definitions.
182*/
183#define WXS_MODELGROUPDEF_MODEL(mgd) (WXS_MODEL_GROUP_CAST (mgd))->children
184/*
185* Macros for model groups.
186*/
187#define WXS_IS_MODEL_GROUP(i) \
188 (((i)->type == XML_SCHEMA_TYPE_SEQUENCE) || \
189 ((i)->type == XML_SCHEMA_TYPE_CHOICE) || \
190 ((i)->type == XML_SCHEMA_TYPE_ALL))
191
192#define WXS_MODELGROUP_PARTICLE(mg) WXS_PTC_CAST (mg)->children
193/*
194* Macros for schema buckets.
195*/
196#define WXS_IS_BUCKET_INCREDEF(t) (((t) == XML_SCHEMA_SCHEMA_INCLUDE) || \
197 ((t) == XML_SCHEMA_SCHEMA_REDEFINE))
198
199#define WXS_IS_BUCKET_IMPMAIN(t) (((t) == XML_SCHEMA_SCHEMA_MAIN) || \
200 ((t) == XML_SCHEMA_SCHEMA_IMPORT))
201
202#define WXS_IMPBUCKET(b) ((xmlSchemaImportPtr) (b))
203
204#define WXS_INCBUCKET(b) ((xmlSchemaIncludePtr) (b))
205/*
206* Macros for complex/simple types.
207*/
208#define WXS_IS_ANYTYPE(i) \
209 (( (i)->type == XML_SCHEMA_TYPE_BASIC) && \
210 ( (WXS_TYPE_CAST (i))->builtInType == XML_SCHEMAS_ANYTYPE))
211
212#define WXS_IS_COMPLEX(i) \
213 (((i)->type == XML_SCHEMA_TYPE_COMPLEX) || \
214 ((i)->builtInType == XML_SCHEMAS_ANYTYPE))
215
216#define WXS_IS_SIMPLE(item) \
217 ((item->type == XML_SCHEMA_TYPE_SIMPLE) || \
218 ((item->type == XML_SCHEMA_TYPE_BASIC) && \
219 (item->builtInType != XML_SCHEMAS_ANYTYPE)))
220
221#define WXS_IS_ANY_SIMPLE_TYPE(i) \
222 (((i)->type == XML_SCHEMA_TYPE_BASIC) && \
223 ((i)->builtInType == XML_SCHEMAS_ANYSIMPLETYPE))
224
225#define WXS_IS_RESTRICTION(t) \
226 ((t)->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION)
227
228#define WXS_IS_EXTENSION(t) \
229 ((t)->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION)
230
231#define WXS_IS_TYPE_NOT_FIXED(i) \
232 (((i)->type != XML_SCHEMA_TYPE_BASIC) && \
233 (((i)->flags & XML_SCHEMAS_TYPE_INTERNAL_RESOLVED) == 0))
234
235#define WXS_IS_TYPE_NOT_FIXED_1(item) \
236 (((item)->type != XML_SCHEMA_TYPE_BASIC) && \
237 (((item)->flags & XML_SCHEMAS_TYPE_FIXUP_1) == 0))
238
239#define WXS_TYPE_IS_GLOBAL(t) ((t)->flags & XML_SCHEMAS_TYPE_GLOBAL)
240
241#define WXS_TYPE_IS_LOCAL(t) (((t)->flags & XML_SCHEMAS_TYPE_GLOBAL) == 0)
242/*
243* Macros for exclusively for complex types.
244*/
245#define WXS_HAS_COMPLEX_CONTENT(item) \
246 ((item->contentType == XML_SCHEMA_CONTENT_MIXED) || \
247 (item->contentType == XML_SCHEMA_CONTENT_EMPTY) || \
248 (item->contentType == XML_SCHEMA_CONTENT_ELEMENTS))
249
250#define WXS_HAS_SIMPLE_CONTENT(item) \
251 ((item->contentType == XML_SCHEMA_CONTENT_SIMPLE) || \
252 (item->contentType == XML_SCHEMA_CONTENT_BASIC))
253
254#define WXS_HAS_MIXED_CONTENT(item) \
255 (item->contentType == XML_SCHEMA_CONTENT_MIXED)
256
257#define WXS_EMPTIABLE(t) \
258 (xmlSchemaIsParticleEmptiable(WXS_PTC_CAST (t)->subtypes))
259
260#define WXS_TYPE_CONTENTTYPE(t) (t)->subtypes
261
262#define WXS_TYPE_PARTICLE(t) WXS_PTC_CAST (t)->subtypes
263
264#define WXS_TYPE_PARTICLE_TERM(t) WXS_PARTICLE_TERM(WXS_TYPE_PARTICLE(t))
265/*
266* Macros for exclusively for simple types.
267*/
268#define WXS_LIST_ITEMTYPE(t) (t)->subtypes
269
270#define WXS_IS_ATOMIC(t) (t->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC)
271
272#define WXS_IS_LIST(t) (t->flags & XML_SCHEMAS_TYPE_VARIETY_LIST)
273
274#define WXS_IS_UNION(t) (t->flags & XML_SCHEMAS_TYPE_VARIETY_UNION)
275/*
276* Misc parser context macros.
277*/
278#define WXS_CONSTRUCTOR(ctx) (ctx)->constructor
279
280#define WXS_HAS_BUCKETS(ctx) \
281( (WXS_CONSTRUCTOR((ctx))->buckets != NULL) && \
282(WXS_CONSTRUCTOR((ctx))->buckets->nbItems > 0) )
283
284#define WXS_SUBST_GROUPS(ctx) WXS_CONSTRUCTOR((ctx))->substGroups
285
286#define WXS_BUCKET(ctx) WXS_CONSTRUCTOR((ctx))->bucket
287
288#define WXS_SCHEMA(ctx) (ctx)->schema
289
290#define WXS_ADD_LOCAL(ctx, item) \
291 do { \
292 if (xmlSchemaAddItemSize(&(WXS_BUCKET(ctx)->locals), 10, item) < 0) { \
293 xmlFree(item); \
294 item = NULL; \
295 } \
296 } while (0)
297
298#define WXS_ADD_GLOBAL(ctx, item) \
299 do { \
300 if (xmlSchemaAddItemSize(&(WXS_BUCKET(ctx)->globals), 5, item) < 0) { \
301 xmlFree(item); \
302 item = NULL; \
303 } \
304 } while (0)
305
306#define WXS_ADD_PENDING(ctx, item) \
307 xmlSchemaAddItemSize(&((ctx)->constructor->pending), 10, item)
308/*
309* xmlSchemaItemList macros.
310*/
311#define WXS_ILIST_IS_EMPTY(l) ((l == NULL) || ((l)->nbItems == 0))
312/*
313* Misc macros.
314*/
315#define IS_SCHEMA(node, type) \
316 ((node != NULL) && (node->ns != NULL) && \
317 (xmlStrEqual(node->name, (const xmlChar *) type)) && \
318 (xmlStrEqual(node->ns->href, xmlSchemaNs)))
319
320#define FREE_AND_NULL(str) if ((str) != NULL) { xmlFree((xmlChar *) (str)); str = NULL; }
321
322/*
323* Since we put the default/fixed values into the dict, we can
324* use pointer comparison for those values.
325* REMOVED: (xmlStrEqual((v1), (v2)))
326*/
327#define WXS_ARE_DEFAULT_STR_EQUAL(v1, v2) ((v1) == (v2))
328
329#define INODE_NILLED(item) (item->flags & XML_SCHEMA_ELEM_INFO_NILLED)
330
331#define CAN_PARSE_SCHEMA(b) (((b)->doc != NULL) && ((b)->parsed == 0))
332
333#define HFAILURE if (res == -1) goto exit_failure;
334
335#define HERROR if (res != 0) goto exit_error;
336
337#define HSTOP(ctx) if ((ctx)->stop) goto exit;
338/*
339* Some flags used for various schema constraints.
340*/
341#define SUBSET_RESTRICTION 1<<0
342#define SUBSET_EXTENSION 1<<1
343#define SUBSET_SUBSTITUTION 1<<2
344#define SUBSET_LIST 1<<3
345#define SUBSET_UNION 1<<4
346
347typedef struct _xmlSchemaNodeInfo xmlSchemaNodeInfo;
348typedef xmlSchemaNodeInfo *xmlSchemaNodeInfoPtr;
349
350typedef struct _xmlSchemaItemList xmlSchemaItemList;
351typedef xmlSchemaItemList *xmlSchemaItemListPtr;
352struct _xmlSchemaItemList {
353 void **items; /* used for dynamic addition of schemata */
354 int nbItems; /* used for dynamic addition of schemata */
355 int sizeItems; /* used for dynamic addition of schemata */
356};
357
358#define XML_SCHEMA_CTXT_PARSER 1
359#define XML_SCHEMA_CTXT_VALIDATOR 2
360
361typedef struct _xmlSchemaAbstractCtxt xmlSchemaAbstractCtxt;
362typedef xmlSchemaAbstractCtxt *xmlSchemaAbstractCtxtPtr;
363struct _xmlSchemaAbstractCtxt {
364 int type; /* E.g. XML_SCHEMA_CTXT_VALIDATOR */
365 void *dummy; /* Fix alignment issues */
366};
367
368typedef struct _xmlSchemaBucket xmlSchemaBucket;
369typedef xmlSchemaBucket *xmlSchemaBucketPtr;
370
371#define XML_SCHEMA_SCHEMA_MAIN 0
372#define XML_SCHEMA_SCHEMA_IMPORT 1
373#define XML_SCHEMA_SCHEMA_INCLUDE 2
374#define XML_SCHEMA_SCHEMA_REDEFINE 3
375
381typedef struct _xmlSchemaSchemaRelation xmlSchemaSchemaRelation;
382typedef xmlSchemaSchemaRelation *xmlSchemaSchemaRelationPtr;
383struct _xmlSchemaSchemaRelation {
384 xmlSchemaSchemaRelationPtr next;
385 int type; /* E.g. XML_SCHEMA_SCHEMA_IMPORT */
386 const xmlChar *importNamespace;
387 xmlSchemaBucketPtr bucket;
388};
389
390#define XML_SCHEMA_BUCKET_MARKED 1<<0
391#define XML_SCHEMA_BUCKET_COMPS_ADDED 1<<1
392
393struct _xmlSchemaBucket {
394 int type;
395 int flags;
396 const xmlChar *schemaLocation;
397 const xmlChar *origTargetNamespace;
398 const xmlChar *targetNamespace;
399 xmlDocPtr doc;
400 xmlSchemaSchemaRelationPtr relations;
401 int located;
402 int parsed;
403 int imported;
404 int preserveDoc;
405 xmlSchemaItemListPtr globals; /* Global components. */
406 xmlSchemaItemListPtr locals; /* Local components. */
407};
408
417typedef struct _xmlSchemaImport xmlSchemaImport;
418typedef xmlSchemaImport *xmlSchemaImportPtr;
419struct _xmlSchemaImport {
420 int type; /* Main OR import OR include. */
421 int flags;
422 const xmlChar *schemaLocation; /* The URI of the schema document. */
423 /* For chameleon includes, @origTargetNamespace will be NULL */
424 const xmlChar *origTargetNamespace;
425 /*
426 * For chameleon includes, @targetNamespace will be the
427 * targetNamespace of the including schema.
428 */
429 const xmlChar *targetNamespace;
430 xmlDocPtr doc; /* The schema node-tree. */
431 /* @relations will hold any included/imported/redefined schemas. */
432 xmlSchemaSchemaRelationPtr relations;
433 int located;
434 int parsed;
435 int imported;
436 int preserveDoc;
437 xmlSchemaItemListPtr globals;
438 xmlSchemaItemListPtr locals;
439 /* The imported schema. */
440 xmlSchemaPtr schema;
441};
442
443/*
444* (extends xmlSchemaBucket)
445*/
446typedef struct _xmlSchemaInclude xmlSchemaInclude;
447typedef xmlSchemaInclude *xmlSchemaIncludePtr;
448struct _xmlSchemaInclude {
449 int type;
450 int flags;
451 const xmlChar *schemaLocation;
452 const xmlChar *origTargetNamespace;
453 const xmlChar *targetNamespace;
454 xmlDocPtr doc;
455 xmlSchemaSchemaRelationPtr relations;
456 int located;
457 int parsed;
458 int imported;
459 int preserveDoc;
460 xmlSchemaItemListPtr globals; /* Global components. */
461 xmlSchemaItemListPtr locals; /* Local components. */
462
463 /* The owning main or import schema bucket. */
464 xmlSchemaImportPtr ownerImport;
465};
466
472typedef struct _xmlSchemaBasicItem xmlSchemaBasicItem;
473typedef xmlSchemaBasicItem *xmlSchemaBasicItemPtr;
474struct _xmlSchemaBasicItem {
475 xmlSchemaTypeType type;
476 void *dummy; /* Fix alignment issues */
477};
478
485typedef struct _xmlSchemaAnnotItem xmlSchemaAnnotItem;
486typedef xmlSchemaAnnotItem *xmlSchemaAnnotItemPtr;
487struct _xmlSchemaAnnotItem {
488 xmlSchemaTypeType type;
489 xmlSchemaAnnotPtr annot;
490};
491
498typedef struct _xmlSchemaTreeItem xmlSchemaTreeItem;
499typedef xmlSchemaTreeItem *xmlSchemaTreeItemPtr;
500struct _xmlSchemaTreeItem {
501 xmlSchemaTypeType type;
502 xmlSchemaAnnotPtr annot;
503 xmlSchemaTreeItemPtr next;
504 xmlSchemaTreeItemPtr children;
505};
506
507
508#define XML_SCHEMA_ATTR_USE_FIXED 1<<0
515typedef struct _xmlSchemaAttributeUse xmlSchemaAttributeUse;
516typedef xmlSchemaAttributeUse *xmlSchemaAttributeUsePtr;
517struct _xmlSchemaAttributeUse {
518 xmlSchemaTypeType type;
519 xmlSchemaAnnotPtr annot;
520 xmlSchemaAttributeUsePtr next; /* The next attr. use. */
521 /*
522 * The attr. decl. OR a QName-ref. to an attr. decl. OR
523 * a QName-ref. to an attribute group definition.
524 */
525 xmlSchemaAttributePtr attrDecl;
526
527 int flags;
528 xmlNodePtr node;
529 int occurs; /* required, optional */
530 const xmlChar * defValue;
531 xmlSchemaValPtr defVal;
532};
533
540typedef struct _xmlSchemaAttributeUseProhib xmlSchemaAttributeUseProhib;
541typedef xmlSchemaAttributeUseProhib *xmlSchemaAttributeUseProhibPtr;
542struct _xmlSchemaAttributeUseProhib {
543 xmlSchemaTypeType type; /* == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB */
544 xmlNodePtr node;
545 const xmlChar *name;
546 const xmlChar *targetNamespace;
547 int isRef;
548};
549
553typedef struct _xmlSchemaRedef xmlSchemaRedef;
554typedef xmlSchemaRedef *xmlSchemaRedefPtr;
555struct _xmlSchemaRedef {
556 xmlSchemaRedefPtr next;
557 xmlSchemaBasicItemPtr item; /* The redefining component. */
558 xmlSchemaBasicItemPtr reference; /* The referencing component. */
559 xmlSchemaBasicItemPtr target; /* The to-be-redefined component. */
560 const xmlChar *refName; /* The name of the to-be-redefined component. */
561 const xmlChar *refTargetNs; /* The target namespace of the
562 to-be-redefined comp. */
563 xmlSchemaBucketPtr targetBucket; /* The redefined schema. */
564};
565
569typedef struct _xmlSchemaConstructionCtxt xmlSchemaConstructionCtxt;
570typedef xmlSchemaConstructionCtxt *xmlSchemaConstructionCtxtPtr;
571struct _xmlSchemaConstructionCtxt {
572 xmlSchemaPtr mainSchema; /* The main schema. */
573 xmlSchemaBucketPtr mainBucket; /* The main schema bucket */
574 xmlDictPtr dict;
575 xmlSchemaItemListPtr buckets; /* List of schema buckets. */
576 /* xmlSchemaItemListPtr relations; */ /* List of schema relations. */
577 xmlSchemaBucketPtr bucket; /* The current schema bucket */
578 xmlSchemaItemListPtr pending; /* All Components of all schemas that
579 need to be fixed. */
580 xmlHashTablePtr substGroups;
581 xmlSchemaRedefPtr redefs;
582 xmlSchemaRedefPtr lastRedef;
583};
584
585#define XML_SCHEMAS_PARSE_ERROR 1
586#define SCHEMAS_PARSE_OPTIONS XML_PARSE_NOENT
587
588struct _xmlSchemaParserCtxt {
589 int type;
590 void *errCtxt; /* user specific error context */
591 xmlSchemaValidityErrorFunc error; /* the callback in case of errors */
592 xmlSchemaValidityWarningFunc warning; /* the callback in case of warning */
593 int err;
594 int nberrors;
596
597 xmlSchemaConstructionCtxtPtr constructor;
598 int ownsConstructor; /* TODO: Move this to parser *flags*. */
599
600 /* xmlSchemaPtr topschema; */
601 /* xmlHashTablePtr namespaces; */
602
603 xmlSchemaPtr schema; /* The main schema in use */
604 int counter;
605
606 const xmlChar *URL;
607 xmlDocPtr doc;
608 int preserve; /* Whether the doc should be freed */
609
610 const char *buffer;
611 int size;
612
613 /*
614 * Used to build complex element content models
615 */
616 xmlAutomataPtr am;
617 xmlAutomataStatePtr start;
618 xmlAutomataStatePtr end;
619 xmlAutomataStatePtr state;
620
621 xmlDictPtr dict; /* dictionary for interned string names */
622 xmlSchemaTypePtr ctxtType; /* The current context simple/complex type */
623 int options;
624 xmlSchemaValidCtxtPtr vctxt;
625 int isS4S;
626 int isRedefine;
627 int xsiAssemble;
628 int stop; /* If the parser should stop; i.e. a critical error. */
629 const xmlChar *targetNamespace;
630 xmlSchemaBucketPtr redefined; /* The schema to be redefined. */
631
632 xmlSchemaRedefPtr redef; /* Used for redefinitions. */
633 int redefCounter; /* Used for redefinitions. */
634 xmlSchemaItemListPtr attrProhibs;
635};
636
643typedef struct _xmlSchemaQNameRef xmlSchemaQNameRef;
644typedef xmlSchemaQNameRef *xmlSchemaQNameRefPtr;
645struct _xmlSchemaQNameRef {
646 xmlSchemaTypeType type;
647 xmlSchemaBasicItemPtr item; /* The resolved referenced item. */
648 xmlSchemaTypeType itemType;
649 const xmlChar *name;
650 const xmlChar *targetNamespace;
651 xmlNodePtr node;
652};
653
660typedef struct _xmlSchemaParticle xmlSchemaParticle;
661typedef xmlSchemaParticle *xmlSchemaParticlePtr;
662struct _xmlSchemaParticle {
663 xmlSchemaTypeType type;
664 xmlSchemaAnnotPtr annot;
665 xmlSchemaTreeItemPtr next; /* next particle */
666 xmlSchemaTreeItemPtr children; /* the "term" (e.g. a model group,
667 a group definition, a XML_SCHEMA_EXTRA_QNAMEREF (if a reference),
668 etc.) */
669 int minOccurs;
670 int maxOccurs;
671 xmlNodePtr node;
672};
673
680typedef struct _xmlSchemaModelGroup xmlSchemaModelGroup;
681typedef xmlSchemaModelGroup *xmlSchemaModelGroupPtr;
682struct _xmlSchemaModelGroup {
683 xmlSchemaTypeType type; /* XML_SCHEMA_TYPE_SEQUENCE, XML_SCHEMA_TYPE_CHOICE, XML_SCHEMA_TYPE_ALL */
684 xmlSchemaAnnotPtr annot;
685 xmlSchemaTreeItemPtr next; /* not used */
686 xmlSchemaTreeItemPtr children; /* first particle (OR "element decl" OR "wildcard") */
687 xmlNodePtr node;
688};
689
690#define XML_SCHEMA_MODEL_GROUP_DEF_MARKED 1<<0
691#define XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED 1<<1
698typedef struct _xmlSchemaModelGroupDef xmlSchemaModelGroupDef;
699typedef xmlSchemaModelGroupDef *xmlSchemaModelGroupDefPtr;
700struct _xmlSchemaModelGroupDef {
701 xmlSchemaTypeType type; /* XML_SCHEMA_TYPE_GROUP */
702 xmlSchemaAnnotPtr annot;
703 xmlSchemaTreeItemPtr next; /* not used */
704 xmlSchemaTreeItemPtr children; /* the "model group" */
705 const xmlChar *name;
706 const xmlChar *targetNamespace;
707 xmlNodePtr node;
708 int flags;
709};
710
711typedef struct _xmlSchemaIDC xmlSchemaIDC;
712typedef xmlSchemaIDC *xmlSchemaIDCPtr;
713
720typedef struct _xmlSchemaIDCSelect xmlSchemaIDCSelect;
721typedef xmlSchemaIDCSelect *xmlSchemaIDCSelectPtr;
722struct _xmlSchemaIDCSelect {
723 xmlSchemaIDCSelectPtr next;
724 xmlSchemaIDCPtr idc;
725 int index; /* an index position if significant for IDC key-sequences */
726 const xmlChar *xpath; /* the XPath expression */
727 void *xpathComp; /* the compiled XPath expression */
728};
729
737struct _xmlSchemaIDC {
738 xmlSchemaTypeType type;
739 xmlSchemaAnnotPtr annot;
740 xmlSchemaIDCPtr next;
741 xmlNodePtr node;
742 const xmlChar *name;
743 const xmlChar *targetNamespace;
744 xmlSchemaIDCSelectPtr selector;
745 xmlSchemaIDCSelectPtr fields;
746 int nbFields;
747 xmlSchemaQNameRefPtr ref;
748};
749
755typedef struct _xmlSchemaIDCAug xmlSchemaIDCAug;
756typedef xmlSchemaIDCAug *xmlSchemaIDCAugPtr;
757struct _xmlSchemaIDCAug {
758 xmlSchemaIDCAugPtr next; /* next in a list */
759 xmlSchemaIDCPtr def; /* the IDC definition */
760 int keyrefDepth; /* the lowest tree level to which IDC
761 tables need to be bubbled upwards */
762};
763
769typedef struct _xmlSchemaPSVIIDCKey xmlSchemaPSVIIDCKey;
770typedef xmlSchemaPSVIIDCKey *xmlSchemaPSVIIDCKeyPtr;
771struct _xmlSchemaPSVIIDCKey {
772 xmlSchemaTypePtr type;
773 xmlSchemaValPtr val;
774};
775
781typedef struct _xmlSchemaPSVIIDCNode xmlSchemaPSVIIDCNode;
782typedef xmlSchemaPSVIIDCNode *xmlSchemaPSVIIDCNodePtr;
783struct _xmlSchemaPSVIIDCNode {
784 xmlNodePtr node;
785 xmlSchemaPSVIIDCKeyPtr *keys;
786 int nodeLine;
787 int nodeQNameID;
788
789};
790
796typedef struct _xmlSchemaPSVIIDCBinding xmlSchemaPSVIIDCBinding;
797typedef xmlSchemaPSVIIDCBinding *xmlSchemaPSVIIDCBindingPtr;
798struct _xmlSchemaPSVIIDCBinding {
799 xmlSchemaPSVIIDCBindingPtr next; /* next binding of a specific node */
800 xmlSchemaIDCPtr definition; /* the IDC definition */
801 xmlSchemaPSVIIDCNodePtr *nodeTable; /* array of key-sequences */
802 int nbNodes; /* number of entries in the node table */
803 int sizeNodes; /* size of the node table */
804 xmlSchemaItemListPtr dupls;
805};
806
807
808#define XPATH_STATE_OBJ_TYPE_IDC_SELECTOR 1
809#define XPATH_STATE_OBJ_TYPE_IDC_FIELD 2
810
811#define XPATH_STATE_OBJ_MATCHES -2
812#define XPATH_STATE_OBJ_BLOCKED -3
813
814typedef struct _xmlSchemaIDCMatcher xmlSchemaIDCMatcher;
815typedef xmlSchemaIDCMatcher *xmlSchemaIDCMatcherPtr;
816
822typedef struct _xmlSchemaIDCStateObj xmlSchemaIDCStateObj;
823typedef xmlSchemaIDCStateObj *xmlSchemaIDCStateObjPtr;
824struct _xmlSchemaIDCStateObj {
825 int type;
826 xmlSchemaIDCStateObjPtr next; /* next if in a list */
827 int depth; /* depth of creation */
828 int *history; /* list of (depth, state-id) tuples */
829 int nbHistory;
830 int sizeHistory;
831 xmlSchemaIDCMatcherPtr matcher; /* the correspondent field/selector
832 matcher */
833 xmlSchemaIDCSelectPtr sel;
834 void *xpathCtxt;
835};
836
837#define IDC_MATCHER 0
838
844struct _xmlSchemaIDCMatcher {
845 int type;
846 int depth; /* the tree depth at creation time */
847 xmlSchemaIDCMatcherPtr next; /* next in the list */
848 xmlSchemaIDCMatcherPtr nextCached; /* next in the cache list */
849 xmlSchemaIDCAugPtr aidc; /* the augmented IDC item */
850 int idcType;
851 xmlSchemaPSVIIDCKeyPtr **keySeqs; /* the key-sequences of the target
852 elements */
853 int sizeKeySeqs;
854 xmlSchemaItemListPtr targets; /* list of target-node
855 (xmlSchemaPSVIIDCNodePtr) entries */
856 xmlHashTablePtr htab;
857};
858
859/*
860* Element info flags.
861*/
862#define XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES 1<<0
863#define XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES 1<<1
864#define XML_SCHEMA_ELEM_INFO_NILLED 1<<2
865#define XML_SCHEMA_ELEM_INFO_LOCAL_TYPE 1<<3
866
867#define XML_SCHEMA_NODE_INFO_VALUE_NEEDED 1<<4
868#define XML_SCHEMA_ELEM_INFO_EMPTY 1<<5
869#define XML_SCHEMA_ELEM_INFO_HAS_CONTENT 1<<6
870
871#define XML_SCHEMA_ELEM_INFO_HAS_ELEM_CONTENT 1<<7
872#define XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT 1<<8
873#define XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED 1<<9
874#define XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE 1<<10
875
881struct _xmlSchemaNodeInfo {
882 int nodeType;
883 xmlNodePtr node;
884 int nodeLine;
885 const xmlChar *localName;
886 const xmlChar *nsName;
887 const xmlChar *value;
888 xmlSchemaValPtr val; /* the pre-computed value if any */
889 xmlSchemaTypePtr typeDef; /* the complex/simple type definition if any */
890
891 int flags; /* combination of node info flags */
892
893 int valNeeded;
894 int normVal;
895
896 xmlSchemaElementPtr decl; /* the element/attribute declaration */
897 int depth;
898 xmlSchemaPSVIIDCBindingPtr idcTable; /* the table of PSVI IDC bindings
899 for the scope element*/
900 xmlSchemaIDCMatcherPtr idcMatchers; /* the IDC matchers for the scope
901 element */
902 xmlRegExecCtxtPtr regexCtxt;
903
904 const xmlChar **nsBindings; /* Namespace bindings on this element */
905 int nbNsBindings;
906 int sizeNsBindings;
907
908 int hasKeyrefs;
909 int appliedXPath; /* Indicates that an XPath has been applied. */
910};
911
912#define XML_SCHEMAS_ATTR_UNKNOWN 1
913#define XML_SCHEMAS_ATTR_ASSESSED 2
914#define XML_SCHEMAS_ATTR_PROHIBITED 3
915#define XML_SCHEMAS_ATTR_ERR_MISSING 4
916#define XML_SCHEMAS_ATTR_INVALID_VALUE 5
917#define XML_SCHEMAS_ATTR_ERR_NO_TYPE 6
918#define XML_SCHEMAS_ATTR_ERR_FIXED_VALUE 7
919#define XML_SCHEMAS_ATTR_DEFAULT 8
920#define XML_SCHEMAS_ATTR_VALIDATE_VALUE 9
921#define XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL 10
922#define XML_SCHEMAS_ATTR_HAS_ATTR_USE 11
923#define XML_SCHEMAS_ATTR_HAS_ATTR_DECL 12
924#define XML_SCHEMAS_ATTR_WILD_SKIP 13
925#define XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL 14
926#define XML_SCHEMAS_ATTR_ERR_WILD_DUPLICATE_ID 15
927#define XML_SCHEMAS_ATTR_ERR_WILD_AND_USE_ID 16
928#define XML_SCHEMAS_ATTR_META 17
929/*
930* @metaType values of xmlSchemaAttrInfo.
931*/
932#define XML_SCHEMA_ATTR_INFO_META_XSI_TYPE 1
933#define XML_SCHEMA_ATTR_INFO_META_XSI_NIL 2
934#define XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC 3
935#define XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC 4
936#define XML_SCHEMA_ATTR_INFO_META_XMLNS 5
937
938typedef struct _xmlSchemaAttrInfo xmlSchemaAttrInfo;
939typedef xmlSchemaAttrInfo *xmlSchemaAttrInfoPtr;
940struct _xmlSchemaAttrInfo {
941 int nodeType;
942 xmlNodePtr node;
943 int nodeLine;
944 const xmlChar *localName;
945 const xmlChar *nsName;
946 const xmlChar *value;
947 xmlSchemaValPtr val; /* the pre-computed value if any */
948 xmlSchemaTypePtr typeDef; /* the complex/simple type definition if any */
949 int flags; /* combination of node info flags */
950
951 xmlSchemaAttributePtr decl; /* the attribute declaration */
952 xmlSchemaAttributeUsePtr use; /* the attribute use */
953 int state;
954 int metaType;
955 const xmlChar *vcValue; /* the value constraint value */
956 xmlSchemaNodeInfoPtr parent;
957};
958
959
960#define XML_SCHEMA_VALID_CTXT_FLAG_STREAM 1
966struct _xmlSchemaValidCtxt {
967 int type;
968 void *errCtxt; /* user specific data block */
969 xmlSchemaValidityErrorFunc error; /* the callback in case of errors */
970 xmlSchemaValidityWarningFunc warning; /* the callback in case of warning */
972
973 xmlSchemaPtr schema; /* The schema in use */
974 xmlDocPtr doc;
975 xmlParserInputBufferPtr input;
976 xmlCharEncoding enc;
977 xmlSAXHandlerPtr sax;
978 xmlParserCtxtPtr parserCtxt;
979 void *user_data; /* TODO: What is this for? */
980 char *filename;
981
982 int err;
983 int nberrors;
984
985 xmlNodePtr node;
986 xmlNodePtr cur;
987 /* xmlSchemaTypePtr type; */
988
989 xmlRegExecCtxtPtr regexp;
990 xmlSchemaValPtr value;
991
992 int valueWS;
993 int options;
994 xmlNodePtr validationRoot;
995 xmlSchemaParserCtxtPtr pctxt;
996 int xsiAssemble;
997
998 int depth;
999 xmlSchemaNodeInfoPtr *elemInfos; /* array of element information */
1000 int sizeElemInfos;
1001 xmlSchemaNodeInfoPtr inode; /* the current element information */
1002
1003 xmlSchemaIDCAugPtr aidcs; /* a list of augmented IDC information */
1004
1005 xmlSchemaIDCStateObjPtr xpathStates; /* first active state object. */
1006 xmlSchemaIDCStateObjPtr xpathStatePool; /* first stored state object. */
1007 xmlSchemaIDCMatcherPtr idcMatcherCache; /* Cache for IDC matcher objects. */
1008
1009 xmlSchemaPSVIIDCNodePtr *idcNodes; /* list of all IDC node-table entries*/
1010 int nbIdcNodes;
1011 int sizeIdcNodes;
1012
1013 xmlSchemaPSVIIDCKeyPtr *idcKeys; /* list of all IDC node-table entries */
1014 int nbIdcKeys;
1015 int sizeIdcKeys;
1016
1017 int flags;
1018
1019 xmlDictPtr dict;
1020
1021#ifdef LIBXML_READER_ENABLED
1022 xmlTextReaderPtr reader;
1023#endif
1024
1025 xmlSchemaAttrInfoPtr *attrInfos;
1026 int nbAttrInfos;
1027 int sizeAttrInfos;
1028
1029 int skipDepth;
1030 xmlSchemaItemListPtr nodeQNames;
1031 int hasKeyrefs;
1032 int createIDCNodeTables;
1033 int psviExposeIDCNodeTables;
1034
1035 /* Locator for error reporting in streaming mode */
1036 xmlSchemaValidityLocatorFunc locFunc;
1037 void *locCtxt;
1038};
1039
1045typedef struct _xmlSchemaSubstGroup xmlSchemaSubstGroup;
1046typedef xmlSchemaSubstGroup *xmlSchemaSubstGroupPtr;
1047struct _xmlSchemaSubstGroup {
1048 xmlSchemaElementPtr head;
1049 xmlSchemaItemListPtr members;
1050};
1051
1057typedef struct _xmlIDCHashEntry xmlIDCHashEntry;
1058typedef xmlIDCHashEntry *xmlIDCHashEntryPtr;
1059struct _xmlIDCHashEntry {
1060 xmlIDCHashEntryPtr next; /* next item with same hash */
1061 int index; /* index into associated item list */
1062};
1063
1064/************************************************************************
1065 * *
1066 * Some predeclarations *
1067 * *
1068 ************************************************************************/
1069
1070static int xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt,
1071 xmlSchemaPtr schema,
1072 xmlNodePtr node);
1073static int xmlSchemaParseRedefine(xmlSchemaParserCtxtPtr ctxt,
1074 xmlSchemaPtr schema,
1075 xmlNodePtr node);
1076static int
1077xmlSchemaTypeFixup(xmlSchemaTypePtr type,
1078 xmlSchemaAbstractCtxtPtr ctxt);
1079static const xmlChar *
1080xmlSchemaFacetTypeToString(xmlSchemaTypeType type);
1081static int
1082xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1083 xmlNodePtr node);
1084static int
1085xmlSchemaCheckFacetValues(xmlSchemaTypePtr typeDecl,
1086 xmlSchemaParserCtxtPtr ctxt);
1087static void
1088xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt);
1089static xmlSchemaWhitespaceValueType
1090xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type);
1091static xmlSchemaTreeItemPtr
1092xmlSchemaParseModelGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1093 xmlNodePtr node, xmlSchemaTypeType type,
1094 int withParticle);
1095static const xmlChar *
1096xmlSchemaGetComponentTypeStr(xmlSchemaBasicItemPtr item);
1097static xmlSchemaTypeLinkPtr
1098xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type);
1099static void
1100xmlSchemaInternalErr(xmlSchemaAbstractCtxtPtr actxt,
1101 const char *funcName,
1102 const char *message) LIBXML_ATTR_FORMAT(3,0);
1103static int
1104xmlSchemaCheckCOSSTDerivedOK(xmlSchemaAbstractCtxtPtr ctxt,
1105 xmlSchemaTypePtr type,
1106 xmlSchemaTypePtr baseType,
1107 int subset);
1108static void
1109xmlSchemaCheckElementDeclComponent(xmlSchemaElementPtr elemDecl,
1110 xmlSchemaParserCtxtPtr ctxt);
1111static void
1112xmlSchemaComponentListFree(xmlSchemaItemListPtr list);
1113static xmlSchemaQNameRefPtr
1114xmlSchemaParseAttributeGroupRef(xmlSchemaParserCtxtPtr pctxt,
1115 xmlSchemaPtr schema,
1116 xmlNodePtr node);
1117
1118/************************************************************************
1119 * *
1120 * Helper functions *
1121 * *
1122 ************************************************************************/
1123
1130static const xmlChar *
1131xmlSchemaItemTypeToStr(xmlSchemaTypeType type)
1132{
1133 switch (type) {
1134 case XML_SCHEMA_TYPE_BASIC:
1135 return(BAD_CAST "simple type definition");
1136 case XML_SCHEMA_TYPE_SIMPLE:
1137 return(BAD_CAST "simple type definition");
1138 case XML_SCHEMA_TYPE_COMPLEX:
1139 return(BAD_CAST "complex type definition");
1140 case XML_SCHEMA_TYPE_ELEMENT:
1141 return(BAD_CAST "element declaration");
1142 case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
1143 return(BAD_CAST "attribute use");
1144 case XML_SCHEMA_TYPE_ATTRIBUTE:
1145 return(BAD_CAST "attribute declaration");
1146 case XML_SCHEMA_TYPE_GROUP:
1147 return(BAD_CAST "model group definition");
1148 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1149 return(BAD_CAST "attribute group definition");
1150 case XML_SCHEMA_TYPE_NOTATION:
1151 return(BAD_CAST "notation declaration");
1152 case XML_SCHEMA_TYPE_SEQUENCE:
1153 return(BAD_CAST "model group (sequence)");
1154 case XML_SCHEMA_TYPE_CHOICE:
1155 return(BAD_CAST "model group (choice)");
1156 case XML_SCHEMA_TYPE_ALL:
1157 return(BAD_CAST "model group (all)");
1158 case XML_SCHEMA_TYPE_PARTICLE:
1159 return(BAD_CAST "particle");
1160 case XML_SCHEMA_TYPE_IDC_UNIQUE:
1161 return(BAD_CAST "unique identity-constraint");
1162 /* return(BAD_CAST "IDC (unique)"); */
1163 case XML_SCHEMA_TYPE_IDC_KEY:
1164 return(BAD_CAST "key identity-constraint");
1165 /* return(BAD_CAST "IDC (key)"); */
1166 case XML_SCHEMA_TYPE_IDC_KEYREF:
1167 return(BAD_CAST "keyref identity-constraint");
1168 /* return(BAD_CAST "IDC (keyref)"); */
1169 case XML_SCHEMA_TYPE_ANY:
1170 return(BAD_CAST "wildcard (any)");
1171 case XML_SCHEMA_EXTRA_QNAMEREF:
1172 return(BAD_CAST "[helper component] QName reference");
1173 case XML_SCHEMA_EXTRA_ATTR_USE_PROHIB:
1174 return(BAD_CAST "[helper component] attribute use prohibition");
1175 default:
1176 return(BAD_CAST "Not a schema component");
1177 }
1178}
1179
1186static const xmlChar *
1187xmlSchemaGetComponentTypeStr(xmlSchemaBasicItemPtr item)
1188{
1189 switch (item->type) {
1190 case XML_SCHEMA_TYPE_BASIC:
1191 if (WXS_IS_COMPLEX(WXS_TYPE_CAST item))
1192 return(BAD_CAST "complex type definition");
1193 else
1194 return(BAD_CAST "simple type definition");
1195 default:
1196 return(xmlSchemaItemTypeToStr(item->type));
1197 }
1198}
1199
1210static xmlNodePtr
1211xmlSchemaGetComponentNode(xmlSchemaBasicItemPtr item)
1212{
1213 switch (item->type) {
1214 case XML_SCHEMA_TYPE_ELEMENT:
1215 return (((xmlSchemaElementPtr) item)->node);
1216 case XML_SCHEMA_TYPE_ATTRIBUTE:
1217 return (((xmlSchemaAttributePtr) item)->node);
1218 case XML_SCHEMA_TYPE_COMPLEX:
1219 case XML_SCHEMA_TYPE_SIMPLE:
1220 return (((xmlSchemaTypePtr) item)->node);
1221 case XML_SCHEMA_TYPE_ANY:
1222 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
1223 return (((xmlSchemaWildcardPtr) item)->node);
1224 case XML_SCHEMA_TYPE_PARTICLE:
1225 return (((xmlSchemaParticlePtr) item)->node);
1226 case XML_SCHEMA_TYPE_SEQUENCE:
1227 case XML_SCHEMA_TYPE_CHOICE:
1228 case XML_SCHEMA_TYPE_ALL:
1229 return (((xmlSchemaModelGroupPtr) item)->node);
1230 case XML_SCHEMA_TYPE_GROUP:
1231 return (((xmlSchemaModelGroupDefPtr) item)->node);
1232 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1233 return (((xmlSchemaAttributeGroupPtr) item)->node);
1234 case XML_SCHEMA_TYPE_IDC_UNIQUE:
1235 case XML_SCHEMA_TYPE_IDC_KEY:
1236 case XML_SCHEMA_TYPE_IDC_KEYREF:
1237 return (((xmlSchemaIDCPtr) item)->node);
1238 case XML_SCHEMA_EXTRA_QNAMEREF:
1239 return(((xmlSchemaQNameRefPtr) item)->node);
1240 /* TODO: What to do with NOTATIONs?
1241 case XML_SCHEMA_TYPE_NOTATION:
1242 return (((xmlSchemaNotationPtr) item)->node);
1243 */
1244 case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
1245 return (((xmlSchemaAttributeUsePtr) item)->node);
1246 default:
1247 return (NULL);
1248 }
1249}
1250
1251#if 0
1258static xmlSchemaBasicItemPtr
1259xmlSchemaGetNextComponent(xmlSchemaBasicItemPtr item)
1260{
1261 switch (item->type) {
1262 case XML_SCHEMA_TYPE_ELEMENT:
1263 return ((xmlSchemaBasicItemPtr) ((xmlSchemaElementPtr) item)->next);
1264 case XML_SCHEMA_TYPE_ATTRIBUTE:
1265 return ((xmlSchemaBasicItemPtr) ((xmlSchemaAttributePtr) item)->next);
1266 case XML_SCHEMA_TYPE_COMPLEX:
1267 case XML_SCHEMA_TYPE_SIMPLE:
1268 return ((xmlSchemaBasicItemPtr) ((xmlSchemaTypePtr) item)->next);
1269 case XML_SCHEMA_TYPE_ANY:
1270 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
1271 return (NULL);
1272 case XML_SCHEMA_TYPE_PARTICLE:
1273 return ((xmlSchemaBasicItemPtr) ((xmlSchemaParticlePtr) item)->next);
1274 case XML_SCHEMA_TYPE_SEQUENCE:
1275 case XML_SCHEMA_TYPE_CHOICE:
1276 case XML_SCHEMA_TYPE_ALL:
1277 return (NULL);
1278 case XML_SCHEMA_TYPE_GROUP:
1279 return (NULL);
1280 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1281 return ((xmlSchemaBasicItemPtr) ((xmlSchemaAttributeGroupPtr) item)->next);
1282 case XML_SCHEMA_TYPE_IDC_UNIQUE:
1283 case XML_SCHEMA_TYPE_IDC_KEY:
1284 case XML_SCHEMA_TYPE_IDC_KEYREF:
1285 return ((xmlSchemaBasicItemPtr) ((xmlSchemaIDCPtr) item)->next);
1286 default:
1287 return (NULL);
1288 }
1289}
1290#endif
1291
1292
1305static const xmlChar*
1306xmlSchemaFormatQName(xmlChar **buf,
1307 const xmlChar *namespaceName,
1308 const xmlChar *localName)
1309{
1310 FREE_AND_NULL(*buf)
1311 if (namespaceName != NULL) {
1312 *buf = xmlStrdup(BAD_CAST "{");
1313 *buf = xmlStrcat(*buf, namespaceName);
1314 *buf = xmlStrcat(*buf, BAD_CAST "}");
1315 }
1316 if (localName != NULL) {
1317 if (namespaceName == NULL)
1318 return(localName);
1319 *buf = xmlStrcat(*buf, localName);
1320 } else {
1321 *buf = xmlStrcat(*buf, BAD_CAST "(NULL)");
1322 }
1323 return ((const xmlChar *) *buf);
1324}
1325
1326static const xmlChar*
1327xmlSchemaFormatQNameNs(xmlChar **buf, xmlNsPtr ns, const xmlChar *localName)
1328{
1329 if (ns != NULL)
1330 return (xmlSchemaFormatQName(buf, ns->href, localName));
1331 else
1332 return (xmlSchemaFormatQName(buf, NULL, localName));
1333}
1334
1335static const xmlChar *
1336xmlSchemaGetComponentName(xmlSchemaBasicItemPtr item)
1337{
1338 if (item == NULL) {
1339 return (NULL);
1340 }
1341 switch (item->type) {
1342 case XML_SCHEMA_TYPE_ELEMENT:
1343 return (((xmlSchemaElementPtr) item)->name);
1344 case XML_SCHEMA_TYPE_ATTRIBUTE:
1345 return (((xmlSchemaAttributePtr) item)->name);
1346 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1347 return (((xmlSchemaAttributeGroupPtr) item)->name);
1348 case XML_SCHEMA_TYPE_BASIC:
1349 case XML_SCHEMA_TYPE_SIMPLE:
1350 case XML_SCHEMA_TYPE_COMPLEX:
1351 return (((xmlSchemaTypePtr) item)->name);
1352 case XML_SCHEMA_TYPE_GROUP:
1353 return (((xmlSchemaModelGroupDefPtr) item)->name);
1354 case XML_SCHEMA_TYPE_IDC_KEY:
1355 case XML_SCHEMA_TYPE_IDC_UNIQUE:
1356 case XML_SCHEMA_TYPE_IDC_KEYREF:
1357 return (((xmlSchemaIDCPtr) item)->name);
1358 case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
1359 if (WXS_ATTRUSE_DECL(item) != NULL) {
1360 return(xmlSchemaGetComponentName(
1361 WXS_BASIC_CAST WXS_ATTRUSE_DECL(item)));
1362 } else
1363 return(NULL);
1364 case XML_SCHEMA_EXTRA_QNAMEREF:
1365 return (((xmlSchemaQNameRefPtr) item)->name);
1366 case XML_SCHEMA_TYPE_NOTATION:
1367 return (((xmlSchemaNotationPtr) item)->name);
1368 default:
1369 /*
1370 * Other components cannot have names.
1371 */
1372 break;
1373 }
1374 return (NULL);
1375}
1376
1377#define xmlSchemaGetQNameRefName(r) (WXS_QNAME_CAST (r))->name
1378#define xmlSchemaGetQNameRefTargetNs(r) (WXS_QNAME_CAST (r))->targetNamespace
1379/*
1380static const xmlChar *
1381xmlSchemaGetQNameRefName(void *ref)
1382{
1383 return(((xmlSchemaQNameRefPtr) ref)->name);
1384}
1385
1386static const xmlChar *
1387xmlSchemaGetQNameRefTargetNs(void *ref)
1388{
1389 return(((xmlSchemaQNameRefPtr) ref)->targetNamespace);
1390}
1391*/
1392
1393static const xmlChar *
1394xmlSchemaGetComponentTargetNs(xmlSchemaBasicItemPtr item)
1395{
1396 if (item == NULL) {
1397 return (NULL);
1398 }
1399 switch (item->type) {
1400 case XML_SCHEMA_TYPE_ELEMENT:
1401 return (((xmlSchemaElementPtr) item)->targetNamespace);
1402 case XML_SCHEMA_TYPE_ATTRIBUTE:
1403 return (((xmlSchemaAttributePtr) item)->targetNamespace);
1404 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1405 return (((xmlSchemaAttributeGroupPtr) item)->targetNamespace);
1406 case XML_SCHEMA_TYPE_BASIC:
1407 return (BAD_CAST "http://www.w3.org/2001/XMLSchema");
1408 case XML_SCHEMA_TYPE_SIMPLE:
1409 case XML_SCHEMA_TYPE_COMPLEX:
1410 return (((xmlSchemaTypePtr) item)->targetNamespace);
1411 case XML_SCHEMA_TYPE_GROUP:
1412 return (((xmlSchemaModelGroupDefPtr) item)->targetNamespace);
1413 case XML_SCHEMA_TYPE_IDC_KEY:
1414 case XML_SCHEMA_TYPE_IDC_UNIQUE:
1415 case XML_SCHEMA_TYPE_IDC_KEYREF:
1416 return (((xmlSchemaIDCPtr) item)->targetNamespace);
1417 case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
1418 if (WXS_ATTRUSE_DECL(item) != NULL) {
1419 return(xmlSchemaGetComponentTargetNs(
1420 WXS_BASIC_CAST WXS_ATTRUSE_DECL(item)));
1421 }
1422 /* TODO: Will returning NULL break something? */
1423 break;
1424 case XML_SCHEMA_EXTRA_QNAMEREF:
1425 return (((xmlSchemaQNameRefPtr) item)->targetNamespace);
1426 case XML_SCHEMA_TYPE_NOTATION:
1427 return (((xmlSchemaNotationPtr) item)->targetNamespace);
1428 default:
1429 /*
1430 * Other components cannot have names.
1431 */
1432 break;
1433 }
1434 return (NULL);
1435}
1436
1437static const xmlChar*
1438xmlSchemaGetComponentQName(xmlChar **buf,
1439 void *item)
1440{
1441 return (xmlSchemaFormatQName(buf,
1442 xmlSchemaGetComponentTargetNs((xmlSchemaBasicItemPtr) item),
1443 xmlSchemaGetComponentName((xmlSchemaBasicItemPtr) item)));
1444}
1445
1446static const xmlChar*
1447xmlSchemaGetComponentDesignation(xmlChar **buf, void *item)
1448{
1449 xmlChar *str = NULL;
1450
1451 *buf = xmlStrcat(*buf, WXS_ITEM_TYPE_NAME(item));
1452 *buf = xmlStrcat(*buf, BAD_CAST " '");
1453 *buf = xmlStrcat(*buf, xmlSchemaGetComponentQName(&str,
1454 (xmlSchemaBasicItemPtr) item));
1455 *buf = xmlStrcat(*buf, BAD_CAST "'");
1456 FREE_AND_NULL(str);
1457 return(*buf);
1458}
1459
1460static const xmlChar*
1461xmlSchemaGetIDCDesignation(xmlChar **buf, xmlSchemaIDCPtr idc)
1462{
1463 return(xmlSchemaGetComponentDesignation(buf, idc));
1464}
1465
1473static const xmlChar *
1474xmlSchemaWildcardPCToString(int pc)
1475{
1476 switch (pc) {
1477 case XML_SCHEMAS_ANY_SKIP:
1478 return (BAD_CAST "skip");
1479 case XML_SCHEMAS_ANY_LAX:
1480 return (BAD_CAST "lax");
1481 case XML_SCHEMAS_ANY_STRICT:
1482 return (BAD_CAST "strict");
1483 default:
1484 return (BAD_CAST "invalid process contents");
1485 }
1486}
1487
1501static int
1502xmlSchemaGetCanonValueWhtspExt_1(xmlSchemaValPtr val,
1503 xmlSchemaWhitespaceValueType ws,
1504 xmlChar **retValue,
1505 int for_hash)
1506{
1507 int list;
1508 xmlSchemaValType valType;
1509 const xmlChar *value, *value2 = NULL;
1510
1511
1512 if ((retValue == NULL) || (val == NULL))
1513 return (-1);
1514 list = xmlSchemaValueGetNext(val) ? 1 : 0;
1515 *retValue = NULL;
1516 do {
1517 value = NULL;
1518 valType = xmlSchemaGetValType(val);
1519 switch (valType) {
1520 case XML_SCHEMAS_STRING:
1521 case XML_SCHEMAS_NORMSTRING:
1522 case XML_SCHEMAS_ANYSIMPLETYPE:
1523 value = xmlSchemaValueGetAsString(val);
1524 if (value != NULL) {
1525 if (ws == XML_SCHEMA_WHITESPACE_COLLAPSE)
1526 value2 = xmlSchemaCollapseString(value);
1527 else if (ws == XML_SCHEMA_WHITESPACE_REPLACE)
1528 value2 = xmlSchemaWhiteSpaceReplace(value);
1529 if (value2 != NULL)
1530 value = value2;
1531 }
1532 break;
1533 default:
1534 if (xmlSchemaGetCanonValue(val, &value2) == -1) {
1535 if (value2 != NULL)
1536 xmlFree((xmlChar *) value2);
1537 goto internal_error;
1538 }
1539 if (for_hash && valType == XML_SCHEMAS_DECIMAL) {
1540 /* We can mostly use the canonical value for hashing,
1541 except in the case of decimal. There the canonical
1542 representation requires a trailing '.0' even for
1543 non-fractional numbers, but for the derived integer
1544 types it forbids any decimal point. Nevertheless they
1545 compare equal if the value is equal. We need to generate
1546 the same hash value for this to work, and it's easiest
1547 to just cut off the useless '.0' suffix for the
1548 decimal type. */
1549 int len = xmlStrlen(value2);
1550 if (len > 2 && value2[len-1] == '0' && value2[len-2] == '.')
1551 ((xmlChar*)value2)[len-2] = 0;
1552 }
1553 value = value2;
1554 }
1555 if (*retValue == NULL)
1556 if (value == NULL) {
1557 if (! list)
1558 *retValue = xmlStrdup(BAD_CAST "");
1559 } else
1560 *retValue = xmlStrdup(value);
1561 else if (value != NULL) {
1562 /* List. */
1563 *retValue = xmlStrcat((xmlChar *) *retValue, BAD_CAST " ");
1564 *retValue = xmlStrcat((xmlChar *) *retValue, value);
1565 }
1566 FREE_AND_NULL(value2)
1567 val = xmlSchemaValueGetNext(val);
1568 } while (val != NULL);
1569
1570 return (0);
1571internal_error:
1572 if (*retValue != NULL)
1573 xmlFree((xmlChar *) (*retValue));
1574 if (value2 != NULL)
1575 xmlFree((xmlChar *) value2);
1576 return (-1);
1577}
1578
1579static int
1580xmlSchemaGetCanonValueWhtspExt(xmlSchemaValPtr val,
1581 xmlSchemaWhitespaceValueType ws,
1582 xmlChar **retValue)
1583{
1584 return xmlSchemaGetCanonValueWhtspExt_1(val, ws, retValue, 0);
1585}
1586
1587static int
1588xmlSchemaGetCanonValueHash(xmlSchemaValPtr val,
1589 xmlChar **retValue)
1590{
1591 return xmlSchemaGetCanonValueWhtspExt_1(val, XML_SCHEMA_WHITESPACE_COLLAPSE,
1592 retValue, 1);
1593}
1594
1621static xmlChar*
1622xmlSchemaFormatItemForReport(xmlChar **buf,
1623 const xmlChar *itemDes,
1624 xmlSchemaBasicItemPtr item,
1625 xmlNodePtr itemNode)
1626{
1627 xmlChar *str = NULL;
1628 int named = 1;
1629
1630 if (*buf != NULL) {
1631 xmlFree(*buf);
1632 *buf = NULL;
1633 }
1634
1635 if (itemDes != NULL) {
1636 *buf = xmlStrdup(itemDes);
1637 } else if (item != NULL) {
1638 switch (item->type) {
1639 case XML_SCHEMA_TYPE_BASIC: {
1640 xmlSchemaTypePtr type = WXS_TYPE_CAST item;
1641
1642 if (WXS_IS_ATOMIC(type))
1643 *buf = xmlStrdup(BAD_CAST "atomic type 'xs:");
1644 else if (WXS_IS_LIST(type))
1645 *buf = xmlStrdup(BAD_CAST "list type 'xs:");
1646 else if (WXS_IS_UNION(type))
1647 *buf = xmlStrdup(BAD_CAST "union type 'xs:");
1648 else
1649 *buf = xmlStrdup(BAD_CAST "simple type 'xs:");
1650 *buf = xmlStrcat(*buf, type->name);
1651 *buf = xmlStrcat(*buf, BAD_CAST "'");
1652 }
1653 break;
1654 case XML_SCHEMA_TYPE_SIMPLE: {
1655 xmlSchemaTypePtr type = WXS_TYPE_CAST item;
1656
1657 if (type->flags & XML_SCHEMAS_TYPE_GLOBAL) {
1658 *buf = xmlStrdup(BAD_CAST"");
1659 } else {
1660 *buf = xmlStrdup(BAD_CAST "local ");
1661 }
1662 if (WXS_IS_ATOMIC(type))
1663 *buf = xmlStrcat(*buf, BAD_CAST "atomic type");
1664 else if (WXS_IS_LIST(type))
1665 *buf = xmlStrcat(*buf, BAD_CAST "list type");
1666 else if (WXS_IS_UNION(type))
1667 *buf = xmlStrcat(*buf, BAD_CAST "union type");
1668 else
1669 *buf = xmlStrcat(*buf, BAD_CAST "simple type");
1670 if (type->flags & XML_SCHEMAS_TYPE_GLOBAL) {
1671 *buf = xmlStrcat(*buf, BAD_CAST " '");
1672 *buf = xmlStrcat(*buf, type->name);
1673 *buf = xmlStrcat(*buf, BAD_CAST "'");
1674 }
1675 }
1676 break;
1677 case XML_SCHEMA_TYPE_COMPLEX: {
1678 xmlSchemaTypePtr type = WXS_TYPE_CAST item;
1679
1680 if (type->flags & XML_SCHEMAS_TYPE_GLOBAL)
1681 *buf = xmlStrdup(BAD_CAST "");
1682 else
1683 *buf = xmlStrdup(BAD_CAST "local ");
1684 *buf = xmlStrcat(*buf, BAD_CAST "complex type");
1685 if (type->flags & XML_SCHEMAS_TYPE_GLOBAL) {
1686 *buf = xmlStrcat(*buf, BAD_CAST " '");
1687 *buf = xmlStrcat(*buf, type->name);
1688 *buf = xmlStrcat(*buf, BAD_CAST "'");
1689 }
1690 }
1691 break;
1692 case XML_SCHEMA_TYPE_ATTRIBUTE_USE: {
1693 xmlSchemaAttributeUsePtr ause;
1694
1695 ause = WXS_ATTR_USE_CAST item;
1696 *buf = xmlStrdup(BAD_CAST "attribute use ");
1697 if (WXS_ATTRUSE_DECL(ause) != NULL) {
1698 *buf = xmlStrcat(*buf, BAD_CAST "'");
1699 *buf = xmlStrcat(*buf,
1700 xmlSchemaGetComponentQName(&str, WXS_ATTRUSE_DECL(ause)));
1701 FREE_AND_NULL(str)
1702 *buf = xmlStrcat(*buf, BAD_CAST "'");
1703 } else {
1704 *buf = xmlStrcat(*buf, BAD_CAST "(unknown)");
1705 }
1706 }
1707 break;
1708 case XML_SCHEMA_TYPE_ATTRIBUTE: {
1709 xmlSchemaAttributePtr attr;
1710
1711 attr = (xmlSchemaAttributePtr) item;
1712 *buf = xmlStrdup(BAD_CAST "attribute decl.");
1713 *buf = xmlStrcat(*buf, BAD_CAST " '");
1714 *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1715 attr->targetNamespace, attr->name));
1716 FREE_AND_NULL(str)
1717 *buf = xmlStrcat(*buf, BAD_CAST "'");
1718 }
1719 break;
1720 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1721 xmlSchemaGetComponentDesignation(buf, item);
1722 break;
1723 case XML_SCHEMA_TYPE_ELEMENT: {
1724 xmlSchemaElementPtr elem;
1725
1726 elem = (xmlSchemaElementPtr) item;
1727 *buf = xmlStrdup(BAD_CAST "element decl.");
1728 *buf = xmlStrcat(*buf, BAD_CAST " '");
1729 *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1730 elem->targetNamespace, elem->name));
1731 *buf = xmlStrcat(*buf, BAD_CAST "'");
1732 }
1733 break;
1734 case XML_SCHEMA_TYPE_IDC_UNIQUE:
1735 case XML_SCHEMA_TYPE_IDC_KEY:
1736 case XML_SCHEMA_TYPE_IDC_KEYREF:
1737 if (item->type == XML_SCHEMA_TYPE_IDC_UNIQUE)
1738 *buf = xmlStrdup(BAD_CAST "unique '");
1739 else if (item->type == XML_SCHEMA_TYPE_IDC_KEY)
1740 *buf = xmlStrdup(BAD_CAST "key '");
1741 else
1742 *buf = xmlStrdup(BAD_CAST "keyRef '");
1743 *buf = xmlStrcat(*buf, ((xmlSchemaIDCPtr) item)->name);
1744 *buf = xmlStrcat(*buf, BAD_CAST "'");
1745 break;
1746 case XML_SCHEMA_TYPE_ANY:
1747 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
1748 *buf = xmlStrdup(xmlSchemaWildcardPCToString(
1749 ((xmlSchemaWildcardPtr) item)->processContents));
1750 *buf = xmlStrcat(*buf, BAD_CAST " wildcard");
1751 break;
1752 case XML_SCHEMA_FACET_MININCLUSIVE:
1753 case XML_SCHEMA_FACET_MINEXCLUSIVE:
1754 case XML_SCHEMA_FACET_MAXINCLUSIVE:
1755 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
1756 case XML_SCHEMA_FACET_TOTALDIGITS:
1757 case XML_SCHEMA_FACET_FRACTIONDIGITS:
1758 case XML_SCHEMA_FACET_PATTERN:
1759 case XML_SCHEMA_FACET_ENUMERATION:
1760 case XML_SCHEMA_FACET_WHITESPACE:
1761 case XML_SCHEMA_FACET_LENGTH:
1762 case XML_SCHEMA_FACET_MAXLENGTH:
1763 case XML_SCHEMA_FACET_MINLENGTH:
1764 *buf = xmlStrdup(BAD_CAST "facet '");
1765 *buf = xmlStrcat(*buf, xmlSchemaFacetTypeToString(item->type));
1766 *buf = xmlStrcat(*buf, BAD_CAST "'");
1767 break;
1768 case XML_SCHEMA_TYPE_GROUP: {
1769 *buf = xmlStrdup(BAD_CAST "model group def.");
1770 *buf = xmlStrcat(*buf, BAD_CAST " '");
1771 *buf = xmlStrcat(*buf, xmlSchemaGetComponentQName(&str, item));
1772 *buf = xmlStrcat(*buf, BAD_CAST "'");
1773 FREE_AND_NULL(str)
1774 }
1775 break;
1776 case XML_SCHEMA_TYPE_SEQUENCE:
1777 case XML_SCHEMA_TYPE_CHOICE:
1778 case XML_SCHEMA_TYPE_ALL:
1779 case XML_SCHEMA_TYPE_PARTICLE:
1780 *buf = xmlStrdup(WXS_ITEM_TYPE_NAME(item));
1781 break;
1782 case XML_SCHEMA_TYPE_NOTATION: {
1783 *buf = xmlStrdup(WXS_ITEM_TYPE_NAME(item));
1784 *buf = xmlStrcat(*buf, BAD_CAST " '");
1785 *buf = xmlStrcat(*buf, xmlSchemaGetComponentQName(&str, item));
1786 *buf = xmlStrcat(*buf, BAD_CAST "'");
1787 FREE_AND_NULL(str);
1788 }
1789 /* Falls through. */
1790 default:
1791 named = 0;
1792 }
1793 } else
1794 named = 0;
1795
1796 if ((named == 0) && (itemNode != NULL)) {
1797 xmlNodePtr elem;
1798
1799 if (itemNode->type == XML_ATTRIBUTE_NODE)
1800 elem = itemNode->parent;
1801 else
1802 elem = itemNode;
1803 *buf = xmlStrdup(BAD_CAST "Element '");
1804 if (elem->ns != NULL) {
1805 *buf = xmlStrcat(*buf,
1806 xmlSchemaFormatQName(&str, elem->ns->href, elem->name));
1807 FREE_AND_NULL(str)
1808 } else
1809 *buf = xmlStrcat(*buf, elem->name);
1810 *buf = xmlStrcat(*buf, BAD_CAST "'");
1811
1812 }
1813 if ((itemNode != NULL) && (itemNode->type == XML_ATTRIBUTE_NODE)) {
1814 *buf = xmlStrcat(*buf, BAD_CAST ", attribute '");
1815 if (itemNode->ns != NULL) {
1816 *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1817 itemNode->ns->href, itemNode->name));
1818 FREE_AND_NULL(str)
1819 } else
1820 *buf = xmlStrcat(*buf, itemNode->name);
1821 *buf = xmlStrcat(*buf, BAD_CAST "'");
1822 }
1823 FREE_AND_NULL(str)
1824
1825 return (xmlEscapeFormatString(buf));
1826}
1827
1837static const xmlChar *
1838xmlSchemaFormatFacetEnumSet(xmlSchemaAbstractCtxtPtr actxt,
1839 xmlChar **buf, xmlSchemaTypePtr type)
1840{
1841 xmlSchemaFacetPtr facet;
1842 xmlSchemaWhitespaceValueType ws;
1843 xmlChar *value = NULL;
1844 int res, found = 0;
1845
1846 if (*buf != NULL)
1847 xmlFree(*buf);
1848 *buf = NULL;
1849
1850 do {
1851 /*
1852 * Use the whitespace type of the base type.
1853 */
1854 ws = xmlSchemaGetWhiteSpaceFacetValue(type->baseType);
1855 for (facet = type->facets; facet != NULL; facet = facet->next) {
1856 if (facet->type != XML_SCHEMA_FACET_ENUMERATION)
1857 continue;
1858 found = 1;
1859 res = xmlSchemaGetCanonValueWhtspExt(facet->val,
1860 ws, &value);
1861 if (res == -1) {
1862 xmlSchemaInternalErr(actxt,
1863 "xmlSchemaFormatFacetEnumSet",
1864 "compute the canonical lexical representation");
1865 if (*buf != NULL)
1866 xmlFree(*buf);
1867 *buf = NULL;
1868 return (NULL);
1869 }
1870 if (*buf == NULL)
1871 *buf = xmlStrdup(BAD_CAST "'");
1872 else
1873 *buf = xmlStrcat(*buf, BAD_CAST ", '");
1875 *buf = xmlStrcat(*buf, BAD_CAST "'");
1876 if (value != NULL) {
1877 xmlFree((xmlChar *)value);
1878 value = NULL;
1879 }
1880 }
1881 /*
1882 * The enumeration facet of a type restricts the enumeration
1883 * facet of the ancestor type; i.e., such restricted enumerations
1884 * do not belong to the set of the given type. Thus we break
1885 * on the first found enumeration.
1886 */
1887 if (found)
1888 break;
1889 type = type->baseType;
1890 } while ((type != NULL) && (type->type != XML_SCHEMA_TYPE_BASIC));
1891
1892 return ((const xmlChar *) *buf);
1893}
1894
1895/************************************************************************
1896 * *
1897 * Error functions *
1898 * *
1899 ************************************************************************/
1900
1901#if 0
1902static void
1903xmlSchemaErrMemory(const char *msg)
1904{
1906 msg);
1907}
1908#endif
1909
1910static void
1911xmlSchemaPSimpleErr(const char *msg)
1912{
1914 msg);
1915}
1916
1924static void
1925xmlSchemaPErrMemory(xmlSchemaParserCtxtPtr ctxt,
1926 const char *extra, xmlNodePtr node)
1927{
1928 if (ctxt != NULL)
1929 ctxt->nberrors++;
1931 extra);
1932}
1933
1945static void LIBXML_ATTR_FORMAT(4,0)
1946xmlSchemaPErr(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
1948{
1949 xmlGenericErrorFunc channel = NULL;
1950 xmlStructuredErrorFunc schannel = NULL;
1951 void *data = NULL;
1952
1953 if (ctxt != NULL) {
1954 ctxt->nberrors++;
1955 ctxt->err = error;
1956 channel = ctxt->error;
1957 data = ctxt->errCtxt;
1958 schannel = ctxt->serror;
1959 }
1960 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
1962 (const char *) str1, (const char *) str2, NULL, 0, 0,
1963 msg, str1, str2);
1964}
1965
1978static void LIBXML_ATTR_FORMAT(5,0)
1979xmlSchemaPErr2(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
1980 xmlNodePtr child, int error,
1982{
1983 if (child != NULL)
1984 xmlSchemaPErr(ctxt, child, error, msg, str1, str2);
1985 else
1986 xmlSchemaPErr(ctxt, node, error, msg, str1, str2);
1987}
1988
1989
2007static void LIBXML_ATTR_FORMAT(7,0)
2008xmlSchemaPErrExt(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
2009 const xmlChar * strData1, const xmlChar * strData2,
2010 const xmlChar * strData3, const char *msg, const xmlChar * str1,
2011 const xmlChar * str2, const xmlChar * str3, const xmlChar * str4,
2012 const xmlChar * str5)
2013{
2014
2015 xmlGenericErrorFunc channel = NULL;
2016 xmlStructuredErrorFunc schannel = NULL;
2017 void *data = NULL;
2018
2019 if (ctxt != NULL) {
2020 ctxt->nberrors++;
2021 ctxt->err = error;
2022 channel = ctxt->error;
2023 data = ctxt->errCtxt;
2024 schannel = ctxt->serror;
2025 }
2026 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
2028 (const char *) strData1, (const char *) strData2,
2029 (const char *) strData3, 0, 0, msg, str1, str2,
2030 str3, str4, str5);
2031}
2032
2033/************************************************************************
2034 * *
2035 * Allround error functions *
2036 * *
2037 ************************************************************************/
2038
2046static void
2047xmlSchemaVErrMemory(xmlSchemaValidCtxtPtr ctxt,
2048 const char *extra, xmlNodePtr node)
2049{
2050 if (ctxt != NULL) {
2051 ctxt->nberrors++;
2052 ctxt->err = XML_SCHEMAV_INTERNAL;
2053 }
2055 extra);
2056}
2057
2058static void LIBXML_ATTR_FORMAT(2,0)
2059xmlSchemaPSimpleInternalErr(xmlNodePtr node,
2060 const char *msg, const xmlChar *str)
2061{
2063 msg, (const char *) str);
2064}
2065
2066#define WXS_ERROR_TYPE_ERROR 1
2067#define WXS_ERROR_TYPE_WARNING 2
2083static void LIBXML_ATTR_FORMAT(6,0)
2084xmlSchemaErr4Line(xmlSchemaAbstractCtxtPtr ctxt,
2085 xmlErrorLevel errorLevel,
2086 int error, xmlNodePtr node, int line, const char *msg,
2088 const xmlChar *str3, const xmlChar *str4)
2089{
2090 xmlStructuredErrorFunc schannel = NULL;
2091 xmlGenericErrorFunc channel = NULL;
2092 void *data = NULL;
2093
2094 if (ctxt != NULL) {
2095 if (ctxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
2096 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctxt;
2097 const char *file = NULL;
2098 int col = 0;
2099 if (errorLevel != XML_ERR_WARNING) {
2100 vctxt->nberrors++;
2101 vctxt->err = error;
2102 channel = vctxt->error;
2103 } else {
2104 channel = vctxt->warning;
2105 }
2106 schannel = vctxt->serror;
2107 data = vctxt->errCtxt;
2108
2109 /*
2110 * Error node. If we specify a line number, then
2111 * do not channel any node to the error function.
2112 */
2113 if (line == 0) {
2114 if ((node == NULL) &&
2115 (vctxt->depth >= 0) &&
2116 (vctxt->inode != NULL)) {
2117 node = vctxt->inode->node;
2118 }
2119 /*
2120 * Get filename and line if no node-tree.
2121 */
2122 if ((node == NULL) &&
2123 (vctxt->parserCtxt != NULL) &&
2124 (vctxt->parserCtxt->input != NULL)) {
2125 file = vctxt->parserCtxt->input->filename;
2126 if (vctxt->inode != NULL) {
2127 line = vctxt->inode->nodeLine;
2128 col = 0;
2129 } else {
2130 /* This is inaccurate. */
2131 line = vctxt->parserCtxt->input->line;
2132 col = vctxt->parserCtxt->input->col;
2133 }
2134 }
2135 } else {
2136 /*
2137 * Override the given node's (if any) position
2138 * and channel only the given line number.
2139 */
2140 node = NULL;
2141 /*
2142 * Get filename.
2143 */
2144 if (vctxt->doc != NULL)
2145 file = (const char *) vctxt->doc->URL;
2146 else if ((vctxt->parserCtxt != NULL) &&
2147 (vctxt->parserCtxt->input != NULL))
2148 file = vctxt->parserCtxt->input->filename;
2149 }
2150 if (vctxt->locFunc != NULL) {
2151 if ((file == NULL) || (line == 0)) {
2152 unsigned long l;
2153 const char *f;
2154 vctxt->locFunc(vctxt->locCtxt, &f, &l);
2155 if (file == NULL)
2156 file = f;
2157 if (line == 0)
2158 line = (int) l;
2159 }
2160 }
2161 if ((file == NULL) && (vctxt->filename != NULL))
2162 file = vctxt->filename;
2163
2164 __xmlRaiseError(schannel, channel, data, ctxt,
2166 error, errorLevel, file, line,
2167 (const char *) str1, (const char *) str2,
2168 (const char *) str3, 0, col, msg, str1, str2, str3, str4);
2169
2170 } else if (ctxt->type == XML_SCHEMA_CTXT_PARSER) {
2171 xmlSchemaParserCtxtPtr pctxt = (xmlSchemaParserCtxtPtr) ctxt;
2172 if (errorLevel != XML_ERR_WARNING) {
2173 pctxt->nberrors++;
2174 pctxt->err = error;
2175 channel = pctxt->error;
2176 } else {
2177 channel = pctxt->warning;
2178 }
2179 schannel = pctxt->serror;
2180 data = pctxt->errCtxt;
2181 __xmlRaiseError(schannel, channel, data, ctxt,
2183 errorLevel, NULL, 0,
2184 (const char *) str1, (const char *) str2,
2185 (const char *) str3, 0, 0, msg, str1, str2, str3, str4);
2186 } else {
2187 TODO
2188 }
2189 }
2190}
2191
2204static void LIBXML_ATTR_FORMAT(4,0)
2205xmlSchemaErr3(xmlSchemaAbstractCtxtPtr actxt,
2206 int error, xmlNodePtr node, const char *msg,
2208{
2209 xmlSchemaErr4Line(actxt, XML_ERR_ERROR, error, node, 0,
2210 msg, str1, str2, str3, NULL);
2211}
2212
2213static void LIBXML_ATTR_FORMAT(4,0)
2214xmlSchemaErr4(xmlSchemaAbstractCtxtPtr actxt,
2215 int error, xmlNodePtr node, const char *msg,
2217 const xmlChar *str3, const xmlChar *str4)
2218{
2219 xmlSchemaErr4Line(actxt, XML_ERR_ERROR, error, node, 0,
2220 msg, str1, str2, str3, str4);
2221}
2222
2223static void LIBXML_ATTR_FORMAT(4,0)
2224xmlSchemaErr(xmlSchemaAbstractCtxtPtr actxt,
2225 int error, xmlNodePtr node, const char *msg,
2227{
2228 xmlSchemaErr4(actxt, error, node, msg, str1, str2, NULL, NULL);
2229}
2230
2231static xmlChar *
2232xmlSchemaFormatNodeForError(xmlChar ** msg,
2233 xmlSchemaAbstractCtxtPtr actxt,
2234 xmlNodePtr node)
2235{
2236 xmlChar *str = NULL;
2237
2238 *msg = NULL;
2239 if ((node != NULL) &&
2240 (node->type != XML_ELEMENT_NODE) &&
2241 (node->type != XML_ATTRIBUTE_NODE))
2242 {
2243 /*
2244 * Don't try to format other nodes than element and
2245 * attribute nodes.
2246 * Play safe and return an empty string.
2247 */
2248 *msg = xmlStrdup(BAD_CAST "");
2249 return(*msg);
2250 }
2251 if (node != NULL) {
2252 /*
2253 * Work on tree nodes.
2254 */
2255 if (node->type == XML_ATTRIBUTE_NODE) {
2256 xmlNodePtr elem = node->parent;
2257
2258 *msg = xmlStrdup(BAD_CAST "Element '");
2259 if (elem->ns != NULL)
2260 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2261 elem->ns->href, elem->name));
2262 else
2263 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2264 NULL, elem->name));
2265 FREE_AND_NULL(str);
2266 *msg = xmlStrcat(*msg, BAD_CAST "', ");
2267 *msg = xmlStrcat(*msg, BAD_CAST "attribute '");
2268 } else {
2269 *msg = xmlStrdup(BAD_CAST "Element '");
2270 }
2271 if (node->ns != NULL)
2272 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2273 node->ns->href, node->name));
2274 else
2275 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2276 NULL, node->name));
2277 FREE_AND_NULL(str);
2278 *msg = xmlStrcat(*msg, BAD_CAST "': ");
2279 } else if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
2280 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) actxt;
2281 /*
2282 * Work on node infos.
2283 */
2284 if (vctxt->inode->nodeType == XML_ATTRIBUTE_NODE) {
2285 xmlSchemaNodeInfoPtr ielem =
2286 vctxt->elemInfos[vctxt->depth];
2287
2288 *msg = xmlStrdup(BAD_CAST "Element '");
2289 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2290 ielem->nsName, ielem->localName));
2291 FREE_AND_NULL(str);
2292 *msg = xmlStrcat(*msg, BAD_CAST "', ");
2293 *msg = xmlStrcat(*msg, BAD_CAST "attribute '");
2294 } else {
2295 *msg = xmlStrdup(BAD_CAST "Element '");
2296 }
2297 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2298 vctxt->inode->nsName, vctxt->inode->localName));
2299 FREE_AND_NULL(str);
2300 *msg = xmlStrcat(*msg, BAD_CAST "': ");
2301 } else if (actxt->type == XML_SCHEMA_CTXT_PARSER) {
2302 /*
2303 * Hmm, no node while parsing?
2304 * Return an empty string, in case NULL will break something.
2305 */
2306 *msg = xmlStrdup(BAD_CAST "");
2307 } else {
2308 TODO
2309 return (NULL);
2310 }
2311
2312 /*
2313 * xmlSchemaFormatItemForReport() also returns an escaped format
2314 * string, so do this before calling it below (in the future).
2315 */
2317
2318 /*
2319 * VAL TODO: The output of the given schema component is currently
2320 * disabled.
2321 */
2322#if 0
2323 if ((type != NULL) && (xmlSchemaIsGlobalItem(type))) {
2324 *msg = xmlStrcat(*msg, BAD_CAST " [");
2325 *msg = xmlStrcat(*msg, xmlSchemaFormatItemForReport(&str,
2326 NULL, type, NULL, 0));
2327 FREE_AND_NULL(str)
2328 *msg = xmlStrcat(*msg, BAD_CAST "]");
2329 }
2330#endif
2331 return (*msg);
2332}
2333
2334static void LIBXML_ATTR_FORMAT(3,0)
2335xmlSchemaInternalErr2(xmlSchemaAbstractCtxtPtr actxt,
2336 const char *funcName,
2337 const char *message,
2340{
2341 xmlChar *msg = NULL;
2342
2343 if (actxt == NULL)
2344 return;
2345 msg = xmlStrdup(BAD_CAST "Internal error: %s, ");
2347 msg = xmlStrcat(msg, BAD_CAST ".\n");
2348
2349 if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR)
2350 xmlSchemaErr3(actxt, XML_SCHEMAV_INTERNAL, NULL,
2351 (const char *) msg, (const xmlChar *) funcName, str1, str2);
2352 else if (actxt->type == XML_SCHEMA_CTXT_PARSER)
2353 xmlSchemaErr3(actxt, XML_SCHEMAP_INTERNAL, NULL,
2354 (const char *) msg, (const xmlChar *) funcName, str1, str2);
2355
2356 FREE_AND_NULL(msg)
2357}
2358
2359static void LIBXML_ATTR_FORMAT(3,0)
2360xmlSchemaInternalErr(xmlSchemaAbstractCtxtPtr actxt,
2361 const char *funcName,
2362 const char *message)
2363{
2364 xmlSchemaInternalErr2(actxt, funcName, message, NULL, NULL);
2365}
2366
2367#if 0
2368static void LIBXML_ATTR_FORMAT(3,0)
2369xmlSchemaPInternalErr(xmlSchemaParserCtxtPtr pctxt,
2370 const char *funcName,
2371 const char *message,
2374{
2375 xmlSchemaInternalErr2(ACTXT_CAST pctxt, funcName, message,
2376 str1, str2);
2377}
2378#endif
2379
2380static void LIBXML_ATTR_FORMAT(5,0)
2381xmlSchemaCustomErr4(xmlSchemaAbstractCtxtPtr actxt,
2383 xmlNodePtr node,
2384 xmlSchemaBasicItemPtr item,
2385 const char *message,
2387 const xmlChar *str3, const xmlChar *str4)
2388{
2389 xmlChar *msg = NULL;
2390
2391 if ((node == NULL) && (item != NULL) &&
2392 (actxt->type == XML_SCHEMA_CTXT_PARSER)) {
2393 node = WXS_ITEM_NODE(item);
2394 xmlSchemaFormatItemForReport(&msg, NULL, item, NULL);
2395 msg = xmlStrcat(msg, BAD_CAST ": ");
2396 } else
2397 xmlSchemaFormatNodeForError(&msg, actxt, node);
2398 msg = xmlStrcat(msg, (const xmlChar *) message);
2399 msg = xmlStrcat(msg, BAD_CAST ".\n");
2400 xmlSchemaErr4(actxt, error, node,
2401 (const char *) msg, str1, str2, str3, str4);
2402 FREE_AND_NULL(msg)
2403}
2404
2405static void LIBXML_ATTR_FORMAT(5,0)
2406xmlSchemaCustomErr(xmlSchemaAbstractCtxtPtr actxt,
2408 xmlNodePtr node,
2409 xmlSchemaBasicItemPtr item,
2410 const char *message,
2413{
2414 xmlSchemaCustomErr4(actxt, error, node, item,
2415 message, str1, str2, NULL, NULL);
2416}
2417
2418
2419
2420static void LIBXML_ATTR_FORMAT(5,0)
2421xmlSchemaCustomWarning(xmlSchemaAbstractCtxtPtr actxt,
2423 xmlNodePtr node,
2424 xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
2425 const char *message,
2428 const xmlChar *str3)
2429{
2430 xmlChar *msg = NULL;
2431
2432 xmlSchemaFormatNodeForError(&msg, actxt, node);
2433 msg = xmlStrcat(msg, (const xmlChar *) message);
2434 msg = xmlStrcat(msg, BAD_CAST ".\n");
2435
2436 /* URGENT TODO: Set the error code to something sane. */
2437 xmlSchemaErr4Line(actxt, XML_ERR_WARNING, error, node, 0,
2438 (const char *) msg, str1, str2, str3, NULL);
2439
2440 FREE_AND_NULL(msg)
2441}
2442
2443
2444
2445static void LIBXML_ATTR_FORMAT(5,0)
2446xmlSchemaKeyrefErr(xmlSchemaValidCtxtPtr vctxt,
2448 xmlSchemaPSVIIDCNodePtr idcNode,
2449 xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
2450 const char *message,
2453{
2454 xmlChar *msg = NULL, *qname = NULL;
2455
2456 msg = xmlStrdup(BAD_CAST "Element '%s': ");
2457 msg = xmlStrcat(msg, (const xmlChar *) message);
2458 msg = xmlStrcat(msg, BAD_CAST ".\n");
2459 xmlSchemaErr4Line(ACTXT_CAST vctxt, XML_ERR_ERROR,
2460 error, NULL, idcNode->nodeLine, (const char *) msg,
2461 xmlSchemaFormatQName(&qname,
2462 vctxt->nodeQNames->items[idcNode->nodeQNameID +1],
2463 vctxt->nodeQNames->items[idcNode->nodeQNameID]),
2464 str1, str2, NULL);
2465 FREE_AND_NULL(qname);
2466 FREE_AND_NULL(msg);
2467}
2468
2469static int
2470xmlSchemaEvalErrorNodeType(xmlSchemaAbstractCtxtPtr actxt,
2471 xmlNodePtr node)
2472{
2473 if (node != NULL)
2474 return (node->type);
2475 if ((actxt->type == XML_SCHEMA_CTXT_VALIDATOR) &&
2476 (((xmlSchemaValidCtxtPtr) actxt)->inode != NULL))
2477 return ( ((xmlSchemaValidCtxtPtr) actxt)->inode->nodeType);
2478 return (-1);
2479}
2480
2481static int
2482xmlSchemaIsGlobalItem(xmlSchemaTypePtr item)
2483{
2484 switch (item->type) {
2485 case XML_SCHEMA_TYPE_COMPLEX:
2486 case XML_SCHEMA_TYPE_SIMPLE:
2487 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL)
2488 return(1);
2489 break;
2490 case XML_SCHEMA_TYPE_GROUP:
2491 return (1);
2492 case XML_SCHEMA_TYPE_ELEMENT:
2493 if ( ((xmlSchemaElementPtr) item)->flags &
2494 XML_SCHEMAS_ELEM_GLOBAL)
2495 return(1);
2496 break;
2497 case XML_SCHEMA_TYPE_ATTRIBUTE:
2498 if ( ((xmlSchemaAttributePtr) item)->flags &
2499 XML_SCHEMAS_ATTR_GLOBAL)
2500 return(1);
2501 break;
2502 /* Note that attribute groups are always global. */
2503 default:
2504 return(1);
2505 }
2506 return (0);
2507}
2508
2509static void
2510xmlSchemaSimpleTypeErr(xmlSchemaAbstractCtxtPtr actxt,
2512 xmlNodePtr node,
2513 const xmlChar *value,
2514 xmlSchemaTypePtr type,
2515 int displayValue)
2516{
2517 xmlChar *msg = NULL;
2518
2519 xmlSchemaFormatNodeForError(&msg, actxt, node);
2520
2521 if (displayValue || (xmlSchemaEvalErrorNodeType(actxt, node) ==
2522 XML_ATTRIBUTE_NODE))
2523 msg = xmlStrcat(msg, BAD_CAST "'%s' is not a valid value of ");
2524 else
2525 msg = xmlStrcat(msg, BAD_CAST "The character content is not a valid "
2526 "value of ");
2527
2528 if (! xmlSchemaIsGlobalItem(type))
2529 msg = xmlStrcat(msg, BAD_CAST "the local ");
2530 else
2531 msg = xmlStrcat(msg, BAD_CAST "the ");
2532
2533 if (WXS_IS_ATOMIC(type))
2534 msg = xmlStrcat(msg, BAD_CAST "atomic type");
2535 else if (WXS_IS_LIST(type))
2536 msg = xmlStrcat(msg, BAD_CAST "list type");
2537 else if (WXS_IS_UNION(type))
2538 msg = xmlStrcat(msg, BAD_CAST "union type");
2539
2540 if (xmlSchemaIsGlobalItem(type)) {
2541 xmlChar *str = NULL;
2542 msg = xmlStrcat(msg, BAD_CAST " '");
2543 if (type->builtInType != 0) {
2544 msg = xmlStrcat(msg, BAD_CAST "xs:");
2545 str = xmlStrdup(type->name);
2546 } else {
2547 const xmlChar *qName = xmlSchemaFormatQName(&str, type->targetNamespace, type->name);
2548 if (!str)
2549 str = xmlStrdup(qName);
2550 }
2552 msg = xmlStrcat(msg, BAD_CAST "'");
2553 FREE_AND_NULL(str);
2554 }
2555 msg = xmlStrcat(msg, BAD_CAST ".\n");
2556 if (displayValue || (xmlSchemaEvalErrorNodeType(actxt, node) ==
2557 XML_ATTRIBUTE_NODE))
2558 xmlSchemaErr(actxt, error, node, (const char *) msg, value, NULL);
2559 else
2560 xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
2561 FREE_AND_NULL(msg)
2562}
2563
2564static const xmlChar *
2565xmlSchemaFormatErrorNodeQName(xmlChar ** str,
2566 xmlSchemaNodeInfoPtr ni,
2567 xmlNodePtr node)
2568{
2569 if (node != NULL) {
2570 if (node->ns != NULL)
2571 return (xmlSchemaFormatQName(str, node->ns->href, node->name));
2572 else
2573 return (xmlSchemaFormatQName(str, NULL, node->name));
2574 } else if (ni != NULL)
2575 return (xmlSchemaFormatQName(str, ni->nsName, ni->localName));
2576 return (NULL);
2577}
2578
2579static void
2580xmlSchemaIllegalAttrErr(xmlSchemaAbstractCtxtPtr actxt,
2582 xmlSchemaAttrInfoPtr ni,
2583 xmlNodePtr node)
2584{
2585 xmlChar *msg = NULL, *str = NULL;
2586
2587 xmlSchemaFormatNodeForError(&msg, actxt, node);
2588 msg = xmlStrcat(msg, BAD_CAST "The attribute '%s' is not allowed.\n");
2589 xmlSchemaErr(actxt, error, node, (const char *) msg,
2590 xmlSchemaFormatErrorNodeQName(&str, (xmlSchemaNodeInfoPtr) ni, node),
2591 NULL);
2592 FREE_AND_NULL(str)
2593 FREE_AND_NULL(msg)
2594}
2595
2596static void LIBXML_ATTR_FORMAT(5,0)
2597xmlSchemaComplexTypeErr(xmlSchemaAbstractCtxtPtr actxt,
2599 xmlNodePtr node,
2600 xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
2601 const char *message,
2602 int nbval,
2603 int nbneg,
2604 xmlChar **values)
2605{
2606 xmlChar *str = NULL, *msg = NULL;
2607 xmlChar *localName, *nsName;
2608 const xmlChar *cur, *end;
2609 int i;
2610
2611 xmlSchemaFormatNodeForError(&msg, actxt, node);
2612 msg = xmlStrcat(msg, (const xmlChar *) message);
2613 msg = xmlStrcat(msg, BAD_CAST ".");
2614 /*
2615 * Note that is does not make sense to report that we have a
2616 * wildcard here, since the wildcard might be unfolded into
2617 * multiple transitions.
2618 */
2619 if (nbval + nbneg > 0) {
2620 if (nbval + nbneg > 1) {
2621 str = xmlStrdup(BAD_CAST " Expected is one of ( ");
2622 } else
2623 str = xmlStrdup(BAD_CAST " Expected is ( ");
2624 nsName = NULL;
2625
2626 for (i = 0; i < nbval + nbneg; i++) {
2627 cur = values[i];
2628 if (cur == NULL)
2629 continue;
2630 if ((cur[0] == 'n') && (cur[1] == 'o') && (cur[2] == 't') &&
2631 (cur[3] == ' ')) {
2632 cur += 4;
2633 str = xmlStrcat(str, BAD_CAST "##other");
2634 }
2635 /*
2636 * Get the local name.
2637 */
2638 localName = NULL;
2639
2640 end = cur;
2641 if (*end == '*') {
2642 localName = xmlStrdup(BAD_CAST "*");
2643 end++;
2644 } else {
2645 while ((*end != 0) && (*end != '|'))
2646 end++;
2647 localName = xmlStrncat(localName, BAD_CAST cur, end - cur);
2648 }
2649 if (*end != 0) {
2650 end++;
2651 /*
2652 * Skip "*|*" if they come with negated expressions, since
2653 * they represent the same negated wildcard.
2654 */
2655 if ((nbneg == 0) || (*end != '*') || (*localName != '*')) {
2656 /*
2657 * Get the namespace name.
2658 */
2659 cur = end;
2660 if (*end == '*') {
2661 nsName = xmlStrdup(BAD_CAST "{*}");
2662 } else {
2663 while (*end != 0)
2664 end++;
2665
2666 if (i >= nbval)
2667 nsName = xmlStrdup(BAD_CAST "{##other:");
2668 else
2669 nsName = xmlStrdup(BAD_CAST "{");
2670
2671 nsName = xmlStrncat(nsName, BAD_CAST cur, end - cur);
2672 nsName = xmlStrcat(nsName, BAD_CAST "}");
2673 }
2674 str = xmlStrcat(str, BAD_CAST nsName);
2675 FREE_AND_NULL(nsName)
2676 } else {
2677 FREE_AND_NULL(localName);
2678 continue;
2679 }
2680 }
2681 str = xmlStrcat(str, BAD_CAST localName);
2682 FREE_AND_NULL(localName);
2683
2684 if (i < nbval + nbneg -1)
2685 str = xmlStrcat(str, BAD_CAST ", ");
2686 }
2687 str = xmlStrcat(str, BAD_CAST " ).\n");
2689 FREE_AND_NULL(str)
2690 } else
2691 msg = xmlStrcat(msg, BAD_CAST "\n");
2692 xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
2693 xmlFree(msg);
2694}
2695
2696static void LIBXML_ATTR_FORMAT(8,0)
2697xmlSchemaFacetErr(xmlSchemaAbstractCtxtPtr actxt,
2699 xmlNodePtr node,
2701 unsigned long length,
2702 xmlSchemaTypePtr type,
2703 xmlSchemaFacetPtr facet,
2704 const char *message,
2707{
2708 xmlChar *str = NULL, *msg = NULL;
2709 xmlSchemaTypeType facetType;
2710 int nodeType = xmlSchemaEvalErrorNodeType(actxt, node);
2711
2712 xmlSchemaFormatNodeForError(&msg, actxt, node);
2714 facetType = XML_SCHEMA_FACET_ENUMERATION;
2715 /*
2716 * If enumerations are validated, one must not expect the
2717 * facet to be given.
2718 */
2719 } else
2720 facetType = facet->type;
2721 msg = xmlStrcat(msg, BAD_CAST "[");
2722 msg = xmlStrcat(msg, BAD_CAST "facet '");
2723 msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facetType));
2724 msg = xmlStrcat(msg, BAD_CAST "'] ");
2725 if (message == NULL) {
2726 /*
2727 * Use a default message.
2728 */
2729 if ((facetType == XML_SCHEMA_FACET_LENGTH) ||
2730 (facetType == XML_SCHEMA_FACET_MINLENGTH) ||
2731 (facetType == XML_SCHEMA_FACET_MAXLENGTH)) {
2732
2733 char len[25], actLen[25];
2734
2735 /* FIXME, TODO: What is the max expected string length of the
2736 * this value?
2737 */
2738 if (nodeType == XML_ATTRIBUTE_NODE)
2739 msg = xmlStrcat(msg, BAD_CAST "The value '%s' has a length of '%s'; ");
2740 else
2741 msg = xmlStrcat(msg, BAD_CAST "The value has a length of '%s'; ");
2742
2743 snprintf(len, 24, "%lu", xmlSchemaGetFacetValueAsULong(facet));
2744 snprintf(actLen, 24, "%lu", length);
2745
2746 if (facetType == XML_SCHEMA_FACET_LENGTH)
2747 msg = xmlStrcat(msg,
2748 BAD_CAST "this differs from the allowed length of '%s'.\n");
2749 else if (facetType == XML_SCHEMA_FACET_MAXLENGTH)
2750 msg = xmlStrcat(msg,
2751 BAD_CAST "this exceeds the allowed maximum length of '%s'.\n");
2752 else if (facetType == XML_SCHEMA_FACET_MINLENGTH)
2753 msg = xmlStrcat(msg,
2754 BAD_CAST "this underruns the allowed minimum length of '%s'.\n");
2755
2756 if (nodeType == XML_ATTRIBUTE_NODE)
2757 xmlSchemaErr3(actxt, error, node, (const char *) msg,
2758 value, (const xmlChar *) actLen, (const xmlChar *) len);
2759 else
2760 xmlSchemaErr(actxt, error, node, (const char *) msg,
2761 (const xmlChar *) actLen, (const xmlChar *) len);
2762
2763 } else if (facetType == XML_SCHEMA_FACET_ENUMERATION) {
2764 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not an element "
2765 "of the set {%s}.\n");
2766 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2767 xmlSchemaFormatFacetEnumSet(actxt, &str, type));
2768 } else if (facetType == XML_SCHEMA_FACET_PATTERN) {
2769 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not accepted "
2770 "by the pattern '%s'.\n");
2771 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2772 facet->value);
2773 } else if (facetType == XML_SCHEMA_FACET_MININCLUSIVE) {
2774 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is less than the "
2775 "minimum value allowed ('%s').\n");
2776 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2777 facet->value);
2778 } else if (facetType == XML_SCHEMA_FACET_MAXINCLUSIVE) {
2779 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is greater than the "
2780 "maximum value allowed ('%s').\n");
2781 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2782 facet->value);
2783 } else if (facetType == XML_SCHEMA_FACET_MINEXCLUSIVE) {
2784 msg = xmlStrcat(msg, BAD_CAST "The value '%s' must be greater than "
2785 "'%s'.\n");
2786 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2787 facet->value);
2788 } else if (facetType == XML_SCHEMA_FACET_MAXEXCLUSIVE) {
2789 msg = xmlStrcat(msg, BAD_CAST "The value '%s' must be less than "
2790 "'%s'.\n");
2791 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2792 facet->value);
2793 } else if (facetType == XML_SCHEMA_FACET_TOTALDIGITS) {
2794 msg = xmlStrcat(msg, BAD_CAST "The value '%s' has more "
2795 "digits than are allowed ('%s').\n");
2796 xmlSchemaErr(actxt, error, node, (const char*) msg, value,
2797 facet->value);
2798 } else if (facetType == XML_SCHEMA_FACET_FRACTIONDIGITS) {
2799 msg = xmlStrcat(msg, BAD_CAST "The value '%s' has more fractional "
2800 "digits than are allowed ('%s').\n");
2801 xmlSchemaErr(actxt, error, node, (const char*) msg, value,
2802 facet->value);
2803 } else if (nodeType == XML_ATTRIBUTE_NODE) {
2804 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not facet-valid.\n");
2805 xmlSchemaErr(actxt, error, node, (const char *) msg, value, NULL);
2806 } else {
2807 msg = xmlStrcat(msg, BAD_CAST "The value is not facet-valid.\n");
2808 xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
2809 }
2810 } else {
2811 msg = xmlStrcat(msg, (const xmlChar *) message);
2812 msg = xmlStrcat(msg, BAD_CAST ".\n");
2813 xmlSchemaErr(actxt, error, node, (const char *) msg, str1, str2);
2814 }
2815 FREE_AND_NULL(str)
2816 xmlFree(msg);
2817}
2818
2819#define VERROR(err, type, msg) \
2820 xmlSchemaCustomErr(ACTXT_CAST vctxt, err, NULL, type, msg, NULL, NULL);
2821
2822#define VERROR_INT(func, msg) xmlSchemaInternalErr(ACTXT_CAST vctxt, func, msg);
2823
2824#define PERROR_INT(func, msg) xmlSchemaInternalErr(ACTXT_CAST pctxt, func, msg);
2825#define PERROR_INT2(func, msg) xmlSchemaInternalErr(ACTXT_CAST ctxt, func, msg);
2826
2827#define AERROR_INT(func, msg) xmlSchemaInternalErr(actxt, func, msg);
2828
2829
2840static void
2841xmlSchemaPMissingAttrErr(xmlSchemaParserCtxtPtr ctxt,
2843 xmlSchemaBasicItemPtr ownerItem,
2844 xmlNodePtr ownerElem,
2845 const char *name,
2846 const char *message)
2847{
2848 xmlChar *des = NULL;
2849
2850 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
2851
2852 if (message != NULL)
2853 xmlSchemaPErr(ctxt, ownerElem, error, "%s: %s.\n", BAD_CAST des, BAD_CAST message);
2854 else
2855 xmlSchemaPErr(ctxt, ownerElem, error,
2856 "%s: The attribute '%s' is required but missing.\n",
2858 FREE_AND_NULL(des);
2859}
2860
2861
2876static void
2877xmlSchemaPResCompAttrErr(xmlSchemaParserCtxtPtr ctxt,
2879 xmlSchemaBasicItemPtr ownerItem,
2880 xmlNodePtr ownerElem,
2881 const char *name,
2882 const xmlChar *refName,
2883 const xmlChar *refURI,
2884 xmlSchemaTypeType refType,
2885 const char *refTypeStr)
2886{
2887 xmlChar *des = NULL, *strA = NULL;
2888
2889 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
2890 if (refTypeStr == NULL)
2891 refTypeStr = (const char *) xmlSchemaItemTypeToStr(refType);
2892 xmlSchemaPErrExt(ctxt, ownerElem, error,
2893 NULL, NULL, NULL,
2894 "%s, attribute '%s': The QName value '%s' does not resolve to a(n) "
2895 "%s.\n", BAD_CAST des, BAD_CAST name,
2896 xmlSchemaFormatQName(&strA, refURI, refName),
2897 BAD_CAST refTypeStr, NULL);
2898 FREE_AND_NULL(des)
2899 FREE_AND_NULL(strA)
2900}
2901
2912static void
2913xmlSchemaPCustomAttrErr(xmlSchemaParserCtxtPtr ctxt,
2915 xmlChar **ownerDes,
2916 xmlSchemaBasicItemPtr ownerItem,
2917 xmlAttrPtr attr,
2918 const char *msg)
2919{
2920 xmlChar *des = NULL;
2921
2922 if (ownerDes == NULL)
2923 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent);
2924 else if (*ownerDes == NULL) {
2925 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent);
2926 des = *ownerDes;
2927 } else
2928 des = *ownerDes;
2929 if (attr == NULL) {
2930 xmlSchemaPErrExt(ctxt, NULL, error, NULL, NULL, NULL,
2931 "%s, attribute '%s': %s.\n",
2932 BAD_CAST des, (const xmlChar *) "Unknown",
2933 (const xmlChar *) msg, NULL, NULL);
2934 } else {
2935 xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
2936 "%s, attribute '%s': %s.\n",
2937 BAD_CAST des, attr->name, (const xmlChar *) msg, NULL, NULL);
2938 }
2939 if (ownerDes == NULL)
2940 FREE_AND_NULL(des);
2941}
2942
2952static void
2953xmlSchemaPIllegalAttrErr(xmlSchemaParserCtxtPtr ctxt,
2955 xmlSchemaBasicItemPtr ownerComp ATTRIBUTE_UNUSED,
2956 xmlAttrPtr attr)
2957{
2958 xmlChar *strA = NULL, *strB = NULL;
2959
2960 xmlSchemaFormatNodeForError(&strA, ACTXT_CAST ctxt, attr->parent);
2961 xmlSchemaErr4(ACTXT_CAST ctxt, error, (xmlNodePtr) attr,
2962 "%sThe attribute '%s' is not allowed.\n", BAD_CAST strA,
2963 xmlSchemaFormatQNameNs(&strB, attr->ns, attr->name),
2964 NULL, NULL);
2965 FREE_AND_NULL(strA);
2966 FREE_AND_NULL(strB);
2967}
2968
2983static void LIBXML_ATTR_FORMAT(5,0)
2984xmlSchemaPCustomErrExt(xmlSchemaParserCtxtPtr ctxt,
2986 xmlSchemaBasicItemPtr item,
2987 xmlNodePtr itemElem,
2988 const char *message,
2991 const xmlChar *str3)
2992{
2993 xmlChar *des = NULL, *msg = NULL;
2994
2995 xmlSchemaFormatItemForReport(&des, NULL, item, itemElem);
2996 msg = xmlStrdup(BAD_CAST "%s: ");
2997 msg = xmlStrcat(msg, (const xmlChar *) message);
2998 msg = xmlStrcat(msg, BAD_CAST ".\n");
2999 if ((itemElem == NULL) && (item != NULL))
3000 itemElem = WXS_ITEM_NODE(item);
3001 xmlSchemaPErrExt(ctxt, itemElem, error, NULL, NULL, NULL,
3002 (const char *) msg, BAD_CAST des, str1, str2, str3, NULL);
3003 FREE_AND_NULL(des);
3004 FREE_AND_NULL(msg);
3005}
3006
3019static void LIBXML_ATTR_FORMAT(5,0)
3020xmlSchemaPCustomErr(xmlSchemaParserCtxtPtr ctxt,
3022 xmlSchemaBasicItemPtr item,
3023 xmlNodePtr itemElem,
3024 const char *message,
3026{
3027 xmlSchemaPCustomErrExt(ctxt, error, item, itemElem, message,
3028 str1, NULL, NULL);
3029}
3030
3044static void LIBXML_ATTR_FORMAT(6,0)
3045xmlSchemaPAttrUseErr4(xmlSchemaParserCtxtPtr ctxt,
3047 xmlNodePtr node,
3048 xmlSchemaBasicItemPtr ownerItem,
3049 const xmlSchemaAttributeUsePtr attruse,
3050 const char *message,
3052 const xmlChar *str3,const xmlChar *str4)
3053{
3054 xmlChar *str = NULL, *msg = NULL;
3055
3056 xmlSchemaFormatItemForReport(&msg, NULL, ownerItem, NULL);
3057 msg = xmlStrcat(msg, BAD_CAST ", ");
3058 msg = xmlStrcat(msg,
3059 BAD_CAST xmlSchemaFormatItemForReport(&str, NULL,
3060 WXS_BASIC_CAST attruse, NULL));
3061 FREE_AND_NULL(str);
3062 msg = xmlStrcat(msg, BAD_CAST ": ");
3063 msg = xmlStrcat(msg, (const xmlChar *) message);
3064 msg = xmlStrcat(msg, BAD_CAST ".\n");
3065 xmlSchemaErr4(ACTXT_CAST ctxt, error, node,
3066 (const char *) msg, str1, str2, str3, str4);
3067 xmlFree(msg);
3068}
3069
3080static void
3081xmlSchemaPIllegalFacetAtomicErr(xmlSchemaParserCtxtPtr ctxt,
3083 xmlSchemaTypePtr type,
3084 xmlSchemaTypePtr baseType,
3085 xmlSchemaFacetPtr facet)
3086{
3087 xmlChar *des = NULL, *strT = NULL;
3088
3089 xmlSchemaFormatItemForReport(&des, NULL, WXS_BASIC_CAST type, type->node);
3090 xmlSchemaPErrExt(ctxt, type->node, error, NULL, NULL, NULL,
3091 "%s: The facet '%s' is not allowed on types derived from the "
3092 "type %s.\n",
3093 BAD_CAST des, xmlSchemaFacetTypeToString(facet->type),
3094 xmlSchemaFormatItemForReport(&strT, NULL, WXS_BASIC_CAST baseType, NULL),
3095 NULL, NULL);
3096 FREE_AND_NULL(des);
3097 FREE_AND_NULL(strT);
3098}
3099
3110static void
3111xmlSchemaPIllegalFacetListUnionErr(xmlSchemaParserCtxtPtr ctxt,
3113 xmlSchemaTypePtr type,
3114 xmlSchemaFacetPtr facet)
3115{
3116 xmlChar *des = NULL;
3117
3118 xmlSchemaFormatItemForReport(&des, NULL, WXS_BASIC_CAST type,
3119 type->node);
3120 xmlSchemaPErr(ctxt, type->node, error,
3121 "%s: The facet '%s' is not allowed.\n",
3122 BAD_CAST des, xmlSchemaFacetTypeToString(facet->type));
3123 FREE_AND_NULL(des);
3124}
3125
3136static void
3137xmlSchemaPMutualExclAttrErr(xmlSchemaParserCtxtPtr ctxt,
3139 xmlSchemaBasicItemPtr ownerItem,
3140 xmlAttrPtr attr,
3141 const char *name1,
3142 const char *name2)
3143{
3144 xmlChar *des = NULL;
3145
3146 xmlSchemaFormatItemForReport(&des, NULL, WXS_BASIC_CAST ownerItem, attr->parent);
3147 xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
3148 "%s: The attributes '%s' and '%s' are mutually exclusive.\n",
3150 FREE_AND_NULL(des);
3151}
3152
3165static void LIBXML_ATTR_FORMAT(8,0)
3166xmlSchemaPSimpleTypeErr(xmlSchemaParserCtxtPtr ctxt,
3168 xmlSchemaBasicItemPtr ownerItem ATTRIBUTE_UNUSED,
3169 xmlNodePtr node,
3170 xmlSchemaTypePtr type,
3171 const char *expected,
3173 const char *message,
3176{
3177 xmlChar *msg = NULL;
3178
3179 xmlSchemaFormatNodeForError(&msg, ACTXT_CAST ctxt, node);
3180 if (message == NULL) {
3181 /*
3182 * Use default messages.
3183 */
3184 if (type != NULL) {
3185 if (node->type == XML_ATTRIBUTE_NODE)
3186 msg = xmlStrcat(msg, BAD_CAST "'%s' is not a valid value of ");
3187 else
3188 msg = xmlStrcat(msg, BAD_CAST "The character content is not a "
3189 "valid value of ");
3190 if (! xmlSchemaIsGlobalItem(type))
3191 msg = xmlStrcat(msg, BAD_CAST "the local ");
3192 else
3193 msg = xmlStrcat(msg, BAD_CAST "the ");
3194
3195 if (WXS_IS_ATOMIC(type))
3196 msg = xmlStrcat(msg, BAD_CAST "atomic type");
3197 else if (WXS_IS_LIST(type))
3198 msg = xmlStrcat(msg, BAD_CAST "list type");
3199 else if (WXS_IS_UNION(type))
3200 msg = xmlStrcat(msg, BAD_CAST "union type");
3201
3202 if (xmlSchemaIsGlobalItem(type)) {
3203 xmlChar *str = NULL;
3204 msg = xmlStrcat(msg, BAD_CAST " '");
3205 if (type->builtInType != 0) {
3206 msg = xmlStrcat(msg, BAD_CAST "xs:");
3207 str = xmlStrdup(type->name);
3208 } else {
3209 const xmlChar *qName = xmlSchemaFormatQName(&str, type->targetNamespace, type->name);
3210 if (!str)
3211 str = xmlStrdup(qName);
3212 }
3214 msg = xmlStrcat(msg, BAD_CAST "'.");
3215 FREE_AND_NULL(str);
3216 }
3217 } else {
3218 if (node->type == XML_ATTRIBUTE_NODE)
3219 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not valid.");
3220 else
3221 msg = xmlStrcat(msg, BAD_CAST "The character content is not "
3222 "valid.");
3223 }
3224 if (expected) {
3225 xmlChar *expectedEscaped = xmlCharStrdup(expected);
3226 msg = xmlStrcat(msg, BAD_CAST " Expected is '");
3227 msg = xmlStrcat(msg, xmlEscapeFormatString(&expectedEscaped));
3228 FREE_AND_NULL(expectedEscaped);
3229 msg = xmlStrcat(msg, BAD_CAST "'.\n");
3230 } else
3231 msg = xmlStrcat(msg, BAD_CAST "\n");
3232 if (node->type == XML_ATTRIBUTE_NODE)
3233 xmlSchemaPErr(ctxt, node, error, (const char *) msg, value, NULL);
3234 else
3235 xmlSchemaPErr(ctxt, node, error, (const char *) msg, NULL, NULL);
3236 } else {
3238 msg = xmlStrcat(msg, BAD_CAST ".\n");
3239 xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL,
3240 (const char*) msg, str1, str2, NULL, NULL, NULL);
3241 }
3242 /* Cleanup. */
3243 FREE_AND_NULL(msg)
3244}
3245
3258static void
3259xmlSchemaPContentErr(xmlSchemaParserCtxtPtr ctxt,
3261 xmlSchemaBasicItemPtr ownerItem,
3262 xmlNodePtr ownerElem,
3263 xmlNodePtr child,
3264 const char *message,
3265 const char *content)
3266{
3267 xmlChar *des = NULL;
3268
3269 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
3270 if (message != NULL)
3271 xmlSchemaPErr2(ctxt, ownerElem, child, error,
3272 "%s: %s.\n",
3274 else {
3275 if (content != NULL) {
3276 xmlSchemaPErr2(ctxt, ownerElem, child, error,
3277 "%s: The content is not valid. Expected is %s.\n",
3279 } else {
3280 xmlSchemaPErr2(ctxt, ownerElem, child, error,
3281 "%s: The content is not valid.\n",
3282 BAD_CAST des, NULL);
3283 }
3284 }
3285 FREE_AND_NULL(des)
3286}
3287
3288/************************************************************************
3289 * *
3290 * Streamable error functions *
3291 * *
3292 ************************************************************************/
3293
3294
3295
3296
3297/************************************************************************
3298 * *
3299 * Validation helper functions *
3300 * *
3301 ************************************************************************/
3302
3303
3304/************************************************************************
3305 * *
3306 * Allocation functions *
3307 * *
3308 ************************************************************************/
3309
3318static xmlSchemaPtr
3319xmlSchemaNewSchema(xmlSchemaParserCtxtPtr ctxt)
3320{
3321 xmlSchemaPtr ret;
3322
3323 ret = (xmlSchemaPtr) xmlMalloc(sizeof(xmlSchema));
3324 if (ret == NULL) {
3325 xmlSchemaPErrMemory(ctxt, "allocating schema", NULL);
3326 return (NULL);
3327 }
3328 memset(ret, 0, sizeof(xmlSchema));
3329 ret->dict = ctxt->dict;
3330 xmlDictReference(ret->dict);
3331
3332 return (ret);
3333}
3334
3342xmlSchemaFacetPtr
3343xmlSchemaNewFacet(void)
3344{
3345 xmlSchemaFacetPtr ret;
3346
3347 ret = (xmlSchemaFacetPtr) xmlMalloc(sizeof(xmlSchemaFacet));
3348 if (ret == NULL) {
3349 return (NULL);
3350 }
3351 memset(ret, 0, sizeof(xmlSchemaFacet));
3352
3353 return (ret);
3354}
3355
3365static xmlSchemaAnnotPtr
3366xmlSchemaNewAnnot(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
3367{
3368 xmlSchemaAnnotPtr ret;
3369
3370 ret = (xmlSchemaAnnotPtr) xmlMalloc(sizeof(xmlSchemaAnnot));
3371 if (ret == NULL) {
3372 xmlSchemaPErrMemory(ctxt, "allocating annotation", node);
3373 return (NULL);
3374 }
3375 memset(ret, 0, sizeof(xmlSchemaAnnot));
3376 ret->content = node;
3377 return (ret);
3378}
3379
3380static xmlSchemaItemListPtr
3381xmlSchemaItemListCreate(void)
3382{
3383 xmlSchemaItemListPtr ret;
3384
3385 ret = xmlMalloc(sizeof(xmlSchemaItemList));
3386 if (ret == NULL) {
3387 xmlSchemaPErrMemory(NULL,
3388 "allocating an item list structure", NULL);
3389 return (NULL);
3390 }
3391 memset(ret, 0, sizeof(xmlSchemaItemList));
3392 return (ret);
3393}
3394
3395static void
3396xmlSchemaItemListClear(xmlSchemaItemListPtr list)
3397{
3398 if (list->items != NULL) {
3399 xmlFree(list->items);
3400 list->items = NULL;
3401 }
3402 list->nbItems = 0;
3403 list->sizeItems = 0;
3404}
3405
3406static int
3407xmlSchemaItemListAdd(xmlSchemaItemListPtr list, void *item)
3408{
3409 if (list->sizeItems <= list->nbItems) {
3410 void **tmp;
3411 size_t newSize = list->sizeItems == 0 ? 20 : list->sizeItems * 2;
3412
3413 tmp = (void **) xmlRealloc(list->items, newSize * sizeof(void *));
3414 if (tmp == NULL) {
3415 xmlSchemaPErrMemory(NULL, "growing item list", NULL);
3416 return(-1);
3417 }
3418 list->items = tmp;
3419 list->sizeItems = newSize;
3420 }
3421 list->items[list->nbItems++] = item;
3422 return(0);
3423}
3424
3425static int
3426xmlSchemaItemListAddSize(xmlSchemaItemListPtr list,
3427 int initialSize,
3428 void *item)
3429{
3430 if (list->items == NULL) {
3431 if (initialSize <= 0)
3432 initialSize = 1;
3433 list->items = (void **) xmlMalloc(
3434 initialSize * sizeof(void *));
3435 if (list->items == NULL) {
3436 xmlSchemaPErrMemory(NULL, "allocating new item list", NULL);
3437 return(-1);
3438 }
3439 list->sizeItems = initialSize;
3440 } else if (list->sizeItems <= list->nbItems) {
3441 void **tmp;
3442
3443 list->sizeItems *= 2;
3444 tmp = (void **) xmlRealloc(list->items,
3445 list->sizeItems * sizeof(void *));
3446 if (tmp == NULL) {
3447 xmlSchemaPErrMemory(NULL, "growing item list", NULL);
3448 list->sizeItems /= 2;
3449 return(-1);
3450 }
3451 list->items = tmp;
3452 }
3453 list->items[list->nbItems++] = item;
3454 return(0);
3455}
3456
3457static int
3458xmlSchemaItemListInsert(xmlSchemaItemListPtr list, void *item, int idx)
3459{
3460 if (list->sizeItems <= list->nbItems) {
3461 void **tmp;
3462 size_t newSize = list->sizeItems == 0 ? 20 : list->sizeItems * 2;
3463
3464 tmp = (void **) xmlRealloc(list->items, newSize * sizeof(void *));
3465 if (tmp == NULL) {
3466 xmlSchemaPErrMemory(NULL, "growing item list", NULL);
3467 return(-1);
3468 }
3469 list->items = tmp;
3470 list->sizeItems = newSize;
3471 }
3472 /*
3473 * Just append if the index is greater/equal than the item count.
3474 */
3475 if (idx >= list->nbItems) {
3476 list->items[list->nbItems++] = item;
3477 } else {
3478 int i;
3479 for (i = list->nbItems; i > idx; i--)
3480 list->items[i] = list->items[i-1];
3481 list->items[idx] = item;
3482 list->nbItems++;
3483 }
3484 return(0);
3485}
3486
3487#if 0 /* enable if ever needed */
3488static int
3489xmlSchemaItemListInsertSize(xmlSchemaItemListPtr list,
3490 int initialSize,
3491 void *item,
3492 int idx)
3493{
3494 if (list->items == NULL) {
3495 if (initialSize <= 0)
3496 initialSize = 1;
3497 list->items = (void **) xmlMalloc(
3498 initialSize * sizeof(void *));
3499 if (list->items == NULL) {
3500 xmlSchemaPErrMemory(NULL, "allocating new item list", NULL);
3501 return(-1);
3502 }
3503 list->sizeItems = initialSize;
3504 } else if (list->sizeItems <= list->nbItems) {
3505 list->sizeItems *= 2;
3506 list->items = (void **) xmlRealloc(list->items,
3507 list->sizeItems * sizeof(void *));
3508 if (list->items == NULL) {
3509 xmlSchemaPErrMemory(NULL, "growing item list", NULL);
3510 list->sizeItems = 0;
3511 return(-1);
3512 }
3513 }
3514 /*
3515 * Just append if the index is greater/equal than the item count.
3516 */
3517 if (idx >= list->nbItems) {
3518 list->items[list->nbItems++] = item;
3519 } else {
3520 int i;
3521 for (i = list->nbItems; i > idx; i--)
3522 list->items[i] = list->items[i-1];
3523 list->items[idx] = item;
3524 list->nbItems++;
3525 }
3526 return(0);
3527}
3528#endif
3529
3530static int
3531xmlSchemaItemListRemove(xmlSchemaItemListPtr list, int idx)
3532{
3533 int i;
3534 if ((list->items == NULL) || (idx >= list->nbItems)) {
3535 xmlSchemaPSimpleErr("Internal error: xmlSchemaItemListRemove, "
3536 "index error.\n");
3537 return(-1);
3538 }
3539
3540 if (list->nbItems == 1) {
3541 /* TODO: Really free the list? */
3542 xmlFree(list->items);
3543 list->items = NULL;
3544 list->nbItems = 0;
3545 list->sizeItems = 0;
3546 } else if (list->nbItems -1 == idx) {
3547 list->nbItems--;
3548 } else {
3549 for (i = idx; i < list->nbItems -1; i++)
3550 list->items[i] = list->items[i+1];
3551 list->nbItems--;
3552 }
3553 return(0);
3554}
3555
3562static void
3563xmlSchemaItemListFree(xmlSchemaItemListPtr list)
3564{
3565 if (list == NULL)
3566 return;
3567 if (list->items != NULL)
3568 xmlFree(list->items);
3569 xmlFree(list);
3570}
3571
3572static void
3573xmlSchemaBucketFree(xmlSchemaBucketPtr bucket)
3574{
3575 if (bucket == NULL)
3576 return;
3577 if (bucket->globals != NULL) {
3578 xmlSchemaComponentListFree(bucket->globals);
3579 xmlSchemaItemListFree(bucket->globals);
3580 }
3581 if (bucket->locals != NULL) {
3582 xmlSchemaComponentListFree(bucket->locals);
3583 xmlSchemaItemListFree(bucket->locals);
3584 }
3585 if (bucket->relations != NULL) {
3586 xmlSchemaSchemaRelationPtr prev, cur = bucket->relations;
3587 do {
3588 prev = cur;
3589 cur = cur->next;
3590 xmlFree(prev);
3591 } while (cur != NULL);
3592 }
3593 if ((! bucket->preserveDoc) && (bucket->doc != NULL)) {
3594 xmlFreeDoc(bucket->doc);
3595 }
3596 if (bucket->type == XML_SCHEMA_SCHEMA_IMPORT) {
3597 if (WXS_IMPBUCKET(bucket)->schema != NULL)
3598 xmlSchemaFree(WXS_IMPBUCKET(bucket)->schema);
3599 }
3600 xmlFree(bucket);
3601}
3602
3603static void
3604xmlSchemaBucketFreeEntry(void *bucket, const xmlChar *name ATTRIBUTE_UNUSED)
3605{
3606 xmlSchemaBucketFree((xmlSchemaBucketPtr) bucket);
3607}
3608
3609static xmlSchemaBucketPtr
3610xmlSchemaBucketCreate(xmlSchemaParserCtxtPtr pctxt,
3611 int type, const xmlChar *targetNamespace)
3612{
3613 xmlSchemaBucketPtr ret;
3614 int size;
3615 xmlSchemaPtr mainSchema;
3616
3617 if (WXS_CONSTRUCTOR(pctxt)->mainSchema == NULL) {
3618 PERROR_INT("xmlSchemaBucketCreate",
3619 "no main schema on constructor");
3620 return(NULL);
3621 }
3622 mainSchema = WXS_CONSTRUCTOR(pctxt)->mainSchema;
3623 /* Create the schema bucket. */
3624 if (WXS_IS_BUCKET_INCREDEF(type))
3625 size = sizeof(xmlSchemaInclude);
3626 else
3627 size = sizeof(xmlSchemaImport);
3628 ret = (xmlSchemaBucketPtr) xmlMalloc(size);
3629 if (ret == NULL) {
3630 xmlSchemaPErrMemory(NULL, "allocating schema bucket", NULL);
3631 return(NULL);
3632 }
3633 memset(ret, 0, size);
3634 ret->targetNamespace = targetNamespace;
3635 ret->type = type;
3636 ret->globals = xmlSchemaItemListCreate();
3637 if (ret->globals == NULL) {
3638 xmlSchemaBucketFree(ret);
3639 return(NULL);
3640 }
3641 ret->locals = xmlSchemaItemListCreate();
3642 if (ret->locals == NULL) {
3643 xmlSchemaBucketFree(ret);
3644 return(NULL);
3645 }
3646 /*
3647 * The following will assure that only the first bucket is marked as
3648 * XML_SCHEMA_SCHEMA_MAIN and it points to the *main* schema.
3649 * For each following import buckets an xmlSchema will be created.
3650 * An xmlSchema will be created for every distinct targetNamespace.
3651 * We assign the targetNamespace to the schemata here.
3652 */
3653 if (! WXS_HAS_BUCKETS(pctxt)) {
3654 if (WXS_IS_BUCKET_INCREDEF(type)) {
3655 PERROR_INT("xmlSchemaBucketCreate",
3656 "first bucket but it's an include or redefine");
3657 xmlSchemaBucketFree(ret);
3658 return(NULL);
3659 }
3660 /* Force the type to be XML_SCHEMA_SCHEMA_MAIN. */
3661 ret->type = XML_SCHEMA_SCHEMA_MAIN;
3662 /* Point to the *main* schema. */
3663 WXS_CONSTRUCTOR(pctxt)->mainBucket = ret;
3664 WXS_IMPBUCKET(ret)->schema = mainSchema;
3665 /*
3666 * Ensure that the main schema gets a targetNamespace.
3667 */
3668 mainSchema->targetNamespace = targetNamespace;
3669 } else {
3670 if (type == XML_SCHEMA_SCHEMA_MAIN) {
3671 PERROR_INT("xmlSchemaBucketCreate",
3672 "main bucket but it's not the first one");
3673 xmlSchemaBucketFree(ret);
3674 return(NULL);
3675 } else if (type == XML_SCHEMA_SCHEMA_IMPORT) {
3676 /*
3677 * Create a schema for imports and assign the
3678 * targetNamespace.
3679 */
3680 WXS_IMPBUCKET(ret)->schema = xmlSchemaNewSchema(pctxt);
3681 if (WXS_IMPBUCKET(ret)->schema == NULL) {
3682 xmlSchemaBucketFree(ret);
3683 return(NULL);
3684 }
3685 WXS_IMPBUCKET(ret)->schema->targetNamespace = targetNamespace;
3686 }
3687 }
3688 if (WXS_IS_BUCKET_IMPMAIN(type)) {
3689 int res;
3690 /*
3691 * Imports go into the "schemasImports" slot of the main *schema*.
3692 * Note that we create an import entry for the main schema as well; i.e.,
3693 * even if there's only one schema, we'll get an import.
3694 */
3695 if (mainSchema->schemasImports == NULL) {
3696 mainSchema->schemasImports = xmlHashCreateDict(5,
3697 WXS_CONSTRUCTOR(pctxt)->dict);
3698 if (mainSchema->schemasImports == NULL) {
3699 xmlSchemaBucketFree(ret);
3700 return(NULL);
3701 }
3702 }
3703 if (targetNamespace == NULL)
3704 res = xmlHashAddEntry(mainSchema->schemasImports,
3705 XML_SCHEMAS_NO_NAMESPACE, ret);
3706 else
3707 res = xmlHashAddEntry(mainSchema->schemasImports,
3708 targetNamespace, ret);
3709 if (res != 0) {
3710 PERROR_INT("xmlSchemaBucketCreate",
3711 "failed to add the schema bucket to the hash");
3712 xmlSchemaBucketFree(ret);
3713 return(NULL);
3714 }
3715 } else {
3716 /* Set the @ownerImport of an include bucket. */
3717 if (WXS_IS_BUCKET_IMPMAIN(WXS_CONSTRUCTOR(pctxt)->bucket->type))
3718 WXS_INCBUCKET(ret)->ownerImport =
3719 WXS_IMPBUCKET(WXS_CONSTRUCTOR(pctxt)->bucket);
3720 else
3721 WXS_INCBUCKET(ret)->ownerImport =
3722 WXS_INCBUCKET(WXS_CONSTRUCTOR(pctxt)->bucket)->ownerImport;
3723
3724 /* Includes got into the "includes" slot of the *main* schema. */
3725 if (mainSchema->includes == NULL) {
3726 mainSchema->includes = xmlSchemaItemListCreate();
3727 if (mainSchema->includes == NULL) {
3728 xmlSchemaBucketFree(ret);
3729 return(NULL);
3730 }
3731 }
3732 if (xmlSchemaItemListAdd(mainSchema->includes, ret) < 0) {
3733 xmlSchemaBucketFree(ret);
3734 return(NULL);
3735 }
3736 }
3737 /*
3738 * Add to list of all buckets; this is used for lookup
3739 * during schema construction time only.
3740 */
3741 if (xmlSchemaItemListAdd(WXS_CONSTRUCTOR(pctxt)->buckets, ret) == -1)
3742 return(NULL);
3743 return(ret);
3744}
3745
3746static int
3747xmlSchemaAddItemSize(xmlSchemaItemListPtr *list, int initialSize, void *item)
3748{
3749 if (*list == NULL) {
3750 *list = xmlSchemaItemListCreate();
3751 if (*list == NULL)
3752 return(-1);
3753 }
3754 return(xmlSchemaItemListAddSize(*list, initialSize, item));
3755}
3756
3763static void
3764xmlSchemaFreeAnnot(xmlSchemaAnnotPtr annot)
3765{
3766 if (annot == NULL)
3767 return;
3768 if (annot->next == NULL) {
3769 xmlFree(annot);
3770 } else {
3771 xmlSchemaAnnotPtr prev;
3772
3773 do {
3774 prev = annot;
3775 annot = annot->next;
3776 xmlFree(prev);
3777 } while (annot != NULL);
3778 }
3779}
3780
3787static void
3788xmlSchemaFreeNotation(xmlSchemaNotationPtr nota)
3789{
3790 if (nota == NULL)
3791 return;
3792 if (nota->annot != NULL)
3793 xmlSchemaFreeAnnot(nota->annot);
3794 xmlFree(nota);
3795}
3796
3803static void
3804xmlSchemaFreeAttribute(xmlSchemaAttributePtr attr)
3805{
3806 if (attr == NULL)
3807 return;
3808 if (attr->annot != NULL)
3809 xmlSchemaFreeAnnot(attr->annot);
3810 if (attr->defVal != NULL)
3811 xmlSchemaFreeValue(attr->defVal);
3812 xmlFree(attr);
3813}
3814
3821static void
3822xmlSchemaFreeAttributeUse(xmlSchemaAttributeUsePtr use)
3823{
3824 if (use == NULL)
3825 return;
3826 if (use->annot != NULL)
3827 xmlSchemaFreeAnnot(use->annot);
3828 if (use->defVal != NULL)
3829 xmlSchemaFreeValue(use->defVal);
3830 xmlFree(use);
3831}
3832
3839static void
3840xmlSchemaFreeAttributeUseProhib(xmlSchemaAttributeUseProhibPtr prohib)
3841{
3842 if (prohib == NULL)
3843 return;
3844 xmlFree(prohib);
3845}
3846
3853static void
3854xmlSchemaFreeWildcardNsSet(xmlSchemaWildcardNsPtr set)
3855{
3856 xmlSchemaWildcardNsPtr next;
3857
3858 while (set != NULL) {
3859 next = set->next;
3860 xmlFree(set);
3861 set = next;
3862 }
3863}
3864
3871void
3872xmlSchemaFreeWildcard(xmlSchemaWildcardPtr wildcard)
3873{
3874 if (wildcard == NULL)
3875 return;
3876 if (wildcard->annot != NULL)
3877 xmlSchemaFreeAnnot(wildcard->annot);
3878 if (wildcard->nsSet != NULL)
3879 xmlSchemaFreeWildcardNsSet(wildcard->nsSet);
3880 if (wildcard->negNsSet != NULL)
3881 xmlFree(wildcard->negNsSet);
3882 xmlFree(wildcard);
3883}
3884
3891static void
3892xmlSchemaFreeAttributeGroup(xmlSchemaAttributeGroupPtr attrGr)
3893{
3894 if (attrGr == NULL)
3895 return;
3896 if (attrGr->annot != NULL)
3897 xmlSchemaFreeAnnot(attrGr->annot);
3898 if (attrGr->attrUses != NULL)
3899 xmlSchemaItemListFree(WXS_LIST_CAST attrGr->attrUses);
3900 xmlFree(attrGr);
3901}
3902
3909static void
3910xmlSchemaFreeQNameRef(xmlSchemaQNameRefPtr item)
3911{
3912 xmlFree(item);
3913}
3914
3921static void
3922xmlSchemaFreeTypeLinkList(xmlSchemaTypeLinkPtr link)
3923{
3924 xmlSchemaTypeLinkPtr next;
3925
3926 while (link != NULL) {
3927 next = link->next;
3928 xmlFree(link);
3929 link = next;
3930 }
3931}
3932
3933static void
3934xmlSchemaFreeIDCStateObjList(xmlSchemaIDCStateObjPtr sto)
3935{
3936 xmlSchemaIDCStateObjPtr next;
3937 while (sto != NULL) {
3938 next = sto->next;
3939 if (sto->history != NULL)
3940 xmlFree(sto->history);
3941 if (sto->xpathCtxt != NULL)
3942 xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
3943 xmlFree(sto);
3944 sto = next;
3945 }
3946}
3947
3954static void
3955xmlSchemaFreeIDC(xmlSchemaIDCPtr idcDef)
3956{
3957 xmlSchemaIDCSelectPtr cur, prev;
3958
3959 if (idcDef == NULL)
3960 return;
3961 if (idcDef->annot != NULL)
3962 xmlSchemaFreeAnnot(idcDef->annot);
3963 /* Selector */
3964 if (idcDef->selector != NULL) {
3965 if (idcDef->selector->xpathComp != NULL)
3966 xmlFreePattern((xmlPatternPtr) idcDef->selector->xpathComp);
3967 xmlFree(idcDef->selector);
3968 }
3969 /* Fields */
3970 if (idcDef->fields != NULL) {
3971 cur = idcDef->fields;
3972 do {
3973 prev = cur;
3974 cur = cur->next;
3975 if (prev->xpathComp != NULL)
3976 xmlFreePattern((xmlPatternPtr) prev->xpathComp);
3977 xmlFree(prev);
3978 } while (cur != NULL);
3979 }
3980 xmlFree(idcDef);
3981}
3982
3989static void
3990xmlSchemaFreeElement(xmlSchemaElementPtr elem)
3991{
3992 if (elem == NULL)
3993 return;
3994 if (elem->annot != NULL)
3995 xmlSchemaFreeAnnot(elem->annot);
3996 if (elem->contModel != NULL)
3997 xmlRegFreeRegexp(elem->contModel);
3998 if (elem->defVal != NULL)
3999 xmlSchemaFreeValue(elem->defVal);
4000 xmlFree(elem);
4001}
4002
4009void
4010xmlSchemaFreeFacet(xmlSchemaFacetPtr facet)
4011{
4012 if (facet == NULL)
4013 return;
4014 if (facet->val != NULL)
4015 xmlSchemaFreeValue(facet->val);
4016 if (facet->regexp != NULL)
4017 xmlRegFreeRegexp(facet->regexp);
4018 if (facet->annot != NULL)
4019 xmlSchemaFreeAnnot(facet->annot);
4020 xmlFree(facet);
4021}
4022
4029void
4030xmlSchemaFreeType(xmlSchemaTypePtr type)
4031{
4032 if (type == NULL)
4033 return;
4034 if (type->annot != NULL)
4035 xmlSchemaFreeAnnot(type->annot);
4036 if (type->facets != NULL) {
4037 xmlSchemaFacetPtr facet, next;
4038
4039 facet = type->facets;
4040 while (facet != NULL) {
4041 next = facet->next;
4042 xmlSchemaFreeFacet(facet);
4043 facet = next;
4044 }
4045 }
4046 if (type->attrUses != NULL)
4047 xmlSchemaItemListFree((xmlSchemaItemListPtr) type->attrUses);
4048 if (type->memberTypes != NULL)
4049 xmlSchemaFreeTypeLinkList(type->memberTypes);
4050 if (type->facetSet != NULL) {
4051 xmlSchemaFacetLinkPtr next, link;
4052
4053 link = type->facetSet;
4054 do {
4055 next = link->next;
4056 xmlFree(link);
4057 link = next;
4058 } while (link != NULL);
4059 }
4060 if (type->contModel != NULL)
4061 xmlRegFreeRegexp(type->contModel);
4062 xmlFree(type);
4063}
4064
4071static void
4072xmlSchemaFreeModelGroupDef(xmlSchemaModelGroupDefPtr item)
4073{
4074 if (item->annot != NULL)
4075 xmlSchemaFreeAnnot(item->annot);
4076 xmlFree(item);
4077}
4078
4085static void
4086xmlSchemaFreeModelGroup(xmlSchemaModelGroupPtr item)
4087{
4088 if (item->annot != NULL)
4089 xmlSchemaFreeAnnot(item->annot);
4090 xmlFree(item);
4091}
4092
4093static void
4094xmlSchemaComponentListFree(xmlSchemaItemListPtr list)
4095{
4096 if ((list == NULL) || (list->nbItems == 0))
4097 return;
4098 {
4099 xmlSchemaTreeItemPtr item;
4100 xmlSchemaTreeItemPtr *items = (xmlSchemaTreeItemPtr *) list->items;
4101 int i;
4102
4103 for (i = 0; i < list->nbItems; i++) {
4104 item = items[i];
4105 if (item == NULL)
4106 continue;
4107 switch (item->type) {
4108 case XML_SCHEMA_TYPE_SIMPLE:
4109 case XML_SCHEMA_TYPE_COMPLEX:
4110 xmlSchemaFreeType((xmlSchemaTypePtr) item);
4111 break;
4112 case XML_SCHEMA_TYPE_ATTRIBUTE:
4113 xmlSchemaFreeAttribute((xmlSchemaAttributePtr) item);
4114 break;
4115 case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
4116 xmlSchemaFreeAttributeUse((xmlSchemaAttributeUsePtr) item);
4117 break;
4118 case XML_SCHEMA_EXTRA_ATTR_USE_PROHIB:
4119 xmlSchemaFreeAttributeUseProhib(
4120 (xmlSchemaAttributeUseProhibPtr) item);
4121 break;
4122 case XML_SCHEMA_TYPE_ELEMENT:
4123 xmlSchemaFreeElement((xmlSchemaElementPtr) item);
4124 break;
4125 case XML_SCHEMA_TYPE_PARTICLE:
4126 if (item->annot != NULL)
4127 xmlSchemaFreeAnnot(item->annot);
4128 xmlFree(item);
4129 break;
4130 case XML_SCHEMA_TYPE_SEQUENCE:
4131 case XML_SCHEMA_TYPE_CHOICE:
4132 case XML_SCHEMA_TYPE_ALL:
4133 xmlSchemaFreeModelGroup((xmlSchemaModelGroupPtr) item);
4134 break;
4135 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
4136 xmlSchemaFreeAttributeGroup(
4137 (xmlSchemaAttributeGroupPtr) item);
4138 break;
4139 case XML_SCHEMA_TYPE_GROUP:
4140 xmlSchemaFreeModelGroupDef(
4141 (xmlSchemaModelGroupDefPtr) item);
4142 break;
4143 case XML_SCHEMA_TYPE_ANY:
4144 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
4145 xmlSchemaFreeWildcard((xmlSchemaWildcardPtr) item);
4146 break;
4147 case XML_SCHEMA_TYPE_IDC_KEY:
4148 case XML_SCHEMA_TYPE_IDC_UNIQUE:
4149 case XML_SCHEMA_TYPE_IDC_KEYREF:
4150 xmlSchemaFreeIDC((xmlSchemaIDCPtr) item);
4151 break;
4152 case XML_SCHEMA_TYPE_NOTATION:
4153 xmlSchemaFreeNotation((xmlSchemaNotationPtr) item);
4154 break;
4155 case XML_SCHEMA_EXTRA_QNAMEREF:
4156 xmlSchemaFreeQNameRef((xmlSchemaQNameRefPtr) item);
4157 break;
4158 default: {
4159 /* TODO: This should never be hit. */
4160 xmlSchemaPSimpleInternalErr(NULL,
4161 "Internal error: xmlSchemaComponentListFree, "
4162 "unexpected component type '%s'\n",
4163 (const xmlChar *) WXS_ITEM_TYPE_NAME(item));
4164 }
4165 break;
4166 }
4167 }
4168 list->nbItems = 0;
4169 }
4170}
4171
4178void
4179xmlSchemaFree(xmlSchemaPtr schema)
4180{
4181 if (schema == NULL)
4182 return;
4183 /* @volatiles is not used anymore :-/ */
4184 if (schema->volatiles != NULL)
4185 TODO
4186 /*
4187 * Note that those slots are not responsible for freeing
4188 * schema components anymore; this will now be done by
4189 * the schema buckets.
4190 */
4191 if (schema->notaDecl != NULL)
4192 xmlHashFree(schema->notaDecl, NULL);
4193 if (schema->attrDecl != NULL)
4194 xmlHashFree(schema->attrDecl, NULL);
4195 if (schema->attrgrpDecl != NULL)
4196 xmlHashFree(schema->attrgrpDecl, NULL);
4197 if (schema->elemDecl != NULL)
4198 xmlHashFree(schema->elemDecl, NULL);
4199 if (schema->typeDecl != NULL)
4200 xmlHashFree(schema->typeDecl, NULL);
4201 if (schema->groupDecl != NULL)
4202 xmlHashFree(schema->groupDecl, NULL);
4203 if (schema->idcDef != NULL)
4204 xmlHashFree(schema->idcDef, NULL);
4205
4206 if (schema->schemasImports != NULL)
4207 xmlHashFree(schema->schemasImports, xmlSchemaBucketFreeEntry);
4208 if (schema->includes != NULL) {
4209 xmlSchemaItemListPtr list = (xmlSchemaItemListPtr) schema->includes;
4210 int i;
4211 for (i = 0; i < list->nbItems; i++) {
4212 xmlSchemaBucketFree((xmlSchemaBucketPtr) list->items[i]);
4213 }
4214 xmlSchemaItemListFree(list);
4215 }
4216 if (schema->annot != NULL)
4217 xmlSchemaFreeAnnot(schema->annot);
4218 /* Never free the doc here, since this will be done by the buckets. */
4219
4220 xmlDictFree(schema->dict);
4221 xmlFree(schema);
4222}
4223
4224/************************************************************************
4225 * *
4226 * Debug functions *
4227 * *
4228 ************************************************************************/
4229
4230#ifdef LIBXML_OUTPUT_ENABLED
4231
4232static void
4233xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output); /* forward */
4234
4242static void
4243xmlSchemaElementDump(void *payload, void *data,
4245 const xmlChar * namespace ATTRIBUTE_UNUSED,
4247{
4248 xmlSchemaElementPtr elem = (xmlSchemaElementPtr) payload;
4249 FILE *output = (FILE *) data;
4250 if (elem == NULL)
4251 return;
4252
4253
4254 fprintf(output, "Element");
4255 if (elem->flags & XML_SCHEMAS_ELEM_GLOBAL)
4256 fprintf(output, " (global)");
4257 fprintf(output, ": '%s' ", elem->name);
4258 if (namespace != NULL)
4259 fprintf(output, "ns '%s'", namespace);
4260 fprintf(output, "\n");
4261#if 0
4262 if ((elem->minOccurs != 1) || (elem->maxOccurs != 1)) {
4263 fprintf(output, " min %d ", elem->minOccurs);
4264 if (elem->maxOccurs >= UNBOUNDED)
4265 fprintf(output, "max: unbounded\n");
4266 else if (elem->maxOccurs != 1)
4267 fprintf(output, "max: %d\n", elem->maxOccurs);
4268 else
4269 fprintf(output, "\n");
4270 }
4271#endif
4272 /*
4273 * Misc other properties.
4274 */
4275 if ((elem->flags & XML_SCHEMAS_ELEM_NILLABLE) ||
4276 (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT) ||
4277 (elem->flags & XML_SCHEMAS_ELEM_FIXED) ||
4278 (elem->flags & XML_SCHEMAS_ELEM_DEFAULT)) {
4279 fprintf(output, " props: ");
4280 if (elem->flags & XML_SCHEMAS_ELEM_FIXED)
4281 fprintf(output, "[fixed] ");
4282 if (elem->flags & XML_SCHEMAS_ELEM_DEFAULT)
4283 fprintf(output, "[default] ");
4284 if (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT)
4285 fprintf(output, "[abstract] ");
4286 if (elem->flags & XML_SCHEMAS_ELEM_NILLABLE)
4287 fprintf(output, "[nillable] ");
4288 fprintf(output, "\n");
4289 }
4290 /*
4291 * Default/fixed value.
4292 */
4293 if (elem->value != NULL)
4294 fprintf(output, " value: '%s'\n", elem->value);
4295 /*
4296 * Type.
4297 */
4298 if (elem->namedType != NULL) {
4299 fprintf(output, " type: '%s' ", elem->namedType);
4300 if (elem->namedTypeNs != NULL)
4301 fprintf(output, "ns '%s'\n", elem->namedTypeNs);
4302 else
4303 fprintf(output, "\n");
4304 } else if (elem->subtypes != NULL) {
4305 /*
4306 * Dump local types.
4307 */
4308 xmlSchemaTypeDump(elem->subtypes, output);
4309 }
4310 /*
4311 * Substitution group.
4312 */
4313 if (elem->substGroup != NULL) {
4314 fprintf(output, " substitutionGroup: '%s' ", elem->substGroup);
4315 if (elem->substGroupNs != NULL)
4316 fprintf(output, "ns '%s'\n", elem->substGroupNs);
4317 else
4318 fprintf(output, "\n");
4319 }
4320}
4321
4329static void
4330xmlSchemaAnnotDump(FILE * output, xmlSchemaAnnotPtr annot)
4331{
4333
4334 if (annot == NULL)
4335 return;
4336
4337 content = xmlNodeGetContent(annot->content);
4338 if (content != NULL) {
4339 fprintf(output, " Annot: %s\n", content);
4341 } else
4342 fprintf(output, " Annot: empty\n");
4343}
4344
4353static void
4354xmlSchemaContentModelDump(xmlSchemaParticlePtr particle, FILE * output, int depth)
4355{
4356 xmlChar *str = NULL;
4357 xmlSchemaTreeItemPtr term;
4358 char shift[100];
4359 int i;
4360
4361 if (particle == NULL)
4362 return;
4363 for (i = 0;((i < depth) && (i < 25));i++)
4364 shift[2 * i] = shift[2 * i + 1] = ' ';
4365 shift[2 * i] = shift[2 * i + 1] = 0;
4366 fprintf(output, "%s", shift);
4367 if (particle->children == NULL) {
4368 fprintf(output, "MISSING particle term\n");
4369 return;
4370 }
4371 term = particle->children;
4372 if (term == NULL) {
4373 fprintf(output, "(NULL)");
4374 } else {
4375 switch (term->type) {
4376 case XML_SCHEMA_TYPE_ELEMENT:
4377 fprintf(output, "ELEM '%s'", xmlSchemaFormatQName(&str,
4378 ((xmlSchemaElementPtr)term)->targetNamespace,
4379 ((xmlSchemaElementPtr)term)->name));
4380 FREE_AND_NULL(str);
4381 break;
4382 case XML_SCHEMA_TYPE_SEQUENCE:
4383 fprintf(output, "SEQUENCE");
4384 break;
4385 case XML_SCHEMA_TYPE_CHOICE:
4386 fprintf(output, "CHOICE");
4387 break;
4388 case XML_SCHEMA_TYPE_ALL:
4389 fprintf(output, "ALL");
4390 break;
4391 case XML_SCHEMA_TYPE_ANY:
4392 fprintf(output, "ANY");
4393 break;
4394 default:
4395 fprintf(output, "UNKNOWN\n");
4396 return;
4397 }
4398 }
4399 if (particle->minOccurs != 1)
4400 fprintf(output, " min: %d", particle->minOccurs);
4401 if (particle->maxOccurs >= UNBOUNDED)
4402 fprintf(output, " max: unbounded");
4403 else if (particle->maxOccurs != 1)
4404 fprintf(output, " max: %d", particle->maxOccurs);
4405 fprintf(output, "\n");
4406 if (term &&
4407 ((term->type == XML_SCHEMA_TYPE_SEQUENCE) ||
4408 (term->type == XML_SCHEMA_TYPE_CHOICE) ||
4409 (term->type == XML_SCHEMA_TYPE_ALL)) &&
4410 (term->children != NULL)) {
4411 xmlSchemaContentModelDump((xmlSchemaParticlePtr) term->children,
4412 output, depth +1);
4413 }
4414 if (particle->next != NULL)
4415 xmlSchemaContentModelDump((xmlSchemaParticlePtr) particle->next,
4416 output, depth);
4417}
4418
4426static void
4427xmlSchemaAttrUsesDump(xmlSchemaItemListPtr uses, FILE * output)
4428{
4429 xmlSchemaAttributeUsePtr use;
4430 xmlSchemaAttributeUseProhibPtr prohib;
4431 xmlSchemaQNameRefPtr ref;
4432 const xmlChar *name, *tns;
4433 xmlChar *str = NULL;
4434 int i;
4435
4436 if ((uses == NULL) || (uses->nbItems == 0))
4437 return;
4438
4439 fprintf(output, " attributes:\n");
4440 for (i = 0; i < uses->nbItems; i++) {
4441 use = uses->items[i];
4442 if (use->type == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB) {
4443 fprintf(output, " [prohibition] ");
4444 prohib = (xmlSchemaAttributeUseProhibPtr) use;
4445 name = prohib->name;
4446 tns = prohib->targetNamespace;
4447 } else if (use->type == XML_SCHEMA_EXTRA_QNAMEREF) {
4448 fprintf(output, " [reference] ");
4449 ref = (xmlSchemaQNameRefPtr) use;
4450 name = ref->name;
4451 tns = ref->targetNamespace;
4452 } else {
4453 fprintf(output, " [use] ");
4454 name = WXS_ATTRUSE_DECL_NAME(use);
4455 tns = WXS_ATTRUSE_DECL_TNS(use);
4456 }
4457 fprintf(output, "'%s'\n",
4458 (const char *) xmlSchemaFormatQName(&str, tns, name));
4459 FREE_AND_NULL(str);
4460 }
4461}
4462
4470static void
4471xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output)
4472{
4473 if (type == NULL) {
4474 fprintf(output, "Type: NULL\n");
4475 return;
4476 }
4477 fprintf(output, "Type: ");
4478 if (type->name != NULL)
4479 fprintf(output, "'%s' ", type->name);
4480 else
4481 fprintf(output, "(no name) ");
4482 if (type->targetNamespace != NULL)
4483 fprintf(output, "ns '%s' ", type->targetNamespace);
4484 switch (type->type) {
4485 case XML_SCHEMA_TYPE_BASIC:
4486 fprintf(output, "[basic] ");
4487 break;
4488 case XML_SCHEMA_TYPE_SIMPLE:
4489 fprintf(output, "[simple] ");
4490 break;
4491 case XML_SCHEMA_TYPE_COMPLEX:
4492 fprintf(output, "[complex] ");
4493 break;
4494 case XML_SCHEMA_TYPE_SEQUENCE:
4495 fprintf(output, "[sequence] ");
4496 break;
4497 case XML_SCHEMA_TYPE_CHOICE:
4498 fprintf(output, "[choice] ");
4499 break;
4500 case XML_SCHEMA_TYPE_ALL:
4501 fprintf(output, "[all] ");
4502 break;
4503 case XML_SCHEMA_TYPE_UR:
4504 fprintf(output, "[ur] ");
4505 break;
4506 case XML_SCHEMA_TYPE_RESTRICTION:
4507 fprintf(output, "[restriction] ");
4508 break;
4509 case XML_SCHEMA_TYPE_EXTENSION:
4510 fprintf(output, "[extension] ");
4511 break;
4512 default:
4513 fprintf(output, "[unknown type %d] ", type->type);
4514 break;
4515 }
4516 fprintf(output, "content: ");
4517 switch (type->contentType) {
4518 case XML_SCHEMA_CONTENT_UNKNOWN:
4519 fprintf(output, "[unknown] ");
4520 break;
4521 case XML_SCHEMA_CONTENT_EMPTY:
4522 fprintf(output, "[empty] ");
4523 break;
4524 case XML_SCHEMA_CONTENT_ELEMENTS:
4525 fprintf(output, "[element] ");
4526 break;
4527 case XML_SCHEMA_CONTENT_MIXED:
4528 fprintf(output, "[mixed] ");
4529 break;
4530 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
4531 /* not used. */
4532 break;
4533 case XML_SCHEMA_CONTENT_BASIC:
4534 fprintf(output, "[basic] ");
4535 break;
4536 case XML_SCHEMA_CONTENT_SIMPLE:
4537 fprintf(output, "[simple] ");
4538 break;
4539 case XML_SCHEMA_CONTENT_ANY:
4540 fprintf(output, "[any] ");
4541 break;
4542 }
4543 fprintf(output, "\n");
4544 if (type->base != NULL) {
4545 fprintf(output, " base type: '%s'", type->base);
4546 if (type->baseNs != NULL)
4547 fprintf(output, " ns '%s'\n", type->baseNs);
4548 else
4549 fprintf(output, "\n");
4550 }
4551 if (type->attrUses != NULL)
4552 xmlSchemaAttrUsesDump(type->attrUses, output);
4553 if (type->annot != NULL)
4554 xmlSchemaAnnotDump(output, type->annot);
4555#ifdef DUMP_CONTENT_MODEL
4556 if ((type->type == XML_SCHEMA_TYPE_COMPLEX) &&
4557 (type->subtypes != NULL)) {
4558 xmlSchemaContentModelDump((xmlSchemaParticlePtr) type->subtypes,
4559 output, 1);
4560 }
4561#endif
4562}
4563
4564static void
4565xmlSchemaTypeDumpEntry(void *type, void *output,
4567{
4568 xmlSchemaTypeDump((xmlSchemaTypePtr) type, (FILE *) output);
4569}
4570
4578void
4579xmlSchemaDump(FILE * output, xmlSchemaPtr schema)
4580{
4581 if (output == NULL)
4582 return;
4583 if (schema == NULL) {
4584 fprintf(output, "Schemas: NULL\n");
4585 return;
4586 }
4587 fprintf(output, "Schemas: ");
4588 if (schema->name != NULL)
4589 fprintf(output, "%s, ", schema->name);
4590 else
4591 fprintf(output, "no name, ");
4592 if (schema->targetNamespace != NULL)
4593 fprintf(output, "%s", (const char *) schema->targetNamespace);
4594 else
4595 fprintf(output, "no target namespace");
4596 fprintf(output, "\n");
4597 if (schema->annot != NULL)
4598 xmlSchemaAnnotDump(output, schema->annot);
4599 xmlHashScan(schema->typeDecl, xmlSchemaTypeDumpEntry, output);
4600 xmlHashScanFull(schema->elemDecl, xmlSchemaElementDump, output);
4601}
4602
4603#endif /* LIBXML_OUTPUT_ENABLED */
4604
4605/************************************************************************
4606 * *
4607 * Utilities *
4608 * *
4609 ************************************************************************/
4610
4621static xmlAttrPtr
4622xmlSchemaGetPropNode(xmlNodePtr node, const char *name)
4623{
4624 xmlAttrPtr prop;
4625
4626 if ((node == NULL) || (name == NULL))
4627 return(NULL);
4628 prop = node->properties;
4629 while (prop != NULL) {
4630 if ((prop->ns == NULL) && xmlStrEqual(prop->name, BAD_CAST name))
4631 return(prop);
4632 prop = prop->next;
4633 }
4634 return (NULL);
4635}
4636
4648static xmlAttrPtr
4649xmlSchemaGetPropNodeNs(xmlNodePtr node, const char *uri, const char *name)
4650{
4651 xmlAttrPtr prop;
4652
4653 if ((node == NULL) || (name == NULL))
4654 return(NULL);
4655 prop = node->properties;
4656 while (prop != NULL) {
4657 if ((prop->ns != NULL) &&
4658 xmlStrEqual(prop->name, BAD_CAST name) &&
4659 xmlStrEqual(prop->ns->href, BAD_CAST uri))
4660 return(prop);
4661 prop = prop->next;
4662 }
4663 return (NULL);
4664}
4665
4666static const xmlChar *
4667xmlSchemaGetNodeContent(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
4668{
4669 xmlChar *val;
4670 const xmlChar *ret;
4671
4672 val = xmlNodeGetContent(node);
4673 if (val == NULL)
4674 val = xmlStrdup((xmlChar *)"");
4675 ret = xmlDictLookup(ctxt->dict, val, -1);
4676 xmlFree(val);
4677 if (ret == NULL)
4678 xmlSchemaPErrMemory(ctxt, "getting node content", node);
4679 return(ret);
4680}
4681
4682static const xmlChar *
4683xmlSchemaGetNodeContentNoDict(xmlNodePtr node)
4684{
4685 return((const xmlChar*) xmlNodeGetContent(node));
4686}
4687
4698static const xmlChar *
4699xmlSchemaGetProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
4700 const char *name)
4701{
4702 xmlChar *val;
4703 const xmlChar *ret;
4704
4705 val = xmlGetNoNsProp(node, BAD_CAST name);
4706 if (val == NULL)
4707 return(NULL);
4708 ret = xmlDictLookup(ctxt->dict, val, -1);
4709 xmlFree(val);
4710 return(ret);
4711}
4712
4713/************************************************************************
4714 * *
4715 * Parsing functions *
4716 * *
4717 ************************************************************************/
4718
4719#define WXS_FIND_GLOBAL_ITEM(slot) \
4720 if (xmlStrEqual(nsName, schema->targetNamespace)) { \
4721 ret = xmlHashLookup(schema->slot, name); \
4722 if (ret != NULL) goto exit; \
4723 } \
4724 if (xmlHashSize(schema->schemasImports) > 1) { \
4725 xmlSchemaImportPtr import; \
4726 if (nsName == NULL) \
4727 import = xmlHashLookup(schema->schemasImports, \
4728 XML_SCHEMAS_NO_NAMESPACE); \
4729 else \
4730 import = xmlHashLookup(schema->schemasImports, nsName); \
4731 if (import == NULL) \
4732 goto exit; \
4733 ret = xmlHashLookup(import->schema->slot, name); \
4734 }
4735
4746static xmlSchemaElementPtr
4747xmlSchemaGetElem(xmlSchemaPtr schema, const xmlChar * name,
4748 const xmlChar * nsName)
4749{
4750 xmlSchemaElementPtr ret = NULL;
4751
4752 if ((name == NULL) || (schema == NULL))
4753 return(NULL);
4754 if (schema != NULL) {
4755 WXS_FIND_GLOBAL_ITEM(elemDecl)
4756 }
4757exit:
4758 return (ret);
4759}
4760
4771static xmlSchemaTypePtr
4772xmlSchemaGetType(xmlSchemaPtr schema, const xmlChar * name,
4773 const xmlChar * nsName)
4774{
4775 xmlSchemaTypePtr ret = NULL;
4776
4777 if (name == NULL)
4778 return (NULL);
4779 /* First try the built-in types. */
4780 if ((nsName != NULL) && xmlStrEqual(nsName, xmlSchemaNs)) {
4781 ret = xmlSchemaGetPredefinedType(name, nsName);
4782 if (ret != NULL)
4783 goto exit;
4784 /*
4785 * Note that we try the parsed schemas as well here
4786 * since one might have parsed the S4S, which contain more
4787 * than the built-in types.
4788 * TODO: Can we optimize this?
4789 */
4790 }
4791 if (schema != NULL) {
4792 WXS_FIND_GLOBAL_ITEM(typeDecl)
4793 }
4794exit:
4795
4796 return (ret);
4797}
4798
4809static xmlSchemaAttributePtr
4810xmlSchemaGetAttributeDecl(xmlSchemaPtr schema, const xmlChar * name,
4811 const xmlChar * nsName)
4812{
4813 xmlSchemaAttributePtr ret = NULL;
4814
4815 if ((name == NULL) || (schema == NULL))
4816 return (NULL);
4817 if (schema != NULL) {
4818 WXS_FIND_GLOBAL_ITEM(attrDecl)
4819 }
4820exit:
4821 return (ret);
4822}
4823
4834static xmlSchemaAttributeGroupPtr
4835xmlSchemaGetAttributeGroup(xmlSchemaPtr schema, const xmlChar * name,
4836 const xmlChar * nsName)
4837{
4838 xmlSchemaAttributeGroupPtr ret = NULL;
4839
4840 if ((name == NULL) || (schema == NULL))
4841 return (NULL);
4842 if (schema != NULL) {
4843 WXS_FIND_GLOBAL_ITEM(attrgrpDecl)
4844 }
4845exit:
4846 /* TODO:
4847 if ((ret != NULL) && (ret->redef != NULL)) {
4848 * Return the last redefinition. *
4849 ret = ret->redef;
4850 }
4851 */
4852 return (ret);
4853}
4854
4865static xmlSchemaModelGroupDefPtr
4866xmlSchemaGetGroup(xmlSchemaPtr schema, const xmlChar * name,
4867 const xmlChar * nsName)
4868{
4869 xmlSchemaModelGroupDefPtr ret = NULL;
4870
4871 if ((name == NULL) || (schema == NULL))
4872 return (NULL);
4873 if (schema != NULL) {
4874 WXS_FIND_GLOBAL_ITEM(groupDecl)
4875 }
4876exit:
4877
4878 return (ret);
4879}
4880
4881static xmlSchemaNotationPtr
4882xmlSchemaGetNotation(xmlSchemaPtr schema,
4883 const xmlChar *name,
4884 const xmlChar *nsName)
4885{
4886 xmlSchemaNotationPtr ret = NULL;
4887
4888 if ((name == NULL) || (schema == NULL))
4889 return (NULL);
4890 if (schema != NULL) {
4891 WXS_FIND_GLOBAL_ITEM(notaDecl)
4892 }
4893exit:
4894 return (ret);
4895}
4896
4897static xmlSchemaIDCPtr
4898xmlSchemaGetIDC(xmlSchemaPtr schema,
4899 const xmlChar *name,
4900 const xmlChar *nsName)
4901{
4902 xmlSchemaIDCPtr ret = NULL;
4903
4904 if ((name == NULL) || (schema == NULL))
4905 return (NULL);
4906 if (schema != NULL) {
4907 WXS_FIND_GLOBAL_ITEM(idcDef)
4908 }
4909exit:
4910 return (ret);
4911}
4912
4923static xmlSchemaBasicItemPtr
4924xmlSchemaGetNamedComponent(xmlSchemaPtr schema,
4925 xmlSchemaTypeType itemType,
4926 const xmlChar *name,
4927 const xmlChar *targetNs)
4928{
4929 switch (itemType) {
4930 case XML_SCHEMA_TYPE_GROUP:
4931 return ((xmlSchemaBasicItemPtr) xmlSchemaGetGroup(schema,
4932 name, targetNs));
4933 case XML_SCHEMA_TYPE_ELEMENT:
4934 return ((xmlSchemaBasicItemPtr) xmlSchemaGetElem(schema,
4935 name, targetNs));
4936 default:
4937 TODO
4938 return (NULL);
4939 }
4940}
4941
4942/************************************************************************
4943 * *
4944 * Parsing functions *
4945 * *
4946 ************************************************************************/
4947
4948#define IS_BLANK_NODE(n) \
4949 (((n)->type == XML_TEXT_NODE) && (xmlSchemaIsBlank((n)->content, -1)))
4950
4960static int
4961xmlSchemaIsBlank(xmlChar * str, int len)
4962{
4963 if (str == NULL)
4964 return (1);
4965 if (len < 0) {
4966 while (*str != 0) {
4967 if (!(IS_BLANK_CH(*str)))
4968 return (0);
4969 str++;
4970 }
4971 } else while ((*str != 0) && (len != 0)) {
4972 if (!(IS_BLANK_CH(*str)))
4973 return (0);
4974 str++;
4975 len--;
4976 }
4977
4978 return (1);
4979}
4980
4981#define WXS_COMP_NAME(c, t) ((t) (c))->name
4982#define WXS_COMP_TNS(c, t) ((t) (c))->targetNamespace
4983/*
4984* xmlSchemaFindRedefCompInGraph:
4985* ATTENTION TODO: This uses pointer comp. for strings.
4986*/
4987static xmlSchemaBasicItemPtr
4988xmlSchemaFindRedefCompInGraph(xmlSchemaBucketPtr bucket,
4989 xmlSchemaTypeType type,
4990 const xmlChar *name,
4991 const xmlChar *nsName)
4992{
4993 xmlSchemaBasicItemPtr ret;
4994 int i;
4995
4996 if ((bucket == NULL) || (name == NULL))
4997 return(NULL);
4998 if ((bucket->globals == NULL) ||
4999 (bucket->globals->nbItems == 0))
5000 goto subschemas;
5001 /*
5002 * Search in global components.
5003 */
5004 for (i = 0; i < bucket->globals->nbItems; i++) {
5005 ret = bucket->globals->items[i];
5006 if (ret->type == type) {
5007 switch (type) {
5008 case XML_SCHEMA_TYPE_COMPLEX:
5009 case XML_SCHEMA_TYPE_SIMPLE:
5010 if ((WXS_COMP_NAME(ret, xmlSchemaTypePtr) == name) &&
5011 (WXS_COMP_TNS(ret, xmlSchemaTypePtr) ==
5012 nsName))
5013 {
5014 return(ret);
5015 }
5016 break;
5017 case XML_SCHEMA_TYPE_GROUP:
5018 if ((WXS_COMP_NAME(ret,
5019 xmlSchemaModelGroupDefPtr) == name) &&
5020 (WXS_COMP_TNS(ret,
5021 xmlSchemaModelGroupDefPtr) == nsName))
5022 {
5023 return(ret);
5024 }
5025 break;
5026 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
5027 if ((WXS_COMP_NAME(ret,
5028 xmlSchemaAttributeGroupPtr) == name) &&
5029 (WXS_COMP_TNS(ret,
5030 xmlSchemaAttributeGroupPtr) == nsName))
5031 {
5032 return(ret);
5033 }
5034 break;
5035 default:
5036 /* Should not be hit. */
5037 return(NULL);
5038 }
5039 }
5040 }
5041subschemas:
5042 /*
5043 * Process imported/included schemas.
5044 */
5045 if (bucket->relations != NULL) {
5046 xmlSchemaSchemaRelationPtr rel = bucket->relations;
5047
5048 /*
5049 * TODO: Marking the bucket will not avoid multiple searches
5050 * in the same schema, but avoids at least circularity.
5051 */
5052 bucket->flags |= XML_SCHEMA_BUCKET_MARKED;
5053 do {
5054 if ((rel->bucket != NULL) &&
5055 ((rel->bucket->flags & XML_SCHEMA_BUCKET_MARKED) == 0)) {
5056 ret = xmlSchemaFindRedefCompInGraph(rel->bucket,
5057 type, name, nsName);
5058 if (ret != NULL)
5059 return(ret);
5060 }
5061 rel = rel->next;
5062 } while (rel != NULL);
5063 bucket->flags ^= XML_SCHEMA_BUCKET_MARKED;
5064 }
5065 return(NULL);
5066}
5067
5079static xmlSchemaNotationPtr
5080xmlSchemaAddNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5081 const xmlChar *name, const xmlChar *nsName,
5082 xmlNodePtr node ATTRIBUTE_UNUSED)
5083{
5084 xmlSchemaNotationPtr ret = NULL;
5085
5086 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
5087 return (NULL);
5088
5089 ret = (xmlSchemaNotationPtr) xmlMalloc(sizeof(xmlSchemaNotation));
5090 if (ret == NULL) {
5091 xmlSchemaPErrMemory(ctxt, "add annotation", NULL);
5092 return (NULL);
5093 }
5094 memset(ret, 0, sizeof(xmlSchemaNotation));
5095 ret->type = XML_SCHEMA_TYPE_NOTATION;
5096 ret->name = name;
5097 ret->targetNamespace = nsName;
5098 /* TODO: do we need the node to be set?
5099 * ret->node = node;*/
5100 WXS_ADD_GLOBAL(ctxt, ret);
5101 return (ret);
5102}
5103
5116static xmlSchemaAttributePtr
5117xmlSchemaAddAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5118 const xmlChar * name, const xmlChar * nsName,
5119 xmlNodePtr node, int topLevel)
5120{
5121 xmlSchemaAttributePtr ret = NULL;
5122
5123 if ((ctxt == NULL) || (schema == NULL))
5124 return (NULL);
5125
5126 ret = (xmlSchemaAttributePtr) xmlMalloc(sizeof(xmlSchemaAttribute));
5127 if (ret == NULL) {
5128 xmlSchemaPErrMemory(ctxt, "allocating attribute", NULL);
5129 return (NULL);
5130 }
5131 memset(ret, 0, sizeof(xmlSchemaAttribute));
5132 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
5133 ret->node = node;
5134 ret->name = name;
5135 ret->targetNamespace = nsName;
5136
5137 if (topLevel)
5138 WXS_ADD_GLOBAL(ctxt, ret);
5139 else
5140 WXS_ADD_LOCAL(ctxt, ret);
5141 WXS_ADD_PENDING(ctxt, ret);
5142 return (ret);
5143}
5144
5157static xmlSchemaAttributeUsePtr
5158xmlSchemaAddAttributeUse(xmlSchemaParserCtxtPtr pctxt,
5159 xmlNodePtr node)
5160{
5161 xmlSchemaAttributeUsePtr ret = NULL;
5162
5163 if (pctxt == NULL)
5164 return (NULL);
5165
5166 ret = (xmlSchemaAttributeUsePtr) xmlMalloc(sizeof(xmlSchemaAttributeUse));
5167 if (ret == NULL) {
5168 xmlSchemaPErrMemory(pctxt, "allocating attribute", NULL);
5169 return (NULL);
5170 }
5171 memset(ret, 0, sizeof(xmlSchemaAttributeUse));
5172 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE_USE;
5173 ret->node = node;
5174
5175 WXS_ADD_LOCAL(pctxt, ret);
5176 return (ret);
5177}
5178
5179/*
5180* xmlSchemaAddRedef:
5181*
5182* Adds a redefinition information. This is used at a later stage to:
5183* resolve references to the redefined components and to check constraints.
5184*/
5185static xmlSchemaRedefPtr
5186xmlSchemaAddRedef(xmlSchemaParserCtxtPtr pctxt,
5187 xmlSchemaBucketPtr targetBucket,
5188 void *item,
5189 const xmlChar *refName,
5190 const xmlChar *refTargetNs)
5191{
5192 xmlSchemaRedefPtr ret;
5193
5194 ret = (xmlSchemaRedefPtr)
5195 xmlMalloc(sizeof(xmlSchemaRedef));
5196 if (ret == NULL) {
5197 xmlSchemaPErrMemory(pctxt,
5198 "allocating redefinition info", NULL);
5199 return (NULL);
5200 }
5201 memset(ret, 0, sizeof(xmlSchemaRedef));
5202 ret->item = item;
5203 ret->targetBucket = targetBucket;
5204 ret->refName = refName;
5205 ret->refTargetNs = refTargetNs;
5206 if (WXS_CONSTRUCTOR(pctxt)->redefs == NULL)
5207 WXS_CONSTRUCTOR(pctxt)->redefs = ret;
5208 else
5209 WXS_CONSTRUCTOR(pctxt)->lastRedef->next = ret;
5210 WXS_CONSTRUCTOR(pctxt)->lastRedef = ret;
5211
5212 return (ret);
5213}
5214
5227static xmlSchemaAttributeGroupPtr
5228xmlSchemaAddAttributeGroupDefinition(xmlSchemaParserCtxtPtr pctxt,
5229 xmlSchemaPtr schema ATTRIBUTE_UNUSED,
5230 const xmlChar *name,
5231 const xmlChar *nsName,
5232 xmlNodePtr node)
5233{
5234 xmlSchemaAttributeGroupPtr ret = NULL;
5235
5236 if ((pctxt == NULL) || (name == NULL))
5237 return (NULL);
5238
5239 ret = (xmlSchemaAttributeGroupPtr)
5240 xmlMalloc(sizeof(xmlSchemaAttributeGroup));
5241 if (ret == NULL) {
5242 xmlSchemaPErrMemory(pctxt, "allocating attribute group", NULL);
5243 return (NULL);
5244 }
5245 memset(ret, 0, sizeof(xmlSchemaAttributeGroup));
5246 ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
5247 ret->name = name;
5248 ret->targetNamespace = nsName;
5249 ret->node = node;
5250
5251 /* TODO: Remove the flag. */
5252 ret->flags |= XML_SCHEMAS_ATTRGROUP_GLOBAL;
5253 if (pctxt->isRedefine) {
5254 pctxt->redef = xmlSchemaAddRedef(pctxt, pctxt->redefined,
5255 ret, name, nsName);
5256 if (pctxt->redef == NULL) {
5257 xmlFree(ret);
5258 return(NULL);
5259 }
5260 pctxt->redefCounter = 0;
5261 }
5262 WXS_ADD_GLOBAL(pctxt, ret);
5263 WXS_ADD_PENDING(pctxt, ret);
5264 return (ret);
5265}
5266
5279static xmlSchemaElementPtr
5280xmlSchemaAddElement(xmlSchemaParserCtxtPtr ctxt,
5281 const xmlChar * name, const xmlChar * nsName,
5282 xmlNodePtr node, int topLevel)
5283{
5284 xmlSchemaElementPtr ret = NULL;
5285
5286 if ((ctxt == NULL) || (name == NULL))
5287 return (NULL);
5288
5289 ret = (xmlSchemaElementPtr) xmlMalloc(sizeof(xmlSchemaElement));
5290 if (ret == NULL) {
5291 xmlSchemaPErrMemory(ctxt, "allocating element", NULL);
5292 return (NULL);
5293 }
5294 memset(ret, 0, sizeof(xmlSchemaElement));
5295 ret->type = XML_SCHEMA_TYPE_ELEMENT;
5296 ret->name = name;
5297 ret->targetNamespace = nsName;
5298 ret->node = node;
5299
5300 if (topLevel)
5301 WXS_ADD_GLOBAL(ctxt, ret);
5302 else
5303 WXS_ADD_LOCAL(ctxt, ret);
5304 WXS_ADD_PENDING(ctxt, ret);
5305 return (ret);
5306}
5307
5320static xmlSchemaTypePtr
5321xmlSchemaAddType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5322 xmlSchemaTypeType type,
5323 const xmlChar * name, const xmlChar * nsName,
5324 xmlNodePtr node, int topLevel)
5325{
5326 xmlSchemaTypePtr ret = NULL;
5327
5328 if ((ctxt == NULL) || (schema == NULL))
5329 return (NULL);
5330
5331 ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
5332 if (ret == NULL) {
5333 xmlSchemaPErrMemory(ctxt, "allocating type", NULL);
5334 return (NULL);
5335 }
5336 memset(ret, 0, sizeof(xmlSchemaType));
5337 ret->type = type;
5338 ret->name = name;
5339 ret->targetNamespace = nsName;
5340 ret->node = node;
5341 if (topLevel) {
5342 if (ctxt->isRedefine) {
5343 ctxt->redef = xmlSchemaAddRedef(ctxt, ctxt->redefined,
5344 ret, name, nsName);
5345 if (ctxt->redef == NULL) {
5346 xmlFree(ret);
5347 return(NULL);
5348 }
5349 ctxt->redefCounter = 0;
5350 }
5351 WXS_ADD_GLOBAL(ctxt, ret);
5352 } else
5353 WXS_ADD_LOCAL(ctxt, ret);
5354 WXS_ADD_PENDING(ctxt, ret);
5355 return (ret);
5356}
5357
5358static xmlSchemaQNameRefPtr
5359xmlSchemaNewQNameRef(xmlSchemaParserCtxtPtr pctxt,
5360 xmlSchemaTypeType refType,
5361 const xmlChar *refName,
5362 const xmlChar *refNs)
5363{
5364 xmlSchemaQNameRefPtr ret;
5365
5366 ret = (xmlSchemaQNameRefPtr)
5367 xmlMalloc(sizeof(xmlSchemaQNameRef));
5368 if (ret == NULL) {
5369 xmlSchemaPErrMemory(pctxt,
5370 "allocating QName reference item", NULL);
5371 return (NULL);
5372 }
5373 ret->node = NULL;
5374 ret->type = XML_SCHEMA_EXTRA_QNAMEREF;
5375 ret->name = refName;
5376 ret->targetNamespace = refNs;
5377 ret->item = NULL;
5378 ret->itemType = refType;
5379 /*
5380 * Store the reference item in the schema.
5381 */
5382 WXS_ADD_LOCAL(pctxt, ret);
5383 return (ret);
5384}
5385
5386static xmlSchemaAttributeUseProhibPtr
5387xmlSchemaAddAttributeUseProhib(xmlSchemaParserCtxtPtr pctxt)
5388{
5389 xmlSchemaAttributeUseProhibPtr ret;
5390
5391 ret = (xmlSchemaAttributeUseProhibPtr)
5392 xmlMalloc(sizeof(xmlSchemaAttributeUseProhib));
5393 if (ret == NULL) {
5394 xmlSchemaPErrMemory(pctxt,
5395 "allocating attribute use prohibition", NULL);
5396 return (NULL);
5397 }
5398 memset(ret, 0, sizeof(xmlSchemaAttributeUseProhib));
5399 ret->type = XML_SCHEMA_EXTRA_ATTR_USE_PROHIB;
5400 WXS_ADD_LOCAL(pctxt, ret);
5401 return (ret);
5402}
5403
5404
5417static xmlSchemaModelGroupPtr
5418xmlSchemaAddModelGroup(xmlSchemaParserCtxtPtr ctxt,
5419 xmlSchemaPtr schema,
5420 xmlSchemaTypeType type,
5421 xmlNodePtr node)
5422{
5423 xmlSchemaModelGroupPtr ret = NULL;
5424
5425 if ((ctxt == NULL) || (schema == NULL))
5426 return (NULL);
5427
5428 ret = (xmlSchemaModelGroupPtr)
5429 xmlMalloc(sizeof(xmlSchemaModelGroup));
5430 if (ret == NULL) {
5431 xmlSchemaPErrMemory(ctxt, "allocating model group component",
5432 NULL);
5433 return (NULL);
5434 }
5435 memset(ret, 0, sizeof(xmlSchemaModelGroup));
5436 ret->type = type;
5437 ret->node = node;
5438 WXS_ADD_LOCAL(ctxt, ret);
5439 if ((type == XML_SCHEMA_TYPE_SEQUENCE) ||
5440 (type == XML_SCHEMA_TYPE_CHOICE))
5441 WXS_ADD_PENDING(ctxt, ret);
5442 return (ret);
5443}
5444
5445
5459static xmlSchemaParticlePtr
5460xmlSchemaAddParticle(xmlSchemaParserCtxtPtr ctxt,
5461 xmlNodePtr node, int min, int max)
5462{
5463 xmlSchemaParticlePtr ret = NULL;
5464 if (ctxt == NULL)
5465 return (NULL);
5466
5467 ret = (xmlSchemaParticlePtr)
5468 xmlMalloc(sizeof(xmlSchemaParticle));
5469 if (ret == NULL) {
5470 xmlSchemaPErrMemory(ctxt, "allocating particle component",
5471 NULL);
5472 return (NULL);
5473 }
5474 ret->type = XML_SCHEMA_TYPE_PARTICLE;
5475 ret->annot = NULL;
5476 ret->node = node;
5477 ret->minOccurs = min;
5478 ret->maxOccurs = max;
5479 ret->next = NULL;
5480 ret->children = NULL;
5481
5482 WXS_ADD_LOCAL(ctxt, ret);
5483 /*
5484 * Note that addition to pending components will be done locally
5485 * to the specific parsing function, since the most particles
5486 * need not to be fixed up (i.e. the reference to be resolved).
5487 * REMOVED: WXS_ADD_PENDING(ctxt, ret);
5488 */
5489 return (ret);
5490}
5491
5502static xmlSchemaModelGroupDefPtr
5503xmlSchemaAddModelGroupDefinition(xmlSchemaParserCtxtPtr ctxt,
5504 xmlSchemaPtr schema,
5505 const xmlChar *name,
5506 const xmlChar *nsName,
5507 xmlNodePtr node)
5508{
5509 xmlSchemaModelGroupDefPtr ret = NULL;
5510
5511 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
5512 return (NULL);
5513
5514 ret = (xmlSchemaModelGroupDefPtr)
5515 xmlMalloc(sizeof(xmlSchemaModelGroupDef));
5516 if (ret == NULL) {
5517 xmlSchemaPErrMemory(ctxt, "adding group", NULL);
5518 return (NULL);
5519 }
5520 memset(ret, 0, sizeof(xmlSchemaModelGroupDef));
5521 ret->name = name;
5522 ret->type = XML_SCHEMA_TYPE_GROUP;
5523 ret->node = node;
5524 ret->targetNamespace = nsName;
5525
5526 if (ctxt->isRedefine) {
5527 ctxt->redef = xmlSchemaAddRedef(ctxt, ctxt->redefined,
5528 ret, name, nsName);
5529 if (ctxt->redef == NULL) {
5530 xmlFree(ret);
5531 return(NULL);
5532 }
5533 ctxt->redefCounter = 0;
5534 }
5535 WXS_ADD_GLOBAL(ctxt, ret);
5536 WXS_ADD_PENDING(ctxt, ret);
5537 return (ret);
5538}
5539
5548static xmlSchemaWildcardNsPtr
5549xmlSchemaNewWildcardNsConstraint(xmlSchemaParserCtxtPtr ctxt)
5550{
5551 xmlSchemaWildcardNsPtr ret;
5552
5553 ret = (xmlSchemaWildcardNsPtr)
5554 xmlMalloc(sizeof(xmlSchemaWildcardNs));
5555 if (ret == NULL) {
5556 xmlSchemaPErrMemory(ctxt, "creating wildcard namespace constraint", NULL);
5557 return (NULL);
5558 }
5559 ret->value = NULL;
5560 ret->next = NULL;
5561 return (ret);
5562}
5563
5564static xmlSchemaIDCPtr
5565xmlSchemaAddIDC(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5566 const xmlChar *name, const xmlChar *nsName,
5567 int category, xmlNodePtr node)
5568{
5569 xmlSchemaIDCPtr ret = NULL;
5570
5571 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
5572 return (NULL);
5573
5574 ret = (xmlSchemaIDCPtr) xmlMalloc(sizeof(xmlSchemaIDC));
5575 if (ret == NULL) {
5576 xmlSchemaPErrMemory(ctxt,
5577 "allocating an identity-constraint definition", NULL);
5578 return (NULL);
5579 }
5580 memset(ret, 0, sizeof(xmlSchemaIDC));
5581 /* The target namespace of the parent element declaration. */
5582 ret->targetNamespace = nsName;
5583 ret->name = name;
5584 ret->type = category;
5585 ret->node = node;
5586
5587 WXS_ADD_GLOBAL(ctxt, ret);
5588 /*
5589 * Only keyrefs need to be fixup up.
5590 */
5591 if (category == XML_SCHEMA_TYPE_IDC_KEYREF)
5592 WXS_ADD_PENDING(ctxt, ret);
5593 return (ret);
5594}
5595
5606static xmlSchemaWildcardPtr
5607xmlSchemaAddWildcard(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5608 xmlSchemaTypeType type, xmlNodePtr node)
5609{
5610 xmlSchemaWildcardPtr ret = NULL;
5611
5612 if ((ctxt == NULL) || (schema == NULL))
5613 return (NULL);
5614
5615 ret = (xmlSchemaWildcardPtr) xmlMalloc(sizeof(xmlSchemaWildcard));
5616 if (ret == NULL) {
5617 xmlSchemaPErrMemory(ctxt, "adding wildcard", NULL);
5618 return (NULL);
5619 }
5620 memset(ret, 0, sizeof(xmlSchemaWildcard));
5621 ret->type = type;
5622 ret->node = node;
5623 WXS_ADD_LOCAL(ctxt, ret);
5624 return (ret);
5625}
5626
5627static void
5628xmlSchemaSubstGroupFree(xmlSchemaSubstGroupPtr group)
5629{
5630 if (group == NULL)
5631 return;
5632 if (group->members != NULL)
5633 xmlSchemaItemListFree(group->members);
5634 xmlFree(group);
5635}
5636
5637static void
5638xmlSchemaSubstGroupFreeEntry(void *group, const xmlChar *name ATTRIBUTE_UNUSED)
5639{
5640 xmlSchemaSubstGroupFree((xmlSchemaSubstGroupPtr) group);
5641}
5642
5643static xmlSchemaSubstGroupPtr
5644xmlSchemaSubstGroupAdd(xmlSchemaParserCtxtPtr pctxt,
5645 xmlSchemaElementPtr head)
5646{
5647 xmlSchemaSubstGroupPtr ret;
5648
5649 /* Init subst group hash. */
5650 if (WXS_SUBST_GROUPS(pctxt) == NULL) {
5651 WXS_SUBST_GROUPS(pctxt) = xmlHashCreateDict(10, pctxt->dict);
5652 if (WXS_SUBST_GROUPS(pctxt) == NULL)
5653 return(NULL);
5654 }
5655 /* Create a new substitution group. */
5656 ret = (xmlSchemaSubstGroupPtr) xmlMalloc(sizeof(xmlSchemaSubstGroup));
5657 if (ret == NULL) {
5658 xmlSchemaPErrMemory(NULL,
5659 "allocating a substitution group container", NULL);
5660 return(NULL);
5661 }
5662 memset(ret, 0, sizeof(xmlSchemaSubstGroup));
5663 ret->head = head;
5664 /* Create list of members. */
5665 ret->members = xmlSchemaItemListCreate();
5666 if (ret->members == NULL) {
5667 xmlSchemaSubstGroupFree(ret);
5668 return(NULL);
5669 }
5670 /* Add subst group to hash. */
5671 if (xmlHashAddEntry2(WXS_SUBST_GROUPS(pctxt),
5672 head->name, head->targetNamespace, ret) != 0) {
5673 PERROR_INT("xmlSchemaSubstGroupAdd",
5674 "failed to add a new substitution container");
5675 xmlSchemaSubstGroupFree(ret);
5676 return(NULL);
5677 }
5678 return(ret);
5679}
5680
5681static xmlSchemaSubstGroupPtr
5682xmlSchemaSubstGroupGet(xmlSchemaParserCtxtPtr pctxt,
5683 xmlSchemaElementPtr head)
5684{
5685 if (WXS_SUBST_GROUPS(pctxt) == NULL)
5686 return(NULL);
5687 return(xmlHashLookup2(WXS_SUBST_GROUPS(pctxt),
5688 head->name, head->targetNamespace));
5689
5690}
5691
5702static int
5703xmlSchemaAddElementSubstitutionMember(xmlSchemaParserCtxtPtr pctxt,
5704 xmlSchemaElementPtr head,
5705 xmlSchemaElementPtr member)
5706{
5707 xmlSchemaSubstGroupPtr substGroup = NULL;
5708
5709 if ((pctxt == NULL) || (head == NULL) || (member == NULL))
5710 return (-1);
5711
5712 substGroup = xmlSchemaSubstGroupGet(pctxt, head);
5713 if (substGroup == NULL)
5714 substGroup = xmlSchemaSubstGroupAdd(pctxt, head);
5715 if (substGroup == NULL)
5716 return(-1);
5717 if (xmlSchemaItemListAdd(substGroup->members, member) == -1)
5718 return(-1);
5719 return(0);
5720}
5721
5722/************************************************************************
5723 * *
5724 * Utilities for parsing *
5725 * *
5726 ************************************************************************/
5727
5744static int
5745xmlSchemaPValAttrNodeQNameValue(xmlSchemaParserCtxtPtr ctxt,
5746 xmlSchemaPtr schema,
5747 xmlSchemaBasicItemPtr ownerItem,
5748 xmlAttrPtr attr,
5749 const xmlChar *value,
5750 const xmlChar **uri,
5751 const xmlChar **local)
5752{
5753 const xmlChar *pref;
5754 xmlNsPtr ns;
5755 int len, ret;
5756
5757 *uri = NULL;
5758 *local = NULL;
5759 ret = xmlValidateQName(value, 1);
5760 if (ret > 0) {
5761 xmlSchemaPSimpleTypeErr(ctxt,
5763 ownerItem, (xmlNodePtr) attr,
5764 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
5765 NULL, value, NULL, NULL, NULL);
5766 *local = value;
5767 return (ctxt->err);
5768 } else if (ret < 0)
5769 return (-1);
5770
5771 if (!strchr((char *) value, ':')) {
5772 ns = xmlSearchNs(attr->doc, attr->parent, NULL);
5773 if (ns && ns->href && ns->href[0])
5774 *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
5775 else if (schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) {
5776 /* TODO: move XML_SCHEMAS_INCLUDING_CONVERT_NS to the
5777 * parser context. */
5778 /*
5779 * This one takes care of included schemas with no
5780 * target namespace.
5781 */
5782 *uri = ctxt->targetNamespace;
5783 }
5784 *local = xmlDictLookup(ctxt->dict, value, -1);
5785 return (0);
5786 }
5787 /*
5788 * At this point xmlSplitQName3 has to return a local name.
5789 */
5790 *local = xmlSplitQName3(value, &len);
5791 *local = xmlDictLookup(ctxt->dict, *local, -1);
5792 pref = xmlDictLookup(ctxt->dict, value, len);
5793 ns = xmlSearchNs(attr->doc, attr->parent, pref);
5794 if (ns == NULL) {
5795 xmlSchemaPSimpleTypeErr(ctxt,
5797 ownerItem, (xmlNodePtr) attr,
5798 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), NULL, value,
5799 "The value '%s' of simple type 'xs:QName' has no "
5800 "corresponding namespace declaration in scope", value, NULL);
5801 return (ctxt->err);
5802 } else {
5803 *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
5804 }
5805 return (0);
5806}
5807
5824static int
5825xmlSchemaPValAttrNodeQName(xmlSchemaParserCtxtPtr ctxt,
5826 xmlSchemaPtr schema,
5827 xmlSchemaBasicItemPtr ownerItem,
5828 xmlAttrPtr attr,
5829 const xmlChar **uri,
5830 const xmlChar **local)
5831{
5832 const xmlChar *value;
5833
5834 value = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5835 return (xmlSchemaPValAttrNodeQNameValue(ctxt, schema,
5836 ownerItem, attr, value, uri, local));
5837}
5838
5854static int
5855xmlSchemaPValAttrQName(xmlSchemaParserCtxtPtr ctxt,
5856 xmlSchemaPtr schema,
5857 xmlSchemaBasicItemPtr ownerItem,
5858 xmlNodePtr ownerElem,
5859 const char *name,
5860 const xmlChar **uri,
5861 const xmlChar **local)
5862{
5863 xmlAttrPtr attr;
5864
5865 attr = xmlSchemaGetPropNode(ownerElem, name);
5866 if (attr == NULL) {
5867 *local = NULL;
5868 *uri = NULL;
5869 return (0);
5870 }
5871 return (xmlSchemaPValAttrNodeQName(ctxt, schema,
5872 ownerItem, attr, uri, local));
5873}
5874
5884static int
5885xmlSchemaPValAttrNodeID(xmlSchemaParserCtxtPtr ctxt, xmlAttrPtr attr)
5886{
5887 int ret;
5888 const xmlChar *value;
5889
5890 if (attr == NULL)
5891 return(0);
5892 value = xmlSchemaGetNodeContentNoDict((xmlNodePtr) attr);
5893 ret = xmlValidateNCName(value, 1);
5894 if (ret == 0) {
5895 /*
5896 * NOTE: the IDness might have already be declared in the DTD
5897 */
5898 if (attr->atype != XML_ATTRIBUTE_ID) {
5899 xmlIDPtr res;
5900 xmlChar *strip;
5901
5902 /*
5903 * TODO: Use xmlSchemaStrip here; it's not exported at this
5904 * moment.
5905 */
5906 strip = xmlSchemaCollapseString(value);
5907 if (strip != NULL) {
5908 xmlFree((xmlChar *) value);
5909 value = strip;
5910 }
5911 res = xmlAddID(NULL, attr->doc, value, attr);
5912 if (res == NULL) {
5914 xmlSchemaPSimpleTypeErr(ctxt,
5916 NULL, (xmlNodePtr) attr,
5917 xmlSchemaGetBuiltInType(XML_SCHEMAS_ID),
5918 NULL, NULL, "Duplicate value '%s' of simple "
5919 "type 'xs:ID'", value, NULL);
5920 } else
5921 attr->atype = XML_ATTRIBUTE_ID;
5922 }
5923 } else if (ret > 0) {
5925 xmlSchemaPSimpleTypeErr(ctxt,
5927 NULL, (xmlNodePtr) attr,
5928 xmlSchemaGetBuiltInType(XML_SCHEMAS_ID),
5929 NULL, NULL, "The value '%s' of simple type 'xs:ID' is "
5930 "not a valid 'xs:NCName'",
5931 value, NULL);
5932 }
5933 if (value != NULL)
5934 xmlFree((xmlChar *)value);
5935
5936 return (ret);
5937}
5938
5939static int
5940xmlSchemaPValAttrID(xmlSchemaParserCtxtPtr ctxt,
5941 xmlNodePtr ownerElem,
5942 const xmlChar *name)
5943{
5944 xmlAttrPtr attr;
5945
5946 attr = xmlSchemaGetPropNode(ownerElem, (const char *) name);
5947 if (attr == NULL)
5948 return(0);
5949 return(xmlSchemaPValAttrNodeID(ctxt, attr));
5950
5951}
5952
5962static int
5963xmlGetMaxOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
5964 int min, int max, int def, const char *expected)
5965{
5966 const xmlChar *val, *cur;
5967 int ret = 0;
5968 xmlAttrPtr attr;
5969
5970 attr = xmlSchemaGetPropNode(node, "maxOccurs");
5971 if (attr == NULL)
5972 return (def);
5973 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5974 if (val == NULL)
5975 return (def);
5976
5977 if (xmlStrEqual(val, (const xmlChar *) "unbounded")) {
5978 if (max != UNBOUNDED) {
5979 xmlSchemaPSimpleTypeErr(ctxt,
5981 /* XML_SCHEMAP_INVALID_MINOCCURS, */
5982 NULL, (xmlNodePtr) attr, NULL, expected,
5983 val, NULL, NULL, NULL);
5984 return (def);
5985 } else
5986 return (UNBOUNDED); /* encoding it with -1 might be another option */
5987 }
5988
5989 cur = val;
5990 while (IS_BLANK_CH(*cur))
5991 cur++;
5992 if (*cur == 0) {
5993 xmlSchemaPSimpleTypeErr(ctxt,
5995 /* XML_SCHEMAP_INVALID_MINOCCURS, */
5996 NULL, (xmlNodePtr) attr, NULL, expected,
5997 val, NULL, NULL, NULL);
5998 return (def);
5999 }
6000 while ((*cur >= '0') && (*cur <= '9')) {
6001 if (ret > INT_MAX / 10) {
6002 ret = INT_MAX;
6003 } else {
6004 int digit = *cur - '0';
6005 ret *= 10;
6006 if (ret > INT_MAX - digit)
6007 ret = INT_MAX;
6008 else
6009 ret += digit;
6010 }
6011 cur++;
6012 }
6013 while (IS_BLANK_CH(*cur))
6014 cur++;
6015 /*
6016 * TODO: Restrict the maximal value to Integer.
6017 */
6018 if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
6019 xmlSchemaPSimpleTypeErr(ctxt,
6021 /* XML_SCHEMAP_INVALID_MINOCCURS, */
6022 NULL, (xmlNodePtr) attr, NULL, expected,
6023 val, NULL, NULL, NULL);
6024 return (def);
6025 }
6026 return (ret);
6027}
6028
6038static int
6039xmlGetMinOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
6040 int min, int max, int def, const char *expected)
6041{
6042 const xmlChar *val, *cur;
6043 int ret = 0;
6044 xmlAttrPtr attr;
6045
6046 attr = xmlSchemaGetPropNode(node, "minOccurs");
6047 if (attr == NULL)
6048 return (def);
6049 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6050 if (val == NULL)
6051 return (def);
6052 cur = val;
6053 while (IS_BLANK_CH(*cur))
6054 cur++;
6055 if (*cur == 0) {
6056 xmlSchemaPSimpleTypeErr(ctxt,
6058 /* XML_SCHEMAP_INVALID_MINOCCURS, */
6059 NULL, (xmlNodePtr) attr, NULL, expected,
6060 val, NULL, NULL, NULL);
6061 return (def);
6062 }
6063 while ((*cur >= '0') && (*cur <= '9')) {
6064 if (ret > INT_MAX / 10) {
6065 ret = INT_MAX;
6066 } else {
6067 int digit = *cur - '0';
6068 ret *= 10;
6069 if (ret > INT_MAX - digit)
6070 ret = INT_MAX;
6071 else
6072 ret += digit;
6073 }
6074 cur++;
6075 }
6076 while (IS_BLANK_CH(*cur))
6077 cur++;
6078 /*
6079 * TODO: Restrict the maximal value to Integer.
6080 */
6081 if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
6082 xmlSchemaPSimpleTypeErr(ctxt,
6084 /* XML_SCHEMAP_INVALID_MINOCCURS, */
6085 NULL, (xmlNodePtr) attr, NULL, expected,
6086 val, NULL, NULL, NULL);
6087 return (def);
6088 }
6089 return (ret);
6090}
6091
6102static int
6103xmlSchemaPGetBoolNodeValue(xmlSchemaParserCtxtPtr ctxt,
6104 xmlSchemaBasicItemPtr ownerItem,
6105 xmlNodePtr node)
6106{
6107 xmlChar *value = NULL;
6108 int res = 0;
6109
6110 value = xmlNodeGetContent(node);
6111 /*
6112 * 3.2.2.1 Lexical representation
6113 * An instance of a datatype that is defined as `boolean`
6114 * can have the following legal literals {true, false, 1, 0}.
6115 */
6116 if (xmlStrEqual(BAD_CAST value, BAD_CAST "true"))
6117 res = 1;
6118 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "false"))
6119 res = 0;
6120 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "1"))
6121 res = 1;
6122 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "0"))
6123 res = 0;
6124 else {
6125 xmlSchemaPSimpleTypeErr(ctxt,
6127 ownerItem, node,
6128 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
6130 NULL, NULL, NULL);
6131 }
6132 if (value != NULL)
6133 xmlFree(value);
6134 return (res);
6135}
6136
6149static int
6150xmlGetBooleanProp(xmlSchemaParserCtxtPtr ctxt,
6151 xmlNodePtr node,
6152 const char *name, int def)
6153{
6154 const xmlChar *val;
6155
6156 val = xmlSchemaGetProp(ctxt, node, name);
6157 if (val == NULL)
6158 return (def);
6159 /*
6160 * 3.2.2.1 Lexical representation
6161 * An instance of a datatype that is defined as `boolean`
6162 * can have the following legal literals {true, false, 1, 0}.
6163 */
6164 if (xmlStrEqual(val, BAD_CAST "true"))
6165 def = 1;
6166 else if (xmlStrEqual(val, BAD_CAST "false"))
6167 def = 0;
6168 else if (xmlStrEqual(val, BAD_CAST "1"))
6169 def = 1;
6170 else if (xmlStrEqual(val, BAD_CAST "0"))
6171 def = 0;
6172 else {
6173 xmlSchemaPSimpleTypeErr(ctxt,
6175 NULL,
6176 (xmlNodePtr) xmlSchemaGetPropNode(node, name),
6177 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
6178 NULL, val, NULL, NULL, NULL);
6179 }
6180 return (def);
6181}
6182
6183/************************************************************************
6184 * *
6185 * Schema extraction from an Infoset *
6186 * *
6187 ************************************************************************/
6188static xmlSchemaTypePtr xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr
6189 ctxt, xmlSchemaPtr schema,
6190 xmlNodePtr node,
6191 int topLevel);
6192static xmlSchemaTypePtr xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr
6193 ctxt,
6194 xmlSchemaPtr schema,
6195 xmlNodePtr node,
6196 int topLevel);
6197static xmlSchemaTypePtr xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr
6198 ctxt,
6199 xmlSchemaPtr schema,
6200 xmlNodePtr node,
6201 xmlSchemaTypeType parentType);
6202static xmlSchemaBasicItemPtr
6203xmlSchemaParseLocalAttribute(xmlSchemaParserCtxtPtr pctxt,
6204 xmlSchemaPtr schema,
6205 xmlNodePtr node,
6206 xmlSchemaItemListPtr uses,
6207 int parentType);
6208static xmlSchemaTypePtr xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt,
6209 xmlSchemaPtr schema,
6210 xmlNodePtr node);
6211static xmlSchemaWildcardPtr
6212xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
6213 xmlSchemaPtr schema, xmlNodePtr node);
6214
6231static int
6232xmlSchemaPValAttrNodeValue(xmlSchemaParserCtxtPtr pctxt,
6233 xmlSchemaBasicItemPtr ownerItem,
6234 xmlAttrPtr attr,
6235 const xmlChar *value,
6236 xmlSchemaTypePtr type)
6237{
6238
6239 int ret = 0;
6240
6241 /*
6242 * NOTE: Should we move this to xmlschematypes.c? Hmm, but this
6243 * one is really meant to be used internally, so better not.
6244 */
6245 if ((pctxt == NULL) || (type == NULL) || (attr == NULL))
6246 return (-1);
6247 if (type->type != XML_SCHEMA_TYPE_BASIC) {
6248 PERROR_INT("xmlSchemaPValAttrNodeValue",
6249 "the given type is not a built-in type");
6250 return (-1);
6251 }
6252 switch (type->builtInType) {
6253 case XML_SCHEMAS_NCNAME:
6254 case XML_SCHEMAS_QNAME:
6255 case XML_SCHEMAS_ANYURI:
6256 case XML_SCHEMAS_TOKEN:
6257 case XML_SCHEMAS_LANGUAGE:
6258 ret = xmlSchemaValPredefTypeNode(type, value, NULL,
6259 (xmlNodePtr) attr);
6260 break;
6261 default: {
6262 PERROR_INT("xmlSchemaPValAttrNodeValue",
6263 "validation using the given type is not supported while "
6264 "parsing a schema");
6265 return (-1);
6266 }
6267 }
6268 /*
6269 * TODO: Should we use the S4S error codes instead?
6270 */
6271 if (ret < 0) {
6272 PERROR_INT("xmlSchemaPValAttrNodeValue",
6273 "failed to validate a schema attribute value");
6274 return (-1);
6275 } else if (ret > 0) {
6276 if (WXS_IS_LIST(type))
6278 else
6280 xmlSchemaPSimpleTypeErr(pctxt,
6281 ret, ownerItem, (xmlNodePtr) attr,
6282 type, NULL, value, NULL, NULL, NULL);
6283 }
6284 return (ret);
6285}
6286
6303static int
6304xmlSchemaPValAttrNode(xmlSchemaParserCtxtPtr ctxt,
6305 xmlSchemaBasicItemPtr ownerItem,
6306 xmlAttrPtr attr,
6307 xmlSchemaTypePtr type,
6308 const xmlChar **value)
6309{
6310 const xmlChar *val;
6311
6312 if ((ctxt == NULL) || (type == NULL) || (attr == NULL))
6313 return (-1);
6314
6315 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6316 if (value != NULL)
6317 *value = val;
6318
6319 return (xmlSchemaPValAttrNodeValue(ctxt, ownerItem, attr,
6320 val, type));
6321}
6322
6341static int
6342xmlSchemaPValAttr(xmlSchemaParserCtxtPtr ctxt,
6343 xmlSchemaBasicItemPtr ownerItem,
6344 xmlNodePtr ownerElem,
6345 const char *name,
6346 xmlSchemaTypePtr type,
6347 const xmlChar **value)
6348{
6349 xmlAttrPtr attr;
6350
6351 if ((ctxt == NULL) || (type == NULL)) {
6352 if (value != NULL)
6353 *value = NULL;
6354 return (-1);
6355 }
6356 if (type->type != XML_SCHEMA_TYPE_BASIC) {
6357 if (value != NULL)
6358 *value = NULL;
6359 xmlSchemaPErr(ctxt, ownerElem,
6361 "Internal error: xmlSchemaPValAttr, the given "
6362 "type '%s' is not a built-in type.\n",
6363 type->name, NULL);
6364 return (-1);
6365 }
6366 attr = xmlSchemaGetPropNode(ownerElem, name);
6367 if (attr == NULL) {
6368 if (value != NULL)
6369 *value = NULL;
6370 return (0);
6371 }
6372 return (xmlSchemaPValAttrNode(ctxt, ownerItem, attr,
6373 type, value));
6374}
6375
6376static int
6377xmlSchemaCheckReference(xmlSchemaParserCtxtPtr pctxt,
6378 xmlSchemaPtr schema ATTRIBUTE_UNUSED,
6379 xmlNodePtr node,
6380 xmlAttrPtr attr,
6381 const xmlChar *namespaceName)
6382{
6383 /* TODO: Pointer comparison instead? */
6384 if (xmlStrEqual(pctxt->targetNamespace, namespaceName))
6385 return (0);
6386 if (xmlStrEqual(xmlSchemaNs, namespaceName))
6387 return (0);
6388 /*
6389 * Check if the referenced namespace was <import>ed.
6390 */
6391 if (WXS_BUCKET(pctxt)->relations != NULL) {
6392 xmlSchemaSchemaRelationPtr rel;
6393
6394 rel = WXS_BUCKET(pctxt)->relations;
6395 do {
6396 if (WXS_IS_BUCKET_IMPMAIN(rel->type) &&
6397 xmlStrEqual(namespaceName, rel->importNamespace))
6398 return (0);
6399 rel = rel->next;
6400 } while (rel != NULL);
6401 }
6402 /*
6403 * No matching <import>ed namespace found.
6404 */
6405 {
6406 xmlNodePtr n = (attr != NULL) ? (xmlNodePtr) attr : node;
6407
6408 if (namespaceName == NULL)
6409 xmlSchemaCustomErr(ACTXT_CAST pctxt,
6411 "References from this schema to components in no "
6412 "namespace are not allowed, since not indicated by an "
6413 "import statement", NULL, NULL);
6414 else
6415 xmlSchemaCustomErr(ACTXT_CAST pctxt,
6417 "References from this schema to components in the "
6418 "namespace '%s' are not allowed, since not indicated by an "
6419 "import statement", namespaceName, NULL);
6420 }
6421 return (XML_SCHEMAP_SRC_RESOLVE);
6422}
6423
6434static int
6435xmlSchemaParseLocalAttributes(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6436 xmlNodePtr *child, xmlSchemaItemListPtr *list,
6437 int parentType, int *hasRefs)
6438{
6439 void *item;
6440
6441 while ((IS_SCHEMA((*child), "attribute")) ||
6442 (IS_SCHEMA((*child), "attributeGroup"))) {
6443 if (IS_SCHEMA((*child), "attribute")) {
6444 item = xmlSchemaParseLocalAttribute(ctxt, schema, *child,
6445 *list, parentType);
6446 } else {
6447 item = xmlSchemaParseAttributeGroupRef(ctxt, schema, *child);
6448 if ((item != NULL) && (hasRefs != NULL))
6449 *hasRefs = 1;
6450 }
6451 if (item != NULL) {
6452 if (*list == NULL) {
6453 /* TODO: Customize grow factor. */
6454 *list = xmlSchemaItemListCreate();
6455 if (*list == NULL)
6456 return(-1);
6457 }
6458 if (xmlSchemaItemListAddSize(*list, 2, item) == -1)
6459 return(-1);
6460 }
6461 *child = (*child)->next;
6462 }
6463 return (0);
6464}
6465
6478static xmlSchemaAnnotPtr
6479xmlSchemaParseAnnotation(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int needed)
6480{
6481 xmlSchemaAnnotPtr ret;
6482 xmlNodePtr child = NULL;
6483 xmlAttrPtr attr;
6484 int barked = 0;
6485
6486 /*
6487 * INFO: S4S completed.
6488 */
6489 /*
6490 * id = ID
6491 * {any attributes with non-schema namespace . . .}>
6492 * Content: (appinfo | documentation)*
6493 */
6494 if ((ctxt == NULL) || (node == NULL))
6495 return (NULL);
6496 if (needed)
6497 ret = xmlSchemaNewAnnot(ctxt, node);
6498 else
6499 ret = NULL;
6500 attr = node->properties;
6501 while (attr != NULL) {
6502 if (((attr->ns == NULL) &&
6503 (!xmlStrEqual(attr->name, BAD_CAST "id"))) ||
6504 ((attr->ns != NULL) &&
6505 xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
6506
6507 xmlSchemaPIllegalAttrErr(ctxt,
6509 }
6510 attr = attr->next;
6511 }
6512 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
6513 /*
6514 * And now for the children...
6515 */
6516 child = node->children;
6517 while (child != NULL) {
6518 if (IS_SCHEMA(child, "appinfo")) {
6519 /* TODO: make available the content of "appinfo". */
6520 /*
6521 * source = anyURI
6522 * {any attributes with non-schema namespace . . .}>
6523 * Content: ({any})*
6524 */
6525 attr = child->properties;
6526 while (attr != NULL) {
6527 if (((attr->ns == NULL) &&
6528 (!xmlStrEqual(attr->name, BAD_CAST "source"))) ||
6529 ((attr->ns != NULL) &&
6530 xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
6531
6532 xmlSchemaPIllegalAttrErr(ctxt,
6534 }
6535 attr = attr->next;
6536 }
6537 xmlSchemaPValAttr(ctxt, NULL, child, "source",
6538 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), NULL);
6539 child = child->next;
6540 } else if (IS_SCHEMA(child, "documentation")) {
6541 /* TODO: make available the content of "documentation". */
6542 /*
6543 * source = anyURI
6544 * {any attributes with non-schema namespace . . .}>
6545 * Content: ({any})*
6546 */
6547 attr = child->properties;
6548 while (attr != NULL) {
6549 if (attr->ns == NULL) {
6550 if (!xmlStrEqual(attr->name, BAD_CAST "source")) {
6551 xmlSchemaPIllegalAttrErr(ctxt,
6553 }
6554 } else {
6555 if (xmlStrEqual(attr->ns->href, xmlSchemaNs) ||
6556 (xmlStrEqual(attr->name, BAD_CAST "lang") &&
6557 (!xmlStrEqual(attr->ns->href, XML_XML_NAMESPACE)))) {
6558
6559 xmlSchemaPIllegalAttrErr(ctxt,
6561 }
6562 }
6563 attr = attr->next;
6564 }
6565 /*
6566 * Attribute "xml:lang".
6567 */
6568 attr = xmlSchemaGetPropNodeNs(child, (const char *) XML_XML_NAMESPACE, "lang");
6569 if (attr != NULL)
6570 xmlSchemaPValAttrNode(ctxt, NULL, attr,
6571 xmlSchemaGetBuiltInType(XML_SCHEMAS_LANGUAGE), NULL);
6572 child = child->next;
6573 } else {
6574 if (!barked)
6575 xmlSchemaPContentErr(ctxt,
6577 NULL, node, child, NULL, "(appinfo | documentation)*");
6578 barked = 1;
6579 child = child->next;
6580 }
6581 }
6582
6583 return (ret);
6584}
6585
6597static xmlSchemaFacetPtr
6598xmlSchemaParseFacet(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6599 xmlNodePtr node)
6600{
6601 xmlSchemaFacetPtr facet;
6602 xmlNodePtr child = NULL;
6603 const xmlChar *value;
6604
6605 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6606 return (NULL);
6607
6608 facet = xmlSchemaNewFacet();
6609 if (facet == NULL) {
6610 xmlSchemaPErrMemory(ctxt, "allocating facet", node);
6611 return (NULL);
6612 }
6613 facet->node = node;
6614 value = xmlSchemaGetProp(ctxt, node, "value");
6615 if (value == NULL) {
6616 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_FACET_NO_VALUE,
6617 "Facet %s has no value\n", node->name, NULL);
6618 xmlSchemaFreeFacet(facet);
6619 return (NULL);
6620 }
6621 if (IS_SCHEMA(node, "minInclusive")) {
6622 facet->type = XML_SCHEMA_FACET_MININCLUSIVE;
6623 } else if (IS_SCHEMA(node, "minExclusive")) {
6624 facet->type = XML_SCHEMA_FACET_MINEXCLUSIVE;
6625 } else if (IS_SCHEMA(node, "maxInclusive")) {
6626 facet->type = XML_SCHEMA_FACET_MAXINCLUSIVE;
6627 } else if (IS_SCHEMA(node, "maxExclusive")) {
6628 facet->type = XML_SCHEMA_FACET_MAXEXCLUSIVE;
6629 } else if (IS_SCHEMA(node, "totalDigits")) {
6630 facet->type = XML_SCHEMA_FACET_TOTALDIGITS;
6631 } else if (IS_SCHEMA(node, "fractionDigits")) {
6632 facet->type = XML_SCHEMA_FACET_FRACTIONDIGITS;
6633 } else if (IS_SCHEMA(node, "pattern")) {
6634 facet->type = XML_SCHEMA_FACET_PATTERN;
6635 } else if (IS_SCHEMA(node, "enumeration")) {
6636 facet->type = XML_SCHEMA_FACET_ENUMERATION;
6637 } else if (IS_SCHEMA(node, "whiteSpace")) {
6638 facet->type = XML_SCHEMA_FACET_WHITESPACE;
6639 } else if (IS_SCHEMA(node, "length")) {
6640 facet->type = XML_SCHEMA_FACET_LENGTH;
6641 } else if (IS_SCHEMA(node, "maxLength")) {
6642 facet->type = XML_SCHEMA_FACET_MAXLENGTH;
6643 } else if (IS_SCHEMA(node, "minLength")) {
6644 facet->type = XML_SCHEMA_FACET_MINLENGTH;
6645 } else {
6646 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_TYPE,
6647 "Unknown facet type %s\n", node->name, NULL);
6648 xmlSchemaFreeFacet(facet);
6649 return (NULL);
6650 }
6651 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
6652 facet->value = value;
6653 if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
6654 (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
6655 const xmlChar *fixed;
6656
6657 fixed = xmlSchemaGetProp(ctxt, node, "fixed");
6658 if (fixed != NULL) {
6659 if (xmlStrEqual(fixed, BAD_CAST "true"))
6660 facet->fixed = 1;
6661 }
6662 }
6663 child = node->children;
6664
6665 if (IS_SCHEMA(child, "annotation")) {
6666 facet->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
6667 child = child->next;
6668 }
6669 if (child != NULL) {
6670 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_CHILD,
6671 "Facet %s has unexpected child content\n",
6672 node->name, NULL);
6673 }
6674 return (facet);
6675}
6676
6690static int
6691xmlSchemaParseWildcardNs(xmlSchemaParserCtxtPtr ctxt,
6692 xmlSchemaPtr schema ATTRIBUTE_UNUSED,
6693 xmlSchemaWildcardPtr wildc,
6694 xmlNodePtr node)
6695{
6696 const xmlChar *pc, *ns, *dictnsItem;
6697 int ret = 0;
6698 xmlChar *nsItem;
6699 xmlSchemaWildcardNsPtr tmp, lastNs = NULL;
6700 xmlAttrPtr attr;
6701
6702 pc = xmlSchemaGetProp(ctxt, node, "processContents");
6703 if ((pc == NULL)
6704 || (xmlStrEqual(pc, (const xmlChar *) "strict"))) {
6705 wildc->processContents = XML_SCHEMAS_ANY_STRICT;
6706 } else if (xmlStrEqual(pc, (const xmlChar *) "skip")) {
6707 wildc->processContents = XML_SCHEMAS_ANY_SKIP;
6708 } else if (xmlStrEqual(pc, (const xmlChar *) "lax")) {
6709 wildc->processContents = XML_SCHEMAS_ANY_LAX;
6710 } else {
6711 xmlSchemaPSimpleTypeErr(ctxt,
6713 NULL, node,
6714 NULL, "(strict | skip | lax)", pc,
6715 NULL, NULL, NULL);
6716 wildc->processContents = XML_SCHEMAS_ANY_STRICT;
6718 }
6719 /*
6720 * Build the namespace constraints.
6721 */
6722 attr = xmlSchemaGetPropNode(node, "namespace");
6723 ns = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6724 if (ns == NULL)
6725 return (-1);
6726 if ((attr == NULL) || (xmlStrEqual(ns, BAD_CAST "##any")))
6727 wildc->any = 1;
6728 else if (xmlStrEqual(ns, BAD_CAST "##other")) {
6729 wildc->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
6730 if (wildc->negNsSet == NULL) {
6731 return (-1);
6732 }
6733 wildc->negNsSet->value = ctxt->targetNamespace;
6734 } else {
6735 const xmlChar *end, *cur;
6736
6737 cur = ns;
6738 do {
6739 while (IS_BLANK_CH(*cur))
6740 cur++;
6741 end = cur;
6742 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
6743 end++;
6744 if (end == cur)
6745 break;
6746 nsItem = xmlStrndup(cur, end - cur);
6747 if ((xmlStrEqual(nsItem, BAD_CAST "##other")) ||
6748 (xmlStrEqual(nsItem, BAD_CAST "##any"))) {
6749 xmlSchemaPSimpleTypeErr(ctxt,
6751 NULL, (xmlNodePtr) attr,
6752 NULL,
6753 "((##any | ##other) | List of (xs:anyURI | "
6754 "(##targetNamespace | ##local)))",
6755 nsItem, NULL, NULL, NULL);
6757 } else {
6758 if (xmlStrEqual(nsItem, BAD_CAST "##targetNamespace")) {
6759 dictnsItem = ctxt->targetNamespace;
6760 } else if (xmlStrEqual(nsItem, BAD_CAST "##local")) {
6761 dictnsItem = NULL;
6762 } else {
6763 /*
6764 * Validate the item (anyURI).
6765 */
6766 xmlSchemaPValAttrNodeValue(ctxt, NULL, attr,
6767 nsItem, xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI));
6768 dictnsItem = xmlDictLookup(ctxt->dict, nsItem, -1);
6769 }
6770 /*
6771 * Avoid duplicate namespaces.
6772 */
6773 tmp = wildc->nsSet;
6774 while (tmp != NULL) {
6775 if (dictnsItem == tmp->value)
6776 break;
6777 tmp = tmp->next;
6778 }
6779 if (tmp == NULL) {
6780 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
6781 if (tmp == NULL) {
6782 xmlFree(nsItem);
6783 return (-1);
6784 }
6785 tmp->value = dictnsItem;
6786 tmp->next = NULL;
6787 if (wildc->nsSet == NULL)
6788 wildc->nsSet = tmp;
6789 else if (lastNs != NULL)
6790 lastNs->next = tmp;
6791 lastNs = tmp;
6792 }
6793
6794 }
6795 xmlFree(nsItem);
6796 cur = end;
6797 } while (*cur != 0);
6798 }
6799 return (ret);
6800}
6801
6802static int
6803xmlSchemaPCheckParticleCorrect_2(xmlSchemaParserCtxtPtr ctxt,
6804 xmlSchemaParticlePtr item ATTRIBUTE_UNUSED,
6805 xmlNodePtr node,
6806 int minOccurs,
6807 int maxOccurs) {
6808
6809 if ((maxOccurs == 0) && ( minOccurs == 0))
6810 return (0);
6811 if (maxOccurs != UNBOUNDED) {
6812 /*
6813 * TODO: Maybe we should better not create the particle,
6814 * if min/max is invalid, since it could confuse the build of the
6815 * content model.
6816 */
6817 /*
6818 * 3.9.6 Schema Component Constraint: Particle Correct
6819 *
6820 */
6821 if (maxOccurs < 1) {
6822 /*
6823 * 2.2 {max occurs} must be greater than or equal to 1.
6824 */
6825 xmlSchemaPCustomAttrErr(ctxt,
6827 NULL, NULL,
6828 xmlSchemaGetPropNode(node, "maxOccurs"),
6829 "The value must be greater than or equal to 1");
6831 } else if (minOccurs > maxOccurs) {
6832 /*
6833 * 2.1 {min occurs} must not be greater than {max occurs}.
6834 */
6835 xmlSchemaPCustomAttrErr(ctxt,
6837 NULL, NULL,
6838 xmlSchemaGetPropNode(node, "minOccurs"),
6839 "The value must not be greater than the value of 'maxOccurs'");
6841 }
6842 }
6843 return (0);
6844}
6845
6859static xmlSchemaParticlePtr
6860xmlSchemaParseAny(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6861 xmlNodePtr node)
6862{
6863 xmlSchemaParticlePtr particle;
6864 xmlNodePtr child = NULL;
6865 xmlSchemaWildcardPtr wild;
6866 int min, max;
6867 xmlAttrPtr attr;
6868 xmlSchemaAnnotPtr annot = NULL;
6869
6870 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6871 return (NULL);
6872 /*
6873 * Check for illegal attributes.
6874 */
6875 attr = node->properties;
6876 while (attr != NULL) {
6877 if (attr->ns == NULL) {
6878 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6879 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
6880 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
6881 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
6882 (!xmlStrEqual(attr->name, BAD_CAST "processContents"))) {
6883 xmlSchemaPIllegalAttrErr(ctxt,
6885 }
6886 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6887 xmlSchemaPIllegalAttrErr(ctxt,
6889 }
6890 attr = attr->next;
6891 }
6892 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
6893 /*
6894 * minOccurs/maxOccurs.
6895 */
6896 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
6897 "(xs:nonNegativeInteger | unbounded)");
6898 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1,
6899 "xs:nonNegativeInteger");
6900 xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
6901 /*
6902 * Create & parse the wildcard.
6903 */
6904 wild = xmlSchemaAddWildcard(ctxt, schema, XML_SCHEMA_TYPE_ANY, node);
6905 if (wild == NULL)
6906 return (NULL);
6907 xmlSchemaParseWildcardNs(ctxt, schema, wild, node);
6908 /*
6909 * And now for the children...
6910 */
6911 child = node->children;
6912 if (IS_SCHEMA(child, "annotation")) {
6913 annot = xmlSchemaParseAnnotation(ctxt, child, 1);
6914 child = child->next;
6915 }
6916 if (child != NULL) {
6917 xmlSchemaPContentErr(ctxt,
6919 NULL, node, child,
6920 NULL, "(annotation?)");
6921 }
6922 /*
6923 * No component if minOccurs==maxOccurs==0.
6924 */
6925 if ((min == 0) && (max == 0)) {
6926 /* Don't free the wildcard, since it's already on the list. */
6927 return (NULL);
6928 }
6929 /*
6930 * Create the particle.
6931 */
6932 particle = xmlSchemaAddParticle(ctxt, node, min, max);
6933 if (particle == NULL)
6934 return (NULL);
6935 particle->annot = annot;
6936 particle->children = (xmlSchemaTreeItemPtr) wild;
6937
6938 return (particle);
6939}
6940
6951static xmlSchemaNotationPtr
6952xmlSchemaParseNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6953 xmlNodePtr node)
6954{
6955 const xmlChar *name;
6956 xmlSchemaNotationPtr ret;
6957 xmlNodePtr child = NULL;
6958
6959 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6960 return (NULL);
6961 name = xmlSchemaGetProp(ctxt, node, "name");
6962 if (name == NULL) {
6963 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_NOTATION_NO_NAME,
6964 "Notation has no name\n", NULL, NULL);
6965 return (NULL);
6966 }
6967 ret = xmlSchemaAddNotation(ctxt, schema, name,
6968 ctxt->targetNamespace, node);
6969 if (ret == NULL)
6970 return (NULL);
6971 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
6972
6973 child = node->children;
6974 if (IS_SCHEMA(child, "annotation")) {
6975 ret->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
6976 child = child->next;
6977 }
6978 if (child != NULL) {
6979 xmlSchemaPContentErr(ctxt,
6981 NULL, node, child,
6982 NULL, "(annotation?)");
6983 }
6984
6985 return (ret);
6986}
6987
6999static xmlSchemaWildcardPtr
7000xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
7001 xmlSchemaPtr schema, xmlNodePtr node)
7002{
7003 xmlSchemaWildcardPtr ret;
7004 xmlNodePtr child = NULL;
7005 xmlAttrPtr attr;
7006
7007 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7008 return (NULL);
7009
7010 ret = xmlSchemaAddWildcard(ctxt, schema, XML_SCHEMA_TYPE_ANY_ATTRIBUTE,
7011 node);
7012 if (ret == NULL) {
7013 return (NULL);
7014 }
7015 /*
7016 * Check for illegal attributes.
7017 */
7018 attr = node->properties;
7019 while (attr != NULL) {
7020 if (attr->ns == NULL) {
7021 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7022 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
7023 (!xmlStrEqual(attr->name, BAD_CAST "processContents"))) {
7024 xmlSchemaPIllegalAttrErr(ctxt,
7026 }
7027 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7028 xmlSchemaPIllegalAttrErr(ctxt,
7030 }
7031 attr = attr->next;
7032 }
7033 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
7034 /*
7035 * Parse the namespace list.
7036 */
7037 if (xmlSchemaParseWildcardNs(ctxt, schema, ret, node) != 0)
7038 return (NULL);
7039 /*
7040 * And now for the children...
7041 */
7042 child = node->children;
7043 if (IS_SCHEMA(child, "annotation")) {
7044 ret->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
7045 child = child->next;
7046 }
7047 if (child != NULL) {
7048 xmlSchemaPContentErr(ctxt,
7050 NULL, node, child,
7051 NULL, "(annotation?)");
7052 }
7053
7054 return (ret);
7055}
7056
7057
7069static xmlSchemaBasicItemPtr
7070xmlSchemaParseLocalAttribute(xmlSchemaParserCtxtPtr pctxt,
7071 xmlSchemaPtr schema,
7072 xmlNodePtr node,
7073 xmlSchemaItemListPtr uses,
7074 int parentType)
7075{
7076 const xmlChar *attrValue, *name = NULL, *ns = NULL;
7077 xmlSchemaAttributeUsePtr use = NULL;
7078 xmlNodePtr child = NULL;
7079 xmlAttrPtr attr;
7080 const xmlChar *tmpNs = NULL, *tmpName = NULL, *defValue = NULL;
7081 int isRef = 0, occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
7082 int nberrors, hasForm = 0, defValueType = 0;
7083
7084#define WXS_ATTR_DEF_VAL_DEFAULT 1
7085#define WXS_ATTR_DEF_VAL_FIXED 2
7086
7087 /*
7088 * 3.2.3 Constraints on XML Representations of Attribute Declarations
7089 */
7090
7091 if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
7092 return (NULL);
7093 attr = xmlSchemaGetPropNode(node, "ref");
7094 if (attr != NULL) {
7095 if (xmlSchemaPValAttrNodeQName(pctxt, schema,
7096 NULL, attr, &tmpNs, &tmpName) != 0) {
7097 return (NULL);
7098 }
7099 if (xmlSchemaCheckReference(pctxt, schema, node, attr, tmpNs) != 0)
7100 return(NULL);
7101 isRef = 1;
7102 }
7103 nberrors = pctxt->nberrors;
7104 /*
7105 * Check for illegal attributes.
7106 */
7107 attr = node->properties;
7108 while (attr != NULL) {
7109 if (attr->ns == NULL) {
7110 if (isRef) {
7111 if (xmlStrEqual(attr->name, BAD_CAST "id")) {
7112 xmlSchemaPValAttrNodeID(pctxt, attr);
7113 goto attr_next;
7114 } else if (xmlStrEqual(attr->name, BAD_CAST "ref")) {
7115 goto attr_next;
7116 }
7117 } else {
7118 if (xmlStrEqual(attr->name, BAD_CAST "name")) {
7119 goto attr_next;
7120 } else if (xmlStrEqual(attr->name, BAD_CAST "id")) {
7121 xmlSchemaPValAttrNodeID(pctxt, attr);
7122 goto attr_next;
7123 } else if (xmlStrEqual(attr->name, BAD_CAST "type")) {
7124 xmlSchemaPValAttrNodeQName(pctxt, schema, NULL,
7125 attr, &tmpNs, &tmpName);
7126 goto attr_next;
7127 } else if (xmlStrEqual(attr->name, BAD_CAST "form")) {
7128 /*
7129 * Evaluate the target namespace
7130 */
7131 hasForm = 1;
7132 attrValue = xmlSchemaGetNodeContent(pctxt,
7133 (xmlNodePtr) attr);
7134 if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
7135 ns = pctxt->targetNamespace;
7136 } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified"))
7137 {
7138 xmlSchemaPSimpleTypeErr(pctxt,
7140 NULL, (xmlNodePtr) attr,
7141 NULL, "(qualified | unqualified)",
7142 attrValue, NULL, NULL, NULL);
7143 }
7144 goto attr_next;
7145 }
7146 }
7147 if (xmlStrEqual(attr->name, BAD_CAST "use")) {
7148
7149 attrValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
7150 /* TODO: Maybe we need to normalize the value beforehand. */
7151 if (xmlStrEqual(attrValue, BAD_CAST "optional"))
7152 occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
7153 else if (xmlStrEqual(attrValue, BAD_CAST "prohibited"))
7154 occurs = XML_SCHEMAS_ATTR_USE_PROHIBITED;
7155 else if (xmlStrEqual(attrValue, BAD_CAST "required"))
7156 occurs = XML_SCHEMAS_ATTR_USE_REQUIRED;
7157 else {
7158 xmlSchemaPSimpleTypeErr(pctxt,
7160 NULL, (xmlNodePtr) attr,
7161 NULL, "(optional | prohibited | required)",
7162 attrValue, NULL, NULL, NULL);
7163 }
7164 goto attr_next;
7165 } else if (xmlStrEqual(attr->name, BAD_CAST "default")) {
7166 /*
7167 * 3.2.3 : 1
7168 * default and fixed must not both be present.
7169 */
7170 if (defValue) {
7171 xmlSchemaPMutualExclAttrErr(pctxt,
7173 NULL, attr, "default", "fixed");
7174 } else {
7175 defValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
7176 defValueType = WXS_ATTR_DEF_VAL_DEFAULT;
7177 }
7178 goto attr_next;
7179 } else if (xmlStrEqual(attr->name, BAD_CAST "fixed")) {
7180 /*
7181 * 3.2.3 : 1
7182 * default and fixed must not both be present.
7183 */
7184 if (defValue) {
7185 xmlSchemaPMutualExclAttrErr(pctxt,
7187 NULL, attr, "default", "fixed");
7188 } else {
7189 defValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
7190 defValueType = WXS_ATTR_DEF_VAL_FIXED;
7191 }
7192 goto attr_next;
7193 }
7194 } else if (! xmlStrEqual(attr->ns->href, xmlSchemaNs))
7195 goto attr_next;
7196
7197 xmlSchemaPIllegalAttrErr(pctxt,
7199
7200attr_next:
7201 attr = attr->next;
7202 }
7203 /*
7204 * 3.2.3 : 2
7205 * If default and use are both present, use must have
7206 * the actual value optional.
7207 */
7208 if ((defValueType == WXS_ATTR_DEF_VAL_DEFAULT) &&
7209 (occurs != XML_SCHEMAS_ATTR_USE_OPTIONAL)) {
7210 xmlSchemaPSimpleTypeErr(pctxt,
7212 NULL, node, NULL,
7213 "(optional | prohibited | required)", NULL,
7214 "The value of the attribute 'use' must be 'optional' "
7215 "if the attribute 'default' is present",
7216 NULL, NULL);
7217 }
7218 /*
7219 * We want correct attributes.
7220 */
7221 if (nberrors != pctxt->nberrors)
7222 return(NULL);
7223 if (! isRef) {
7224 xmlSchemaAttributePtr attrDecl;
7225
7226 /* TODO: move XML_SCHEMAS_QUALIF_ATTR to the parser. */
7227 if ((! hasForm) && (schema->flags & XML_SCHEMAS_QUALIF_ATTR))
7228 ns = pctxt->targetNamespace;
7229 /*
7230 * 3.2.6 Schema Component Constraint: xsi: Not Allowed
7231 * TODO: Move this to the component layer.
7232 */
7233 if (xmlStrEqual(ns, xmlSchemaInstanceNs)) {
7234 xmlSchemaCustomErr(ACTXT_CAST pctxt,
7236 node, NULL,
7237 "The target namespace must not match '%s'",
7238 xmlSchemaInstanceNs, NULL);
7239 }
7240 attr = xmlSchemaGetPropNode(node, "name");
7241 if (attr == NULL) {
7242 xmlSchemaPMissingAttrErr(pctxt, XML_SCHEMAP_S4S_ATTR_MISSING,
7243 NULL, node, "name", NULL);
7244 return (NULL);
7245 }
7246 if (xmlSchemaPValAttrNode(pctxt, NULL, attr,
7247 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
7248 return (NULL);
7249 }
7250 /*
7251 * 3.2.6 Schema Component Constraint: xmlns Not Allowed
7252 * TODO: Move this to the component layer.
7253 */
7254 if (xmlStrEqual(name, BAD_CAST "xmlns")) {
7255 xmlSchemaPSimpleTypeErr(pctxt,
7257 NULL, (xmlNodePtr) attr,
7258 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), NULL, NULL,
7259 "The value of the attribute must not match 'xmlns'",
7260 NULL, NULL);
7261 return (NULL);
7262 }
7263 if (occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED)
7264 goto check_children;
7265 /*
7266 * Create the attribute use component.
7267 */
7268 use = xmlSchemaAddAttributeUse(pctxt, node);
7269 if (use == NULL)
7270 return(NULL);
7271 use->occurs = occurs;
7272 /*
7273 * Create the attribute declaration.
7274 */
7275 attrDecl = xmlSchemaAddAttribute(pctxt, schema, name, ns, node, 0);
7276 if (attrDecl == NULL)
7277 return (NULL);
7278 if (tmpName != NULL) {
7279 attrDecl->typeName = tmpName;
7280 attrDecl->typeNs = tmpNs;
7281 }
7282 use->attrDecl = attrDecl;
7283 /*
7284 * Value constraint.
7285 */
7286 if (defValue != NULL) {
7287 attrDecl->defValue = defValue;
7288 if (defValueType == WXS_ATTR_DEF_VAL_FIXED)
7289 attrDecl->flags |= XML_SCHEMAS_ATTR_FIXED;
7290 }
7291 } else if (occurs != XML_SCHEMAS_ATTR_USE_PROHIBITED) {
7292 xmlSchemaQNameRefPtr ref;
7293
7294 /*
7295 * Create the attribute use component.
7296 */
7297 use = xmlSchemaAddAttributeUse(pctxt, node);
7298 if (use == NULL)
7299 return(NULL);
7300 /*
7301 * We need to resolve the reference at later stage.
7302 */
7303 WXS_ADD_PENDING(pctxt, use);
7304 use->occurs = occurs;
7305 /*
7306 * Create a QName reference to the attribute declaration.
7307 */
7308 ref = xmlSchemaNewQNameRef(pctxt, XML_SCHEMA_TYPE_ATTRIBUTE,
7309 tmpName, tmpNs);
7310 if (ref == NULL)
7311 return(NULL);
7312 /*
7313 * Assign the reference. This will be substituted for the
7314 * referenced attribute declaration when the QName is resolved.
7315 */
7316 use->attrDecl = WXS_ATTR_CAST ref;
7317 /*
7318 * Value constraint.
7319 */
7320 if (defValue != NULL)
7321 use->defValue = defValue;
7322 if (defValueType == WXS_ATTR_DEF_VAL_FIXED)
7323 use->flags |= XML_SCHEMA_ATTR_USE_FIXED;
7324 }
7325
7326check_children:
7327 /*
7328 * And now for the children...
7329 */
7330 child = node->children;
7331 if (occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) {
7332 xmlSchemaAttributeUseProhibPtr prohib;
7333
7334 if (IS_SCHEMA(child, "annotation")) {
7335 xmlSchemaParseAnnotation(pctxt, child, 0);
7336 child = child->next;
7337 }
7338 if (child != NULL) {
7339 xmlSchemaPContentErr(pctxt,
7341 NULL, node, child, NULL,
7342 "(annotation?)");
7343 }
7344 /*
7345 * Check for pointlessness of attribute prohibitions.
7346 */
7347 if (parentType == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
7348 xmlSchemaCustomWarning(ACTXT_CAST pctxt,
7350 node, NULL,
7351 "Skipping attribute use prohibition, since it is "
7352 "pointless inside an <attributeGroup>",
7353 NULL, NULL, NULL);
7354 return(NULL);
7355 } else if (parentType == XML_SCHEMA_TYPE_EXTENSION) {
7356 xmlSchemaCustomWarning(ACTXT_CAST pctxt,
7358 node, NULL,
7359 "Skipping attribute use prohibition, since it is "
7360 "pointless when extending a type",
7361 NULL, NULL, NULL);
7362 return(NULL);
7363 }
7364 if (! isRef) {
7365 tmpName = name;
7366 tmpNs = ns;
7367 }
7368 /*
7369 * Check for duplicate attribute prohibitions.
7370 */
7371 if (uses) {
7372 int i;
7373
7374 for (i = 0; i < uses->nbItems; i++) {
7375 use = uses->items[i];
7376 if ((use->type == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB) &&
7377 (tmpName == (WXS_ATTR_PROHIB_CAST use)->name) &&
7378 (tmpNs == (WXS_ATTR_PROHIB_CAST use)->targetNamespace))
7379 {
7380 xmlChar *str = NULL;
7381
7382 xmlSchemaCustomWarning(ACTXT_CAST pctxt,
7384 node, NULL,
7385 "Skipping duplicate attribute use prohibition '%s'",
7386 xmlSchemaFormatQName(&str, tmpNs, tmpName),
7387 NULL, NULL);
7388 FREE_AND_NULL(str)
7389 return(NULL);
7390 }
7391 }
7392 }
7393 /*
7394 * Create the attribute prohibition helper component.
7395 */
7396 prohib = xmlSchemaAddAttributeUseProhib(pctxt);
7397 if (prohib == NULL)
7398 return(NULL);
7399 prohib->node = node;
7400 prohib->name = tmpName;
7401 prohib->targetNamespace = tmpNs;
7402 if (isRef) {
7403 /*
7404 * We need at least to resolve to the attribute declaration.
7405 */
7406 WXS_ADD_PENDING(pctxt, prohib);
7407 }
7408 return(WXS_BASIC_CAST prohib);
7409 } else {
7410 if (IS_SCHEMA(child, "annotation")) {
7411 /*
7412 * TODO: Should this go into the attr decl?
7413 */
7414 use->annot = xmlSchemaParseAnnotation(pctxt, child, 1);
7415 child = child->next;
7416 }
7417 if (isRef) {
7418 if (child != NULL) {
7419 if (IS_SCHEMA(child, "simpleType"))
7420 /*
7421 * 3.2.3 : 3.2
7422 * If ref is present, then all of <simpleType>,
7423 * form and type must be absent.
7424 */
7425 xmlSchemaPContentErr(pctxt,
7427 NULL, node, child, NULL,
7428 "(annotation?)");
7429 else
7430 xmlSchemaPContentErr(pctxt,
7432 NULL, node, child, NULL,
7433 "(annotation?)");
7434 }
7435 } else {
7436 if (IS_SCHEMA(child, "simpleType")) {
7437 if (WXS_ATTRUSE_DECL(use)->typeName != NULL) {
7438 /*
7439 * 3.2.3 : 4
7440 * type and <simpleType> must not both be present.
7441 */
7442 xmlSchemaPContentErr(pctxt, XML_SCHEMAP_SRC_ATTRIBUTE_4,
7443 NULL, node, child,
7444 "The attribute 'type' and the <simpleType> child "
7445 "are mutually exclusive", NULL);
7446 } else
7447 WXS_ATTRUSE_TYPEDEF(use) =
7448 xmlSchemaParseSimpleType(pctxt, schema, child, 0);
7449 child = child->next;
7450 }
7451 if (child != NULL)
7452 xmlSchemaPContentErr(pctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7453 NULL, node, child, NULL,
7454 "(annotation?, simpleType?)");
7455 }
7456 }
7457 return (WXS_BASIC_CAST use);
7458}
7459
7460
7461static xmlSchemaAttributePtr
7462xmlSchemaParseGlobalAttribute(xmlSchemaParserCtxtPtr pctxt,
7463 xmlSchemaPtr schema,
7464 xmlNodePtr node)
7465{
7466 const xmlChar *attrValue;
7467 xmlSchemaAttributePtr ret;
7468 xmlNodePtr child = NULL;
7469 xmlAttrPtr attr;
7470
7471 /*
7472 * Note that the w3c spec assumes the schema to be validated with schema
7473 * for schemas beforehand.
7474 *
7475 * 3.2.3 Constraints on XML Representations of Attribute Declarations
7476 */
7477 if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
7478 return (NULL);
7479 /*
7480 * 3.2.3 : 3.1
7481 * One of ref or name must be present, but not both
7482 */
7483 attr = xmlSchemaGetPropNode(node, "name");
7484 if (attr == NULL) {
7485 xmlSchemaPMissingAttrErr(pctxt, XML_SCHEMAP_S4S_ATTR_MISSING,
7486 NULL, node, "name", NULL);
7487 return (NULL);
7488 }
7489 if (xmlSchemaPValAttrNode(pctxt, NULL, attr,
7490 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &attrValue) != 0) {
7491 return (NULL);
7492 }
7493 /*
7494 * 3.2.6 Schema Component Constraint: xmlns Not Allowed
7495 * TODO: Move this to the component layer.
7496 */
7497 if (xmlStrEqual(attrValue, BAD_CAST "xmlns")) {
7498 xmlSchemaPSimpleTypeErr(pctxt,
7500 NULL, (xmlNodePtr) attr,
7501 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), NULL, NULL,
7502 "The value of the attribute must not match 'xmlns'",
7503 NULL, NULL);
7504 return (NULL);
7505 }
7506 /*
7507 * 3.2.6 Schema Component Constraint: xsi: Not Allowed
7508 * TODO: Move this to the component layer.
7509 * Or better leave it here and add it to the component layer
7510 * if we have a schema construction API.
7511 */
7512 if (xmlStrEqual(pctxt->targetNamespace, xmlSchemaInstanceNs)) {
7513 xmlSchemaCustomErr(ACTXT_CAST pctxt,
7515 "The target namespace must not match '%s'",
7516 xmlSchemaInstanceNs, NULL);
7517 }
7518
7519 ret = xmlSchemaAddAttribute(pctxt, schema, attrValue,
7520 pctxt->targetNamespace, node, 1);
7521 if (ret == NULL)
7522 return (NULL);
7523 ret->flags |= XML_SCHEMAS_ATTR_GLOBAL;
7524
7525 /*
7526 * Check for illegal attributes.
7527 */
7528 attr = node->properties;
7529 while (attr != NULL) {
7530 if (attr->ns == NULL) {
7531 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7532 (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
7533 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
7534 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
7535 (!xmlStrEqual(attr->name, BAD_CAST "type")))
7536 {
7537 xmlSchemaPIllegalAttrErr(pctxt,
7539 }
7540 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7541 xmlSchemaPIllegalAttrErr(pctxt,
7543 }
7544 attr = attr->next;
7545 }
7546 xmlSchemaPValAttrQName(pctxt, schema, NULL,
7547 node, "type", &ret->typeNs, &ret->typeName);
7548
7549 xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
7550 /*
7551 * Attribute "fixed".
7552 */
7553 ret->defValue = xmlSchemaGetProp(pctxt, node, "fixed");
7554 if (ret->defValue != NULL)
7555 ret->flags |= XML_SCHEMAS_ATTR_FIXED;
7556 /*
7557 * Attribute "default".
7558 */
7559 attr = xmlSchemaGetPropNode(node, "default");
7560 if (attr != NULL) {
7561 /*
7562 * 3.2.3 : 1
7563 * default and fixed must not both be present.
7564 */
7565 if (ret->flags & XML_SCHEMAS_ATTR_FIXED) {
7566 xmlSchemaPMutualExclAttrErr(pctxt, XML_SCHEMAP_SRC_ATTRIBUTE_1,
7567 WXS_BASIC_CAST ret, attr, "default", "fixed");
7568 } else
7569 ret->defValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
7570 }
7571 /*
7572 * And now for the children...
7573 */
7574 child = node->children;
7575 if (IS_SCHEMA(child, "annotation")) {
7576 ret->annot = xmlSchemaParseAnnotation(pctxt, child, 1);
7577 child = child->next;
7578 }
7579 if (IS_SCHEMA(child, "simpleType")) {
7580 if (ret->typeName != NULL) {
7581 /*
7582 * 3.2.3 : 4
7583 * type and <simpleType> must not both be present.
7584 */
7585 xmlSchemaPContentErr(pctxt, XML_SCHEMAP_SRC_ATTRIBUTE_4,
7586 NULL, node, child,
7587 "The attribute 'type' and the <simpleType> child "
7588 "are mutually exclusive", NULL);
7589 } else
7590 ret->subtypes = xmlSchemaParseSimpleType(pctxt, schema, child, 0);
7591 child = child->next;
7592 }
7593 if (child != NULL)
7594 xmlSchemaPContentErr(pctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7595 NULL, node, child, NULL,
7596 "(annotation?, simpleType?)");
7597
7598 return (ret);
7599}
7600
7614static xmlSchemaQNameRefPtr
7615xmlSchemaParseAttributeGroupRef(xmlSchemaParserCtxtPtr pctxt,
7616 xmlSchemaPtr schema,
7617 xmlNodePtr node)
7618{
7619 xmlSchemaQNameRefPtr ret;
7620 xmlNodePtr child = NULL;
7621 xmlAttrPtr attr;
7622 const xmlChar *refNs = NULL, *ref = NULL;
7623
7624 if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
7625 return (NULL);
7626
7627 attr = xmlSchemaGetPropNode(node, "ref");
7628 if (attr == NULL) {
7629 xmlSchemaPMissingAttrErr(pctxt,
7631 NULL, node, "ref", NULL);
7632 return (NULL);
7633 }
7634 xmlSchemaPValAttrNodeQName(pctxt, schema,
7635 NULL, attr, &refNs, &ref);
7636 if (xmlSchemaCheckReference(pctxt, schema, node, attr, refNs) != 0)
7637 return(NULL);
7638
7639 /*
7640 * Check for illegal attributes.
7641 */
7642 attr = node->properties;
7643 while (attr != NULL) {
7644 if (attr->ns == NULL) {
7645 if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
7646 (!xmlStrEqual(attr->name, BAD_CAST "id")))
7647 {
7648 xmlSchemaPIllegalAttrErr(pctxt,
7650 }
7651 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7652 xmlSchemaPIllegalAttrErr(pctxt,
7654 }
7655 attr = attr->next;
7656 }
7657 /* Attribute ID */
7658 xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
7659
7660 /*
7661 * And now for the children...
7662 */
7663 child = node->children;
7664 if (IS_SCHEMA(child, "annotation")) {
7665 /*
7666 * TODO: We do not have a place to store the annotation, do we?
7667 */
7668 xmlSchemaParseAnnotation(pctxt, child, 0);
7669 child = child->next;
7670 }
7671 if (child != NULL) {
7672 xmlSchemaPContentErr(pctxt,
7674 NULL, node, child, NULL,
7675 "(annotation?)");
7676 }
7677
7678 /*
7679 * Handle attribute group redefinitions.
7680 */
7681 if (pctxt->isRedefine && pctxt->redef &&
7682 (pctxt->redef->item->type ==
7683 XML_SCHEMA_TYPE_ATTRIBUTEGROUP) &&
7684 (ref == pctxt->redef->refName) &&
7685 (refNs == pctxt->redef->refTargetNs))
7686 {
7687 /*
7688 * SPEC src-redefine:
7689 * (7.1) "If it has an <attributeGroup> among its contents
7690 * the `actual value` of whose ref [attribute] is the same
7691 * as the `actual value` of its own name attribute plus
7692 * target namespace, then it must have exactly one such group."
7693 */
7694 if (pctxt->redefCounter != 0) {
7695 xmlChar *str = NULL;
7696
7697 xmlSchemaCustomErr(ACTXT_CAST pctxt,
7699 "The redefining attribute group definition "
7700 "'%s' must not contain more than one "
7701 "reference to the redefined definition",
7702 xmlSchemaFormatQName(&str, refNs, ref), NULL);
7703 FREE_AND_NULL(str);
7704 return(NULL);
7705 }
7706 pctxt->redefCounter++;
7707 /*
7708 * URGENT TODO: How to ensure that the reference will not be
7709 * handled by the normal component resolution mechanism?
7710 */
7711 ret = xmlSchemaNewQNameRef(pctxt,
7712 XML_SCHEMA_TYPE_ATTRIBUTEGROUP, ref, refNs);
7713 if (ret == NULL)
7714 return(NULL);
7715 ret->node = node;
7716 pctxt->redef->reference = WXS_BASIC_CAST ret;
7717 } else {
7718 /*
7719 * Create a QName-reference helper component. We will substitute this
7720 * component for the attribute uses of the referenced attribute group
7721 * definition.
7722 */
7723 ret = xmlSchemaNewQNameRef(pctxt,
7724 XML_SCHEMA_TYPE_ATTRIBUTEGROUP, ref, refNs);
7725 if (ret == NULL)
7726 return(NULL);
7727 ret->node = node;
7728 /* Add to pending items, to be able to resolve the reference. */
7729 WXS_ADD_PENDING(pctxt, ret);
7730 }
7731 return (ret);
7732}
7733
7745static xmlSchemaAttributeGroupPtr
7746xmlSchemaParseAttributeGroupDefinition(xmlSchemaParserCtxtPtr pctxt,
7747 xmlSchemaPtr schema,
7748 xmlNodePtr node)
7749{
7750 const xmlChar *name;
7751 xmlSchemaAttributeGroupPtr ret;
7752 xmlNodePtr child = NULL;
7753 xmlAttrPtr attr;
7754 int hasRefs = 0;
7755
7756 if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
7757 return (NULL);
7758
7759 attr = xmlSchemaGetPropNode(node, "name");
7760 if (attr == NULL) {
7761 xmlSchemaPMissingAttrErr(pctxt,
7763 NULL, node, "name", NULL);
7764 return (NULL);
7765 }
7766 /*
7767 * The name is crucial, exit if invalid.
7768 */
7769 if (xmlSchemaPValAttrNode(pctxt,
7770 NULL, attr,
7771 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
7772 return (NULL);
7773 }
7774 ret = xmlSchemaAddAttributeGroupDefinition(pctxt, schema,
7775 name, pctxt->targetNamespace, node);
7776 if (ret == NULL)
7777 return (NULL);
7778 /*
7779 * Check for illegal attributes.
7780 */
7781 attr = node->properties;
7782 while (attr != NULL) {
7783 if (attr->ns == NULL) {
7784 if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
7785 (!xmlStrEqual(attr->name, BAD_CAST "id")))
7786 {
7787 xmlSchemaPIllegalAttrErr(pctxt,
7789 }
7790 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7791 xmlSchemaPIllegalAttrErr(pctxt,
7793 }
7794 attr = attr->next;
7795 }
7796 /* Attribute ID */
7797 xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
7798 /*
7799 * And now for the children...
7800 */
7801 child = node->children;
7802 if (IS_SCHEMA(child, "annotation")) {
7803 ret->annot = xmlSchemaParseAnnotation(pctxt, child, 1);
7804 child = child->next;
7805 }
7806 /*
7807 * Parse contained attribute decls/refs.
7808 */
7809 if (xmlSchemaParseLocalAttributes(pctxt, schema, &child,
7810 (xmlSchemaItemListPtr *) &(ret->attrUses),
7811 XML_SCHEMA_TYPE_ATTRIBUTEGROUP, &hasRefs) == -1)
7812 return(NULL);
7813 if (hasRefs)
7814 ret->flags |= XML_SCHEMAS_ATTRGROUP_HAS_REFS;
7815 /*
7816 * Parse the attribute wildcard.
7817 */
7818 if (IS_SCHEMA(child, "anyAttribute")) {
7819 ret->attributeWildcard = xmlSchemaParseAnyAttribute(pctxt,
7820 schema, child);
7821 child = child->next;
7822 }
7823 if (child != NULL) {
7824 xmlSchemaPContentErr(pctxt,
7826 NULL, node, child, NULL,
7827 "(annotation?, ((attribute | attributeGroup)*, anyAttribute?))");
7828 }
7829 return (ret);
7830}
7831
7840static int
7841xmlSchemaPValAttrFormDefault(const xmlChar *value,
7842 int *flags,
7843 int flagQualified)
7844{
7845 if (xmlStrEqual(value, BAD_CAST "qualified")) {
7846 if ((*flags & flagQualified) == 0)
7847 *flags |= flagQualified;
7848 } else if (!xmlStrEqual(value, BAD_CAST "unqualified"))
7849 return (1);
7850
7851 return (0);
7852}
7853
7871static int
7872xmlSchemaPValAttrBlockFinal(const xmlChar *value,
7873 int *flags,
7874 int flagAll,
7875 int flagExtension,
7876 int flagRestriction,
7877 int flagSubstitution,
7878 int flagList,
7879 int flagUnion)
7880{
7881 int ret = 0;
7882
7883 /*
7884 * TODO: This does not check for duplicate entries.
7885 */
7886 if ((flags == NULL) || (value == NULL))
7887 return (-1);
7888 if (value[0] == 0)
7889 return (0);
7890 if (xmlStrEqual(value, BAD_CAST "#all")) {
7891 if (flagAll != -1)
7892 *flags |= flagAll;
7893 else {
7894 if (flagExtension != -1)
7895 *flags |= flagExtension;
7896 if (flagRestriction != -1)
7897 *flags |= flagRestriction;
7898 if (flagSubstitution != -1)
7899 *flags |= flagSubstitution;
7900 if (flagList != -1)
7901 *flags |= flagList;
7902 if (flagUnion != -1)
7903 *flags |= flagUnion;
7904 }
7905 } else {
7906 const xmlChar *end, *cur = value;
7907 xmlChar *item;
7908
7909 do {
7910 while (IS_BLANK_CH(*cur))
7911 cur++;
7912 end = cur;
7913 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
7914 end++;
7915 if (end == cur)
7916 break;
7917 item = xmlStrndup(cur, end - cur);
7918 if (xmlStrEqual(item, BAD_CAST "extension")) {
7919 if (flagExtension != -1) {
7920 if ((*flags & flagExtension) == 0)
7921 *flags |= flagExtension;
7922 } else
7923 ret = 1;
7924 } else if (xmlStrEqual(item, BAD_CAST "restriction")) {
7925 if (flagRestriction != -1) {
7926 if ((*flags & flagRestriction) == 0)
7927 *flags |= flagRestriction;
7928 } else
7929 ret = 1;
7930 } else if (xmlStrEqual(item, BAD_CAST "substitution")) {
7931 if (flagSubstitution != -1) {
7932 if ((*flags & flagSubstitution) == 0)
7933 *flags |= flagSubstitution;
7934 } else
7935 ret = 1;
7936 } else if (xmlStrEqual(item, BAD_CAST "list")) {
7937 if (flagList != -1) {
7938 if ((*flags & flagList) == 0)
7939 *flags |= flagList;
7940 } else
7941 ret = 1;
7942 } else if (xmlStrEqual(item, BAD_CAST "union")) {
7943 if (flagUnion != -1) {
7944 if ((*flags & flagUnion) == 0)
7945 *flags |= flagUnion;
7946 } else
7947 ret = 1;
7948 } else
7949 ret = 1;
7950 if (item != NULL)
7951 xmlFree(item);
7952 cur = end;
7953 } while ((ret == 0) && (*cur != 0));
7954 }
7955
7956 return (ret);
7957}
7958
7959static int
7960xmlSchemaCheckCSelectorXPath(xmlSchemaParserCtxtPtr ctxt,
7961 xmlSchemaIDCPtr idc,
7962 xmlSchemaIDCSelectPtr selector,
7963 xmlAttrPtr attr,
7964 int isField)
7965{
7966 xmlNodePtr node;
7967
7968 /*
7969 * c-selector-xpath:
7970 * Schema Component Constraint: Selector Value OK
7971 *
7972 * TODO: 1 The {selector} must be a valid XPath expression, as defined
7973 * in [XPath].
7974 */
7975 if (selector == NULL) {
7976 xmlSchemaPErr(ctxt, idc->node,
7978 "Internal error: xmlSchemaCheckCSelectorXPath, "
7979 "the selector is not specified.\n", NULL, NULL);
7980 return (-1);
7981 }
7982 if (attr == NULL)
7983 node = idc->node;
7984 else
7985 node = (xmlNodePtr) attr;
7986 if (selector->xpath == NULL) {
7987 xmlSchemaPCustomErr(ctxt,
7988 /* TODO: Adjust error code. */
7990 NULL, node,
7991 "The XPath expression of the selector is not valid", NULL);
7993 } else {
7994 const xmlChar **nsArray = NULL;
7995 xmlNsPtr *nsList = NULL;
7996 /*
7997 * Compile the XPath expression.
7998 */
7999 /*
8000 * TODO: We need the array of in-scope namespaces for compilation.
8001 * TODO: Call xmlPatterncompile with different options for selector/
8002 * field.
8003 */
8004 if (attr == NULL)
8005 nsList = NULL;
8006 else
8007 nsList = xmlGetNsList(attr->doc, attr->parent);
8008 /*
8009 * Build an array of prefixes and namespaces.
8010 */
8011 if (nsList != NULL) {
8012 int i, count = 0;
8013
8014 for (i = 0; nsList[i] != NULL; i++)
8015 count++;
8016
8017 nsArray = (const xmlChar **) xmlMalloc(
8018 (count * 2 + 1) * sizeof(const xmlChar *));
8019 if (nsArray == NULL) {
8020 xmlSchemaPErrMemory(ctxt, "allocating a namespace array",
8021 NULL);
8022 xmlFree(nsList);
8023 return (-1);
8024 }
8025 for (i = 0; i < count; i++) {
8026 nsArray[2 * i] = nsList[i]->href;
8027 nsArray[2 * i + 1] = nsList[i]->prefix;
8028 }
8029 nsArray[count * 2] = NULL;
8030 xmlFree(nsList);
8031 }
8032 /*
8033 * TODO: Differentiate between "selector" and "field".
8034 */
8035 if (isField)
8036 selector->xpathComp = (void *) xmlPatterncompile(selector->xpath,
8037 NULL, XML_PATTERN_XSFIELD, nsArray);
8038 else
8039 selector->xpathComp = (void *) xmlPatterncompile(selector->xpath,
8040 NULL, XML_PATTERN_XSSEL, nsArray);
8041 if (nsArray != NULL)
8042 xmlFree((xmlChar **) nsArray);
8043
8044 if (selector->xpathComp == NULL) {
8045 xmlSchemaPCustomErr(ctxt,
8046 /* TODO: Adjust error code? */
8048 NULL, node,
8049 "The XPath expression '%s' could not be "
8050 "compiled", selector->xpath);
8052 }
8053 }
8054 return (0);
8055}
8056
8057#define ADD_ANNOTATION(annot) \
8058 xmlSchemaAnnotPtr cur = item->annot; \
8059 if (item->annot == NULL) { \
8060 item->annot = annot; \
8061 return (annot); \
8062 } \
8063 cur = item->annot; \
8064 if (cur->next != NULL) { \
8065 cur = cur->next; \
8066 } \
8067 cur->next = annot;
8068
8078static xmlSchemaAnnotPtr
8079xmlSchemaAddAnnotation(xmlSchemaAnnotItemPtr annItem,
8080 xmlSchemaAnnotPtr annot)
8081{
8082 if ((annItem == NULL) || (annot == NULL))
8083 return (NULL);
8084 switch (annItem->type) {
8085 case XML_SCHEMA_TYPE_ELEMENT: {
8086 xmlSchemaElementPtr item = (xmlSchemaElementPtr) annItem;
8087 ADD_ANNOTATION(annot)
8088 }
8089 break;
8090 case XML_SCHEMA_TYPE_ATTRIBUTE: {
8091 xmlSchemaAttributePtr item = (xmlSchemaAttributePtr) annItem;
8092 ADD_ANNOTATION(annot)
8093 }
8094 break;
8095 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
8096 case XML_SCHEMA_TYPE_ANY: {
8097 xmlSchemaWildcardPtr item = (xmlSchemaWildcardPtr) annItem;
8098 ADD_ANNOTATION(annot)
8099 }
8100 break;
8101 case XML_SCHEMA_TYPE_PARTICLE:
8102 case XML_SCHEMA_TYPE_IDC_KEY:
8103 case XML_SCHEMA_TYPE_IDC_KEYREF:
8104 case XML_SCHEMA_TYPE_IDC_UNIQUE: {
8105 xmlSchemaAnnotItemPtr item = (xmlSchemaAnnotItemPtr) annItem;
8106 ADD_ANNOTATION(annot)
8107 }
8108 break;
8109 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP: {
8110 xmlSchemaAttributeGroupPtr item =
8111 (xmlSchemaAttributeGroupPtr) annItem;
8112 ADD_ANNOTATION(annot)
8113 }
8114 break;
8115 case XML_SCHEMA_TYPE_NOTATION: {
8116 xmlSchemaNotationPtr item = (xmlSchemaNotationPtr) annItem;
8117 ADD_ANNOTATION(annot)
8118 }
8119 break;
8120 case XML_SCHEMA_FACET_MININCLUSIVE:
8121 case XML_SCHEMA_FACET_MINEXCLUSIVE:
8122 case XML_SCHEMA_FACET_MAXINCLUSIVE:
8123 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
8124 case XML_SCHEMA_FACET_TOTALDIGITS:
8125 case XML_SCHEMA_FACET_FRACTIONDIGITS:
8126 case XML_SCHEMA_FACET_PATTERN:
8127 case XML_SCHEMA_FACET_ENUMERATION:
8128 case XML_SCHEMA_FACET_WHITESPACE:
8129 case XML_SCHEMA_FACET_LENGTH:
8130 case XML_SCHEMA_FACET_MAXLENGTH:
8131 case XML_SCHEMA_FACET_MINLENGTH: {
8132 xmlSchemaFacetPtr item = (xmlSchemaFacetPtr) annItem;
8133 ADD_ANNOTATION(annot)
8134 }
8135 break;
8136 case XML_SCHEMA_TYPE_SIMPLE:
8137 case XML_SCHEMA_TYPE_COMPLEX: {
8138 xmlSchemaTypePtr item = (xmlSchemaTypePtr) annItem;
8139 ADD_ANNOTATION(annot)
8140 }
8141 break;
8142 case XML_SCHEMA_TYPE_GROUP: {
8143 xmlSchemaModelGroupDefPtr item = (xmlSchemaModelGroupDefPtr) annItem;
8144 ADD_ANNOTATION(annot)
8145 }
8146 break;
8147 case XML_SCHEMA_TYPE_SEQUENCE:
8148 case XML_SCHEMA_TYPE_CHOICE:
8149 case XML_SCHEMA_TYPE_ALL: {
8150 xmlSchemaModelGroupPtr item = (xmlSchemaModelGroupPtr) annItem;
8151 ADD_ANNOTATION(annot)
8152 }
8153 break;
8154 default:
8155 xmlSchemaPCustomErr(NULL,
8157 NULL, NULL,
8158 "Internal error: xmlSchemaAddAnnotation, "
8159 "The item is not a annotated schema component", NULL);
8160 break;
8161 }
8162 return (annot);
8163}
8164
8176static xmlSchemaIDCSelectPtr
8177xmlSchemaParseIDCSelectorAndField(xmlSchemaParserCtxtPtr ctxt,
8178 xmlSchemaIDCPtr idc,
8179 xmlNodePtr node,
8180 int isField)
8181{
8182 xmlSchemaIDCSelectPtr item;
8183 xmlNodePtr child = NULL;
8184 xmlAttrPtr attr;
8185
8186 /*
8187 * Check for illegal attributes.
8188 */
8189 attr = node->properties;
8190 while (attr != NULL) {
8191 if (attr->ns == NULL) {
8192 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8193 (!xmlStrEqual(attr->name, BAD_CAST "xpath"))) {
8194 xmlSchemaPIllegalAttrErr(ctxt,
8196 }
8197 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8198 xmlSchemaPIllegalAttrErr(ctxt,
8200 }
8201 attr = attr->next;
8202 }
8203 /*
8204 * Create the item.
8205 */
8206 item = (xmlSchemaIDCSelectPtr) xmlMalloc(sizeof(xmlSchemaIDCSelect));
8207 if (item == NULL) {
8208 xmlSchemaPErrMemory(ctxt,
8209 "allocating a 'selector' of an identity-constraint definition",
8210 NULL);
8211 return (NULL);
8212 }
8213 memset(item, 0, sizeof(xmlSchemaIDCSelect));
8214 /*
8215 * Attribute "xpath" (mandatory).
8216 */
8217 attr = xmlSchemaGetPropNode(node, "xpath");
8218 if (attr == NULL) {
8219 xmlSchemaPMissingAttrErr(ctxt,
8221 NULL, node,
8222 "name", NULL);
8223 } else {
8224 item->xpath = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8225 /*
8226 * URGENT TODO: "field"s have an other syntax than "selector"s.
8227 */
8228
8229 if (xmlSchemaCheckCSelectorXPath(ctxt, idc, item, attr,
8230 isField) == -1) {
8231 xmlSchemaPErr(ctxt,
8232 (xmlNodePtr) attr,
8234 "Internal error: xmlSchemaParseIDCSelectorAndField, "
8235 "validating the XPath expression of a IDC selector.\n",
8236 NULL, NULL);
8237 }
8238
8239 }
8240 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
8241 /*
8242 * And now for the children...
8243 */
8244 child = node->children;
8245 if (IS_SCHEMA(child, "annotation")) {
8246 /*
8247 * Add the annotation to the parent IDC.
8248 */
8249 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) idc,
8250 xmlSchemaParseAnnotation(ctxt, child, 1));
8251 child = child->next;
8252 }
8253 if (child != NULL) {
8254 xmlSchemaPContentErr(ctxt,
8256 NULL, node, child,
8257 NULL, "(annotation?)");
8258 }
8259
8260 return (item);
8261}
8262
8273static xmlSchemaIDCPtr
8274xmlSchemaParseIDC(xmlSchemaParserCtxtPtr ctxt,
8275 xmlSchemaPtr schema,
8276 xmlNodePtr node,
8277 xmlSchemaTypeType idcCategory,
8278 const xmlChar *targetNamespace)
8279{
8280 xmlSchemaIDCPtr item = NULL;
8281 xmlNodePtr child = NULL;
8282 xmlAttrPtr attr;
8283 const xmlChar *name = NULL;
8284 xmlSchemaIDCSelectPtr field = NULL, lastField = NULL;
8285
8286 /*
8287 * Check for illegal attributes.
8288 */
8289 attr = node->properties;
8290 while (attr != NULL) {
8291 if (attr->ns == NULL) {
8292 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8293 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
8294 ((idcCategory != XML_SCHEMA_TYPE_IDC_KEYREF) ||
8295 (!xmlStrEqual(attr->name, BAD_CAST "refer")))) {
8296 xmlSchemaPIllegalAttrErr(ctxt,
8298 }
8299 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8300 xmlSchemaPIllegalAttrErr(ctxt,
8302 }
8303 attr = attr->next;
8304 }
8305 /*
8306 * Attribute "name" (mandatory).
8307 */
8308 attr = xmlSchemaGetPropNode(node, "name");
8309 if (attr == NULL) {
8310 xmlSchemaPMissingAttrErr(ctxt,
8312 NULL, node,
8313 "name", NULL);
8314 return (NULL);
8315 } else if (xmlSchemaPValAttrNode(ctxt,
8316 NULL, attr,
8317 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
8318 return (NULL);
8319 }
8320 /* Create the component. */
8321 item = xmlSchemaAddIDC(ctxt, schema, name, targetNamespace,
8322 idcCategory, node);
8323 if (item == NULL)
8324 return(NULL);
8325
8326 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
8327 if (idcCategory == XML_SCHEMA_TYPE_IDC_KEYREF) {
8328 /*
8329 * Attribute "refer" (mandatory).
8330 */
8331 attr = xmlSchemaGetPropNode(node, "refer");
8332 if (attr == NULL) {
8333 xmlSchemaPMissingAttrErr(ctxt,
8335 NULL, node,
8336 "refer", NULL);
8337 } else {
8338 /*
8339 * Create a reference item.
8340 */
8341 item->ref = xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_IDC_KEY,
8342 NULL, NULL);
8343 if (item->ref == NULL)
8344 return (NULL);
8345 xmlSchemaPValAttrNodeQName(ctxt, schema,
8346 NULL, attr,
8347 &(item->ref->targetNamespace),
8348 &(item->ref->name));
8349 xmlSchemaCheckReference(ctxt, schema, node, attr,
8350 item->ref->targetNamespace);
8351 }
8352 }
8353 /*
8354 * And now for the children...
8355 */
8356 child = node->children;
8357 if (IS_SCHEMA(child, "annotation")) {
8358 item->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
8359 child = child->next;
8360 }
8361 if (child == NULL) {
8362 xmlSchemaPContentErr(ctxt,
8364 NULL, node, child,
8365 "A child element is missing",
8366 "(annotation?, (selector, field+))");
8367 }
8368 /*
8369 * Child element <selector>.
8370 */
8371 if (IS_SCHEMA(child, "selector")) {
8372 item->selector = xmlSchemaParseIDCSelectorAndField(ctxt,
8373 item, child, 0);
8374 child = child->next;
8375 /*
8376 * Child elements <field>.
8377 */
8378 if (IS_SCHEMA(child, "field")) {
8379 do {
8380 field = xmlSchemaParseIDCSelectorAndField(ctxt,
8381 item, child, 1);
8382 if (field != NULL) {
8383 field->index = item->nbFields;
8384 item->nbFields++;
8385 if (lastField != NULL)
8386 lastField->next = field;
8387 else
8388 item->fields = field;
8389 lastField = field;
8390 }
8391 child = child->next;
8392 } while (IS_SCHEMA(child, "field"));
8393 } else {
8394 xmlSchemaPContentErr(ctxt,
8396 NULL, node, child,
8397 NULL, "(annotation?, (selector, field+))");
8398 }
8399 }
8400 if (child != NULL) {
8401 xmlSchemaPContentErr(ctxt,
8403 NULL, node, child,
8404 NULL, "(annotation?, (selector, field+))");
8405 }
8406
8407 return (item);
8408}
8409
8423static xmlSchemaBasicItemPtr
8424xmlSchemaParseElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
8425 xmlNodePtr node, int *isElemRef, int topLevel)
8426{
8427 xmlSchemaElementPtr decl = NULL;
8428 xmlSchemaParticlePtr particle = NULL;
8429 xmlSchemaAnnotPtr annot = NULL;
8430 xmlNodePtr child = NULL;
8431 xmlAttrPtr attr, nameAttr;
8432 int min, max, isRef = 0;
8433 xmlChar *des = NULL;
8434
8435 /* 3.3.3 Constraints on XML Representations of Element Declarations */
8436 /* TODO: Complete implementation of 3.3.6 */
8437
8438 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8439 return (NULL);
8440
8441 if (isElemRef != NULL)
8442 *isElemRef = 0;
8443 /*
8444 * If we get a "ref" attribute on a local <element> we will assume it's
8445 * a reference - even if there's a "name" attribute; this seems to be more
8446 * robust.
8447 */
8448 nameAttr = xmlSchemaGetPropNode(node, "name");
8449 attr = xmlSchemaGetPropNode(node, "ref");
8450 if ((topLevel) || (attr == NULL)) {
8451 if (nameAttr == NULL) {
8452 xmlSchemaPMissingAttrErr(ctxt,
8454 NULL, node, "name", NULL);
8455 return (NULL);
8456 }
8457 } else
8458 isRef = 1;
8459
8460 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
8461 child = node->children;
8462 if (IS_SCHEMA(child, "annotation")) {
8463 annot = xmlSchemaParseAnnotation(ctxt, child, 1);
8464 child = child->next;
8465 }
8466 /*
8467 * Skip particle part if a global declaration.
8468 */
8469 if (topLevel)
8470 goto declaration_part;
8471 /*
8472 * The particle part ==================================================
8473 */
8474 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
8475 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1, "(xs:nonNegativeInteger | unbounded)");
8476 xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
8477 particle = xmlSchemaAddParticle(ctxt, node, min, max);
8478 if (particle == NULL)
8479 goto return_null;
8480
8481 /* ret->flags |= XML_SCHEMAS_ELEM_REF; */
8482
8483 if (isRef) {
8484 const xmlChar *refNs = NULL, *ref = NULL;
8485 xmlSchemaQNameRefPtr refer = NULL;
8486 /*
8487 * The reference part =============================================
8488 */
8489 if (isElemRef != NULL)
8490 *isElemRef = 1;
8491
8492 xmlSchemaPValAttrNodeQName(ctxt, schema,
8493 NULL, attr, &refNs, &ref);
8494 xmlSchemaCheckReference(ctxt, schema, node, attr, refNs);
8495 /*
8496 * SPEC (3.3.3 : 2.1) "One of ref or name must be present, but not both"
8497 */
8498 if (nameAttr != NULL) {
8499 xmlSchemaPMutualExclAttrErr(ctxt,
8500 XML_SCHEMAP_SRC_ELEMENT_2_1, NULL, nameAttr, "ref", "name");
8501 }
8502 /*
8503 * Check for illegal attributes.
8504 */
8505 attr = node->properties;
8506 while (attr != NULL) {
8507 if (attr->ns == NULL) {
8508 if (xmlStrEqual(attr->name, BAD_CAST "ref") ||
8509 xmlStrEqual(attr->name, BAD_CAST "name") ||
8510 xmlStrEqual(attr->name, BAD_CAST "id") ||
8511 xmlStrEqual(attr->name, BAD_CAST "maxOccurs") ||
8512 xmlStrEqual(attr->name, BAD_CAST "minOccurs"))
8513 {
8514 attr = attr->next;
8515 continue;
8516 } else {
8517 /* SPEC (3.3.3 : 2.2) */
8518 xmlSchemaPCustomAttrErr(ctxt,
8520 NULL, NULL, attr,
8521 "Only the attributes 'minOccurs', 'maxOccurs' and "
8522 "'id' are allowed in addition to 'ref'");
8523 break;
8524 }
8525 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8526 xmlSchemaPIllegalAttrErr(ctxt,
8528 }
8529 attr = attr->next;
8530 }
8531 /*
8532 * No children except <annotation> expected.
8533 */
8534 if (child != NULL) {
8535 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8536 NULL, node, child, NULL, "(annotation?)");
8537 }
8538 if ((min == 0) && (max == 0))
8539 goto return_null;
8540 /*
8541 * Create the reference item and attach it to the particle.
8542 */
8543 refer = xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_ELEMENT,
8544 ref, refNs);
8545 if (refer == NULL)
8546 goto return_null;
8547 particle->children = (xmlSchemaTreeItemPtr) refer;
8548 particle->annot = annot;
8549 /*
8550 * Add the particle to pending components, since the reference
8551 * need to be resolved.
8552 */
8553 WXS_ADD_PENDING(ctxt, particle);
8554 return ((xmlSchemaBasicItemPtr) particle);
8555 }
8556 /*
8557 * The declaration part ===============================================
8558 */
8559declaration_part:
8560 {
8561 const xmlChar *ns = NULL, *fixed, *name, *attrValue;
8562 xmlSchemaIDCPtr curIDC = NULL, lastIDC = NULL;
8563
8564 if (xmlSchemaPValAttrNode(ctxt, NULL, nameAttr,
8565 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0)
8566 goto return_null;
8567 /*
8568 * Evaluate the target namespace.
8569 */
8570 if (topLevel) {
8571 ns = ctxt->targetNamespace;
8572 } else {
8573 attr = xmlSchemaGetPropNode(node, "form");
8574 if (attr != NULL) {
8575 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8576 if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
8577 ns = ctxt->targetNamespace;
8578 } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) {
8579 xmlSchemaPSimpleTypeErr(ctxt,
8581 NULL, (xmlNodePtr) attr,
8582 NULL, "(qualified | unqualified)",
8583 attrValue, NULL, NULL, NULL);
8584 }
8585 } else if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
8586 ns = ctxt->targetNamespace;
8587 }
8588 decl = xmlSchemaAddElement(ctxt, name, ns, node, topLevel);
8589 if (decl == NULL) {
8590 goto return_null;
8591 }
8592 /*
8593 * Check for illegal attributes.
8594 */
8595 attr = node->properties;
8596 while (attr != NULL) {
8597 if (attr->ns == NULL) {
8598 if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
8599 (!xmlStrEqual(attr->name, BAD_CAST "type")) &&
8600 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8601 (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
8602 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
8603 (!xmlStrEqual(attr->name, BAD_CAST "block")) &&
8604 (!xmlStrEqual(attr->name, BAD_CAST "nillable")))
8605 {
8606 if (topLevel == 0) {
8607 if ((!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
8608 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
8609 (!xmlStrEqual(attr->name, BAD_CAST "form")))
8610 {
8611 xmlSchemaPIllegalAttrErr(ctxt,
8613 }
8614 } else if ((!xmlStrEqual(attr->name, BAD_CAST "final")) &&
8615 (!xmlStrEqual(attr->name, BAD_CAST "abstract")) &&
8616 (!xmlStrEqual(attr->name, BAD_CAST "substitutionGroup"))) {
8617
8618 xmlSchemaPIllegalAttrErr(ctxt,
8620 }
8621 }
8622 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8623
8624 xmlSchemaPIllegalAttrErr(ctxt,
8626 }
8627 attr = attr->next;
8628 }
8629 /*
8630 * Extract/validate attributes.
8631 */
8632 if (topLevel) {
8633 /*
8634 * Process top attributes of global element declarations here.
8635 */
8636 decl->flags |= XML_SCHEMAS_ELEM_GLOBAL;
8637 decl->flags |= XML_SCHEMAS_ELEM_TOPLEVEL;
8638 xmlSchemaPValAttrQName(ctxt, schema,
8639 NULL, node, "substitutionGroup",
8640 &(decl->substGroupNs), &(decl->substGroup));
8641 if (xmlGetBooleanProp(ctxt, node, "abstract", 0))
8642 decl->flags |= XML_SCHEMAS_ELEM_ABSTRACT;
8643 /*
8644 * Attribute "final".
8645 */
8646 attr = xmlSchemaGetPropNode(node, "final");
8647 if (attr == NULL) {
8648 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
8649 decl->flags |= XML_SCHEMAS_ELEM_FINAL_EXTENSION;
8650 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
8651 decl->flags |= XML_SCHEMAS_ELEM_FINAL_RESTRICTION;
8652 } else {
8653 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8654 if (xmlSchemaPValAttrBlockFinal(attrValue, &(decl->flags),
8655 -1,
8656 XML_SCHEMAS_ELEM_FINAL_EXTENSION,
8657 XML_SCHEMAS_ELEM_FINAL_RESTRICTION, -1, -1, -1) != 0) {
8658 xmlSchemaPSimpleTypeErr(ctxt,
8660 NULL, (xmlNodePtr) attr,
8661 NULL, "(#all | List of (extension | restriction))",
8662 attrValue, NULL, NULL, NULL);
8663 }
8664 }
8665 }
8666 /*
8667 * Attribute "block".
8668 */
8669 attr = xmlSchemaGetPropNode(node, "block");
8670 if (attr == NULL) {
8671 /*
8672 * Apply default "block" values.
8673 */
8674 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
8675 decl->flags |= XML_SCHEMAS_ELEM_BLOCK_RESTRICTION;
8676 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
8677 decl->flags |= XML_SCHEMAS_ELEM_BLOCK_EXTENSION;
8678 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
8679 decl->flags |= XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION;
8680 } else {
8681 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8682 if (xmlSchemaPValAttrBlockFinal(attrValue, &(decl->flags),
8683 -1,
8684 XML_SCHEMAS_ELEM_BLOCK_EXTENSION,
8685 XML_SCHEMAS_ELEM_BLOCK_RESTRICTION,
8686 XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION, -1, -1) != 0) {
8687 xmlSchemaPSimpleTypeErr(ctxt,
8689 NULL, (xmlNodePtr) attr,
8690 NULL, "(#all | List of (extension | "
8691 "restriction | substitution))", attrValue,
8692 NULL, NULL, NULL);
8693 }
8694 }
8695 if (xmlGetBooleanProp(ctxt, node, "nillable", 0))
8696 decl->flags |= XML_SCHEMAS_ELEM_NILLABLE;
8697
8698 attr = xmlSchemaGetPropNode(node, "type");
8699 if (attr != NULL) {
8700 xmlSchemaPValAttrNodeQName(ctxt, schema,
8701 NULL, attr,
8702 &(decl->namedTypeNs), &(decl->namedType));
8703 xmlSchemaCheckReference(ctxt, schema, node,
8704 attr, decl->namedTypeNs);
8705 }
8706 decl->value = xmlSchemaGetProp(ctxt, node, "default");
8707 attr = xmlSchemaGetPropNode(node, "fixed");
8708 if (attr != NULL) {
8709 fixed = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8710 if (decl->value != NULL) {
8711 /*
8712 * 3.3.3 : 1
8713 * default and fixed must not both be present.
8714 */
8715 xmlSchemaPMutualExclAttrErr(ctxt,
8717 NULL, attr, "default", "fixed");
8718 } else {
8719 decl->flags |= XML_SCHEMAS_ELEM_FIXED;
8720 decl->value = fixed;
8721 }
8722 }
8723 /*
8724 * And now for the children...
8725 */
8726 if (IS_SCHEMA(child, "complexType")) {
8727 /*
8728 * 3.3.3 : 3
8729 * "type" and either <simpleType> or <complexType> are mutually
8730 * exclusive
8731 */
8732 if (decl->namedType != NULL) {
8733 xmlSchemaPContentErr(ctxt,
8735 NULL, node, child,
8736 "The attribute 'type' and the <complexType> child are "
8737 "mutually exclusive", NULL);
8738 } else
8739 WXS_ELEM_TYPEDEF(decl) = xmlSchemaParseComplexType(ctxt, schema, child, 0);
8740 child = child->next;
8741 } else if (IS_SCHEMA(child, "simpleType")) {
8742 /*
8743 * 3.3.3 : 3
8744 * "type" and either <simpleType> or <complexType> are
8745 * mutually exclusive
8746 */
8747 if (decl->namedType != NULL) {
8748 xmlSchemaPContentErr(ctxt,
8750 NULL, node, child,
8751 "The attribute 'type' and the <simpleType> child are "
8752 "mutually exclusive", NULL);
8753 } else
8754 WXS_ELEM_TYPEDEF(decl) = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
8755 child = child->next;
8756 }
8757 while ((IS_SCHEMA(child, "unique")) ||
8758 (IS_SCHEMA(child, "key")) || (IS_SCHEMA(child, "keyref"))) {
8759 if (IS_SCHEMA(child, "unique")) {
8760 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
8761 XML_SCHEMA_TYPE_IDC_UNIQUE, decl->targetNamespace);
8762 } else if (IS_SCHEMA(child, "key")) {
8763 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
8764 XML_SCHEMA_TYPE_IDC_KEY, decl->targetNamespace);
8765 } else if (IS_SCHEMA(child, "keyref")) {
8766 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
8767 XML_SCHEMA_TYPE_IDC_KEYREF, decl->targetNamespace);
8768 }
8769 if (lastIDC != NULL)
8770 lastIDC->next = curIDC;
8771 else
8772 decl->idcs = (void *) curIDC;
8773 lastIDC = curIDC;
8774 child = child->next;
8775 }
8776 if (child != NULL) {
8777 xmlSchemaPContentErr(ctxt,
8779 NULL, node, child,
8780 NULL, "(annotation?, ((simpleType | complexType)?, "
8781 "(unique | key | keyref)*))");
8782 }
8783 decl->annot = annot;
8784 }
8785 /*
8786 * NOTE: Element Declaration Representation OK 4. will be checked at a
8787 * different layer.
8788 */
8789 FREE_AND_NULL(des)
8790 if (topLevel)
8791 return ((xmlSchemaBasicItemPtr) decl);
8792 else {
8793 particle->children = (xmlSchemaTreeItemPtr) decl;
8794 return ((xmlSchemaBasicItemPtr) particle);
8795 }
8796
8798 FREE_AND_NULL(des);
8799 if (annot != NULL) {
8800 if (particle != NULL)
8801 particle->annot = NULL;
8802 if (decl != NULL)
8803 decl->annot = NULL;
8804 xmlSchemaFreeAnnot(annot);
8805 }
8806 return (NULL);
8807}
8808
8821static int
8822xmlSchemaParseUnion(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
8823 xmlNodePtr node)
8824{
8825 xmlSchemaTypePtr type;
8826 xmlNodePtr child = NULL;
8827 xmlAttrPtr attr;
8828 const xmlChar *cur = NULL;
8829
8830 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8831 return (-1);
8832 /* Not a component, don't create it. */
8833 type = ctxt->ctxtType;
8834 /*
8835 * Mark the simple type as being of variety "union".
8836 */
8837 type->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
8838 /*
8839 * SPEC (Base type) (2) "If the <list> or <union> alternative is chosen,
8840 * then the `simple ur-type definition`."
8841 */
8842 type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
8843 /*
8844 * Check for illegal attributes.
8845 */
8846 attr = node->properties;
8847 while (attr != NULL) {
8848 if (attr->ns == NULL) {
8849 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8850 (!xmlStrEqual(attr->name, BAD_CAST "memberTypes"))) {
8851 xmlSchemaPIllegalAttrErr(ctxt,
8853 }
8854 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8855 xmlSchemaPIllegalAttrErr(ctxt,
8857 }
8858 attr = attr->next;
8859 }
8860 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
8861 /*
8862 * Attribute "memberTypes". This is a list of QNames.
8863 * TODO: Check the value to contain anything.
8864 */
8865 attr = xmlSchemaGetPropNode(node, "memberTypes");
8866 if (attr != NULL) {
8867 const xmlChar *end;
8868 xmlChar *tmp;
8869 const xmlChar *localName, *nsName;
8870 xmlSchemaTypeLinkPtr link, lastLink = NULL;
8871 xmlSchemaQNameRefPtr ref;
8872
8873 cur = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8874 if (cur == NULL)
8875 return (-1);
8876 type->base = cur;
8877 do {
8878 while (IS_BLANK_CH(*cur))
8879 cur++;
8880 end = cur;
8881 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
8882 end++;
8883 if (end == cur)
8884 break;
8885 tmp = xmlStrndup(cur, end - cur);
8886 if (tmp == NULL) {
8887 xmlSchemaPErrMemory(ctxt, "xmlSchemaParseUnion, "
8888 "duplicating type name", NULL);
8889 return (-1);
8890 }
8891 if (xmlSchemaPValAttrNodeQNameValue(ctxt, schema,
8892 NULL, attr, BAD_CAST tmp, &nsName, &localName) == 0) {
8893 /*
8894 * Create the member type link.
8895 */
8896 link = (xmlSchemaTypeLinkPtr)
8897 xmlMalloc(sizeof(xmlSchemaTypeLink));
8898 if (link == NULL) {
8899 xmlSchemaPErrMemory(ctxt, "xmlSchemaParseUnion, "
8900 "allocating a type link", NULL);
8901 FREE_AND_NULL(tmp)
8902 return (-1);
8903 }
8904 link->type = NULL;
8905 link->next = NULL;
8906 if (lastLink == NULL)
8907 type->memberTypes = link;
8908 else
8909 lastLink->next = link;
8910 lastLink = link;
8911 /*
8912 * Create a reference item.
8913 */
8914 ref = xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_SIMPLE,
8915 localName, nsName);
8916 if (ref == NULL) {
8917 FREE_AND_NULL(tmp)
8918 return (-1);
8919 }
8920 /*
8921 * Assign the reference to the link, it will be resolved
8922 * later during fixup of the union simple type.
8923 */
8924 link->type = (xmlSchemaTypePtr) ref;
8925 }
8926 FREE_AND_NULL(tmp)
8927 cur = end;
8928 } while (*cur != 0);
8929
8930 }
8931 /*
8932 * And now for the children...
8933 */
8934 child = node->children;
8935 if (IS_SCHEMA(child, "annotation")) {
8936 /*
8937 * Add the annotation to the simple type ancestor.
8938 */
8939 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
8940 xmlSchemaParseAnnotation(ctxt, child, 1));
8941 child = child->next;
8942 }
8943 if (IS_SCHEMA(child, "simpleType")) {
8944 xmlSchemaTypePtr subtype, last = NULL;
8945
8946 /*
8947 * Anchor the member types in the "subtypes" field of the
8948 * simple type.
8949 */
8950 while (IS_SCHEMA(child, "simpleType")) {
8951 subtype = (xmlSchemaTypePtr)
8952 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
8953 if (subtype != NULL) {
8954 if (last == NULL) {
8955 type->subtypes = subtype;
8956 last = subtype;
8957 } else {
8958 last->next = subtype;
8959 last = subtype;
8960 }
8961 last->next = NULL;
8962 }
8963 child = child->next;
8964 }
8965 }
8966 if (child != NULL) {
8967 xmlSchemaPContentErr(ctxt,
8969 NULL, node, child, NULL, "(annotation?, simpleType*)");
8970 }
8971 if ((attr == NULL) && (type->subtypes == NULL)) {
8972 /*
8973 * src-union-memberTypes-or-simpleTypes
8974 * Either the memberTypes [attribute] of the <union> element must
8975 * be non-empty or there must be at least one simpleType [child].
8976 */
8977 xmlSchemaPCustomErr(ctxt,
8979 NULL, node,
8980 "Either the attribute 'memberTypes' or "
8981 "at least one <simpleType> child must be present", NULL);
8982 }
8983 return (0);
8984}
8985
8998static xmlSchemaTypePtr
8999xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
9000 xmlNodePtr node)
9001{
9002 xmlSchemaTypePtr type;
9003 xmlNodePtr child = NULL;
9004 xmlAttrPtr attr;
9005
9006 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9007 return (NULL);
9008 /* Not a component, don't create it. */
9009 type = ctxt->ctxtType;
9010 /*
9011 * Mark the type as being of variety "list".
9012 */
9013 type->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
9014 /*
9015 * SPEC (Base type) (2) "If the <list> or <union> alternative is chosen,
9016 * then the `simple ur-type definition`."
9017 */
9018 type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
9019 /*
9020 * Check for illegal attributes.
9021 */
9022 attr = node->properties;
9023 while (attr != NULL) {
9024 if (attr->ns == NULL) {
9025 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9026 (!xmlStrEqual(attr->name, BAD_CAST "itemType"))) {
9027 xmlSchemaPIllegalAttrErr(ctxt,
9029 }
9030 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9031 xmlSchemaPIllegalAttrErr(ctxt,
9033 }
9034 attr = attr->next;
9035 }
9036
9037 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
9038
9039 /*
9040 * Attribute "itemType". NOTE that we will use the "ref" and "refNs"
9041 * fields for holding the reference to the itemType.
9042 *
9043 * REVAMP TODO: Use the "base" and "baseNs" fields, since we will remove
9044 * the "ref" fields.
9045 */
9046 xmlSchemaPValAttrQName(ctxt, schema, NULL,
9047 node, "itemType", &(type->baseNs), &(type->base));
9048 /*
9049 * And now for the children...
9050 */
9051 child = node->children;
9052 if (IS_SCHEMA(child, "annotation")) {
9053 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
9054 xmlSchemaParseAnnotation(ctxt, child, 1));
9055 child = child->next;
9056 }
9057 if (IS_SCHEMA(child, "simpleType")) {
9058 /*
9059 * src-list-itemType-or-simpleType
9060 * Either the itemType [attribute] or the <simpleType> [child] of
9061 * the <list> element must be present, but not both.
9062 */
9063 if (type->base != NULL) {
9064 xmlSchemaPCustomErr(ctxt,
9066 NULL, node,
9067 "The attribute 'itemType' and the <simpleType> child "
9068 "are mutually exclusive", NULL);
9069 } else {
9070 type->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
9071 }
9072 child = child->next;
9073 } else if (type->base == NULL) {
9074 xmlSchemaPCustomErr(ctxt,
9076 NULL, node,
9077 "Either the attribute 'itemType' or the <simpleType> child "
9078 "must be present", NULL);
9079 }
9080 if (child != NULL) {
9081 xmlSchemaPContentErr(ctxt,
9083 NULL, node, child, NULL, "(annotation?, simpleType?)");
9084 }
9085 if ((type->base == NULL) &&
9086 (type->subtypes == NULL) &&
9087 (xmlSchemaGetPropNode(node, "itemType") == NULL)) {
9088 xmlSchemaPCustomErr(ctxt,
9090 NULL, node,
9091 "Either the attribute 'itemType' or the <simpleType> child "
9092 "must be present", NULL);
9093 }
9094 return (NULL);
9095}
9096
9109static xmlSchemaTypePtr
9110xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
9111 xmlNodePtr node, int topLevel)
9112{
9113 xmlSchemaTypePtr type, oldCtxtType;
9114 xmlNodePtr child = NULL;
9115 const xmlChar *attrValue = NULL;
9116 xmlAttrPtr attr;
9117 int hasRestriction = 0;
9118
9119 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9120 return (NULL);
9121
9122 if (topLevel) {
9123 attr = xmlSchemaGetPropNode(node, "name");
9124 if (attr == NULL) {
9125 xmlSchemaPMissingAttrErr(ctxt,
9127 NULL, node,
9128 "name", NULL);
9129 return (NULL);
9130 } else {
9131 if (xmlSchemaPValAttrNode(ctxt,
9132 NULL, attr,
9133 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &attrValue) != 0)
9134 return (NULL);
9135 /*
9136 * Skip built-in types.
9137 */
9138 if (ctxt->isS4S) {
9139 xmlSchemaTypePtr biType;
9140
9141 if (ctxt->isRedefine) {
9142 /*
9143 * REDEFINE: Disallow redefinition of built-in-types.
9144 * TODO: It seems that the spec does not say anything
9145 * about this case.
9146 */
9147 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_SRC_REDEFINE,
9148 NULL, node,
9149 "Redefinition of built-in simple types is not "
9150 "supported", NULL);
9151 return(NULL);
9152 }
9153 biType = xmlSchemaGetPredefinedType(attrValue, xmlSchemaNs);
9154 if (biType != NULL)
9155 return (biType);
9156 }
9157 }
9158 }
9159 /*
9160 * TargetNamespace:
9161 * SPEC "The `actual value` of the targetNamespace [attribute]
9162 * of the <schema> ancestor element information item if present,
9163 * otherwise `absent`.
9164 */
9165 if (topLevel == 0) {
9166#ifdef ENABLE_NAMED_LOCALS
9167 char buf[40];
9168#endif
9169 /*
9170 * Parse as local simple type definition.
9171 */
9172#ifdef ENABLE_NAMED_LOCALS
9173 snprintf(buf, 39, "#ST%d", ctxt->counter++ + 1);
9174 type = xmlSchemaAddType(ctxt, schema,
9175 XML_SCHEMA_TYPE_SIMPLE,
9176 xmlDictLookup(ctxt->dict, (const xmlChar *)buf, -1),
9177 ctxt->targetNamespace, node, 0);
9178#else
9179 type = xmlSchemaAddType(ctxt, schema,
9180 XML_SCHEMA_TYPE_SIMPLE,
9181 NULL, ctxt->targetNamespace, node, 0);
9182#endif
9183 if (type == NULL)
9184 return (NULL);
9185 type->type = XML_SCHEMA_TYPE_SIMPLE;
9186 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
9187 /*
9188 * Check for illegal attributes.
9189 */
9190 attr = node->properties;
9191 while (attr != NULL) {
9192 if (attr->ns == NULL) {
9193 if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
9194 xmlSchemaPIllegalAttrErr(ctxt,
9196 }
9197 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9198 xmlSchemaPIllegalAttrErr(ctxt,
9200 }
9201 attr = attr->next;
9202 }
9203 } else {
9204 /*
9205 * Parse as global simple type definition.
9206 *
9207 * Note that attrValue is the value of the attribute "name" here.
9208 */
9209 type = xmlSchemaAddType(ctxt, schema, XML_SCHEMA_TYPE_SIMPLE,
9210 attrValue, ctxt->targetNamespace, node, 1);
9211 if (type == NULL)
9212 return (NULL);
9213 type->type = XML_SCHEMA_TYPE_SIMPLE;
9214 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
9215 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
9216 /*
9217 * Check for illegal attributes.
9218 */
9219 attr = node->properties;
9220 while (attr != NULL) {
9221 if (attr->ns == NULL) {
9222 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9223 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
9224 (!xmlStrEqual(attr->name, BAD_CAST "final"))) {
9225 xmlSchemaPIllegalAttrErr(ctxt,
9227 }
9228 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9229 xmlSchemaPIllegalAttrErr(ctxt,
9231 }
9232 attr = attr->next;
9233 }
9234 /*
9235 * Attribute "final".
9236 */
9237 attr = xmlSchemaGetPropNode(node, "final");
9238 if (attr == NULL) {
9239 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
9240 type->flags |= XML_SCHEMAS_TYPE_FINAL_RESTRICTION;
9241 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST)
9242 type->flags |= XML_SCHEMAS_TYPE_FINAL_LIST;
9243 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION)
9244 type->flags |= XML_SCHEMAS_TYPE_FINAL_UNION;
9245 } else {
9246 attrValue = xmlSchemaGetProp(ctxt, node, "final");
9247 if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
9248 -1, -1, XML_SCHEMAS_TYPE_FINAL_RESTRICTION, -1,
9249 XML_SCHEMAS_TYPE_FINAL_LIST,
9250 XML_SCHEMAS_TYPE_FINAL_UNION) != 0) {
9251
9252 xmlSchemaPSimpleTypeErr(ctxt,
9254 WXS_BASIC_CAST type, (xmlNodePtr) attr,
9255 NULL, "(#all | List of (list | union | restriction)",
9256 attrValue, NULL, NULL, NULL);
9257 }
9258 }
9259 }
9260 type->targetNamespace = ctxt->targetNamespace;
9261 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
9262 /*
9263 * And now for the children...
9264 */
9265 oldCtxtType = ctxt->ctxtType;
9266
9267 ctxt->ctxtType = type;
9268
9269 child = node->children;
9270 if (IS_SCHEMA(child, "annotation")) {
9271 type->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
9272 child = child->next;
9273 }
9274 if (child == NULL) {
9275 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_MISSING,
9276 NULL, node, child, NULL,
9277 "(annotation?, (restriction | list | union))");
9278 } else if (IS_SCHEMA(child, "restriction")) {
9279 xmlSchemaParseRestriction(ctxt, schema, child,
9280 XML_SCHEMA_TYPE_SIMPLE);
9281 hasRestriction = 1;
9282 child = child->next;
9283 } else if (IS_SCHEMA(child, "list")) {
9284 xmlSchemaParseList(ctxt, schema, child);
9285 child = child->next;
9286 } else if (IS_SCHEMA(child, "union")) {
9287 xmlSchemaParseUnion(ctxt, schema, child);
9288 child = child->next;
9289 }
9290 if (child != NULL) {
9291 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9292 NULL, node, child, NULL,
9293 "(annotation?, (restriction | list | union))");
9294 }
9295 /*
9296 * REDEFINE: SPEC src-redefine (5)
9297 * "Within the [children], each <simpleType> must have a
9298 * <restriction> among its [children] ... the `actual value` of whose
9299 * base [attribute] must be the same as the `actual value` of its own
9300 * name attribute plus target namespace;"
9301 */
9302 if (topLevel && ctxt->isRedefine && (! hasRestriction)) {
9303 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_SRC_REDEFINE,
9304 NULL, node, "This is a redefinition, thus the "
9305 "<simpleType> must have a <restriction> child", NULL);
9306 }
9307
9308 ctxt->ctxtType = oldCtxtType;
9309 return (type);
9310}
9311
9323static xmlSchemaTreeItemPtr
9324xmlSchemaParseModelGroupDefRef(xmlSchemaParserCtxtPtr ctxt,
9325 xmlSchemaPtr schema,
9326 xmlNodePtr node)
9327{
9328 xmlSchemaParticlePtr item;
9329 xmlNodePtr child = NULL;
9330 xmlAttrPtr attr;
9331 const xmlChar *ref = NULL, *refNs = NULL;
9332 int min, max;
9333
9334 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9335 return (NULL);
9336
9337 attr = xmlSchemaGetPropNode(node, "ref");
9338 if (attr == NULL) {
9339 xmlSchemaPMissingAttrErr(ctxt,
9341 NULL, node, "ref", NULL);
9342 return (NULL);
9343 } else if (xmlSchemaPValAttrNodeQName(ctxt, schema, NULL,
9344 attr, &refNs, &ref) != 0) {
9345 return (NULL);
9346 }
9347 xmlSchemaCheckReference(ctxt, schema, node, attr, refNs);
9348 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
9349 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
9350 "(xs:nonNegativeInteger | unbounded)");
9351 /*
9352 * Check for illegal attributes.
9353 */
9354 attr = node->properties;
9355 while (attr != NULL) {
9356 if (attr->ns == NULL) {
9357 if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
9358 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9359 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
9360 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs"))) {
9361 xmlSchemaPIllegalAttrErr(ctxt,
9363 }
9364 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9365 xmlSchemaPIllegalAttrErr(ctxt,
9367 }
9368 attr = attr->next;
9369 }
9370 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
9371 item = xmlSchemaAddParticle(ctxt, node, min, max);
9372 if (item == NULL)
9373 return (NULL);
9374 /*
9375 * Create a qname-reference and set as the term; it will be substituted
9376 * for the model group after the reference has been resolved.
9377 */
9378 item->children = (xmlSchemaTreeItemPtr)
9379 xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_GROUP, ref, refNs);
9380 xmlSchemaPCheckParticleCorrect_2(ctxt, item, node, min, max);
9381 /*
9382 * And now for the children...
9383 */
9384 child = node->children;
9385 /* TODO: Is annotation even allowed for a model group reference? */
9386 if (IS_SCHEMA(child, "annotation")) {
9387 /*
9388 * TODO: What to do exactly with the annotation?
9389 */
9390 item->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
9391 child = child->next;
9392 }
9393 if (child != NULL) {
9394 xmlSchemaPContentErr(ctxt,
9396 NULL, node, child, NULL,
9397 "(annotation?)");
9398 }
9399 /*
9400 * Corresponds to no component at all if minOccurs==maxOccurs==0.
9401 */
9402 if ((min == 0) && (max == 0))
9403 return (NULL);
9404
9405 return ((xmlSchemaTreeItemPtr) item);
9406}
9407
9425static xmlSchemaModelGroupDefPtr
9426xmlSchemaParseModelGroupDefinition(xmlSchemaParserCtxtPtr ctxt,
9427 xmlSchemaPtr schema,
9428 xmlNodePtr node)
9429{
9430 xmlSchemaModelGroupDefPtr item;
9431 xmlNodePtr child = NULL;
9432 xmlAttrPtr attr;
9433 const xmlChar *name;
9434
9435 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9436 return (NULL);
9437
9438 attr = xmlSchemaGetPropNode(node, "name");
9439 if (attr == NULL) {
9440 xmlSchemaPMissingAttrErr(ctxt,
9442 NULL, node,
9443 "name", NULL);
9444 return (NULL);
9445 } else if (xmlSchemaPValAttrNode(ctxt, NULL, attr,
9446 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
9447 return (NULL);
9448 }
9449 item = xmlSchemaAddModelGroupDefinition(ctxt, schema, name,
9450 ctxt->targetNamespace, node);
9451 if (item == NULL)
9452 return (NULL);
9453 /*
9454 * Check for illegal attributes.
9455 */
9456 attr = node->properties;
9457 while (attr != NULL) {
9458 if (attr->ns == NULL) {
9459 if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
9460 (!xmlStrEqual(attr->name, BAD_CAST "id"))) {
9461 xmlSchemaPIllegalAttrErr(ctxt,
9463 }
9464 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9465 xmlSchemaPIllegalAttrErr(ctxt,
9467 }
9468 attr = attr->next;
9469 }
9470 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
9471 /*
9472 * And now for the children...
9473 */
9474 child = node->children;
9475 if (IS_SCHEMA(child, "annotation")) {
9476 item->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
9477 child = child->next;
9478 }
9479 if (IS_SCHEMA(child, "all")) {
9480 item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
9481 XML_SCHEMA_TYPE_ALL, 0);
9482 child = child->next;
9483 } else if (IS_SCHEMA(child, "choice")) {
9484 item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
9485 XML_SCHEMA_TYPE_CHOICE, 0);
9486 child = child->next;
9487 } else if (IS_SCHEMA(child, "sequence")) {
9488 item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
9489 XML_SCHEMA_TYPE_SEQUENCE, 0);
9490 child = child->next;
9491 }
9492
9493
9494
9495 if (child != NULL) {
9496 xmlSchemaPContentErr(ctxt,
9498 NULL, node, child, NULL,
9499 "(annotation?, (all | choice | sequence)?)");
9500 }
9501 return (item);
9502}
9503
9511static void
9512xmlSchemaCleanupDoc(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr root)
9513{
9514 xmlNodePtr delete, cur;
9515
9516 if ((ctxt == NULL) || (root == NULL)) return;
9517
9518 /*
9519 * Remove all the blank text nodes
9520 */
9521 delete = NULL;
9522 cur = root;
9523 while (cur != NULL) {
9524 if (delete != NULL) {
9525 xmlUnlinkNode(delete);
9526 xmlFreeNode(delete);
9527 delete = NULL;
9528 }
9529 if (cur->type == XML_TEXT_NODE) {
9530 if (IS_BLANK_NODE(cur)) {
9531 if (xmlNodeGetSpacePreserve(cur) != 1) {
9532 delete = cur;
9533 }
9534 }
9535 } else if ((cur->type != XML_ELEMENT_NODE) &&
9536 (cur->type != XML_CDATA_SECTION_NODE)) {
9537 delete = cur;
9538 goto skip_children;
9539 }
9540
9541 /*
9542 * Skip to next node
9543 */
9544 if (cur->children != NULL) {
9545 if ((cur->children->type != XML_ENTITY_DECL) &&
9546 (cur->children->type != XML_ENTITY_REF_NODE) &&
9547 (cur->children->type != XML_ENTITY_NODE)) {
9548 cur = cur->children;
9549 continue;
9550 }
9551 }
9552 skip_children:
9553 if (cur->next != NULL) {
9554 cur = cur->next;
9555 continue;
9556 }
9557
9558 do {
9559 cur = cur->parent;
9560 if (cur == NULL)
9561 break;
9562 if (cur == root) {
9563 cur = NULL;
9564 break;
9565 }
9566 if (cur->next != NULL) {
9567 cur = cur->next;
9568 break;
9569 }
9570 } while (cur != NULL);
9571 }
9572 if (delete != NULL) {
9573 xmlUnlinkNode(delete);
9574 xmlFreeNode(delete);
9575 delete = NULL;
9576 }
9577}
9578
9579
9580static void
9581xmlSchemaClearSchemaDefaults(xmlSchemaPtr schema)
9582{
9583 if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
9584 schema->flags ^= XML_SCHEMAS_QUALIF_ELEM;
9585
9586 if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
9587 schema->flags ^= XML_SCHEMAS_QUALIF_ATTR;
9588
9589 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
9590 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_EXTENSION;
9591 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
9592 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION;
9593 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST)
9594 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_LIST;
9595 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION)
9596 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_UNION;
9597
9598 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
9599 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION;
9600 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
9601 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION;
9602 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
9603 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION;
9604}
9605
9606static int
9607xmlSchemaParseSchemaElement(xmlSchemaParserCtxtPtr ctxt,
9608 xmlSchemaPtr schema,
9609 xmlNodePtr node)
9610{
9611 xmlAttrPtr attr;
9612 const xmlChar *val;
9613 int res = 0, oldErrs = ctxt->nberrors;
9614
9615 /*
9616 * Those flags should be moved to the parser context flags,
9617 * since they are not visible at the component level. I.e.
9618 * they are used if processing schema *documents* only.
9619 */
9620 res = xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
9621 HFAILURE;
9622
9623 /*
9624 * Since the version is of type xs:token, we won't bother to
9625 * check it.
9626 */
9627 /* REMOVED:
9628 attr = xmlSchemaGetPropNode(node, "version");
9629 if (attr != NULL) {
9630 res = xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
9631 xmlSchemaGetBuiltInType(XML_SCHEMAS_TOKEN), &val);
9632 HFAILURE;
9633 }
9634 */
9635 attr = xmlSchemaGetPropNode(node, "targetNamespace");
9636 if (attr != NULL) {
9637 res = xmlSchemaPValAttrNode(ctxt, NULL, attr,
9638 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), NULL);
9639 HFAILURE;
9640 if (res != 0) {
9642 goto exit;
9643 }
9644 }
9645 attr = xmlSchemaGetPropNode(node, "elementFormDefault");
9646 if (attr != NULL) {
9647 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
9648 res = xmlSchemaPValAttrFormDefault(val, &schema->flags,
9649 XML_SCHEMAS_QUALIF_ELEM);
9650 HFAILURE;
9651 if (res != 0) {
9652 xmlSchemaPSimpleTypeErr(ctxt,
9654 NULL, (xmlNodePtr) attr, NULL,
9655 "(qualified | unqualified)", val, NULL, NULL, NULL);
9656 }
9657 }
9658 attr = xmlSchemaGetPropNode(node, "attributeFormDefault");
9659 if (attr != NULL) {
9660 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
9661 res = xmlSchemaPValAttrFormDefault(val, &schema->flags,
9662 XML_SCHEMAS_QUALIF_ATTR);
9663 HFAILURE;
9664 if (res != 0) {
9665 xmlSchemaPSimpleTypeErr(ctxt,
9667 NULL, (xmlNodePtr) attr, NULL,
9668 "(qualified | unqualified)", val, NULL, NULL, NULL);
9669 }
9670 }
9671 attr = xmlSchemaGetPropNode(node, "finalDefault");
9672 if (attr != NULL) {
9673 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
9674 res = xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
9675 XML_SCHEMAS_FINAL_DEFAULT_EXTENSION,
9676 XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION,
9677 -1,
9678 XML_SCHEMAS_FINAL_DEFAULT_LIST,
9679 XML_SCHEMAS_FINAL_DEFAULT_UNION);
9680 HFAILURE;
9681 if (res != 0) {
9682 xmlSchemaPSimpleTypeErr(ctxt,
9684 NULL, (xmlNodePtr) attr, NULL,
9685 "(#all | List of (extension | restriction | list | union))",
9686 val, NULL, NULL, NULL);
9687 }
9688 }
9689 attr = xmlSchemaGetPropNode(node, "blockDefault");
9690 if (attr != NULL) {
9691 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
9692 res = xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
9693 XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION,
9694 XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION,
9695 XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION, -1, -1);
9696 HFAILURE;
9697 if (res != 0) {
9698 xmlSchemaPSimpleTypeErr(ctxt,
9700 NULL, (xmlNodePtr) attr, NULL,
9701 "(#all | List of (extension | restriction | substitution))",
9702 val, NULL, NULL, NULL);
9703 }
9704 }
9705
9706exit:
9707 if (oldErrs != ctxt->nberrors)
9708 res = ctxt->err;
9709 return(res);
9710exit_failure:
9711 return(-1);
9712}
9713
9723static int
9724xmlSchemaParseSchemaTopLevel(xmlSchemaParserCtxtPtr ctxt,
9725 xmlSchemaPtr schema, xmlNodePtr nodes)
9726{
9727 xmlNodePtr child;
9728 xmlSchemaAnnotPtr annot;
9729 int res = 0, oldErrs, tmpOldErrs;
9730
9731 if ((ctxt == NULL) || (schema == NULL) || (nodes == NULL))
9732 return(-1);
9733
9734 oldErrs = ctxt->nberrors;
9735 child = nodes;
9736 while ((IS_SCHEMA(child, "include")) ||
9737 (IS_SCHEMA(child, "import")) ||
9738 (IS_SCHEMA(child, "redefine")) ||
9739 (IS_SCHEMA(child, "annotation"))) {
9740 if (IS_SCHEMA(child, "annotation")) {
9741 annot = xmlSchemaParseAnnotation(ctxt, child, 1);
9742 if (schema->annot == NULL)
9743 schema->annot = annot;
9744 else
9745 xmlSchemaFreeAnnot(annot);
9746 } else if (IS_SCHEMA(child, "import")) {
9747 tmpOldErrs = ctxt->nberrors;
9748 res = xmlSchemaParseImport(ctxt, schema, child);
9749 HFAILURE;
9750 HSTOP(ctxt);
9751 if (tmpOldErrs != ctxt->nberrors)
9752 goto exit;
9753 } else if (IS_SCHEMA(child, "include")) {
9754 tmpOldErrs = ctxt->nberrors;
9755 res = xmlSchemaParseInclude(ctxt, schema, child);
9756 HFAILURE;
9757 HSTOP(ctxt);
9758 if (tmpOldErrs != ctxt->nberrors)
9759 goto exit;
9760 } else if (IS_SCHEMA(child, "redefine")) {
9761 tmpOldErrs = ctxt->nberrors;
9762 res = xmlSchemaParseRedefine(ctxt, schema, child);
9763 HFAILURE;
9764 HSTOP(ctxt);
9765 if (tmpOldErrs != ctxt->nberrors)
9766 goto exit;
9767 }
9768 child = child->next;
9769 }
9770 /*
9771 * URGENT TODO: Change the functions to return int results.
9772 * We need especially to catch internal errors.
9773 */
9774 while (child != NULL) {
9775 if (IS_SCHEMA(child, "complexType")) {
9776 xmlSchemaParseComplexType(ctxt, schema, child, 1);
9777 child = child->next;
9778 } else if (IS_SCHEMA(child, "simpleType")) {
9779 xmlSchemaParseSimpleType(ctxt, schema, child, 1);
9780 child = child->next;
9781 } else if (IS_SCHEMA(child, "element")) {
9782 xmlSchemaParseElement(ctxt, schema, child, NULL, 1);
9783 child = child->next;
9784 } else if (IS_SCHEMA(child, "attribute")) {
9785 xmlSchemaParseGlobalAttribute(ctxt, schema, child);
9786 child = child->next;
9787 } else if (IS_SCHEMA(child, "attributeGroup")) {
9788 xmlSchemaParseAttributeGroupDefinition(ctxt, schema, child);
9789 child = child->next;
9790 } else if (IS_SCHEMA(child, "group")) {
9791 xmlSchemaParseModelGroupDefinition(ctxt, schema, child);
9792 child = child->next;
9793 } else if (IS_SCHEMA(child, "notation")) {
9794 xmlSchemaParseNotation(ctxt, schema, child);
9795 child = child->next;
9796 } else {
9797 xmlSchemaPContentErr(ctxt,
9799 NULL, child->parent, child,
9800 NULL, "((include | import | redefine | annotation)*, "
9801 "(((simpleType | complexType | group | attributeGroup) "
9802 "| element | attribute | notation), annotation*)*)");
9803 child = child->next;
9804 }
9805 while (IS_SCHEMA(child, "annotation")) {
9806 /*
9807 * TODO: We should add all annotations.
9808 */
9809 annot = xmlSchemaParseAnnotation(ctxt, child, 1);
9810 if (schema->annot == NULL)
9811 schema->annot = annot;
9812 else
9813 xmlSchemaFreeAnnot(annot);
9814 child = child->next;
9815 }
9816 }
9817exit:
9818 ctxt->ctxtType = NULL;
9819 if (oldErrs != ctxt->nberrors)
9820 res = ctxt->err;
9821 return(res);
9822exit_failure:
9823 return(-1);
9824}
9825
9826static xmlSchemaSchemaRelationPtr
9827xmlSchemaSchemaRelationCreate(void)
9828{
9829 xmlSchemaSchemaRelationPtr ret;
9830
9831 ret = (xmlSchemaSchemaRelationPtr)
9832 xmlMalloc(sizeof(xmlSchemaSchemaRelation));
9833 if (ret == NULL) {
9834 xmlSchemaPErrMemory(NULL, "allocating schema relation", NULL);
9835 return(NULL);
9836 }
9837 memset(ret, 0, sizeof(xmlSchemaSchemaRelation));
9838 return(ret);
9839}
9840
9841#if 0
9842static void
9843xmlSchemaSchemaRelationFree(xmlSchemaSchemaRelationPtr rel)
9844{
9845 xmlFree(rel);
9846}
9847#endif
9848
9849static void
9850xmlSchemaRedefListFree(xmlSchemaRedefPtr redef)
9851{
9852 xmlSchemaRedefPtr prev;
9853
9854 while (redef != NULL) {
9855 prev = redef;
9856 redef = redef->next;
9857 xmlFree(prev);
9858 }
9859}
9860
9861static void
9862xmlSchemaConstructionCtxtFree(xmlSchemaConstructionCtxtPtr con)
9863{
9864 /*
9865 * After the construction context has been freed, there will be
9866 * no schema graph available any more. Only the schema buckets
9867 * will stay alive, which are put into the "schemasImports" and
9868 * "includes" slots of the xmlSchema.
9869 */
9870 if (con->buckets != NULL)
9871 xmlSchemaItemListFree(con->buckets);
9872 if (con->pending != NULL)
9873 xmlSchemaItemListFree(con->pending);
9874 if (con->substGroups != NULL)
9875 xmlHashFree(con->substGroups, xmlSchemaSubstGroupFreeEntry);
9876 if (con->redefs != NULL)
9877 xmlSchemaRedefListFree(con->redefs);
9878 if (con->dict != NULL)
9879 xmlDictFree(con->dict);
9880 xmlFree(con);
9881}
9882
9883static xmlSchemaConstructionCtxtPtr
9884xmlSchemaConstructionCtxtCreate(xmlDictPtr dict)
9885{
9886 xmlSchemaConstructionCtxtPtr ret;
9887
9888 ret = (xmlSchemaConstructionCtxtPtr)
9889 xmlMalloc(sizeof(xmlSchemaConstructionCtxt));
9890 if (ret == NULL) {
9891 xmlSchemaPErrMemory(NULL,
9892 "allocating schema construction context", NULL);
9893 return (NULL);
9894 }
9895 memset(ret, 0, sizeof(xmlSchemaConstructionCtxt));
9896
9897 ret->buckets = xmlSchemaItemListCreate();
9898 if (ret->buckets == NULL) {
9899 xmlSchemaPErrMemory(NULL,
9900 "allocating list of schema buckets", NULL);
9901 xmlFree(ret);
9902 return (NULL);
9903 }
9904 ret->pending = xmlSchemaItemListCreate();
9905 if (ret->pending == NULL) {
9906 xmlSchemaPErrMemory(NULL,
9907 "allocating list of pending global components", NULL);
9908 xmlSchemaConstructionCtxtFree(ret);
9909 return (NULL);
9910 }
9911 ret->dict = dict;
9912 xmlDictReference(dict);
9913 return(ret);
9914}
9915
9916static xmlSchemaParserCtxtPtr
9917xmlSchemaParserCtxtCreate(void)
9918{
9919 xmlSchemaParserCtxtPtr ret;
9920
9921 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
9922 if (ret == NULL) {
9923 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
9924 NULL);
9925 return (NULL);
9926 }
9927 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
9928 ret->type = XML_SCHEMA_CTXT_PARSER;
9929 ret->attrProhibs = xmlSchemaItemListCreate();
9930 if (ret->attrProhibs == NULL) {
9931 xmlFree(ret);
9932 return(NULL);
9933 }
9934 return(ret);
9935}
9936
9947static xmlSchemaParserCtxtPtr
9948xmlSchemaNewParserCtxtUseDict(const char *URL, xmlDictPtr dict)
9949{
9950 xmlSchemaParserCtxtPtr ret;
9951
9952 ret = xmlSchemaParserCtxtCreate();
9953 if (ret == NULL)
9954 return (NULL);
9955 ret->dict = dict;
9956 xmlDictReference(dict);
9957 if (URL != NULL)
9958 ret->URL = xmlDictLookup(dict, (const xmlChar *) URL, -1);
9959 return (ret);
9960}
9961
9962static int
9963xmlSchemaCreatePCtxtOnVCtxt(xmlSchemaValidCtxtPtr vctxt)
9964{
9965 if (vctxt->pctxt == NULL) {
9966 if (vctxt->schema != NULL)
9967 vctxt->pctxt =
9968 xmlSchemaNewParserCtxtUseDict("*", vctxt->schema->dict);
9969 else
9970 vctxt->pctxt = xmlSchemaNewParserCtxt("*");
9971 if (vctxt->pctxt == NULL) {
9972 VERROR_INT("xmlSchemaCreatePCtxtOnVCtxt",
9973 "failed to create a temp. parser context");
9974 return (-1);
9975 }
9976 /* TODO: Pass user data. */
9977 xmlSchemaSetParserErrors(vctxt->pctxt, vctxt->error,
9978 vctxt->warning, vctxt->errCtxt);
9979 xmlSchemaSetParserStructuredErrors(vctxt->pctxt, vctxt->serror,
9980 vctxt->errCtxt);
9981 }
9982 return (0);
9983}
9984
9995static xmlSchemaBucketPtr
9996xmlSchemaGetSchemaBucket(xmlSchemaParserCtxtPtr pctxt,
9997 const xmlChar *schemaLocation)
9998{
9999 xmlSchemaBucketPtr cur;
10000 xmlSchemaItemListPtr list;
10001
10002 list = pctxt->constructor->buckets;
10003 if (list->nbItems == 0)
10004 return(NULL);
10005 else {
10006 int i;
10007 for (i = 0; i < list->nbItems; i++) {
10008 cur = (xmlSchemaBucketPtr) list->items[i];
10009 /* Pointer comparison! */
10010 if (cur->schemaLocation == schemaLocation)
10011 return(cur);
10012 }
10013 }
10014 return(NULL);
10015}
10016
10017static xmlSchemaBucketPtr
10018xmlSchemaGetChameleonSchemaBucket(xmlSchemaParserCtxtPtr pctxt,
10019 const xmlChar *schemaLocation,
10020 const xmlChar *targetNamespace)
10021{
10022 xmlSchemaBucketPtr cur;
10023 xmlSchemaItemListPtr list;
10024
10025 list = pctxt->constructor->buckets;
10026 if (list->nbItems == 0)
10027 return(NULL);
10028 else {
10029 int i;
10030 for (i = 0; i < list->nbItems; i++) {
10031 cur = (xmlSchemaBucketPtr) list->items[i];
10032 /* Pointer comparison! */
10033 if ((cur->origTargetNamespace == NULL) &&
10034 (cur->schemaLocation == schemaLocation) &&
10035 (cur->targetNamespace == targetNamespace))
10036 return(cur);
10037 }
10038 }
10039 return(NULL);
10040}
10041
10042
10043#define IS_BAD_SCHEMA_DOC(b) \
10044 (((b)->doc == NULL) && ((b)->schemaLocation != NULL))
10045
10046static xmlSchemaBucketPtr
10047xmlSchemaGetSchemaBucketByTNS(xmlSchemaParserCtxtPtr pctxt,
10048 const xmlChar *targetNamespace,
10049 int imported)
10050{
10051 xmlSchemaBucketPtr cur;
10052 xmlSchemaItemListPtr list;
10053
10054 list = pctxt->constructor->buckets;
10055 if (list->nbItems == 0)
10056 return(NULL);
10057 else {
10058 int i;
10059 for (i = 0; i < list->nbItems; i++) {
10060 cur = (xmlSchemaBucketPtr) list->items[i];
10061 if ((! IS_BAD_SCHEMA_DOC(cur)) &&
10062 (cur->origTargetNamespace == targetNamespace) &&
10063 ((imported && cur->imported) ||
10064 ((!imported) && (!cur->imported))))
10065 return(cur);
10066 }
10067 }
10068 return(NULL);
10069}
10070
10071static int
10072xmlSchemaParseNewDocWithContext(xmlSchemaParserCtxtPtr pctxt,
10073 xmlSchemaPtr schema,
10074 xmlSchemaBucketPtr bucket)
10075{
10076 int oldFlags;
10077 xmlDocPtr oldDoc;
10078 xmlNodePtr node;
10079 int ret, oldErrs;
10080 xmlSchemaBucketPtr oldbucket = pctxt->constructor->bucket;
10081
10082 /*
10083 * Save old values; reset the *main* schema.
10084 * URGENT TODO: This is not good; move the per-document information
10085 * to the parser. Get rid of passing the main schema to the
10086 * parsing functions.
10087 */
10088 oldFlags = schema->flags;
10089 oldDoc = schema->doc;
10090 if (schema->flags != 0)
10091 xmlSchemaClearSchemaDefaults(schema);
10092 schema->doc = bucket->doc;
10093 pctxt->schema = schema;
10094 /*
10095 * Keep the current target namespace on the parser *not* on the
10096 * main schema.
10097 */
10098 pctxt->targetNamespace = bucket->targetNamespace;
10099 WXS_CONSTRUCTOR(pctxt)->bucket = bucket;
10100
10101 if ((bucket->targetNamespace != NULL) &&
10102 xmlStrEqual(bucket->targetNamespace, xmlSchemaNs)) {
10103 /*
10104 * We are parsing the schema for schemas!
10105 */
10106 pctxt->isS4S = 1;
10107 }
10108 /* Mark it as parsed, even if parsing fails. */
10109 bucket->parsed++;
10110 /* Compile the schema doc. */
10111 node = xmlDocGetRootElement(bucket->doc);
10112 ret = xmlSchemaParseSchemaElement(pctxt, schema, node);
10113 if (ret != 0)
10114 goto exit;
10115 /* An empty schema; just get out. */
10116 if (node->children == NULL)
10117 goto exit;
10118 oldErrs = pctxt->nberrors;
10119 ret = xmlSchemaParseSchemaTopLevel(pctxt, schema, node->children);
10120 if (ret != 0)
10121 goto exit;
10122 /*
10123 * TODO: Not nice, but I'm not 100% sure we will get always an error
10124 * as a result of the above functions; so better rely on pctxt->err
10125 * as well.
10126 */
10127 if ((ret == 0) && (oldErrs != pctxt->nberrors)) {
10128 ret = pctxt->err;
10129 goto exit;
10130 }
10131
10132exit:
10133 WXS_CONSTRUCTOR(pctxt)->bucket = oldbucket;
10134 /* Restore schema values. */
10135 schema->doc = oldDoc;
10136 schema->flags = oldFlags;
10137 return(ret);
10138}
10139
10140static int
10141xmlSchemaParseNewDoc(xmlSchemaParserCtxtPtr pctxt,
10142 xmlSchemaPtr schema,
10143 xmlSchemaBucketPtr bucket)
10144{
10145 xmlSchemaParserCtxtPtr newpctxt;
10146 int res = 0;
10147
10148 if (bucket == NULL)
10149 return(0);
10150 if (bucket->parsed) {
10151 PERROR_INT("xmlSchemaParseNewDoc",
10152 "reparsing a schema doc");
10153 return(-1);
10154 }
10155 if (bucket->doc == NULL) {
10156 PERROR_INT("xmlSchemaParseNewDoc",
10157 "parsing a schema doc, but there's no doc");
10158 return(-1);
10159 }
10160 if (pctxt->constructor == NULL) {
10161 PERROR_INT("xmlSchemaParseNewDoc",
10162 "no constructor");
10163 return(-1);
10164 }
10165 /* Create and init the temporary parser context. */
10166 newpctxt = xmlSchemaNewParserCtxtUseDict(
10167 (const char *) bucket->schemaLocation, pctxt->dict);
10168 if (newpctxt == NULL)
10169 return(-1);
10170 newpctxt->constructor = pctxt->constructor;
10171 /*
10172 * TODO: Can we avoid that the parser knows about the main schema?
10173 * It would be better if he knows about the current schema bucket
10174 * only.
10175 */
10176 newpctxt->schema = schema;
10177 xmlSchemaSetParserErrors(newpctxt, pctxt->error, pctxt->warning,
10178 pctxt->errCtxt);
10179 xmlSchemaSetParserStructuredErrors(newpctxt, pctxt->serror,
10180 pctxt->errCtxt);
10181 newpctxt->counter = pctxt->counter;
10182
10183
10184 res = xmlSchemaParseNewDocWithContext(newpctxt, schema, bucket);
10185
10186 /* Channel back errors and cleanup the temporary parser context. */
10187 if (res != 0)
10188 pctxt->err = res;
10189 pctxt->nberrors += newpctxt->nberrors;
10190 pctxt->counter = newpctxt->counter;
10191 newpctxt->constructor = NULL;
10192 /* Free the parser context. */
10193 xmlSchemaFreeParserCtxt(newpctxt);
10194 return(res);
10195}
10196
10197static void
10198xmlSchemaSchemaRelationAddChild(xmlSchemaBucketPtr bucket,
10199 xmlSchemaSchemaRelationPtr rel)
10200{
10201 xmlSchemaSchemaRelationPtr cur = bucket->relations;
10202
10203 if (cur == NULL) {
10204 bucket->relations = rel;
10205 return;
10206 }
10207 while (cur->next != NULL)
10208 cur = cur->next;
10209 cur->next = rel;
10210}
10211
10212
10213static const xmlChar *
10214xmlSchemaBuildAbsoluteURI(xmlDictPtr dict, const xmlChar* location,
10215 xmlNodePtr ctxtNode)
10216{
10217 /*
10218 * Build an absolute location URI.
10219 */
10220 if (location != NULL) {
10221 if (ctxtNode == NULL)
10222 return(location);
10223 else {
10224 xmlChar *base, *URI;
10225 const xmlChar *ret = NULL;
10226
10227 base = xmlNodeGetBase(ctxtNode->doc, ctxtNode);
10228 if (base == NULL) {
10229 URI = xmlBuildURI(location, ctxtNode->doc->URL);
10230 } else {
10231 URI = xmlBuildURI(location, base);
10232 xmlFree(base);
10233 }
10234 if (URI != NULL) {
10235 ret = xmlDictLookup(dict, URI, -1);
10236 xmlFree(URI);
10237 return(ret);
10238 }
10239 }
10240 }
10241 return(NULL);
10242}
10243
10244
10245
10258static int
10259xmlSchemaAddSchemaDoc(xmlSchemaParserCtxtPtr pctxt,
10260 int type, /* import or include or redefine */
10261 const xmlChar *schemaLocation,
10262 xmlDocPtr schemaDoc,
10263 const char *schemaBuffer,
10264 int schemaBufferLen,
10265 xmlNodePtr invokingNode,
10266 const xmlChar *sourceTargetNamespace,
10267 const xmlChar *importNamespace,
10268 xmlSchemaBucketPtr *bucket)
10269{
10270 const xmlChar *targetNamespace = NULL;
10271 xmlSchemaSchemaRelationPtr relation = NULL;
10272 xmlDocPtr doc = NULL;
10273 int res = 0, err = 0, located = 0, preserveDoc = 0;
10274 xmlSchemaBucketPtr bkt = NULL;
10275
10276 if (bucket != NULL)
10277 *bucket = NULL;
10278
10279 switch (type) {
10280 case XML_SCHEMA_SCHEMA_IMPORT:
10281 case XML_SCHEMA_SCHEMA_MAIN:
10283 break;
10284 case XML_SCHEMA_SCHEMA_INCLUDE:
10286 break;
10287 case XML_SCHEMA_SCHEMA_REDEFINE:
10289 break;
10290 }
10291
10292
10293 /* Special handling for the main schema:
10294 * skip the location and relation logic and just parse the doc.
10295 * We need just a bucket to be returned in this case.
10296 */
10297 if ((type == XML_SCHEMA_SCHEMA_MAIN) || (! WXS_HAS_BUCKETS(pctxt)))
10298 goto doc_load;
10299
10300 /* Note that we expect the location to be an absolute URI. */
10301 if (schemaLocation != NULL) {
10302 bkt = xmlSchemaGetSchemaBucket(pctxt, schemaLocation);
10303 if ((bkt != NULL) &&
10304 (pctxt->constructor->bucket == bkt)) {
10305 /* Report self-imports/inclusions/redefinitions. */
10306
10307 xmlSchemaCustomErr(ACTXT_CAST pctxt, err,
10308 invokingNode, NULL,
10309 "The schema must not import/include/redefine itself",
10310 NULL, NULL);
10311 goto exit;
10312 }
10313 }
10314 /*
10315 * Create a relation for the graph of schemas.
10316 */
10317 relation = xmlSchemaSchemaRelationCreate();
10318 if (relation == NULL)
10319 return(-1);
10320 xmlSchemaSchemaRelationAddChild(pctxt->constructor->bucket,
10321 relation);
10322 relation->type = type;
10323
10324 /*
10325 * Save the namespace import information.
10326 */
10327 if (WXS_IS_BUCKET_IMPMAIN(type)) {
10328 relation->importNamespace = importNamespace;
10329 if (schemaLocation == NULL) {
10330 /*
10331 * No location; this is just an import of the namespace.
10332 * Note that we don't assign a bucket to the relation
10333 * in this case.
10334 */
10335 goto exit;
10336 }
10337 targetNamespace = importNamespace;
10338 }
10339
10340 /* Did we already fetch the doc? */
10341 if (bkt != NULL) {
10342 if ((WXS_IS_BUCKET_IMPMAIN(type)) && (! bkt->imported)) {
10343 /*
10344 * We included/redefined and then try to import a schema,
10345 * but the new location provided for import was different.
10346 */
10347 if (schemaLocation == NULL)
10348 schemaLocation = BAD_CAST "in_memory_buffer";
10349 if (!xmlStrEqual(schemaLocation,
10350 bkt->schemaLocation)) {
10351 xmlSchemaCustomErr(ACTXT_CAST pctxt, err,
10352 invokingNode, NULL,
10353 "The schema document '%s' cannot be imported, since "
10354 "it was already included or redefined",
10355 schemaLocation, NULL);
10356 goto exit;
10357 }
10358 } else if ((! WXS_IS_BUCKET_IMPMAIN(type)) && (bkt->imported)) {
10359 /*
10360 * We imported and then try to include/redefine a schema,
10361 * but the new location provided for the include/redefine
10362 * was different.
10363 */
10364 if (schemaLocation == NULL)
10365 schemaLocation = BAD_CAST "in_memory_buffer";
10366 if (!xmlStrEqual(schemaLocation,
10367 bkt->schemaLocation)) {
10368 xmlSchemaCustomErr(ACTXT_CAST pctxt, err,
10369 invokingNode, NULL,
10370 "The schema document '%s' cannot be included or "
10371 "redefined, since it was already imported",
10372 schemaLocation, NULL);
10373 goto exit;
10374 }
10375 }
10376 }
10377
10378 if (WXS_IS_BUCKET_IMPMAIN(type)) {
10379 /*
10380 * Given that the schemaLocation [attribute] is only a hint, it is open
10381 * to applications to ignore all but the first <import> for a given
10382 * namespace, regardless of the `actual value` of schemaLocation, but
10383 * such a strategy risks missing useful information when new
10384 * schemaLocations are offered.
10385 *
10386 * We will use the first <import> that comes with a location.
10387 * Further <import>s *with* a location, will result in an error.
10388 * TODO: Better would be to just report a warning here, but
10389 * we'll try it this way until someone complains.
10390 *
10391 * Schema Document Location Strategy:
10392 * 3 Based on the namespace name, identify an existing schema document,
10393 * either as a resource which is an XML document or a <schema> element
10394 * information item, in some local schema repository;
10395 * 5 Attempt to resolve the namespace name to locate such a resource.
10396 *
10397 * NOTE: (3) and (5) are not supported.
10398 */
10399 if (bkt != NULL) {
10400 relation->bucket = bkt;
10401 goto exit;
10402 }
10403 bkt = xmlSchemaGetSchemaBucketByTNS(pctxt,
10404 importNamespace, 1);
10405
10406 if (bkt != NULL) {
10407 relation->bucket = bkt;
10408 if (bkt->schemaLocation == NULL) {
10409 /* First given location of the schema; load the doc. */
10410 bkt->schemaLocation = schemaLocation;
10411 } else {
10412 if (!xmlStrEqual(schemaLocation,
10413 bkt->schemaLocation)) {
10414 /*
10415 * Additional location given; just skip it.
10416 * URGENT TODO: We should report a warning here.
10417 * res = XML_SCHEMAP_SRC_IMPORT;
10418 */
10419 if (schemaLocation == NULL)
10420 schemaLocation = BAD_CAST "in_memory_buffer";
10421
10422 xmlSchemaCustomWarning(ACTXT_CAST pctxt,
10424 invokingNode, NULL,
10425 "Skipping import of schema located at '%s' for the "
10426 "namespace '%s', since this namespace was already "
10427 "imported with the schema located at '%s'",
10428 schemaLocation, importNamespace, bkt->schemaLocation);
10429 }
10430 goto exit;
10431 }
10432 }
10433 /*
10434 * No bucket + first location: load the doc and create a
10435 * bucket.
10436 */
10437 } else {
10438 /* <include> and <redefine> */
10439 if (bkt != NULL) {
10440
10441 if ((bkt->origTargetNamespace == NULL) &&
10442 (bkt->targetNamespace != sourceTargetNamespace)) {
10443 xmlSchemaBucketPtr chamel;
10444
10445 /*
10446 * Chameleon include/redefine: skip loading only if it was
10447 * already build for the targetNamespace of the including
10448 * schema.
10449 */
10450 /*
10451 * URGENT TODO: If the schema is a chameleon-include then copy
10452 * the components into the including schema and modify the
10453 * targetNamespace of those components, do nothing otherwise.
10454 * NOTE: This is currently worked-around by compiling the
10455 * chameleon for every distinct including targetNamespace; thus
10456 * not performant at the moment.
10457 * TODO: Check when the namespace in wildcards for chameleons
10458 * needs to be converted: before we built wildcard intersections
10459 * or after.
10460 * Answer: after!
10461 */
10462 chamel = xmlSchemaGetChameleonSchemaBucket(pctxt,
10463 schemaLocation, sourceTargetNamespace);
10464 if (chamel != NULL) {
10465 /* A fitting chameleon was already parsed; NOP. */
10466 relation->bucket = chamel;
10467 goto exit;
10468 }
10469 /*
10470 * We need to parse the chameleon again for a different
10471 * targetNamespace.
10472 * CHAMELEON TODO: Optimize this by only parsing the
10473 * chameleon once, and then copying the components to
10474 * the new targetNamespace.
10475 */
10476 bkt = NULL;
10477 } else {
10478 relation->bucket = bkt;
10479 goto exit;
10480 }
10481 }
10482 }
10483 if ((bkt != NULL) && (bkt->doc != NULL)) {
10484 PERROR_INT("xmlSchemaAddSchemaDoc",
10485 "trying to load a schema doc, but a doc is already "
10486 "assigned to the schema bucket");
10487 goto exit_failure;
10488 }
10489
10490doc_load:
10491 /*
10492 * Load the document.
10493 */
10494 if (schemaDoc != NULL) {
10495 doc = schemaDoc;
10496 /* Don' free this one, since it was provided by the caller. */
10497 preserveDoc = 1;
10498 /* TODO: Does the context or the doc hold the location? */
10499 if (schemaDoc->URL != NULL)
10500 schemaLocation = xmlDictLookup(pctxt->dict,
10501 schemaDoc->URL, -1);
10502 else
10503 schemaLocation = BAD_CAST "in_memory_buffer";
10504 } else if ((schemaLocation != NULL) || (schemaBuffer != NULL)) {
10505 xmlParserCtxtPtr parserCtxt;
10506
10507 parserCtxt = xmlNewParserCtxt();
10508 if (parserCtxt == NULL) {
10509 xmlSchemaPErrMemory(NULL, "xmlSchemaGetDoc, "
10510 "allocating a parser context", NULL);
10511 goto exit_failure;
10512 }
10513 if ((pctxt->dict != NULL) && (parserCtxt->dict != NULL)) {
10514 /*
10515 * TODO: Do we have to burden the schema parser dict with all
10516 * the content of the schema doc?
10517 */
10518 xmlDictFree(parserCtxt->dict);
10519 parserCtxt->dict = pctxt->dict;
10520 xmlDictReference(parserCtxt->dict);
10521 }
10522 if (schemaLocation != NULL) {
10523 /* Parse from file. */
10524 doc = xmlCtxtReadFile(parserCtxt, (const char *) schemaLocation,
10525 NULL, SCHEMAS_PARSE_OPTIONS);
10526 } else if (schemaBuffer != NULL) {
10527 /* Parse from memory buffer. */
10528 doc = xmlCtxtReadMemory(parserCtxt, schemaBuffer, schemaBufferLen,
10529 NULL, NULL, SCHEMAS_PARSE_OPTIONS);
10530 schemaLocation = BAD_CAST "in_memory_buffer";
10531 if (doc != NULL)
10532 doc->URL = xmlStrdup(schemaLocation);
10533 }
10534 /*
10535 * For <import>:
10536 * 2.1 The referent is (a fragment of) a resource which is an
10537 * XML document (see clause 1.1), which in turn corresponds to
10538 * a <schema> element information item in a well-formed information
10539 * set, which in turn corresponds to a valid schema.
10540 * TODO: (2.1) fragments of XML documents are not supported.
10541 *
10542 * 2.2 The referent is a <schema> element information item in
10543 * a well-formed information set, which in turn corresponds
10544 * to a valid schema.
10545 * TODO: (2.2) is not supported.
10546 */
10547 if (doc == NULL) {
10548 const xmlError *lerr;
10549 lerr = xmlGetLastError();
10550 /*
10551 * Check if this a parser error, or if the document could
10552 * just not be located.
10553 * TODO: Try to find specific error codes to react only on
10554 * localisation failures.
10555 */
10556 if ((lerr == NULL) || (lerr->domain != XML_FROM_IO)) {
10557 /*
10558 * We assume a parser error here.
10559 */
10560 located = 1;
10561 /* TODO: Error code ?? */
10563 xmlSchemaCustomErr(ACTXT_CAST pctxt, res,
10564 invokingNode, NULL,
10565 "Failed to parse the XML resource '%s'",
10566 schemaLocation, NULL);
10567 }
10568 }
10569 xmlFreeParserCtxt(parserCtxt);
10570 if ((doc == NULL) && located)
10571 goto exit_error;
10572 } else {
10573 xmlSchemaPErr(pctxt, NULL,
10575 "No information for parsing was provided with the "
10576 "given schema parser context.\n",
10577 NULL, NULL);
10578 goto exit_failure;
10579 }
10580 /*
10581 * Preprocess the document.
10582 */
10583 if (doc != NULL) {
10584 xmlNodePtr docElem = NULL;
10585
10586 located = 1;
10587 docElem = xmlDocGetRootElement(doc);
10588 if (docElem == NULL) {
10589 xmlSchemaCustomErr(ACTXT_CAST pctxt, XML_SCHEMAP_NOROOT,
10590 invokingNode, NULL,
10591 "The document '%s' has no document element",
10592 schemaLocation, NULL);
10593 goto exit_error;
10594 }
10595 /*
10596 * Remove all the blank text nodes.
10597 */
10598 xmlSchemaCleanupDoc(pctxt, docElem);
10599 /*
10600 * Check the schema's top level element.
10601 */
10602 if (!IS_SCHEMA(docElem, "schema")) {
10603 xmlSchemaCustomErr(ACTXT_CAST pctxt, XML_SCHEMAP_NOT_SCHEMA,
10604 invokingNode, NULL,
10605 "The XML document '%s' is not a schema document",
10606 schemaLocation, NULL);
10607 goto exit_error;
10608 }
10609 /*
10610 * Note that we don't apply a type check for the
10611 * targetNamespace value here.
10612 */
10613 targetNamespace = xmlSchemaGetProp(pctxt, docElem,
10614 "targetNamespace");
10615 }
10616
10617/* after_doc_loading: */
10618 if ((bkt == NULL) && located) {
10619 /* Only create a bucket if the schema was located. */
10620 bkt = xmlSchemaBucketCreate(pctxt, type,
10621 targetNamespace);
10622 if (bkt == NULL)
10623 goto exit_failure;
10624 }
10625 if (bkt != NULL) {
10626 bkt->schemaLocation = schemaLocation;
10627 bkt->located = located;
10628 if (doc != NULL) {
10629 bkt->doc = doc;
10630 bkt->targetNamespace = targetNamespace;
10631 bkt->origTargetNamespace = targetNamespace;
10632 if (preserveDoc)
10633 bkt->preserveDoc = 1;
10634 }
10635 if (WXS_IS_BUCKET_IMPMAIN(type))
10636 bkt->imported++;
10637 /*
10638 * Add it to the graph of schemas.
10639 */
10640 if (relation != NULL)
10641 relation->bucket = bkt;
10642 }
10643
10644exit:
10645 /*
10646 * Return the bucket explicitly; this is needed for the
10647 * main schema.
10648 */
10649 if (bucket != NULL)
10650 *bucket = bkt;
10651 return (0);
10652
10653exit_error:
10654 if ((doc != NULL) && (! preserveDoc)) {
10655 xmlFreeDoc(doc);
10656 if (bkt != NULL)
10657 bkt->doc = NULL;
10658 }
10659 return(pctxt->err);
10660
10661exit_failure:
10662 if ((doc != NULL) && (! preserveDoc)) {
10663 xmlFreeDoc(doc);
10664 if (bkt != NULL)
10665 bkt->doc = NULL;
10666 }
10667 return (-1);
10668}
10669
10682static int
10683xmlSchemaParseImport(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema,
10684 xmlNodePtr node)
10685{
10686 xmlNodePtr child;
10687 const xmlChar *namespaceName = NULL, *schemaLocation = NULL;
10688 const xmlChar *thisTargetNamespace;
10689 xmlAttrPtr attr;
10690 int ret = 0;
10691 xmlSchemaBucketPtr bucket = NULL;
10692
10693 if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
10694 return (-1);
10695
10696 /*
10697 * Check for illegal attributes.
10698 */
10699 attr = node->properties;
10700 while (attr != NULL) {
10701 if (attr->ns == NULL) {
10702 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
10703 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
10704 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
10705 xmlSchemaPIllegalAttrErr(pctxt,
10707 }
10708 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
10709 xmlSchemaPIllegalAttrErr(pctxt,
10711 }
10712 attr = attr->next;
10713 }
10714 /*
10715 * Extract and validate attributes.
10716 */
10717 if (xmlSchemaPValAttr(pctxt, NULL, node,
10718 "namespace", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
10719 &namespaceName) != 0) {
10720 xmlSchemaPSimpleTypeErr(pctxt,
10722 NULL, node,
10723 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
10724 NULL, namespaceName, NULL, NULL, NULL);
10725 return (pctxt->err);
10726 }
10727
10728 if (xmlSchemaPValAttr(pctxt, NULL, node,
10729 "schemaLocation", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
10730 &schemaLocation) != 0) {
10731 xmlSchemaPSimpleTypeErr(pctxt,
10733 NULL, node,
10734 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
10735 NULL, schemaLocation, NULL, NULL, NULL);
10736 return (pctxt->err);
10737 }
10738 /*
10739 * And now for the children...
10740 */
10741 child = node->children;
10742 if (IS_SCHEMA(child, "annotation")) {
10743 /*
10744 * the annotation here is simply discarded ...
10745 * TODO: really?
10746 */
10747 child = child->next;
10748 }
10749 if (child != NULL) {
10750 xmlSchemaPContentErr(pctxt,
10752 NULL, node, child, NULL,
10753 "(annotation?)");
10754 }
10755 /*
10756 * Apply additional constraints.
10757 *
10758 * Note that it is important to use the original @targetNamespace
10759 * (or none at all), to rule out imports of schemas _with_ a
10760 * @targetNamespace if the importing schema is a chameleon schema
10761 * (with no @targetNamespace).
10762 */
10763 thisTargetNamespace = WXS_BUCKET(pctxt)->origTargetNamespace;
10764 if (namespaceName != NULL) {
10765 /*
10766 * 1.1 If the namespace [attribute] is present, then its `actual value`
10767 * must not match the `actual value` of the enclosing <schema>'s
10768 * targetNamespace [attribute].
10769 */
10770 if (xmlStrEqual(thisTargetNamespace, namespaceName)) {
10771 xmlSchemaPCustomErr(pctxt,
10773 NULL, node,
10774 "The value of the attribute 'namespace' must not match "
10775 "the target namespace '%s' of the importing schema",
10776 thisTargetNamespace);
10777 return (pctxt->err);
10778 }
10779 } else {
10780 /*
10781 * 1.2 If the namespace [attribute] is not present, then the enclosing
10782 * <schema> must have a targetNamespace [attribute].
10783 */
10784 if (thisTargetNamespace == NULL) {
10785 xmlSchemaPCustomErr(pctxt,
10787 NULL, node,
10788 "The attribute 'namespace' must be existent if "
10789 "the importing schema has no target namespace",
10790 NULL);
10791 return (pctxt->err);
10792 }
10793 }
10794 /*
10795 * Locate and acquire the schema document.
10796 */
10797 if (schemaLocation != NULL)
10798 schemaLocation = xmlSchemaBuildAbsoluteURI(pctxt->dict,
10799 schemaLocation, node);
10800 ret = xmlSchemaAddSchemaDoc(pctxt, XML_SCHEMA_SCHEMA_IMPORT,
10801 schemaLocation, NULL, NULL, 0, node, thisTargetNamespace,
10802 namespaceName, &bucket);
10803
10804 if (ret != 0)
10805 return(ret);
10806
10807 /*
10808 * For <import>: "It is *not* an error for the application
10809 * schema reference strategy to fail."
10810 * So just don't parse if no schema document was found.
10811 * Note that we will get no bucket if the schema could not be
10812 * located or if there was no schemaLocation.
10813 */
10814 if ((bucket == NULL) && (schemaLocation != NULL)) {
10815 xmlSchemaCustomWarning(ACTXT_CAST pctxt,
10817 node, NULL,
10818 "Failed to locate a schema at location '%s'. "
10819 "Skipping the import", schemaLocation, NULL, NULL);
10820 }
10821
10822 if ((bucket != NULL) && CAN_PARSE_SCHEMA(bucket)) {
10823 ret = xmlSchemaParseNewDoc(pctxt, schema, bucket);
10824 }
10825
10826 return (ret);
10827}
10828
10829static int
10830xmlSchemaParseIncludeOrRedefineAttrs(xmlSchemaParserCtxtPtr pctxt,
10831 xmlSchemaPtr schema,
10832 xmlNodePtr node,
10833 xmlChar **schemaLocation,
10834 int type)
10835{
10836 xmlAttrPtr attr;
10837
10838 if ((pctxt == NULL) || (schema == NULL) || (node == NULL) ||
10839 (schemaLocation == NULL))
10840 return (-1);
10841
10842 *schemaLocation = NULL;
10843 /*
10844 * Check for illegal attributes.
10845 * Applies for both <include> and <redefine>.
10846 */
10847 attr = node->properties;
10848 while (attr != NULL) {
10849 if (attr->ns == NULL) {
10850 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
10851 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
10852 xmlSchemaPIllegalAttrErr(pctxt,
10854 }
10855 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
10856 xmlSchemaPIllegalAttrErr(pctxt,
10858 }
10859 attr = attr->next;
10860 }
10861 xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
10862 /*
10863 * Preliminary step, extract the URI-Reference and make an URI
10864 * from the base.
10865 */
10866 /*
10867 * Attribute "schemaLocation" is mandatory.
10868 */
10869 attr = xmlSchemaGetPropNode(node, "schemaLocation");
10870 if (attr != NULL) {
10871 xmlChar *base = NULL;
10872 xmlChar *uri = NULL;
10873
10874 if (xmlSchemaPValAttrNode(pctxt, NULL, attr,
10875 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
10876 (const xmlChar **) schemaLocation) != 0)
10877 goto exit_error;
10878 base = xmlNodeGetBase(node->doc, node);
10879 if (base == NULL) {
10880 uri = xmlBuildURI(*schemaLocation, node->doc->URL);
10881 } else {
10882 uri = xmlBuildURI(*schemaLocation, base);
10883 xmlFree(base);
10884 }
10885 if (uri == NULL) {
10886 PERROR_INT("xmlSchemaParseIncludeOrRedefine",
10887 "could not build an URI from the schemaLocation")
10888 goto exit_failure;
10889 }
10890 (*schemaLocation) = (xmlChar *) xmlDictLookup(pctxt->dict, uri, -1);
10891 xmlFree(uri);
10892 } else {
10893 xmlSchemaPMissingAttrErr(pctxt,
10895 NULL, node, "schemaLocation", NULL);
10896 goto exit_error;
10897 }
10898 /*
10899 * Report self-inclusion and self-redefinition.
10900 */
10901 if (xmlStrEqual(*schemaLocation, pctxt->URL)) {
10902 if (type == XML_SCHEMA_SCHEMA_REDEFINE) {
10903 xmlSchemaPCustomErr(pctxt,
10905 NULL, node,
10906 "The schema document '%s' cannot redefine itself.",
10907 *schemaLocation);
10908 } else {
10909 xmlSchemaPCustomErr(pctxt,
10911 NULL, node,
10912 "The schema document '%s' cannot include itself.",
10913 *schemaLocation);
10914 }
10915 goto exit_error;
10916 }
10917
10918 return(0);
10919exit_error:
10920 return(pctxt->err);
10921exit_failure:
10922 return(-1);
10923}
10924
10925static int
10926xmlSchemaParseIncludeOrRedefine(xmlSchemaParserCtxtPtr pctxt,
10927 xmlSchemaPtr schema,
10928 xmlNodePtr node,
10929 int type)
10930{
10931 xmlNodePtr child = NULL;
10932 const xmlChar *schemaLocation = NULL;
10933 int res = 0; /* hasRedefinitions = 0 */
10934 int isChameleon = 0, wasChameleon = 0;
10935 xmlSchemaBucketPtr bucket = NULL;
10936
10937 if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
10938 return (-1);
10939
10940 /*
10941 * Parse attributes. Note that the returned schemaLocation will
10942 * be already converted to an absolute URI.
10943 */
10944 res = xmlSchemaParseIncludeOrRedefineAttrs(pctxt, schema,
10945 node, (xmlChar **) (&schemaLocation), type);
10946 if (res != 0)
10947 return(res);
10948 /*
10949 * Load and add the schema document.
10950 */
10951 res = xmlSchemaAddSchemaDoc(pctxt, type, schemaLocation, NULL,
10952 NULL, 0, node, pctxt->targetNamespace, NULL, &bucket);
10953 if (res != 0)
10954 return(res);
10955 /*
10956 * If we get no schema bucket back, then this means that the schema
10957 * document could not be located or was broken XML or was not
10958 * a schema document.
10959 */
10960 if ((bucket == NULL) || (bucket->doc == NULL)) {
10961 if (type == XML_SCHEMA_SCHEMA_INCLUDE) {
10962 /*
10963 * WARNING for <include>:
10964 * We will raise an error if the schema cannot be located
10965 * for inclusions, since the that was the feedback from the
10966 * schema people. I.e. the following spec piece will *not* be
10967 * satisfied:
10968 * SPEC src-include: "It is not an error for the `actual value` of the
10969 * schemaLocation [attribute] to fail to resolve it all, in which
10970 * case no corresponding inclusion is performed.
10971 * So do we need a warning report here?"
10972 */
10974 xmlSchemaCustomErr(ACTXT_CAST pctxt, res,
10975 node, NULL,
10976 "Failed to load the document '%s' for inclusion",
10977 schemaLocation, NULL);
10978 } else {
10979 /*
10980 * NOTE: This was changed to raise an error even if no redefinitions
10981 * are specified.
10982 *
10983 * SPEC src-redefine (1)
10984 * "If there are any element information items among the [children]
10985 * other than <annotation> then the `actual value` of the
10986 * schemaLocation [attribute] must successfully resolve."
10987 * TODO: Ask the WG if a the location has always to resolve
10988 * here as well!
10989 */
10991 xmlSchemaCustomErr(ACTXT_CAST pctxt, res,
10992 node, NULL,
10993 "Failed to load the document '%s' for redefinition",
10994 schemaLocation, NULL);
10995 }
10996 } else {
10997 /*
10998 * Check targetNamespace sanity before parsing the new schema.
10999 * TODO: Note that we won't check further content if the
11000 * targetNamespace was bad.
11001 */
11002 if (bucket->origTargetNamespace != NULL) {
11003 /*
11004 * SPEC src-include (2.1)
11005 * "SII has a targetNamespace [attribute], and its `actual
11006 * value` is identical to the `actual value` of the targetNamespace
11007 * [attribute] of SII' (which must have such an [attribute])."
11008 */
11009 if (pctxt->targetNamespace == NULL) {
11010 xmlSchemaCustomErr(ACTXT_CAST pctxt,
11012 node, NULL,
11013 "The target namespace of the included/redefined schema "
11014 "'%s' has to be absent, since the including/redefining "
11015 "schema has no target namespace",
11016 schemaLocation, NULL);
11017 goto exit_error;
11018 } else if (!xmlStrEqual(bucket->origTargetNamespace,
11019 pctxt->targetNamespace)) {
11020 /* TODO: Change error function. */
11021 xmlSchemaPCustomErrExt(pctxt,
11023 NULL, node,
11024 "The target namespace '%s' of the included/redefined "
11025 "schema '%s' differs from '%s' of the "
11026 "including/redefining schema",
11027 bucket->origTargetNamespace, schemaLocation,
11028 pctxt->targetNamespace);
11029 goto exit_error;
11030 }
11031 } else if (pctxt->targetNamespace != NULL) {
11032 /*
11033 * Chameleons: the original target namespace will
11034 * differ from the resulting namespace.
11035 */
11036 isChameleon = 1;
11037 bucket->targetNamespace = pctxt->targetNamespace;
11038 }
11039 }
11040 /*
11041 * Parse the schema.
11042 */
11043 if (bucket && (!bucket->parsed) && (bucket->doc != NULL)) {
11044 if (isChameleon) {
11045 /* TODO: Get rid of this flag on the schema itself. */
11046 if ((schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) == 0) {
11047 schema->flags |= XML_SCHEMAS_INCLUDING_CONVERT_NS;
11048 } else
11049 wasChameleon = 1;
11050 }
11051 xmlSchemaParseNewDoc(pctxt, schema, bucket);
11052 /* Restore chameleon flag. */
11053 if (isChameleon && (!wasChameleon))
11054 schema->flags ^= XML_SCHEMAS_INCLUDING_CONVERT_NS;
11055 }
11056 /*
11057 * And now for the children...
11058 */
11059 child = node->children;
11060 if (type == XML_SCHEMA_SCHEMA_REDEFINE) {
11061 /*
11062 * Parse (simpleType | complexType | group | attributeGroup))*
11063 */
11064 pctxt->redefined = bucket;
11065 /*
11066 * How to proceed if the redefined schema was not located?
11067 */
11068 pctxt->isRedefine = 1;
11069 while (IS_SCHEMA(child, "annotation") ||
11070 IS_SCHEMA(child, "simpleType") ||
11071 IS_SCHEMA(child, "complexType") ||
11072 IS_SCHEMA(child, "group") ||
11073 IS_SCHEMA(child, "attributeGroup")) {
11074 if (IS_SCHEMA(child, "annotation")) {
11075 /*
11076 * TODO: discard or not?
11077 */
11078 } else if (IS_SCHEMA(child, "simpleType")) {
11079 xmlSchemaParseSimpleType(pctxt, schema, child, 1);
11080 } else if (IS_SCHEMA(child, "complexType")) {
11081 xmlSchemaParseComplexType(pctxt, schema, child, 1);
11082 /* hasRedefinitions = 1; */
11083 } else if (IS_SCHEMA(child, "group")) {
11084 /* hasRedefinitions = 1; */
11085 xmlSchemaParseModelGroupDefinition(pctxt,
11086 schema, child);
11087 } else if (IS_SCHEMA(child, "attributeGroup")) {
11088 /* hasRedefinitions = 1; */
11089 xmlSchemaParseAttributeGroupDefinition(pctxt, schema,
11090 child);
11091 }
11092 child = child->next;
11093 }
11094 pctxt->redefined = NULL;
11095 pctxt->isRedefine = 0;
11096 } else {
11097 if (IS_SCHEMA(child, "annotation")) {
11098 /*
11099 * TODO: discard or not?
11100 */
11101 child = child->next;
11102 }
11103 }
11104 if (child != NULL) {
11106 if (type == XML_SCHEMA_SCHEMA_REDEFINE) {
11107 xmlSchemaPContentErr(pctxt, res,
11108 NULL, node, child, NULL,
11109 "(annotation | (simpleType | complexType | group | attributeGroup))*");
11110 } else {
11111 xmlSchemaPContentErr(pctxt, res,
11112 NULL, node, child, NULL,
11113 "(annotation?)");
11114 }
11115 }
11116 return(res);
11117
11118exit_error:
11119 return(pctxt->err);
11120}
11121
11122static int
11123xmlSchemaParseRedefine(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema,
11124 xmlNodePtr node)
11125{
11126 int res;
11127#ifndef ENABLE_REDEFINE
11128 TODO
11129 return(0);
11130#endif
11131 res = xmlSchemaParseIncludeOrRedefine(pctxt, schema, node,
11132 XML_SCHEMA_SCHEMA_REDEFINE);
11133 if (res != 0)
11134 return(res);
11135 return(0);
11136}
11137
11138static int
11139xmlSchemaParseInclude(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema,
11140 xmlNodePtr node)
11141{
11142 int res;
11143
11144 res = xmlSchemaParseIncludeOrRedefine(pctxt, schema, node,
11145 XML_SCHEMA_SCHEMA_INCLUDE);
11146 if (res != 0)
11147 return(res);
11148 return(0);
11149}
11150
11176static xmlSchemaTreeItemPtr
11177xmlSchemaParseModelGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
11178 xmlNodePtr node, xmlSchemaTypeType type,
11179 int withParticle)
11180{
11181 xmlSchemaModelGroupPtr item;
11182 xmlSchemaParticlePtr particle = NULL;
11183 xmlNodePtr child = NULL;
11184 xmlAttrPtr attr;
11185 int min = 1, max = 1, isElemRef, hasRefs = 0;
11186
11187 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
11188 return (NULL);
11189 /*
11190 * Create a model group with the given compositor.
11191 */
11192 item = xmlSchemaAddModelGroup(ctxt, schema, type, node);
11193 if (item == NULL)
11194 return (NULL);
11195
11196 if (withParticle) {
11197 if (type == XML_SCHEMA_TYPE_ALL) {
11198 min = xmlGetMinOccurs(ctxt, node, 0, 1, 1, "(0 | 1)");
11199 max = xmlGetMaxOccurs(ctxt, node, 1, 1, 1, "1");
11200 } else {
11201 /* choice + sequence */
11202 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
11203 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
11204 "(xs:nonNegativeInteger | unbounded)");
11205 }
11206 xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
11207 /*
11208 * Create a particle
11209 */
11210 particle = xmlSchemaAddParticle(ctxt, node, min, max);
11211 if (particle == NULL)
11212 return (NULL);
11213 particle->children = (xmlSchemaTreeItemPtr) item;
11214 /*
11215 * Check for illegal attributes.
11216 */
11217 attr = node->properties;
11218 while (attr != NULL) {
11219 if (attr->ns == NULL) {
11220 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
11221 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
11222 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs"))) {
11223 xmlSchemaPIllegalAttrErr(ctxt,
11225 }
11226 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
11227 xmlSchemaPIllegalAttrErr(ctxt,
11229 }
11230 attr = attr->next;
11231 }
11232 } else {
11233 /*
11234 * Check for illegal attributes.
11235 */
11236 attr = node->properties;
11237 while (attr != NULL) {
11238 if (attr->ns == NULL) {
11239 if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
11240 xmlSchemaPIllegalAttrErr(ctxt,
11242 }
11243 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
11244 xmlSchemaPIllegalAttrErr(ctxt,
11246 }
11247 attr = attr->next;
11248 }
11249 }
11250
11251 /*
11252 * Extract and validate attributes.
11253 */
11254 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
11255 /*
11256 * And now for the children...
11257 */
11258 child = node->children;
11259 if (IS_SCHEMA(child, "annotation")) {
11260 item->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
11261 child = child->next;
11262 }
11263 if (type == XML_SCHEMA_TYPE_ALL) {
11264 xmlSchemaParticlePtr part, last = NULL;
11265
11266 while (IS_SCHEMA(child, "element")) {
11267 part = (xmlSchemaParticlePtr) xmlSchemaParseElement(ctxt,
11268 schema, child, &isElemRef, 0);
11269 /*
11270 * SPEC cos-all-limited (2)
11271 * "The {max occurs} of all the particles in the {particles}
11272 * of the ('all') group must be 0 or 1.
11273 */
11274 if (part != NULL) {
11275 if (isElemRef)
11276 hasRefs++;
11277 if (part->minOccurs > 1) {
11278 xmlSchemaPCustomErr(ctxt,
11280 NULL, child,
11281 "Invalid value for minOccurs (must be 0 or 1)",
11282 NULL);
11283 /* Reset to 1. */
11284 part->minOccurs = 1;
11285 }
11286 if (part->maxOccurs > 1) {
11287 xmlSchemaPCustomErr(ctxt,
11289 NULL, child,
11290 "Invalid value for maxOccurs (must be 0 or 1)",
11291 NULL);
11292 /* Reset to 1. */
11293 part->maxOccurs = 1;
11294 }
11295 if (last == NULL)
11296 item->children = (xmlSchemaTreeItemPtr) part;
11297 else
11298 last->next = (xmlSchemaTreeItemPtr) part;
11299 last = part;
11300 }
11301 child = child->next;
11302 }
11303 if (child != NULL) {
11304 xmlSchemaPContentErr(ctxt,
11306 NULL, node, child, NULL,
11307 "(annotation?, (annotation?, element*)");
11308 }
11309 } else {
11310 /* choice + sequence */
11311 xmlSchemaTreeItemPtr part = NULL, last = NULL;
11312
11313 while ((IS_SCHEMA(child, "element")) ||
11314 (IS_SCHEMA(child, "group")) ||
11315 (IS_SCHEMA(child, "any")) ||
11316 (IS_SCHEMA(child, "choice")) ||
11317 (IS_SCHEMA(child, "sequence"))) {
11318
11319 if (IS_SCHEMA(child, "element")) {
11320 part = (xmlSchemaTreeItemPtr)
11321 xmlSchemaParseElement(ctxt, schema, child, &isElemRef, 0);
11322 if (part && isElemRef)
11323 hasRefs++;
11324 } else if (IS_SCHEMA(child, "group")) {
11325 part =
11326 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
11327 if (part != NULL)
11328 hasRefs++;
11329 /*
11330 * Handle redefinitions.
11331 */
11332 if (ctxt->isRedefine && ctxt->redef &&
11333 (ctxt->redef->item->type == XML_SCHEMA_TYPE_GROUP) &&
11334 part && part->children)
11335 {
11336 if ((xmlSchemaGetQNameRefName(part->children) ==
11337 ctxt->redef->refName) &&
11338 (xmlSchemaGetQNameRefTargetNs(part->children) ==
11339 ctxt->redef->refTargetNs))
11340 {
11341 /*
11342 * SPEC src-redefine:
11343 * (6.1) "If it has a <group> among its contents at
11344 * some level the `actual value` of whose ref
11345 * [attribute] is the same as the `actual value` of
11346 * its own name attribute plus target namespace, then
11347 * all of the following must be true:"
11348 * (6.1.1) "It must have exactly one such group."
11349 */
11350 if (ctxt->redefCounter != 0) {
11351 xmlChar *str = NULL;
11352
11353 xmlSchemaCustomErr(ACTXT_CAST ctxt,
11355 "The redefining model group definition "
11356 "'%s' must not contain more than one "
11357 "reference to the redefined definition",
11358 xmlSchemaFormatQName(&str,
11359 ctxt->redef->refTargetNs,
11360 ctxt->redef->refName),
11361 NULL);
11362 FREE_AND_NULL(str)
11363 part = NULL;
11364 } else if (((WXS_PARTICLE(part))->minOccurs != 1) ||
11365 ((WXS_PARTICLE(part))->maxOccurs != 1))
11366 {
11367 xmlChar *str = NULL;
11368 /*
11369 * SPEC src-redefine:
11370 * (6.1.2) "The `actual value` of both that
11371 * group's minOccurs and maxOccurs [attribute]
11372 * must be 1 (or `absent`).
11373 */
11374 xmlSchemaCustomErr(ACTXT_CAST ctxt,
11376 "The redefining model group definition "
11377 "'%s' must not contain a reference to the "
11378 "redefined definition with a "
11379 "maxOccurs/minOccurs other than 1",
11380 xmlSchemaFormatQName(&str,
11381 ctxt->redef->refTargetNs,
11382 ctxt->redef->refName),
11383 NULL);
11384 FREE_AND_NULL(str)
11385 part = NULL;
11386 }
11387 ctxt->redef->reference = WXS_BASIC_CAST part;
11388 ctxt->redefCounter++;
11389 }
11390 }
11391 } else if (IS_SCHEMA(child, "any")) {
11392 part = (xmlSchemaTreeItemPtr)
11393 xmlSchemaParseAny(ctxt, schema, child);
11394 } else if (IS_SCHEMA(child, "choice")) {
11395 part = xmlSchemaParseModelGroup(ctxt, schema, child,
11396 XML_SCHEMA_TYPE_CHOICE, 1);
11397 } else if (IS_SCHEMA(child, "sequence")) {
11398 part = xmlSchemaParseModelGroup(ctxt, schema, child,
11399 XML_SCHEMA_TYPE_SEQUENCE, 1);
11400 }
11401 if (part != NULL) {
11402 if (last == NULL)
11403 item->children = part;
11404 else
11405 last->next = part;
11406 last = part;
11407 }
11408 child = child->next;
11409 }
11410 if (child != NULL) {
11411 xmlSchemaPContentErr(ctxt,
11413 NULL, node, child, NULL,
11414 "(annotation?, (element | group | choice | sequence | any)*)");
11415 }
11416 }
11417 if ((max == 0) && (min == 0))
11418 return (NULL);
11419 if (hasRefs) {
11420 /*
11421 * We need to resolve references.
11422 */
11423 WXS_ADD_PENDING(ctxt, item);
11424 }
11425 if (withParticle)
11426 return ((xmlSchemaTreeItemPtr) particle);
11427 else
11428 return ((xmlSchemaTreeItemPtr) item);
11429}
11430
11442static xmlSchemaTypePtr
11443xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
11444 xmlNodePtr node, xmlSchemaTypeType parentType)
11445{
11446 xmlSchemaTypePtr type;
11447 xmlNodePtr child = NULL;
11448 xmlAttrPtr attr;
11449
11450 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
11451 return (NULL);
11452 /* Not a component, don't create it. */
11453 type = ctxt->ctxtType;
11454 type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
11455
11456 /*
11457 * Check for illegal attributes.
11458 */
11459 attr = node->properties;
11460 while (attr != NULL) {
11461 if (attr->ns == NULL) {
11462 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
11463 (!xmlStrEqual(attr->name, BAD_CAST "base"))) {
11464 xmlSchemaPIllegalAttrErr(ctxt,
11466 }
11467 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
11468 xmlSchemaPIllegalAttrErr(ctxt,
11470 }
11471 attr = attr->next;
11472 }
11473 /*
11474 * Extract and validate attributes.
11475 */
11476 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
11477 /*
11478 * Attribute
11479 */
11480 /*
11481 * Extract the base type. The "base" attribute is mandatory if inside
11482 * a complex type or if redefining.
11483 *
11484 * SPEC (1.2) "...otherwise (<restriction> has no <simpleType> "
11485 * among its [children]), the simple type definition which is
11486 * the {content type} of the type definition `resolved` to by
11487 * the `actual value` of the base [attribute]"
11488 */
11489 if (xmlSchemaPValAttrQName(ctxt, schema, NULL, node, "base",
11490 &(type->baseNs), &(type->base)) == 0)
11491 {
11492 if ((type->base == NULL) && (type->type == XML_SCHEMA_TYPE_COMPLEX)) {
11493 xmlSchemaPMissingAttrErr(ctxt,
11495 NULL, node, "base", NULL);
11496 } else if ((ctxt->isRedefine) &&
11497 (type->flags & XML_SCHEMAS_TYPE_GLOBAL))
11498 {
11499 if (type->base == NULL) {
11500 xmlSchemaPMissingAttrErr(ctxt,
11502 NULL, node, "base", NULL);
11503 } else if ((! xmlStrEqual(type->base, type->name)) ||
11504 (! xmlStrEqual(type->baseNs, type->targetNamespace)))
11505 {
11506 xmlChar *str1 = NULL, *str2 = NULL;
11507 /*
11508 * REDEFINE: SPEC src-redefine (5)
11509 * "Within the [children], each <simpleType> must have a
11510 * <restriction> among its [children] ... the `actual value` of
11511 * whose base [attribute] must be the same as the `actual value`
11512 * of its own name attribute plus target namespace;"
11513 */
11514 xmlSchemaPCustomErrExt(ctxt, XML_SCHEMAP_SRC_REDEFINE,
11515 NULL, node, "This is a redefinition, but the QName "
11516 "value '%s' of the 'base' attribute does not match the "
11517 "type's designation '%s'",
11518 xmlSchemaFormatQName(&str1, type->baseNs, type->base),
11519 xmlSchemaFormatQName(&str2, type->targetNamespace,
11520 type->name), NULL);
11521 FREE_AND_NULL(str1);
11522 FREE_AND_NULL(str2);
11523 /* Avoid confusion and erase the values. */
11524 type->base = NULL;
11525 type->baseNs = NULL;
11526 }
11527 }
11528 }
11529 /*
11530 * And now for the children...
11531 */
11532 child = node->children;
11533 if (IS_SCHEMA(child, "annotation")) {
11534 /*
11535 * Add the annotation to the simple type ancestor.
11536 */
11537 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
11538 xmlSchemaParseAnnotation(ctxt, child, 1));
11539 child = child->next;
11540 }
11541 if (parentType == XML_SCHEMA_TYPE_SIMPLE) {
11542 /*
11543 * Corresponds to <simpleType><restriction><simpleType>.
11544 */
11545 if (IS_SCHEMA(child, "simpleType")) {
11546 if (type->base != NULL) {
11547 /*
11548 * src-restriction-base-or-simpleType
11549 * Either the base [attribute] or the simpleType [child] of the
11550 * <restriction> element must be present, but not both.
11551 */
11552 xmlSchemaPContentErr(ctxt,
11554 NULL, node, child,
11555 "The attribute 'base' and the <simpleType> child are "
11556 "mutually exclusive", NULL);
11557 } else {
11558 type->baseType = (xmlSchemaTypePtr)
11559 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
11560 }
11561 child = child->next;
11562 } else if (type->base == NULL) {
11563 xmlSchemaPContentErr(ctxt,
11565 NULL, node, child,
11566 "Either the attribute 'base' or a <simpleType> child "
11567 "must be present", NULL);
11568 }
11569 } else if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11570 /*
11571 * Corresponds to <complexType><complexContent><restriction>...
11572 * followed by:
11573 *
11574 * Model groups <all>, <choice> and <sequence>.
11575 */
11576 if (IS_SCHEMA(child, "all")) {
11577 type->subtypes = (xmlSchemaTypePtr)
11578 xmlSchemaParseModelGroup(ctxt, schema, child,
11579 XML_SCHEMA_TYPE_ALL, 1);
11580 child = child->next;
11581 } else if (IS_SCHEMA(child, "choice")) {
11582 type->subtypes = (xmlSchemaTypePtr)
11583 xmlSchemaParseModelGroup(ctxt,
11584 schema, child, XML_SCHEMA_TYPE_CHOICE, 1);
11585 child = child->next;
11586 } else if (IS_SCHEMA(child, "sequence")) {
11587 type->subtypes = (xmlSchemaTypePtr)
11588 xmlSchemaParseModelGroup(ctxt, schema, child,
11589 XML_SCHEMA_TYPE_SEQUENCE, 1);
11590 child = child->next;
11591 /*
11592 * Model group reference <group>.
11593 */
11594 } else if (IS_SCHEMA(child, "group")) {
11595 type->subtypes = (xmlSchemaTypePtr)
11596 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
11597 /*
11598 * Note that the reference will be resolved in
11599 * xmlSchemaResolveTypeReferences();
11600 */
11601 child = child->next;
11602 }
11603 } else if (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
11604 /*
11605 * Corresponds to <complexType><simpleContent><restriction>...
11606 *
11607 * "1.1 the simple type definition corresponding to the <simpleType>
11608 * among the [children] of <restriction> if there is one;"
11609 */
11610 if (IS_SCHEMA(child, "simpleType")) {
11611 /*
11612 * We will store the to-be-restricted simple type in
11613 * type->contentTypeDef *temporarily*.
11614 */
11615 type->contentTypeDef = (xmlSchemaTypePtr)
11616 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
11617 if ( type->contentTypeDef == NULL)
11618 return (NULL);
11619 child = child->next;
11620 }
11621 }
11622
11623 if ((parentType == XML_SCHEMA_TYPE_SIMPLE) ||
11624 (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT)) {
11625 xmlSchemaFacetPtr facet, lastfacet = NULL;
11626 /*
11627 * Corresponds to <complexType><simpleContent><restriction>...
11628 * <simpleType><restriction>...
11629 */
11630
11631 /*
11632 * Add the facets to the simple type ancestor.
11633 */
11634 /*
11635 * TODO: Datatypes: 4.1.3 Constraints on XML Representation of
11636 * Simple Type Definition Schema Representation Constraint:
11637 * *Single Facet Value*
11638 */
11639 while ((IS_SCHEMA(child, "minInclusive")) ||
11640 (IS_SCHEMA(child, "minExclusive")) ||
11641 (IS_SCHEMA(child, "maxInclusive")) ||
11642 (IS_SCHEMA(child, "maxExclusive")) ||
11643 (IS_SCHEMA(child, "totalDigits")) ||
11644 (IS_SCHEMA(child, "fractionDigits")) ||
11645 (IS_SCHEMA(child, "pattern")) ||
11646 (IS_SCHEMA(child, "enumeration")) ||
11647 (IS_SCHEMA(child, "whiteSpace")) ||
11648 (IS_SCHEMA(child, "length")) ||
11649 (IS_SCHEMA(child, "maxLength")) ||
11650 (IS_SCHEMA(child, "minLength"))) {
11651 facet = xmlSchemaParseFacet(ctxt, schema, child);
11652 if (facet != NULL) {
11653 if (lastfacet == NULL)
11654 type->facets = facet;
11655 else
11656 lastfacet->next = facet;
11657 lastfacet = facet;
11658 lastfacet->next = NULL;
11659 }
11660 child = child->next;
11661 }
11662 /*
11663 * Create links for derivation and validation.
11664 */
11665 if (type->facets != NULL) {
11666 xmlSchemaFacetLinkPtr facetLink, lastFacetLink = NULL;
11667
11668 facet = type->facets;
11669 do {
11670 facetLink = (xmlSchemaFacetLinkPtr)
11671 xmlMalloc(sizeof(xmlSchemaFacetLink));
11672 if (facetLink == NULL) {
11673 xmlSchemaPErrMemory(ctxt, "allocating a facet link", NULL);
11674 xmlFree(facetLink);
11675 return (NULL);
11676 }
11677 facetLink->facet = facet;
11678 facetLink->next = NULL;
11679 if (lastFacetLink == NULL)
11680 type->facetSet = facetLink;
11681 else
11682 lastFacetLink->next = facetLink;
11683 lastFacetLink = facetLink;
11684 facet = facet->next;
11685 } while (facet != NULL);
11686 }
11687 }
11688 if (type->type == XML_SCHEMA_TYPE_COMPLEX) {
11689 /*
11690 * Attribute uses/declarations.
11691 */
11692 if (xmlSchemaParseLocalAttributes(ctxt, schema, &child,
11693 (xmlSchemaItemListPtr *) &(type->attrUses),
11694 XML_SCHEMA_TYPE_RESTRICTION, NULL) == -1)
11695 return(NULL);
11696 /*
11697 * Attribute wildcard.
11698 */
11699 if (IS_SCHEMA(child, "anyAttribute")) {
11700 type->attributeWildcard =
11701 xmlSchemaParseAnyAttribute(ctxt, schema, child);
11702 child = child->next;
11703 }
11704 }
11705 if (child != NULL) {
11706 if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11707 xmlSchemaPContentErr(ctxt,
11709 NULL, node, child, NULL,
11710 "annotation?, (group | all | choice | sequence)?, "
11711 "((attribute | attributeGroup)*, anyAttribute?))");
11712 } else if (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
11713 xmlSchemaPContentErr(ctxt,
11715 NULL, node, child, NULL,
11716 "(annotation?, (simpleType?, (minExclusive | minInclusive | "
11717 "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
11718 "length | minLength | maxLength | enumeration | whiteSpace | "
11719 "pattern)*)?, ((attribute | attributeGroup)*, anyAttribute?))");
11720 } else {
11721 /* Simple type */
11722 xmlSchemaPContentErr(ctxt,
11724 NULL, node, child, NULL,
11725 "(annotation?, (simpleType?, (minExclusive | minInclusive | "
11726 "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
11727 "length | minLength | maxLength | enumeration | whiteSpace | "
11728 "pattern)*))");
11729 }
11730 }
11731 return (NULL);
11732}
11733
11746static xmlSchemaTypePtr
11747xmlSchemaParseExtension(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
11748 xmlNodePtr node, xmlSchemaTypeType parentType)
11749{
11750 xmlSchemaTypePtr type;
11751 xmlNodePtr child = NULL;
11752 xmlAttrPtr attr;
11753
11754 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
11755 return (NULL);
11756 /* Not a component, don't create it. */
11757 type = ctxt->ctxtType;
11758 type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION;
11759
11760 /*
11761 * Check for illegal attributes.
11762 */
11763 attr = node->properties;
11764 while (attr != NULL) {
11765 if (attr->ns == NULL) {
11766 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
11767 (!xmlStrEqual(attr->name, BAD_CAST "base"))) {
11768 xmlSchemaPIllegalAttrErr(ctxt,
11770 }
11771 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
11772 xmlSchemaPIllegalAttrErr(ctxt,
11774 }
11775 attr = attr->next;
11776 }
11777
11778 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
11779
11780 /*
11781 * Attribute "base" - mandatory.
11782 */
11783 if ((xmlSchemaPValAttrQName(ctxt, schema, NULL, node,
11784 "base", &(type->baseNs), &(type->base)) == 0) &&
11785 (type->base == NULL)) {
11786 xmlSchemaPMissingAttrErr(ctxt,
11788 NULL, node, "base", NULL);
11789 }
11790 /*
11791 * And now for the children...
11792 */
11793 child = node->children;
11794 if (IS_SCHEMA(child, "annotation")) {
11795 /*
11796 * Add the annotation to the type ancestor.
11797 */
11798 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
11799 xmlSchemaParseAnnotation(ctxt, child, 1));
11800 child = child->next;
11801 }
11802 if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11803 /*
11804 * Corresponds to <complexType><complexContent><extension>... and:
11805 *
11806 * Model groups <all>, <choice>, <sequence> and <group>.
11807 */
11808 if (IS_SCHEMA(child, "all")) {
11809 type->subtypes = (xmlSchemaTypePtr)
11810 xmlSchemaParseModelGroup(ctxt, schema,
11811 child, XML_SCHEMA_TYPE_ALL, 1);
11812 child = child->next;
11813 } else if (IS_SCHEMA(child, "choice")) {
11814 type->subtypes = (xmlSchemaTypePtr)
11815 xmlSchemaParseModelGroup(ctxt, schema,
11816 child, XML_SCHEMA_TYPE_CHOICE, 1);
11817 child = child->next;
11818 } else if (IS_SCHEMA(child, "sequence")) {
11819 type->subtypes = (xmlSchemaTypePtr)
11820 xmlSchemaParseModelGroup(ctxt, schema,
11821 child, XML_SCHEMA_TYPE_SEQUENCE, 1);
11822 child = child->next;
11823 } else if (IS_SCHEMA(child, "group")) {
11824 type->subtypes = (xmlSchemaTypePtr)
11825 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
11826 /*
11827 * Note that the reference will be resolved in
11828 * xmlSchemaResolveTypeReferences();
11829 */
11830 child = child->next;
11831 }
11832 }
11833 if (child != NULL) {
11834 /*
11835 * Attribute uses/declarations.
11836 */
11837 if (xmlSchemaParseLocalAttributes(ctxt, schema, &child,
11838 (xmlSchemaItemListPtr *) &(type->attrUses),
11839 XML_SCHEMA_TYPE_EXTENSION, NULL) == -1)
11840 return(NULL);
11841 /*
11842 * Attribute wildcard.
11843 */
11844 if (IS_SCHEMA(child, "anyAttribute")) {
11845 ctxt->ctxtType->attributeWildcard =
11846 xmlSchemaParseAnyAttribute(ctxt, schema, child);
11847 child = child->next;
11848 }
11849 }
11850 if (child != NULL) {
11851 if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11852 /* Complex content extension. */
11853 xmlSchemaPContentErr(ctxt,
11855 NULL, node, child, NULL,
11856 "(annotation?, ((group | all | choice | sequence)?, "
11857 "((attribute | attributeGroup)*, anyAttribute?)))");
11858 } else {
11859 /* Simple content extension. */
11860 xmlSchemaPContentErr(ctxt,
11862 NULL, node, child, NULL,
11863 "(annotation?, ((attribute | attributeGroup)*, "
11864 "anyAttribute?))");
11865 }
11866 }
11867 return (NULL);
11868}
11869
11881static int
11882xmlSchemaParseSimpleContent(xmlSchemaParserCtxtPtr ctxt,
11883 xmlSchemaPtr schema, xmlNodePtr node,
11884 int *hasRestrictionOrExtension)
11885{
11886 xmlSchemaTypePtr type;
11887 xmlNodePtr child = NULL;
11888 xmlAttrPtr attr;
11889
11890 if ((ctxt == NULL) || (schema == NULL) || (node == NULL) ||
11891 (hasRestrictionOrExtension == NULL))
11892 return (-1);
11893 *hasRestrictionOrExtension = 0;
11894 /* Not a component, don't create it. */
11895 type = ctxt->ctxtType;
11896 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
11897 /*
11898 * Check for illegal attributes.
11899 */
11900 attr = node->properties;
11901 while (attr != NULL) {
11902 if (attr->ns == NULL) {
11903 if ((!xmlStrEqual(attr->name, BAD_CAST "id"))) {
11904 xmlSchemaPIllegalAttrErr(ctxt,
11906 }
11907 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
11908 xmlSchemaPIllegalAttrErr(ctxt,
11910 }
11911 attr = attr->next;
11912 }
11913
11914 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
11915
11916 /*
11917 * And now for the children...
11918 */
11919 child = node->children;
11920 if (IS_SCHEMA(child, "annotation")) {
11921 /*
11922 * Add the annotation to the complex type ancestor.
11923 */
11924 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
11925 xmlSchemaParseAnnotation(ctxt, child, 1));
11926 child = child->next;
11927 }
11928 if (child == NULL) {
11929 xmlSchemaPContentErr(ctxt,
11931 NULL, node, NULL, NULL,
11932 "(annotation?, (restriction | extension))");
11933 }
11934 if (child == NULL) {
11935 xmlSchemaPContentErr(ctxt,
11937 NULL, node, NULL, NULL,
11938 "(annotation?, (restriction | extension))");
11939 }
11940 if (IS_SCHEMA(child, "restriction")) {
11941 xmlSchemaParseRestriction(ctxt, schema, child,
11942 XML_SCHEMA_TYPE_SIMPLE_CONTENT);
11943 (*hasRestrictionOrExtension) = 1;
11944 child = child->next;
11945 } else if (IS_SCHEMA(child, "extension")) {
11946 xmlSchemaParseExtension(ctxt, schema, child,
11947 XML_SCHEMA_TYPE_SIMPLE_CONTENT);
11948 (*hasRestrictionOrExtension) = 1;
11949 child = child->next;
11950 }
11951 if (child != NULL) {
11952 xmlSchemaPContentErr(ctxt,
11954 NULL, node, child, NULL,
11955 "(annotation?, (restriction | extension))");
11956 }
11957 return (0);
11958}
11959
11971static int
11972xmlSchemaParseComplexContent(xmlSchemaParserCtxtPtr ctxt,
11973 xmlSchemaPtr schema, xmlNodePtr node,
11974 int *hasRestrictionOrExtension)
11975{
11976 xmlSchemaTypePtr type;
11977 xmlNodePtr child = NULL;
11978 xmlAttrPtr attr;
11979
11980 if ((ctxt == NULL) || (schema == NULL) || (node == NULL) ||
11981 (hasRestrictionOrExtension == NULL))
11982 return (-1);
11983 *hasRestrictionOrExtension = 0;
11984 /* Not a component, don't create it. */
11985 type = ctxt->ctxtType;
11986 /*
11987 * Check for illegal attributes.
11988 */
11989 attr = node->properties;
11990 while (attr != NULL) {
11991 if (attr->ns == NULL) {
11992 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
11993 (!xmlStrEqual(attr->name, BAD_CAST "mixed")))
11994 {
11995 xmlSchemaPIllegalAttrErr(ctxt,
11997 }
11998 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
11999 xmlSchemaPIllegalAttrErr(ctxt,
12001 }
12002 attr = attr->next;
12003 }
12004
12005 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
12006
12007 /*
12008 * Set the 'mixed' on the complex type ancestor.
12009 */
12010 if (xmlGetBooleanProp(ctxt, node, "mixed", 0)) {
12011 if ((type->flags & XML_SCHEMAS_TYPE_MIXED) == 0)
12012 type->flags |= XML_SCHEMAS_TYPE_MIXED;
12013 }
12014 child = node->children;
12015 if (IS_SCHEMA(child, "annotation")) {
12016 /*
12017 * Add the annotation to the complex type ancestor.
12018 */
12019 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
12020 xmlSchemaParseAnnotation(ctxt, child, 1));
12021 child = child->next;
12022 }
12023 if (child == NULL) {
12024 xmlSchemaPContentErr(ctxt,
12026 NULL, node, NULL,
12027 NULL, "(annotation?, (restriction | extension))");
12028 }
12029 if (child == NULL) {
12030 xmlSchemaPContentErr(ctxt,
12032 NULL, node, NULL,
12033 NULL, "(annotation?, (restriction | extension))");
12034 }
12035 if (IS_SCHEMA(child, "restriction")) {
12036 xmlSchemaParseRestriction(ctxt, schema, child,
12037 XML_SCHEMA_TYPE_COMPLEX_CONTENT);
12038 (*hasRestrictionOrExtension) = 1;
12039 child = child->next;
12040 } else if (IS_SCHEMA(child, "extension")) {
12041 xmlSchemaParseExtension(ctxt, schema, child,
12042 XML_SCHEMA_TYPE_COMPLEX_CONTENT);
12043 (*hasRestrictionOrExtension) = 1;
12044 child = child->next;
12045 }
12046 if (child != NULL) {
12047 xmlSchemaPContentErr(ctxt,
12049 NULL, node, child,
12050 NULL, "(annotation?, (restriction | extension))");
12051 }
12052 return (0);
12053}
12054
12066static xmlSchemaTypePtr
12067xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
12068 xmlNodePtr node, int topLevel)
12069{
12070 xmlSchemaTypePtr type, ctxtType;
12071 xmlNodePtr child = NULL;
12072 const xmlChar *name = NULL;
12073 xmlAttrPtr attr;
12074 const xmlChar *attrValue;
12075#ifdef ENABLE_NAMED_LOCALS
12076 char buf[40];
12077#endif
12078 int final = 0, block = 0, hasRestrictionOrExtension = 0;
12079
12080
12081 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
12082 return (NULL);
12083
12084 ctxtType = ctxt->ctxtType;
12085
12086 if (topLevel) {
12087 attr = xmlSchemaGetPropNode(node, "name");
12088 if (attr == NULL) {
12089 xmlSchemaPMissingAttrErr(ctxt,
12091 return (NULL);
12092 } else if (xmlSchemaPValAttrNode(ctxt, NULL, attr,
12093 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
12094 return (NULL);
12095 }
12096 }
12097
12098 if (topLevel == 0) {
12099 /*
12100 * Parse as local complex type definition.
12101 */
12102#ifdef ENABLE_NAMED_LOCALS
12103 snprintf(buf, 39, "#CT%d", ctxt->counter++ + 1);
12104 type = xmlSchemaAddType(ctxt, schema,
12105 XML_SCHEMA_TYPE_COMPLEX,
12106 xmlDictLookup(ctxt->dict, (const xmlChar *)buf, -1),
12107 ctxt->targetNamespace, node, 0);
12108#else
12109 type = xmlSchemaAddType(ctxt, schema,
12110 XML_SCHEMA_TYPE_COMPLEX,
12111 NULL, ctxt->targetNamespace, node, 0);
12112#endif
12113 if (type == NULL)
12114 return (NULL);
12115 name = type->name;
12116 type->node = node;
12117 type->type = XML_SCHEMA_TYPE_COMPLEX;
12118 /*
12119 * TODO: We need the target namespace.
12120 */
12121 } else {
12122 /*
12123 * Parse as global complex type definition.
12124 */
12125 type = xmlSchemaAddType(ctxt, schema,
12126 XML_SCHEMA_TYPE_COMPLEX,
12127 name, ctxt->targetNamespace, node, 1);
12128 if (type == NULL)
12129 return (NULL);
12130 type->node = node;
12131 type->type = XML_SCHEMA_TYPE_COMPLEX;
12132 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
12133 }
12134 type->targetNamespace = ctxt->targetNamespace;
12135 /*
12136 * Handle attributes.
12137 */
12138 attr = node->properties;
12139 while (attr != NULL) {
12140 if (attr->ns == NULL) {
12141 if (xmlStrEqual(attr->name, BAD_CAST "id")) {
12142 /*
12143 * Attribute "id".
12144 */
12145 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
12146 } else if (xmlStrEqual(attr->name, BAD_CAST "mixed")) {
12147 /*
12148 * Attribute "mixed".
12149 */
12150 if (xmlSchemaPGetBoolNodeValue(ctxt,
12151 NULL, (xmlNodePtr) attr))
12152 type->flags |= XML_SCHEMAS_TYPE_MIXED;
12153 } else if (topLevel) {
12154 /*
12155 * Attributes of global complex type definitions.
12156 */
12157 if (xmlStrEqual(attr->name, BAD_CAST "name")) {
12158 /* Pass. */
12159 } else if (xmlStrEqual(attr->name, BAD_CAST "abstract")) {
12160 /*
12161 * Attribute "abstract".
12162 */
12163 if (xmlSchemaPGetBoolNodeValue(ctxt,
12164 NULL, (xmlNodePtr) attr))
12165 type->flags |= XML_SCHEMAS_TYPE_ABSTRACT;
12166 } else if (xmlStrEqual(attr->name, BAD_CAST "final")) {
12167 /*
12168 * Attribute "final".
12169 */
12170 attrValue = xmlSchemaGetNodeContent(ctxt,
12171 (xmlNodePtr) attr);
12172 if (xmlSchemaPValAttrBlockFinal(attrValue,
12173 &(type->flags),
12174 -1,
12175 XML_SCHEMAS_TYPE_FINAL_EXTENSION,
12176 XML_SCHEMAS_TYPE_FINAL_RESTRICTION,
12177 -1, -1, -1) != 0)
12178 {
12179 xmlSchemaPSimpleTypeErr(ctxt,
12181 NULL, (xmlNodePtr) attr, NULL,
12182 "(#all | List of (extension | restriction))",
12183 attrValue, NULL, NULL, NULL);
12184 } else
12185 final = 1;
12186 } else if (xmlStrEqual(attr->name, BAD_CAST "block")) {
12187 /*
12188 * Attribute "block".
12189 */
12190 attrValue = xmlSchemaGetNodeContent(ctxt,
12191 (xmlNodePtr) attr);
12192 if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
12193 -1,
12194 XML_SCHEMAS_TYPE_BLOCK_EXTENSION,
12195 XML_SCHEMAS_TYPE_BLOCK_RESTRICTION,
12196 -1, -1, -1) != 0) {
12197 xmlSchemaPSimpleTypeErr(ctxt,
12199 NULL, (xmlNodePtr) attr, NULL,
12200 "(#all | List of (extension | restriction)) ",
12201 attrValue, NULL, NULL, NULL);
12202 } else
12203 block = 1;
12204 } else {
12205 xmlSchemaPIllegalAttrErr(ctxt,
12207 }
12208 } else {
12209 xmlSchemaPIllegalAttrErr(ctxt,
12211 }
12212 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
12213 xmlSchemaPIllegalAttrErr(ctxt,
12215 }
12216 attr = attr->next;
12217 }
12218 if (! block) {
12219 /*
12220 * Apply default "block" values.
12221 */
12222 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
12223 type->flags |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
12224 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
12225 type->flags |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
12226 }
12227 if (! final) {
12228 /*
12229 * Apply default "block" values.
12230 */
12231 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
12232 type->flags |= XML_SCHEMAS_TYPE_FINAL_RESTRICTION;
12233 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
12234 type->flags |= XML_SCHEMAS_TYPE_FINAL_EXTENSION;
12235 }
12236 /*
12237 * And now for the children...
12238 */
12239 child = node->children;
12240 if (IS_SCHEMA(child, "annotation")) {
12241 type->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
12242 child = child->next;
12243 }
12244 ctxt->ctxtType = type;
12245 if (IS_SCHEMA(child, "simpleContent")) {
12246 /*
12247 * <complexType><simpleContent>...
12248 * 3.4.3 : 2.2
12249 * Specifying mixed='true' when the <simpleContent>
12250 * alternative is chosen has no effect
12251 */
12252 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
12253 type->flags ^= XML_SCHEMAS_TYPE_MIXED;
12254 xmlSchemaParseSimpleContent(ctxt, schema, child,
12255 &hasRestrictionOrExtension);
12256 child = child->next;
12257 } else if (IS_SCHEMA(child, "complexContent")) {
12258 /*
12259 * <complexType><complexContent>...
12260 */
12261 type->contentType = XML_SCHEMA_CONTENT_EMPTY;
12262 xmlSchemaParseComplexContent(ctxt, schema, child,
12263 &hasRestrictionOrExtension);
12264 child = child->next;
12265 } else {
12266 /*
12267 * E.g <complexType><sequence>... or <complexType><attribute>... etc.
12268 *
12269 * SPEC
12270 * "...the third alternative (neither <simpleContent> nor
12271 * <complexContent>) is chosen. This case is understood as shorthand
12272 * for complex content restricting the `ur-type definition`, and the
12273 * details of the mappings should be modified as necessary.
12274 */
12275 type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
12276 type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
12277 /*
12278 * Parse model groups.
12279 */
12280 if (IS_SCHEMA(child, "all")) {
12281 type->subtypes = (xmlSchemaTypePtr)
12282 xmlSchemaParseModelGroup(ctxt, schema, child,
12283 XML_SCHEMA_TYPE_ALL, 1);
12284 child = child->next;
12285 } else if (IS_SCHEMA(child, "choice")) {
12286 type->subtypes = (xmlSchemaTypePtr)
12287 xmlSchemaParseModelGroup(ctxt, schema, child,
12288 XML_SCHEMA_TYPE_CHOICE, 1);
12289 child = child->next;
12290 } else if (IS_SCHEMA(child, "sequence")) {
12291 type->subtypes = (xmlSchemaTypePtr)
12292 xmlSchemaParseModelGroup(ctxt, schema, child,
12293 XML_SCHEMA_TYPE_SEQUENCE, 1);
12294 child = child->next;
12295 } else if (IS_SCHEMA(child, "group")) {
12296 type->subtypes = (xmlSchemaTypePtr)
12297 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
12298 /*
12299 * Note that the reference will be resolved in
12300 * xmlSchemaResolveTypeReferences();
12301 */
12302 child = child->next;
12303 }
12304 /*
12305 * Parse attribute decls/refs.
12306 */
12307 if (xmlSchemaParseLocalAttributes(ctxt, schema, &child,
12308 (xmlSchemaItemListPtr *) &(type->attrUses),
12309 XML_SCHEMA_TYPE_RESTRICTION, NULL) == -1)
12310 return(NULL);
12311 /*
12312 * Parse attribute wildcard.
12313 */
12314 if (IS_SCHEMA(child, "anyAttribute")) {
12315 type->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
12316 child = child->next;
12317 }
12318 }
12319 if (child != NULL) {
12320 xmlSchemaPContentErr(ctxt,
12322 NULL, node, child,
12323 NULL, "(annotation?, (simpleContent | complexContent | "
12324 "((group | all | choice | sequence)?, ((attribute | "
12325 "attributeGroup)*, anyAttribute?))))");
12326 }
12327 /*
12328 * REDEFINE: SPEC src-redefine (5)
12329 */
12330 if (topLevel && ctxt->isRedefine && (! hasRestrictionOrExtension)) {
12331 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_SRC_REDEFINE,
12332 NULL, node, "This is a redefinition, thus the "
12333 "<complexType> must have a <restriction> or <extension> "
12334 "grand-child", NULL);
12335 }
12336 ctxt->ctxtType = ctxtType;
12337 return (type);
12338}
12339
12340/************************************************************************
12341 * *
12342 * Validating using Schemas *
12343 * *
12344 ************************************************************************/
12345
12346/************************************************************************
12347 * *
12348 * Reading/Writing Schemas *
12349 * *
12350 ************************************************************************/
12351
12352#if 0 /* Will be enabled if it is clear what options are needed. */
12363static int
12364xmlSchemaParserCtxtSetOptions(xmlSchemaParserCtxtPtr ctxt,
12365 int options)
12366
12367{
12368 int i;
12369
12370 if (ctxt == NULL)
12371 return (-1);
12372 /*
12373 * WARNING: Change the start value if adding to the
12374 * xmlSchemaParseOption.
12375 */
12376 for (i = 1; i < (int) sizeof(int) * 8; i++) {
12377 if (options & 1<<i) {
12378 return (-1);
12379 }
12380 }
12381 ctxt->options = options;
12382 return (0);
12383}
12384
12391static int
12392xmlSchemaParserCtxtGetOptions(xmlSchemaParserCtxtPtr ctxt)
12393
12394{
12395 if (ctxt == NULL)
12396 return (-1);
12397 else
12398 return (ctxt->options);
12399}
12400#endif
12401
12411xmlSchemaParserCtxtPtr
12412xmlSchemaNewParserCtxt(const char *URL)
12413{
12414 xmlSchemaParserCtxtPtr ret;
12415
12416 if (URL == NULL)
12417 return (NULL);
12418
12419 ret = xmlSchemaParserCtxtCreate();
12420 if (ret == NULL)
12421 return(NULL);
12422 ret->dict = xmlDictCreate();
12423 ret->URL = xmlDictLookup(ret->dict, (const xmlChar *) URL, -1);
12424 return (ret);
12425}
12426
12437xmlSchemaParserCtxtPtr
12438xmlSchemaNewMemParserCtxt(const char *buffer, int size)
12439{
12440 xmlSchemaParserCtxtPtr ret;
12441
12442 if ((buffer == NULL) || (size <= 0))
12443 return (NULL);
12444 ret = xmlSchemaParserCtxtCreate();
12445 if (ret == NULL)
12446 return(NULL);
12447 ret->buffer = buffer;
12448 ret->size = size;
12449 ret->dict = xmlDictCreate();
12450 return (ret);
12451}
12452
12462xmlSchemaParserCtxtPtr
12463xmlSchemaNewDocParserCtxt(xmlDocPtr doc)
12464{
12465 xmlSchemaParserCtxtPtr ret;
12466
12467 if (doc == NULL)
12468 return (NULL);
12469 ret = xmlSchemaParserCtxtCreate();
12470 if (ret == NULL)
12471 return(NULL);
12472 ret->doc = doc;
12473 ret->dict = xmlDictCreate();
12474 /* The application has responsibility for the document */
12475 ret->preserve = 1;
12476
12477 return (ret);
12478}
12479
12486void
12487xmlSchemaFreeParserCtxt(xmlSchemaParserCtxtPtr ctxt)
12488{
12489 if (ctxt == NULL)
12490 return;
12491 if (ctxt->doc != NULL && !ctxt->preserve)
12492 xmlFreeDoc(ctxt->doc);
12493 if (ctxt->vctxt != NULL) {
12494 xmlSchemaFreeValidCtxt(ctxt->vctxt);
12495 }
12496 if (ctxt->ownsConstructor && (ctxt->constructor != NULL)) {
12497 xmlSchemaConstructionCtxtFree(ctxt->constructor);
12498 ctxt->constructor = NULL;
12499 ctxt->ownsConstructor = 0;
12500 }
12501 if (ctxt->attrProhibs != NULL)
12502 xmlSchemaItemListFree(ctxt->attrProhibs);
12503 xmlDictFree(ctxt->dict);
12504 xmlFree(ctxt);
12505}
12506
12507/************************************************************************
12508 * *
12509 * Building the content models *
12510 * *
12511 ************************************************************************/
12512
12518static int
12519xmlSchemaBuildContentModelForSubstGroup(xmlSchemaParserCtxtPtr pctxt,
12520 xmlSchemaParticlePtr particle, int counter, xmlAutomataStatePtr end)
12521{
12522 xmlAutomataStatePtr start, tmp;
12523 xmlSchemaElementPtr elemDecl, member;
12524 xmlSchemaSubstGroupPtr substGroup;
12525 int i;
12526 int ret = 0;
12527
12528 elemDecl = (xmlSchemaElementPtr) particle->children;
12529 /*
12530 * Wrap the substitution group with a CHOICE.
12531 */
12532 start = pctxt->state;
12533 if (end == NULL)
12534 end = xmlAutomataNewState(pctxt->am);
12535 substGroup = xmlSchemaSubstGroupGet(pctxt, elemDecl);
12536 if (substGroup == NULL) {
12537 xmlSchemaPErr(pctxt, WXS_ITEM_NODE(particle),
12539 "Internal error: xmlSchemaBuildContentModelForSubstGroup, "
12540 "declaration is marked having a subst. group but none "
12541 "available.\n", elemDecl->name, NULL);
12542 return(0);
12543 }
12544 if (counter >= 0) {
12545 /*
12546 * NOTE that we put the declaration in, even if it's abstract.
12547 * However, an error will be raised during *validation* if an element
12548 * information item shall be validated against an abstract element
12549 * declaration.
12550 */
12551 tmp = xmlAutomataNewCountedTrans(pctxt->am, start, NULL, counter);
12552 xmlAutomataNewTransition2(pctxt->am, tmp, end,
12553 elemDecl->name, elemDecl->targetNamespace, elemDecl);
12554 /*
12555 * Add subst. group members.
12556 */
12557 for (i = 0; i < substGroup->members->nbItems; i++) {
12558 member = (xmlSchemaElementPtr) substGroup->members->items[i];
12559 xmlAutomataNewTransition2(pctxt->am, tmp, end,
12560 member->name, member->targetNamespace, member);
12561 }
12562 } else if (particle->maxOccurs == 1) {
12563 /*
12564 * NOTE that we put the declaration in, even if it's abstract,
12565 */
12566 xmlAutomataNewEpsilon(pctxt->am,
12567 xmlAutomataNewTransition2(pctxt->am,
12568 start, NULL,
12569 elemDecl->name, elemDecl->targetNamespace, elemDecl), end);
12570 /*
12571 * Add subst. group members.
12572 */
12573 for (i = 0; i < substGroup->members->nbItems; i++) {
12574 member = (xmlSchemaElementPtr) substGroup->members->items[i];
12575 /*
12576 * NOTE: This fixes bug #341150. xmlAutomataNewOnceTrans2()
12577 * was incorrectly used instead of xmlAutomataNewTransition2()
12578 * (seems like a copy&paste bug from the XML_SCHEMA_TYPE_ALL
12579 * section in xmlSchemaBuildAContentModel() ).
12580 * TODO: Check if xmlAutomataNewOnceTrans2() was instead
12581 * intended for the above "counter" section originally. I.e.,
12582 * check xs:all with subst-groups.
12583 *
12584 * tmp = xmlAutomataNewOnceTrans2(pctxt->am, start, NULL,
12585 * member->name, member->targetNamespace,
12586 * 1, 1, member);
12587 */
12588 tmp = xmlAutomataNewTransition2(pctxt->am, start, NULL,
12589 member->name, member->targetNamespace, member);
12590 xmlAutomataNewEpsilon(pctxt->am, tmp, end);
12591 }
12592 } else {
12593 xmlAutomataStatePtr hop;
12594 int maxOccurs = particle->maxOccurs == UNBOUNDED ?
12595 UNBOUNDED : particle->maxOccurs - 1;
12596 int minOccurs = particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
12597
12598 counter =
12599 xmlAutomataNewCounter(pctxt->am, minOccurs,
12600 maxOccurs);
12601 hop = xmlAutomataNewState(pctxt->am);
12602
12603 xmlAutomataNewEpsilon(pctxt->am,
12604 xmlAutomataNewTransition2(pctxt->am,
12605 start, NULL,
12606 elemDecl->name, elemDecl->targetNamespace, elemDecl),
12607 hop);
12608 /*
12609 * Add subst. group members.
12610 */
12611 for (i = 0; i < substGroup->members->nbItems; i++) {
12612 member = (xmlSchemaElementPtr) substGroup->members->items[i];
12613 xmlAutomataNewEpsilon(pctxt->am,
12614 xmlAutomataNewTransition2(pctxt->am,
12615 start, NULL,
12616 member->name, member->targetNamespace, member),
12617 hop);
12618 }
12619 xmlAutomataNewCountedTrans(pctxt->am, hop, start, counter);
12620 xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
12621 }
12622 if (particle->minOccurs == 0) {
12623 xmlAutomataNewEpsilon(pctxt->am, start, end);
12624 ret = 1;
12625 }
12626 pctxt->state = end;
12627 return(ret);
12628}
12629
12635static int
12636xmlSchemaBuildContentModelForElement(xmlSchemaParserCtxtPtr ctxt,
12637 xmlSchemaParticlePtr particle)
12638{
12639 int ret = 0;
12640
12641 if (((xmlSchemaElementPtr) particle->children)->flags &
12642 XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) {
12643 /*
12644 * Substitution groups.
12645 */
12646 ret = xmlSchemaBuildContentModelForSubstGroup(ctxt, particle, -1, NULL);
12647 } else {
12648 xmlSchemaElementPtr elemDecl;
12649 xmlAutomataStatePtr start;
12650
12651 elemDecl = (xmlSchemaElementPtr) particle->children;
12652
12653 if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT)
12654 return(0);
12655 if (particle->maxOccurs == 1) {
12656 start = ctxt->state;
12657 ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
12658 elemDecl->name, elemDecl->targetNamespace, elemDecl);
12659 } else if ((particle->maxOccurs >= UNBOUNDED) &&
12660 (particle->minOccurs < 2)) {
12661 /* Special case. */
12662 start = ctxt->state;
12663 ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
12664 elemDecl->name, elemDecl->targetNamespace, elemDecl);
12665 ctxt->state = xmlAutomataNewTransition2(ctxt->am, ctxt->state, ctxt->state,
12666 elemDecl->name, elemDecl->targetNamespace, elemDecl);
12667 } else {
12668 int counter;
12669 int maxOccurs = particle->maxOccurs == UNBOUNDED ?
12670 UNBOUNDED : particle->maxOccurs - 1;
12671 int minOccurs = particle->minOccurs < 1 ?
12672 0 : particle->minOccurs - 1;
12673
12674 start = xmlAutomataNewEpsilon(ctxt->am, ctxt->state, NULL);
12675 counter = xmlAutomataNewCounter(ctxt->am, minOccurs, maxOccurs);
12676 ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
12677 elemDecl->name, elemDecl->targetNamespace, elemDecl);
12678 xmlAutomataNewCountedTrans(ctxt->am, ctxt->state, start, counter);
12679 ctxt->state = xmlAutomataNewCounterTrans(ctxt->am, ctxt->state,
12680 NULL, counter);
12681 }
12682 if (particle->minOccurs == 0) {
12683 xmlAutomataNewEpsilon(ctxt->am, start, ctxt->state);
12684 ret = 1;
12685 }
12686 }
12687 return(ret);
12688}
12689
12700static int
12701xmlSchemaBuildAContentModel(xmlSchemaParserCtxtPtr pctxt,
12702 xmlSchemaParticlePtr particle)
12703{
12704 int ret = 0, tmp2;
12705
12706 if (particle == NULL) {
12707 PERROR_INT("xmlSchemaBuildAContentModel", "particle is NULL");
12708 return(1);
12709 }
12710 if (particle->children == NULL) {
12711 /*
12712 * Just return in this case. A missing "term" of the particle
12713 * might arise due to an invalid "term" component.
12714 */
12715 return(1);
12716 }
12717
12718 switch (particle->children->type) {
12719 case XML_SCHEMA_TYPE_ANY: {
12720 xmlAutomataStatePtr start, end;
12721 xmlSchemaWildcardPtr wild;
12722 xmlSchemaWildcardNsPtr ns;
12723
12724 wild = (xmlSchemaWildcardPtr) particle->children;
12725
12726 start = pctxt->state;
12727 end = xmlAutomataNewState(pctxt->am);
12728
12729 if (particle->maxOccurs == 1) {
12730 if (wild->any == 1) {
12731 /*
12732 * We need to add both transitions:
12733 *
12734 * 1. the {"*", "*"} for elements in a namespace.
12735 */
12736 pctxt->state =
12737 xmlAutomataNewTransition2(pctxt->am,
12738 start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
12739 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
12740 /*
12741 * 2. the {"*"} for elements in no namespace.
12742 */
12743 pctxt->state =
12744 xmlAutomataNewTransition2(pctxt->am,
12745 start, NULL, BAD_CAST "*", NULL, wild);
12746 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
12747
12748 } else if (wild->nsSet != NULL) {
12749 ns = wild->nsSet;
12750 do {
12751 pctxt->state = start;
12752 pctxt->state = xmlAutomataNewTransition2(pctxt->am,
12753 pctxt->state, NULL, BAD_CAST "*", ns->value, wild);
12754 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
12755 ns = ns->next;
12756 } while (ns != NULL);
12757
12758 } else if (wild->negNsSet != NULL) {
12759 pctxt->state = xmlAutomataNewNegTrans(pctxt->am,
12760 start, end, BAD_CAST "*", wild->negNsSet->value,
12761 wild);
12762 }
12763 } else {
12764 int counter;
12765 xmlAutomataStatePtr hop;
12766 int maxOccurs =
12767 particle->maxOccurs == UNBOUNDED ? UNBOUNDED :
12768 particle->maxOccurs - 1;
12769 int minOccurs =
12770 particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
12771
12772 counter = xmlAutomataNewCounter(pctxt->am, minOccurs, maxOccurs);
12773 hop = xmlAutomataNewState(pctxt->am);
12774 if (wild->any == 1) {
12775 pctxt->state =
12776 xmlAutomataNewTransition2(pctxt->am,
12777 start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
12778 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
12779 pctxt->state =
12780 xmlAutomataNewTransition2(pctxt->am,
12781 start, NULL, BAD_CAST "*", NULL, wild);
12782 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
12783 } else if (wild->nsSet != NULL) {
12784 ns = wild->nsSet;
12785 do {
12786 pctxt->state =
12787 xmlAutomataNewTransition2(pctxt->am,
12788 start, NULL, BAD_CAST "*", ns->value, wild);
12789 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
12790 ns = ns->next;
12791 } while (ns != NULL);
12792
12793 } else if (wild->negNsSet != NULL) {
12794 pctxt->state = xmlAutomataNewNegTrans(pctxt->am,
12795 start, hop, BAD_CAST "*", wild->negNsSet->value,
12796 wild);
12797 }
12798 xmlAutomataNewCountedTrans(pctxt->am, hop, start, counter);
12799 xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
12800 }
12801 if (particle->minOccurs == 0) {
12802 xmlAutomataNewEpsilon(pctxt->am, start, end);
12803 ret = 1;
12804 }
12805 pctxt->state = end;
12806 break;
12807 }
12808 case XML_SCHEMA_TYPE_ELEMENT:
12809 ret = xmlSchemaBuildContentModelForElement(pctxt, particle);
12810 break;
12811 case XML_SCHEMA_TYPE_SEQUENCE:{
12812 xmlSchemaTreeItemPtr sub;
12813
12814 ret = 1;
12815 /*
12816 * If max and min occurrences are default (1) then
12817 * simply iterate over the particles of the <sequence>.
12818 */
12819 if ((particle->minOccurs == 1) && (particle->maxOccurs == 1)) {
12820 sub = particle->children->children;
12821
12822 while (sub != NULL) {
12823 tmp2 = xmlSchemaBuildAContentModel(pctxt,
12824 (xmlSchemaParticlePtr) sub);
12825 if (tmp2 != 1) ret = 0;
12826 sub = sub->next;
12827 }
12828 } else {
12829 xmlAutomataStatePtr oldstate = pctxt->state;
12830
12831 if (particle->maxOccurs >= UNBOUNDED) {
12832 if (particle->minOccurs > 1) {
12833 xmlAutomataStatePtr tmp;
12834 int counter;
12835
12836 pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
12837 oldstate, NULL);
12838 oldstate = pctxt->state;
12839
12840 counter = xmlAutomataNewCounter(pctxt->am,
12841 particle->minOccurs - 1, UNBOUNDED);
12842
12843 sub = particle->children->children;
12844 while (sub != NULL) {
12845 tmp2 = xmlSchemaBuildAContentModel(pctxt,
12846 (xmlSchemaParticlePtr) sub);
12847 if (tmp2 != 1) ret = 0;
12848 sub = sub->next;
12849 }
12850 tmp = pctxt->state;
12851 xmlAutomataNewCountedTrans(pctxt->am, tmp,
12852 oldstate, counter);
12853 pctxt->state =
12854 xmlAutomataNewCounterTrans(pctxt->am, tmp,
12855 NULL, counter);
12856 if (ret == 1)
12857 xmlAutomataNewEpsilon(pctxt->am,
12858 oldstate, pctxt->state);
12859
12860 } else {
12861 pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
12862 oldstate, NULL);
12863 oldstate = pctxt->state;
12864
12865 sub = particle->children->children;
12866 while (sub != NULL) {
12867 tmp2 = xmlSchemaBuildAContentModel(pctxt,
12868 (xmlSchemaParticlePtr) sub);
12869 if (tmp2 != 1) ret = 0;
12870 sub = sub->next;
12871 }
12872 xmlAutomataNewEpsilon(pctxt->am, pctxt->state,
12873 oldstate);
12874 /*
12875 * epsilon needed to block previous trans from
12876 * being allowed to enter back from another
12877 * construct
12878 */
12879 pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
12880 pctxt->state, NULL);
12881 if (particle->minOccurs == 0) {
12882 xmlAutomataNewEpsilon(pctxt->am,
12883 oldstate, pctxt->state);
12884 ret = 1;
12885 }
12886 }
12887 } else if ((particle->maxOccurs > 1)
12888 || (particle->minOccurs > 1)) {
12889 xmlAutomataStatePtr tmp;
12890 int counter;
12891
12892 pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
12893 oldstate, NULL);
12894 oldstate = pctxt->state;
12895
12896 counter = xmlAutomataNewCounter(pctxt->am,
12897 particle->minOccurs - 1,
12898 particle->maxOccurs - 1);
12899
12900 sub = particle->children->children;
12901 while (sub != NULL) {
12902 tmp2 = xmlSchemaBuildAContentModel(pctxt,
12903 (xmlSchemaParticlePtr) sub);
12904 if (tmp2 != 1) ret = 0;
12905 sub = sub->next;
12906 }
12907 tmp = pctxt->state;
12908 xmlAutomataNewCountedTrans(pctxt->am,
12909 tmp, oldstate, counter);
12910 pctxt->state =
12911 xmlAutomataNewCounterTrans(pctxt->am, tmp, NULL,
12912 counter);
12913 if ((particle->minOccurs == 0) || (ret == 1)) {
12914 xmlAutomataNewEpsilon(pctxt->am,
12915 oldstate, pctxt->state);
12916 ret = 1;
12917 }
12918 } else {
12919 sub = particle->children->children;
12920 while (sub != NULL) {
12921 tmp2 = xmlSchemaBuildAContentModel(pctxt,
12922 (xmlSchemaParticlePtr) sub);
12923 if (tmp2 != 1) ret = 0;
12924 sub = sub->next;
12925 }
12926
12927 /*
12928 * epsilon needed to block previous trans from
12929 * being allowed to enter back from another
12930 * construct
12931 */
12932 pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
12933 pctxt->state, NULL);
12934
12935 if (particle->minOccurs == 0) {
12936 xmlAutomataNewEpsilon(pctxt->am, oldstate,
12937 pctxt->state);
12938 ret = 1;
12939 }
12940 }
12941 }
12942 break;
12943 }
12944 case XML_SCHEMA_TYPE_CHOICE:{
12945 xmlSchemaTreeItemPtr sub;
12946 xmlAutomataStatePtr start, end;
12947
12948 ret = 0;
12949 start = pctxt->state;
12950 end = xmlAutomataNewState(pctxt->am);
12951
12952 /*
12953 * iterate over the subtypes and remerge the end with an
12954 * epsilon transition
12955 */
12956 if (particle->maxOccurs == 1) {
12957 sub = particle->children->children;
12958 while (sub != NULL) {
12959 pctxt->state = start;
12960 tmp2 = xmlSchemaBuildAContentModel(pctxt,
12961 (xmlSchemaParticlePtr) sub);
12962 if (tmp2 == 1) ret = 1;
12963 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
12964 sub = sub->next;
12965 }
12966 } else {
12967 int counter;
12968 xmlAutomataStatePtr hop, base;
12969 int maxOccurs = particle->maxOccurs == UNBOUNDED ?
12970 UNBOUNDED : particle->maxOccurs - 1;
12971 int minOccurs =
12972 particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
12973
12974 /*
12975 * use a counter to keep track of the number of transitions
12976 * which went through the choice.
12977 */
12978 counter =
12979 xmlAutomataNewCounter(pctxt->am, minOccurs, maxOccurs);
12980 hop = xmlAutomataNewState(pctxt->am);
12981 base = xmlAutomataNewState(pctxt->am);
12982
12983 sub = particle->children->children;
12984 while (sub != NULL) {
12985 pctxt->state = base;
12986 tmp2 = xmlSchemaBuildAContentModel(pctxt,
12987 (xmlSchemaParticlePtr) sub);
12988 if (tmp2 == 1) ret = 1;
12989 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
12990 sub = sub->next;
12991 }
12992 xmlAutomataNewEpsilon(pctxt->am, start, base);
12993 xmlAutomataNewCountedTrans(pctxt->am, hop, base, counter);
12994 xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
12995 if (ret == 1)
12996 xmlAutomataNewEpsilon(pctxt->am, base, end);
12997 }
12998 if (particle->minOccurs == 0) {
12999 xmlAutomataNewEpsilon(pctxt->am, start, end);
13000 ret = 1;
13001 }
13002 pctxt->state = end;
13003 break;
13004 }
13005 case XML_SCHEMA_TYPE_ALL:{
13006 xmlAutomataStatePtr start, tmp;
13007 xmlSchemaParticlePtr sub;
13008 xmlSchemaElementPtr elemDecl;
13009
13010 ret = 1;
13011
13012 sub = (xmlSchemaParticlePtr) particle->children->children;
13013 if (sub == NULL)
13014 break;
13015
13016 ret = 0;
13017
13018 start = pctxt->state;
13019 tmp = xmlAutomataNewState(pctxt->am);
13020 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, tmp);
13021 pctxt->state = tmp;
13022 while (sub != NULL) {
13023 pctxt->state = tmp;
13024
13025 elemDecl = (xmlSchemaElementPtr) sub->children;
13026 if (elemDecl == NULL) {
13027 PERROR_INT("xmlSchemaBuildAContentModel",
13028 "<element> particle has no term");
13029 return(ret);
13030 };
13031 /*
13032 * NOTE: The {max occurs} of all the particles in the
13033 * {particles} of the group must be 0 or 1; this is
13034 * already ensured during the parse of the content of
13035 * <all>.
13036 */
13037 if (elemDecl->flags & XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) {
13038 int counter;
13039
13040 /*
13041 * This is an abstract group, we need to share
13042 * the same counter for all the element transitions
13043 * derived from the group
13044 */
13045 counter = xmlAutomataNewCounter(pctxt->am,
13046 sub->minOccurs, sub->maxOccurs);
13047 xmlSchemaBuildContentModelForSubstGroup(pctxt,
13048 sub, counter, pctxt->state);
13049 } else {
13050 if ((sub->minOccurs == 1) &&
13051 (sub->maxOccurs == 1)) {
13052 xmlAutomataNewOnceTrans2(pctxt->am, pctxt->state,
13053 pctxt->state,
13054 elemDecl->name,
13055 elemDecl->targetNamespace,
13056 1, 1, elemDecl);
13057 } else if ((sub->minOccurs == 0) &&
13058 (sub->maxOccurs == 1)) {
13059
13060 xmlAutomataNewCountTrans2(pctxt->am, pctxt->state,
13061 pctxt->state,
13062 elemDecl->name,
13063 elemDecl->targetNamespace,
13064 0,
13065 1,
13066 elemDecl);
13067 }
13068 }
13069 sub = (xmlSchemaParticlePtr) sub->next;
13070 }
13071 pctxt->state =
13072 xmlAutomataNewAllTrans(pctxt->am, pctxt->state, NULL, 0);
13073 if (particle->minOccurs == 0) {
13074 xmlAutomataNewEpsilon(pctxt->am, start, pctxt->state);
13075 ret = 1;
13076 }
13077 break;
13078 }
13079 case XML_SCHEMA_TYPE_GROUP:
13080 /*
13081 * If we hit a model group definition, then this means that
13082 * it was empty, thus was not substituted for the containing
13083 * model group. Just do nothing in this case.
13084 * TODO: But the group should be substituted and not occur at
13085 * all in the content model at this point. Fix this.
13086 */
13087 ret = 1;
13088 break;
13089 default:
13090 xmlSchemaInternalErr2(ACTXT_CAST pctxt,
13091 "xmlSchemaBuildAContentModel",
13092 "found unexpected term of type '%s' in content model",
13093 WXS_ITEM_TYPE_NAME(particle->children), NULL);
13094 return(ret);
13095 }
13096 return(ret);
13097}
13098
13107static void
13108xmlSchemaBuildContentModel(xmlSchemaTypePtr type,
13109 xmlSchemaParserCtxtPtr ctxt)
13110{
13111 if ((type->type != XML_SCHEMA_TYPE_COMPLEX) ||
13112 (type->contModel != NULL) ||
13113 ((type->contentType != XML_SCHEMA_CONTENT_ELEMENTS) &&
13114 (type->contentType != XML_SCHEMA_CONTENT_MIXED)))
13115 return;
13116
13117 ctxt->am = NULL;
13118 ctxt->am = xmlNewAutomata();
13119 if (ctxt->am == NULL) {
13121 "Cannot create automata for complex type %s\n", type->name);
13122 return;
13123 }
13124 ctxt->state = xmlAutomataGetInitState(ctxt->am);
13125 /*
13126 * Build the automaton.
13127 */
13128 xmlSchemaBuildAContentModel(ctxt, WXS_TYPE_PARTICLE(type));
13129 xmlAutomataSetFinalState(ctxt->am, ctxt->state);
13130 type->contModel = xmlAutomataCompile(ctxt->am);
13131 if (type->contModel == NULL) {
13132 xmlSchemaPCustomErr(ctxt,
13134 WXS_BASIC_CAST type, type->node,
13135 "Failed to compile the content model", NULL);
13136#if 0 /* disabled in Wine */
13137 } else if (xmlRegexpIsDeterminist(type->contModel) != 1) {
13138 xmlSchemaPCustomErr(ctxt,
13140 /* XML_SCHEMAS_ERR_NOTDETERMINIST, */
13141 WXS_BASIC_CAST type, type->node,
13142 "The content model is not determinist", NULL);
13143#endif
13144 } else {
13145 }
13146 ctxt->state = NULL;
13147 xmlFreeAutomata(ctxt->am);
13148 ctxt->am = NULL;
13149}
13150
13160static void
13161xmlSchemaResolveElementReferences(xmlSchemaElementPtr elemDecl,
13162 xmlSchemaParserCtxtPtr ctxt)
13163{
13164 if ((ctxt == NULL) || (elemDecl == NULL) ||
13165 ((elemDecl != NULL) &&
13166 (elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_RESOLVED)))
13167 return;
13168 elemDecl->flags |= XML_SCHEMAS_ELEM_INTERNAL_RESOLVED;
13169
13170 if ((elemDecl->subtypes == NULL) && (elemDecl->namedType != NULL)) {
13171 xmlSchemaTypePtr type;
13172
13173 /* (type definition) ... otherwise the type definition `resolved`
13174 * to by the `actual value` of the type [attribute] ...
13175 */
13176 type = xmlSchemaGetType(ctxt->schema, elemDecl->namedType,
13177 elemDecl->namedTypeNs);
13178 if (type == NULL) {
13179 xmlSchemaPResCompAttrErr(ctxt,
13181 WXS_BASIC_CAST elemDecl, elemDecl->node,
13182 "type", elemDecl->namedType, elemDecl->namedTypeNs,
13183 XML_SCHEMA_TYPE_BASIC, "type definition");
13184 } else
13185 elemDecl->subtypes = type;
13186 }
13187 if (elemDecl->substGroup != NULL) {
13188 xmlSchemaElementPtr substHead;
13189
13190 /*
13191 * FIXME TODO: Do we need a new field in _xmlSchemaElement for
13192 * substitutionGroup?
13193 */
13194 substHead = xmlSchemaGetElem(ctxt->schema, elemDecl->substGroup,
13195 elemDecl->substGroupNs);
13196 if (substHead == NULL) {
13197 xmlSchemaPResCompAttrErr(ctxt,
13199 WXS_BASIC_CAST elemDecl, NULL,
13200 "substitutionGroup", elemDecl->substGroup,
13201 elemDecl->substGroupNs, XML_SCHEMA_TYPE_ELEMENT, NULL);
13202 } else {
13203 xmlSchemaResolveElementReferences(substHead, ctxt);
13204 /*
13205 * Set the "substitution group affiliation".
13206 * NOTE that now we use the "refDecl" field for this.
13207 */
13208 WXS_SUBST_HEAD(elemDecl) = substHead;
13209 /*
13210 * The type definitions is set to:
13211 * SPEC "...the {type definition} of the element
13212 * declaration `resolved` to by the `actual value`
13213 * of the substitutionGroup [attribute], if present"
13214 */
13215 if (elemDecl->subtypes == NULL) {
13216 if (substHead->subtypes == NULL) {
13217 /*
13218 * This can happen with self-referencing substitution
13219 * groups. The cycle will be detected later, but we have
13220 * to set subtypes to avoid null-pointer dereferences.
13221 */
13222 elemDecl->subtypes = xmlSchemaGetBuiltInType(
13223 XML_SCHEMAS_ANYTYPE);
13224 } else {
13225 elemDecl->subtypes = substHead->subtypes;
13226 }
13227 }
13228 }
13229 }
13230 /*
13231 * SPEC "The definition of anyType serves as the default type definition
13232 * for element declarations whose XML representation does not specify one."
13233 */
13234 if ((elemDecl->subtypes == NULL) &&
13235 (elemDecl->namedType == NULL) &&
13236 (elemDecl->substGroup == NULL))
13237 elemDecl->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
13238}
13239
13251static int
13252xmlSchemaResolveUnionMemberTypes(xmlSchemaParserCtxtPtr ctxt,
13253 xmlSchemaTypePtr type)
13254{
13255
13256 xmlSchemaTypeLinkPtr link, lastLink, newLink;
13257 xmlSchemaTypePtr memberType;
13258
13259 /*
13260 * SPEC (1) "If the <union> alternative is chosen, then [Definition:]
13261 * define the explicit members as the type definitions `resolved`
13262 * to by the items in the `actual value` of the memberTypes [attribute],
13263 * if any, followed by the type definitions corresponding to the
13264 * <simpleType>s among the [children] of <union>, if any."
13265 */
13266 /*
13267 * Resolve references.
13268 */
13269 link = type->memberTypes;
13270 lastLink = NULL;
13271 while (link != NULL) {
13272 const xmlChar *name, *nsName;
13273
13274 name = ((xmlSchemaQNameRefPtr) link->type)->name;
13275 nsName = ((xmlSchemaQNameRefPtr) link->type)->targetNamespace;
13276
13277 memberType = xmlSchemaGetType(ctxt->schema, name, nsName);
13278 if ((memberType == NULL) || (! WXS_IS_SIMPLE(memberType))) {
13279 xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
13280 WXS_BASIC_CAST type, type->node, "memberTypes",
13281 name, nsName, XML_SCHEMA_TYPE_SIMPLE, NULL);
13282 /*
13283 * Remove the member type link.
13284 */
13285 if (lastLink == NULL)
13286 type->memberTypes = link->next;
13287 else
13288 lastLink->next = link->next;
13289 newLink = link;
13290 link = link->next;
13291 xmlFree(newLink);
13292 } else {
13293 link->type = memberType;
13294 lastLink = link;
13295 link = link->next;
13296 }
13297 }
13298 /*
13299 * Add local simple types,
13300 */
13301 memberType = type->subtypes;
13302 while (memberType != NULL) {
13303 link = (xmlSchemaTypeLinkPtr) xmlMalloc(sizeof(xmlSchemaTypeLink));
13304 if (link == NULL) {
13305 xmlSchemaPErrMemory(ctxt, "allocating a type link", NULL);
13306 return (-1);
13307 }
13308 link->type = memberType;
13309 link->next = NULL;
13310 if (lastLink == NULL)
13311 type->memberTypes = link;
13312 else
13313 lastLink->next = link;
13314 lastLink = link;
13315 memberType = memberType->next;
13316 }
13317 return (0);
13318}
13319
13330static int
13331xmlSchemaIsDerivedFromBuiltInType(xmlSchemaTypePtr type, int valType)
13332{
13333 if (type == NULL)
13334 return (0);
13335 if (WXS_IS_COMPLEX(type))
13336 return (0);
13337 if (type->type == XML_SCHEMA_TYPE_BASIC) {
13338 if (type->builtInType == valType)
13339 return(1);
13340 if ((type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) ||
13341 (type->builtInType == XML_SCHEMAS_ANYTYPE))
13342 return (0);
13343 return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
13344 }
13345 return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
13346}
13347
13348#if 0
13359static int
13360xmlSchemaIsUserDerivedFromBuiltInType(xmlSchemaTypePtr type, int valType)
13361{
13362 if (type == NULL)
13363 return (0);
13364 if (WXS_IS_COMPLEX(type))
13365 return (0);
13366 if (type->type == XML_SCHEMA_TYPE_BASIC) {
13367 if (type->builtInType == valType)
13368 return(1);
13369 return (0);
13370 } else
13371 return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
13372
13373 return (0);
13374}
13375
13376static xmlSchemaTypePtr
13377xmlSchemaQueryBuiltInType(xmlSchemaTypePtr type)
13378{
13379 if (type == NULL)
13380 return (NULL);
13381 if (WXS_IS_COMPLEX(type))
13382 return (NULL);
13383 if (type->type == XML_SCHEMA_TYPE_BASIC)
13384 return(type);
13385 return(xmlSchemaQueryBuiltInType(type->subtypes));
13386}
13387#endif
13388
13396static xmlSchemaTypePtr
13397xmlSchemaGetPrimitiveType(xmlSchemaTypePtr type)
13398{
13399
13400 while (type != NULL) {
13401 /*
13402 * Note that anySimpleType is actually not a primitive type
13403 * but we need that here.
13404 */
13405 if ((type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) ||
13406 (type->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE))
13407 return (type);
13408 type = type->baseType;
13409 }
13410
13411 return (NULL);
13412}
13413
13414#if 0
13422static xmlSchemaTypePtr
13423xmlSchemaGetBuiltInTypeAncestor(xmlSchemaTypePtr type)
13424{
13425 if (WXS_IS_LIST(type) || WXS_IS_UNION(type))
13426 return (0);
13427 while (type != NULL) {
13428 if (type->type == XML_SCHEMA_TYPE_BASIC)
13429 return (type);
13430 type = type->baseType;
13431 }
13432
13433 return (NULL);
13434}
13435#endif
13436
13447static int
13448xmlSchemaCloneWildcardNsConstraints(xmlSchemaParserCtxtPtr ctxt,
13449 xmlSchemaWildcardPtr dest,
13450 xmlSchemaWildcardPtr source)
13451{
13452 xmlSchemaWildcardNsPtr cur, tmp, last;
13453
13454 if ((source == NULL) || (dest == NULL))
13455 return(-1);
13456 dest->any = source->any;
13457 cur = source->nsSet;
13458 last = NULL;
13459 while (cur != NULL) {
13460 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
13461 if (tmp == NULL)
13462 return(-1);
13463 tmp->value = cur->value;
13464 if (last == NULL)
13465 dest->nsSet = tmp;
13466 else
13467 last->next = tmp;
13468 last = tmp;
13469 cur = cur->next;
13470 }
13471 if (dest->negNsSet != NULL)
13472 xmlSchemaFreeWildcardNsSet(dest->negNsSet);
13473 if (source->negNsSet != NULL) {
13474 dest->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13475 if (dest->negNsSet == NULL)
13476 return(-1);
13477 dest->negNsSet->value = source->negNsSet->value;
13478 } else
13479 dest->negNsSet = NULL;
13480 return(0);
13481}
13482
13494static int
13495xmlSchemaUnionWildcards(xmlSchemaParserCtxtPtr ctxt,
13496 xmlSchemaWildcardPtr completeWild,
13497 xmlSchemaWildcardPtr curWild)
13498{
13499 xmlSchemaWildcardNsPtr cur, curB, tmp;
13500
13501 /*
13502 * 1 If O1 and O2 are the same value, then that value must be the
13503 * value.
13504 */
13505 if ((completeWild->any == curWild->any) &&
13506 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
13507 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
13508
13509 if ((completeWild->negNsSet == NULL) ||
13510 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
13511
13512 if (completeWild->nsSet != NULL) {
13513 int found = 0;
13514
13515 /*
13516 * Check equality of sets.
13517 */
13518 cur = completeWild->nsSet;
13519 while (cur != NULL) {
13520 found = 0;
13521 curB = curWild->nsSet;
13522 while (curB != NULL) {
13523 if (cur->value == curB->value) {
13524 found = 1;
13525 break;
13526 }
13527 curB = curB->next;
13528 }
13529 if (!found)
13530 break;
13531 cur = cur->next;
13532 }
13533 if (found)
13534 return(0);
13535 } else
13536 return(0);
13537 }
13538 }
13539 /*
13540 * 2 If either O1 or O2 is any, then any must be the value
13541 */
13542 if (completeWild->any != curWild->any) {
13543 if (completeWild->any == 0) {
13544 completeWild->any = 1;
13545 if (completeWild->nsSet != NULL) {
13546 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13547 completeWild->nsSet = NULL;
13548 }
13549 if (completeWild->negNsSet != NULL) {
13550 xmlFree(completeWild->negNsSet);
13551 completeWild->negNsSet = NULL;
13552 }
13553 }
13554 return (0);
13555 }
13556 /*
13557 * 3 If both O1 and O2 are sets of (namespace names or `absent`),
13558 * then the union of those sets must be the value.
13559 */
13560 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
13561 int found;
13562 xmlSchemaWildcardNsPtr start;
13563
13564 cur = curWild->nsSet;
13565 start = completeWild->nsSet;
13566 while (cur != NULL) {
13567 found = 0;
13568 curB = start;
13569 while (curB != NULL) {
13570 if (cur->value == curB->value) {
13571 found = 1;
13572 break;
13573 }
13574 curB = curB->next;
13575 }
13576 if (!found) {
13577 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
13578 if (tmp == NULL)
13579 return (-1);
13580 tmp->value = cur->value;
13581 tmp->next = completeWild->nsSet;
13582 completeWild->nsSet = tmp;
13583 }
13584 cur = cur->next;
13585 }
13586
13587 return(0);
13588 }
13589 /*
13590 * 4 If the two are negations of different values (namespace names
13591 * or `absent`), then a pair of not and `absent` must be the value.
13592 */
13593 if ((completeWild->negNsSet != NULL) &&
13594 (curWild->negNsSet != NULL) &&
13595 (completeWild->negNsSet->value != curWild->negNsSet->value)) {
13596 completeWild->negNsSet->value = NULL;
13597
13598 return(0);
13599 }
13600 /*
13601 * 5.
13602 */
13603 if (((completeWild->negNsSet != NULL) &&
13604 (completeWild->negNsSet->value != NULL) &&
13605 (curWild->nsSet != NULL)) ||
13606 ((curWild->negNsSet != NULL) &&
13607 (curWild->negNsSet->value != NULL) &&
13608 (completeWild->nsSet != NULL))) {
13609
13610 int nsFound, absentFound = 0;
13611
13612 if (completeWild->nsSet != NULL) {
13613 cur = completeWild->nsSet;
13614 curB = curWild->negNsSet;
13615 } else {
13616 cur = curWild->nsSet;
13617 curB = completeWild->negNsSet;
13618 }
13619 nsFound = 0;
13620 while (cur != NULL) {
13621 if (cur->value == NULL)
13622 absentFound = 1;
13623 else if (cur->value == curB->value)
13624 nsFound = 1;
13625 if (nsFound && absentFound)
13626 break;
13627 cur = cur->next;
13628 }
13629
13630 if (nsFound && absentFound) {
13631 /*
13632 * 5.1 If the set S includes both the negated namespace
13633 * name and `absent`, then any must be the value.
13634 */
13635 completeWild->any = 1;
13636 if (completeWild->nsSet != NULL) {
13637 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13638 completeWild->nsSet = NULL;
13639 }
13640 if (completeWild->negNsSet != NULL) {
13641 xmlFree(completeWild->negNsSet);
13642 completeWild->negNsSet = NULL;
13643 }
13644 } else if (nsFound && (!absentFound)) {
13645 /*
13646 * 5.2 If the set S includes the negated namespace name
13647 * but not `absent`, then a pair of not and `absent` must
13648 * be the value.
13649 */
13650 if (completeWild->nsSet != NULL) {
13651 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13652 completeWild->nsSet = NULL;
13653 }
13654 if (completeWild->negNsSet == NULL) {
13655 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13656 if (completeWild->negNsSet == NULL)
13657 return (-1);
13658 }
13659 completeWild->negNsSet->value = NULL;
13660 } else if ((!nsFound) && absentFound) {
13661 /*
13662 * 5.3 If the set S includes `absent` but not the negated
13663 * namespace name, then the union is not expressible.
13664 */
13665 xmlSchemaPErr(ctxt, completeWild->node,
13667 "The union of the wildcard is not expressible.\n",
13668 NULL, NULL);
13670 } else if ((!nsFound) && (!absentFound)) {
13671 /*
13672 * 5.4 If the set S does not include either the negated namespace
13673 * name or `absent`, then whichever of O1 or O2 is a pair of not
13674 * and a namespace name must be the value.
13675 */
13676 if (completeWild->negNsSet == NULL) {
13677 if (completeWild->nsSet != NULL) {
13678 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13679 completeWild->nsSet = NULL;
13680 }
13681 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13682 if (completeWild->negNsSet == NULL)
13683 return (-1);
13684 completeWild->negNsSet->value = curWild->negNsSet->value;
13685 }
13686 }
13687 return (0);
13688 }
13689 /*
13690 * 6.
13691 */
13692 if (((completeWild->negNsSet != NULL) &&
13693 (completeWild->negNsSet->value == NULL) &&
13694 (curWild->nsSet != NULL)) ||
13695 ((curWild->negNsSet != NULL) &&
13696 (curWild->negNsSet->value == NULL) &&
13697 (completeWild->nsSet != NULL))) {
13698
13699 if (completeWild->nsSet != NULL) {
13700 cur = completeWild->nsSet;
13701 } else {
13702 cur = curWild->nsSet;
13703 }
13704 while (cur != NULL) {
13705 if (cur->value == NULL) {
13706 /*
13707 * 6.1 If the set S includes `absent`, then any must be the
13708 * value.
13709 */
13710 completeWild->any = 1;
13711 if (completeWild->nsSet != NULL) {
13712 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13713 completeWild->nsSet = NULL;
13714 }
13715 if (completeWild->negNsSet != NULL) {
13716 xmlFree(completeWild->negNsSet);
13717 completeWild->negNsSet = NULL;
13718 }
13719 return (0);
13720 }
13721 cur = cur->next;
13722 }
13723 if (completeWild->negNsSet == NULL) {
13724 /*
13725 * 6.2 If the set S does not include `absent`, then a pair of not
13726 * and `absent` must be the value.
13727 */
13728 if (completeWild->nsSet != NULL) {
13729 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13730 completeWild->nsSet = NULL;
13731 }
13732 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13733 if (completeWild->negNsSet == NULL)
13734 return (-1);
13735 completeWild->negNsSet->value = NULL;
13736 }
13737 return (0);
13738 }
13739 return (0);
13740
13741}
13742
13754static int
13755xmlSchemaIntersectWildcards(xmlSchemaParserCtxtPtr ctxt,
13756 xmlSchemaWildcardPtr completeWild,
13757 xmlSchemaWildcardPtr curWild)
13758{
13759 xmlSchemaWildcardNsPtr cur, curB, prev, tmp;
13760
13761 /*
13762 * 1 If O1 and O2 are the same value, then that value must be the
13763 * value.
13764 */
13765 if ((completeWild->any == curWild->any) &&
13766 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
13767 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
13768
13769 if ((completeWild->negNsSet == NULL) ||
13770 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
13771
13772 if (completeWild->nsSet != NULL) {
13773 int found = 0;
13774
13775 /*
13776 * Check equality of sets.
13777 */
13778 cur = completeWild->nsSet;
13779 while (cur != NULL) {
13780 found = 0;
13781 curB = curWild->nsSet;
13782 while (curB != NULL) {
13783 if (cur->value == curB->value) {
13784 found = 1;
13785 break;
13786 }
13787 curB = curB->next;
13788 }
13789 if (!found)
13790 break;
13791 cur = cur->next;
13792 }
13793 if (found)
13794 return(0);
13795 } else
13796 return(0);
13797 }
13798 }
13799 /*
13800 * 2 If either O1 or O2 is any, then the other must be the value.
13801 */
13802 if ((completeWild->any != curWild->any) && (completeWild->any)) {
13803 if (xmlSchemaCloneWildcardNsConstraints(ctxt, completeWild, curWild) == -1)
13804 return(-1);
13805 return(0);
13806 }
13807 /*
13808 * 3 If either O1 or O2 is a pair of not and a value (a namespace
13809 * name or `absent`) and the other is a set of (namespace names or
13810 * `absent`), then that set, minus the negated value if it was in
13811 * the set, minus `absent` if it was in the set, must be the value.
13812 */
13813 if (((completeWild->negNsSet != NULL) && (curWild->nsSet != NULL)) ||
13814 ((curWild->negNsSet != NULL) && (completeWild->nsSet != NULL))) {
13815 const xmlChar *neg;
13816
13817 if (completeWild->nsSet == NULL) {
13818 neg = completeWild->negNsSet->value;
13819 if (xmlSchemaCloneWildcardNsConstraints(ctxt, completeWild, curWild) == -1)
13820 return(-1);
13821 } else
13822 neg = curWild->negNsSet->value;
13823 /*
13824 * Remove absent and negated.
13825 */
13826 prev = NULL;
13827 cur = completeWild->nsSet;
13828 while (cur != NULL) {
13829 if (cur->value == NULL) {
13830 if (prev == NULL)
13831 completeWild->nsSet = cur->next;
13832 else
13833 prev->next = cur->next;
13834 xmlFree(cur);
13835 break;
13836 }
13837 prev = cur;
13838 cur = cur->next;
13839 }
13840 if (neg != NULL) {
13841 prev = NULL;
13842 cur = completeWild->nsSet;
13843 while (cur != NULL) {
13844 if (cur->value == neg) {
13845 if (prev == NULL)
13846 completeWild->nsSet = cur->next;
13847 else
13848 prev->next = cur->next;
13849 xmlFree(cur);
13850 break;
13851 }
13852 prev = cur;
13853 cur = cur->next;
13854 }
13855 }
13856
13857 return(0);
13858 }
13859 /*
13860 * 4 If both O1 and O2 are sets of (namespace names or `absent`),
13861 * then the intersection of those sets must be the value.
13862 */
13863 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
13864 int found;
13865
13866 cur = completeWild->nsSet;
13867 prev = NULL;
13868 while (cur != NULL) {
13869 found = 0;
13870 curB = curWild->nsSet;
13871 while (curB != NULL) {
13872 if (cur->value == curB->value) {
13873 found = 1;
13874 break;
13875 }
13876 curB = curB->next;
13877 }
13878 if (!found) {
13879 if (prev == NULL)
13880 completeWild->nsSet = cur->next;
13881 else
13882 prev->next = cur->next;
13883 tmp = cur->next;
13884 xmlFree(cur);
13885 cur = tmp;
13886 continue;
13887 }
13888 prev = cur;
13889 cur = cur->next;
13890 }
13891
13892 return(0);
13893 }
13894 /* 5 If the two are negations of different namespace names,
13895 * then the intersection is not expressible
13896 */
13897 if ((completeWild->negNsSet != NULL) &&
13898 (curWild->negNsSet != NULL) &&
13899 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
13900 (completeWild->negNsSet->value != NULL) &&
13901 (curWild->negNsSet->value != NULL)) {
13902
13903 xmlSchemaPErr(ctxt, completeWild->node, XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE,
13904 "The intersection of the wildcard is not expressible.\n",
13905 NULL, NULL);
13907 }
13908 /*
13909 * 6 If the one is a negation of a namespace name and the other
13910 * is a negation of `absent`, then the one which is the negation
13911 * of a namespace name must be the value.
13912 */
13913 if ((completeWild->negNsSet != NULL) && (curWild->negNsSet != NULL) &&
13914 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
13915 (completeWild->negNsSet->value == NULL)) {
13916 completeWild->negNsSet->value = curWild->negNsSet->value;
13917 }
13918 return(0);
13919}
13920
13932static int
13933xmlSchemaCheckCOSNSSubset(xmlSchemaWildcardPtr sub,
13934 xmlSchemaWildcardPtr super)
13935{
13936 /*
13937 * 1 super must be any.
13938 */
13939 if (super->any)
13940 return (0);
13941 /*
13942 * 2.1 sub must be a pair of not and a namespace name or `absent`.
13943 * 2.2 super must be a pair of not and the same value.
13944 */
13945 if ((sub->negNsSet != NULL) &&
13946 (super->negNsSet != NULL) &&
13947 (sub->negNsSet->value == super->negNsSet->value))
13948 return (0);
13949 /*
13950 * 3.1 sub must be a set whose members are either namespace names or `absent`.
13951 */
13952 if (sub->nsSet != NULL) {
13953 /*
13954 * 3.2.1 super must be the same set or a superset thereof.
13955 */
13956 if (super->nsSet != NULL) {
13957 xmlSchemaWildcardNsPtr cur, curB;
13958 int found = 0;
13959
13960 cur = sub->nsSet;
13961 while (cur != NULL) {
13962 found = 0;
13963 curB = super->nsSet;
13964 while (curB != NULL) {
13965 if (cur->value == curB->value) {
13966 found = 1;
13967 break;
13968 }
13969 curB = curB->next;
13970 }
13971 if (!found)
13972 return (1);
13973 cur = cur->next;
13974 }
13975 if (found)
13976 return (0);
13977 } else if (super->negNsSet != NULL) {
13978 xmlSchemaWildcardNsPtr cur;
13979 /*
13980 * 3.2.2 super must be a pair of not and a namespace name or
13981 * `absent` and that value must not be in sub's set.
13982 */
13983 cur = sub->nsSet;
13984 while (cur != NULL) {
13985 if (cur->value == super->negNsSet->value)
13986 return (1);
13987 cur = cur->next;
13988 }
13989 return (0);
13990 }
13991 }
13992 return (1);
13993}
13994
13995static int
13996xmlSchemaGetEffectiveValueConstraint(xmlSchemaAttributeUsePtr attruse,
13997 int *fixed,
13998 const xmlChar **value,
13999 xmlSchemaValPtr *val)
14000{
14001 *fixed = 0;
14002 *value = NULL;
14003 if (val != 0)
14004 *val = NULL;
14005
14006 if (attruse->defValue != NULL) {
14007 *value = attruse->defValue;
14008 if (val != NULL)
14009 *val = attruse->defVal;
14010 if (attruse->flags & XML_SCHEMA_ATTR_USE_FIXED)
14011 *fixed = 1;
14012 return(1);
14013 } else if ((attruse->attrDecl != NULL) &&
14014 (attruse->attrDecl->defValue != NULL)) {
14015 *value = attruse->attrDecl->defValue;
14016 if (val != NULL)
14017 *val = attruse->attrDecl->defVal;
14018 if (attruse->attrDecl->flags & XML_SCHEMAS_ATTR_FIXED)
14019 *fixed = 1;
14020 return(1);
14021 }
14022 return(0);
14023}
14035static int
14036xmlSchemaCheckCVCWildcardNamespace(xmlSchemaWildcardPtr wild,
14037 const xmlChar* ns)
14038{
14039 if (wild == NULL)
14040 return(-1);
14041
14042 if (wild->any)
14043 return(0);
14044 else if (wild->nsSet != NULL) {
14045 xmlSchemaWildcardNsPtr cur;
14046
14047 cur = wild->nsSet;
14048 while (cur != NULL) {
14049 if (xmlStrEqual(cur->value, ns))
14050 return(0);
14051 cur = cur->next;
14052 }
14053 } else if ((wild->negNsSet != NULL) && (ns != NULL) &&
14054 (!xmlStrEqual(wild->negNsSet->value, ns)))
14055 return(0);
14056
14057 return(1);
14058}
14059
14060#define XML_SCHEMA_ACTION_DERIVE 0
14061#define XML_SCHEMA_ACTION_REDEFINE 1
14062
14063#define WXS_ACTION_STR(a) \
14064((a) == XML_SCHEMA_ACTION_DERIVE) ? (const xmlChar *) "base" : (const xmlChar *) "redefined"
14065
14066/*
14067* Schema Component Constraint:
14068* Derivation Valid (Restriction, Complex)
14069* derivation-ok-restriction (2) - (4)
14070*
14071* ATTENTION:
14072* In XML Schema 1.1 this will be:
14073* Validation Rule:
14074* Checking complex type subsumption (practicalSubsumption) (1, 2 and 3)
14075*
14076*/
14077static int
14078xmlSchemaCheckDerivationOKRestriction2to4(xmlSchemaParserCtxtPtr pctxt,
14079 int action,
14080 xmlSchemaBasicItemPtr item,
14081 xmlSchemaBasicItemPtr baseItem,
14082 xmlSchemaItemListPtr uses,
14083 xmlSchemaItemListPtr baseUses,
14084 xmlSchemaWildcardPtr wild,
14085 xmlSchemaWildcardPtr baseWild)
14086{
14087 xmlSchemaAttributeUsePtr cur = NULL, bcur;
14088 int i, j, found; /* err = 0; */
14089 const xmlChar *bEffValue;
14090 int effFixed;
14091
14092 if (uses != NULL) {
14093 for (i = 0; i < uses->nbItems; i++) {
14094 cur = uses->items[i];
14095 found = 0;
14096 if (baseUses == NULL)
14097 goto not_found;
14098 for (j = 0; j < baseUses->nbItems; j++) {
14099 bcur = baseUses->items[j];
14100 if ((WXS_ATTRUSE_DECL_NAME(cur) ==
14101 WXS_ATTRUSE_DECL_NAME(bcur)) &&
14102 (WXS_ATTRUSE_DECL_TNS(cur) ==
14103 WXS_ATTRUSE_DECL_TNS(bcur)))
14104 {
14105 /*
14106 * (2.1) "If there is an attribute use in the {attribute
14107 * uses} of the {base type definition} (call this B) whose
14108 * {attribute declaration} has the same {name} and {target
14109 * namespace}, then all of the following must be true:"
14110 */
14111 found = 1;
14112
14113 if ((cur->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
14114 (bcur->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED))
14115 {
14116 xmlChar *str = NULL;
14117 /*
14118 * (2.1.1) "one of the following must be true:"
14119 * (2.1.1.1) "B's {required} is false."
14120 * (2.1.1.2) "R's {required} is true."
14121 */
14122 xmlSchemaPAttrUseErr4(pctxt,
14124 WXS_ITEM_NODE(item), item, cur,
14125 "The 'optional' attribute use is inconsistent "
14126 "with the corresponding 'required' attribute use of "
14127 "the %s %s",
14128 WXS_ACTION_STR(action),
14129 xmlSchemaGetComponentDesignation(&str, baseItem),
14130 NULL, NULL);
14131 FREE_AND_NULL(str);
14132 /* err = pctxt->err; */
14133 } else if (xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST pctxt,
14134 WXS_ATTRUSE_TYPEDEF(cur),
14135 WXS_ATTRUSE_TYPEDEF(bcur), 0) != 0)
14136 {
14137 xmlChar *strA = NULL, *strB = NULL, *strC = NULL;
14138
14139 /*
14140 * SPEC (2.1.2) "R's {attribute declaration}'s
14141 * {type definition} must be validly derived from
14142 * B's {type definition} given the empty set as
14143 * defined in Type Derivation OK (Simple) ($3.14.6)."
14144 */
14145 xmlSchemaPAttrUseErr4(pctxt,
14147 WXS_ITEM_NODE(item), item, cur,
14148 "The attribute declaration's %s "
14149 "is not validly derived from "
14150 "the corresponding %s of the "
14151 "attribute declaration in the %s %s",
14152 xmlSchemaGetComponentDesignation(&strA,
14153 WXS_ATTRUSE_TYPEDEF(cur)),
14154 xmlSchemaGetComponentDesignation(&strB,
14155 WXS_ATTRUSE_TYPEDEF(bcur)),
14156 WXS_ACTION_STR(action),
14157 xmlSchemaGetComponentDesignation(&strC, baseItem));
14158 /* xmlSchemaGetComponentDesignation(&str, baseItem), */
14159 FREE_AND_NULL(strA);
14160 FREE_AND_NULL(strB);
14161 FREE_AND_NULL(strC);
14162 /* err = pctxt->err; */
14163 } else {
14164 /*
14165 * 2.1.3 [Definition:] Let the effective value
14166 * constraint of an attribute use be its {value
14167 * constraint}, if present, otherwise its {attribute
14168 * declaration}'s {value constraint} .
14169 */
14170 xmlSchemaGetEffectiveValueConstraint(bcur,
14171 &effFixed, &bEffValue, NULL);
14172 /*
14173 * 2.1.3 ... one of the following must be true
14174 *
14175 * 2.1.3.1 B's `effective value constraint` is
14176 * `absent` or default.
14177 */
14178 if ((bEffValue != NULL) &&
14179 (effFixed == 1)) {
14180 const xmlChar *rEffValue = NULL;
14181
14182 xmlSchemaGetEffectiveValueConstraint(bcur,
14183 &effFixed, &rEffValue, NULL);
14184 /*
14185 * 2.1.3.2 R's `effective value constraint` is
14186 * fixed with the same string as B's.
14187 * MAYBE TODO: Compare the computed values.
14188 * Hmm, it says "same string" so
14189 * string-equality might really be sufficient.
14190 */
14191 if ((effFixed == 0) ||
14192 (! WXS_ARE_DEFAULT_STR_EQUAL(rEffValue, bEffValue)))
14193 {
14194 xmlChar *str = NULL;
14195
14196 xmlSchemaPAttrUseErr4(pctxt,
14198 WXS_ITEM_NODE(item), item, cur,
14199 "The effective value constraint of the "
14200 "attribute use is inconsistent with "
14201 "its correspondent in the %s %s",
14202 WXS_ACTION_STR(action),
14203 xmlSchemaGetComponentDesignation(&str,
14204 baseItem),
14205 NULL, NULL);
14206 FREE_AND_NULL(str);
14207 /* err = pctxt->err; */
14208 }
14209 }
14210 }
14211 break;
14212 }
14213 }
14214not_found:
14215 if (!found) {
14216 /*
14217 * (2.2) "otherwise the {base type definition} must have an
14218 * {attribute wildcard} and the {target namespace} of the
14219 * R's {attribute declaration} must be `valid` with respect
14220 * to that wildcard, as defined in Wildcard allows Namespace
14221 * Name ($3.10.4)."
14222 */
14223 if ((baseWild == NULL) ||
14224 (xmlSchemaCheckCVCWildcardNamespace(baseWild,
14225 (WXS_ATTRUSE_DECL(cur))->targetNamespace) != 0))
14226 {
14227 xmlChar *str = NULL;
14228
14229 xmlSchemaPAttrUseErr4(pctxt,
14231 WXS_ITEM_NODE(item), item, cur,
14232 "Neither a matching attribute use, "
14233 "nor a matching wildcard exists in the %s %s",
14234 WXS_ACTION_STR(action),
14235 xmlSchemaGetComponentDesignation(&str, baseItem),
14236 NULL, NULL);
14237 FREE_AND_NULL(str);
14238 /* err = pctxt->err; */
14239 }
14240 }
14241 }
14242 }
14243 /*
14244 * SPEC derivation-ok-restriction (3):
14245 * (3) "For each attribute use in the {attribute uses} of the {base type
14246 * definition} whose {required} is true, there must be an attribute
14247 * use with an {attribute declaration} with the same {name} and
14248 * {target namespace} as its {attribute declaration} in the {attribute
14249 * uses} of the complex type definition itself whose {required} is true.
14250 */
14251 if (baseUses != NULL) {
14252 for (j = 0; j < baseUses->nbItems; j++) {
14253 bcur = baseUses->items[j];
14254 if (bcur->occurs != XML_SCHEMAS_ATTR_USE_REQUIRED)
14255 continue;
14256 found = 0;
14257 if (uses != NULL) {
14258 for (i = 0; i < uses->nbItems; i++) {
14259 cur = uses->items[i];
14260 if ((WXS_ATTRUSE_DECL_NAME(cur) ==
14261 WXS_ATTRUSE_DECL_NAME(bcur)) &&
14262 (WXS_ATTRUSE_DECL_TNS(cur) ==
14263 WXS_ATTRUSE_DECL_TNS(bcur))) {
14264 found = 1;
14265 break;
14266 }
14267 }
14268 }
14269 if (!found) {
14270 xmlChar *strA = NULL, *strB = NULL;
14271
14272 xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14274 NULL, item,
14275 "A matching attribute use for the "
14276 "'required' %s of the %s %s is missing",
14277 xmlSchemaGetComponentDesignation(&strA, bcur),
14278 WXS_ACTION_STR(action),
14279 xmlSchemaGetComponentDesignation(&strB, baseItem),
14280 NULL);
14281 FREE_AND_NULL(strA);
14282 FREE_AND_NULL(strB);
14283 }
14284 }
14285 }
14286 /*
14287 * derivation-ok-restriction (4)
14288 */
14289 if (wild != NULL) {
14290 /*
14291 * (4) "If there is an {attribute wildcard}, all of the
14292 * following must be true:"
14293 */
14294 if (baseWild == NULL) {
14295 xmlChar *str = NULL;
14296
14297 /*
14298 * (4.1) "The {base type definition} must also have one."
14299 */
14300 xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14302 NULL, item,
14303 "The %s has an attribute wildcard, "
14304 "but the %s %s '%s' does not have one",
14305 WXS_ITEM_TYPE_NAME(item),
14306 WXS_ACTION_STR(action),
14307 WXS_ITEM_TYPE_NAME(baseItem),
14308 xmlSchemaGetComponentQName(&str, baseItem));
14309 FREE_AND_NULL(str);
14310 return(pctxt->err);
14311 } else if ((baseWild->any == 0) &&
14312 xmlSchemaCheckCOSNSSubset(wild, baseWild))
14313 {
14314 xmlChar *str = NULL;
14315 /*
14316 * (4.2) "The complex type definition's {attribute wildcard}'s
14317 * {namespace constraint} must be a subset of the {base type
14318 * definition}'s {attribute wildcard}'s {namespace constraint},
14319 * as defined by Wildcard Subset ($3.10.6)."
14320 */
14321 xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14323 NULL, item,
14324 "The attribute wildcard is not a valid "
14325 "subset of the wildcard in the %s %s '%s'",
14326 WXS_ACTION_STR(action),
14327 WXS_ITEM_TYPE_NAME(baseItem),
14328 xmlSchemaGetComponentQName(&str, baseItem),
14329 NULL);
14330 FREE_AND_NULL(str);
14331 return(pctxt->err);
14332 }
14333 /* 4.3 Unless the {base type definition} is the `ur-type
14334 * definition`, the complex type definition's {attribute
14335 * wildcard}'s {process contents} must be identical to or
14336 * stronger than the {base type definition}'s {attribute
14337 * wildcard}'s {process contents}, where strict is stronger
14338 * than lax is stronger than skip.
14339 */
14340 if ((! WXS_IS_ANYTYPE(baseItem)) &&
14341 (wild->processContents < baseWild->processContents)) {
14342 xmlChar *str = NULL;
14343 xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14345 NULL, baseItem,
14346 "The {process contents} of the attribute wildcard is "
14347 "weaker than the one in the %s %s '%s'",
14348 WXS_ACTION_STR(action),
14349 WXS_ITEM_TYPE_NAME(baseItem),
14350 xmlSchemaGetComponentQName(&str, baseItem),
14351 NULL);
14352 FREE_AND_NULL(str)
14353 return(pctxt->err);
14354 }
14355 }
14356 return(0);
14357}
14358
14359
14360static int
14361xmlSchemaExpandAttributeGroupRefs(xmlSchemaParserCtxtPtr pctxt,
14362 xmlSchemaBasicItemPtr item,
14363 xmlSchemaWildcardPtr *completeWild,
14364 xmlSchemaItemListPtr list,
14365 xmlSchemaItemListPtr prohibs);
14380static int
14381xmlSchemaFixupTypeAttributeUses(xmlSchemaParserCtxtPtr pctxt,
14382 xmlSchemaTypePtr type)
14383{
14384 xmlSchemaTypePtr baseType = NULL;
14385 xmlSchemaAttributeUsePtr use;
14386 xmlSchemaItemListPtr uses, baseUses, prohibs = NULL;
14387
14388 if (type->baseType == NULL) {
14389 PERROR_INT("xmlSchemaFixupTypeAttributeUses",
14390 "no base type");
14391 return (-1);
14392 }
14393 baseType = type->baseType;
14394 if (WXS_IS_TYPE_NOT_FIXED(baseType))
14395 if (xmlSchemaTypeFixup(baseType, ACTXT_CAST pctxt) == -1)
14396 return(-1);
14397
14398 uses = type->attrUses;
14399 baseUses = baseType->attrUses;
14400 /*
14401 * Expand attribute group references. And build the 'complete'
14402 * wildcard, i.e. intersect multiple wildcards.
14403 * Move attribute prohibitions into a separate list.
14404 */
14405 if (uses != NULL) {
14406 if (WXS_IS_RESTRICTION(type)) {
14407 /*
14408 * This one will transfer all attr. prohibitions
14409 * into pctxt->attrProhibs.
14410 */
14411 if (xmlSchemaExpandAttributeGroupRefs(pctxt,
14412 WXS_BASIC_CAST type, &(type->attributeWildcard), uses,
14413 pctxt->attrProhibs) == -1)
14414 {
14415 PERROR_INT("xmlSchemaFixupTypeAttributeUses",
14416 "failed to expand attributes");
14417 return(-1);
14418 }
14419 if (pctxt->attrProhibs->nbItems != 0)
14420 prohibs = pctxt->attrProhibs;
14421 } else {
14422 if (xmlSchemaExpandAttributeGroupRefs(pctxt,
14423 WXS_BASIC_CAST type, &(type->attributeWildcard), uses,
14424 NULL) == -1)
14425 {
14426 PERROR_INT("xmlSchemaFixupTypeAttributeUses",
14427 "failed to expand attributes");
14428 return(-1);
14429 }
14430 }
14431 }
14432 /*
14433 * Inherit the attribute uses of the base type.
14434 */
14435 if (baseUses != NULL) {
14436 int i, j;
14437 xmlSchemaAttributeUseProhibPtr pro;
14438
14439 if (WXS_IS_RESTRICTION(type)) {
14440 int usesCount;
14441 xmlSchemaAttributeUsePtr tmp;
14442
14443 if (uses != NULL)
14444 usesCount = uses->nbItems;
14445 else
14446 usesCount = 0;
14447
14448 /* Restriction. */
14449 for (i = 0; i < baseUses->nbItems; i++) {
14450 use = baseUses->items[i];
14451 if (prohibs) {
14452 /*
14453 * Filter out prohibited uses.
14454 */
14455 for (j = 0; j < prohibs->nbItems; j++) {
14456 pro = prohibs->items[j];
14457 if ((WXS_ATTRUSE_DECL_NAME(use) == pro->name) &&
14458 (WXS_ATTRUSE_DECL_TNS(use) ==
14459 pro->targetNamespace))
14460 {
14461 goto inherit_next;
14462 }
14463 }
14464 }
14465 if (usesCount) {
14466 /*
14467 * Filter out existing uses.
14468 */
14469 for (j = 0; j < usesCount; j++) {
14470 tmp = uses->items[j];
14471 if ((WXS_ATTRUSE_DECL_NAME(use) ==
14472 WXS_ATTRUSE_DECL_NAME(tmp)) &&
14473 (WXS_ATTRUSE_DECL_TNS(use) ==
14474 WXS_ATTRUSE_DECL_TNS(tmp)))
14475 {
14476 goto inherit_next;
14477 }
14478 }
14479 }
14480 if (uses == NULL) {
14481 type->attrUses = xmlSchemaItemListCreate();
14482 if (type->attrUses == NULL)
14483 goto exit_failure;
14484 uses = type->attrUses;
14485 }
14486 xmlSchemaItemListAddSize(uses, 2, use);
14487inherit_next: {}
14488 }
14489 } else {
14490 /* Extension. */
14491 for (i = 0; i < baseUses->nbItems; i++) {
14492 use = baseUses->items[i];
14493 if (uses == NULL) {
14494 type->attrUses = xmlSchemaItemListCreate();
14495 if (type->attrUses == NULL)
14496 goto exit_failure;
14497 uses = type->attrUses;
14498 }
14499 xmlSchemaItemListAddSize(uses, baseUses->nbItems, use);
14500 }
14501 }
14502 }
14503 /*
14504 * Shrink attr. uses.
14505 */
14506 if (uses) {
14507 if (uses->nbItems == 0) {
14508 xmlSchemaItemListFree(uses);
14509 type->attrUses = NULL;
14510 }
14511 /*
14512 * TODO: We could shrink the size of the array
14513 * to fit the actual number of items.
14514 */
14515 }
14516 /*
14517 * Compute the complete wildcard.
14518 */
14519 if (WXS_IS_EXTENSION(type)) {
14520 if (baseType->attributeWildcard != NULL) {
14521 /*
14522 * (3.2.2.1) "If the `base wildcard` is non-`absent`, then
14523 * the appropriate case among the following:"
14524 */
14525 if (type->attributeWildcard != NULL) {
14526 /*
14527 * Union the complete wildcard with the base wildcard.
14528 * SPEC {attribute wildcard}
14529 * (3.2.2.1.2) "otherwise a wildcard whose {process contents}
14530 * and {annotation} are those of the `complete wildcard`,
14531 * and whose {namespace constraint} is the intensional union
14532 * of the {namespace constraint} of the `complete wildcard`
14533 * and of the `base wildcard`, as defined in Attribute
14534 * Wildcard Union ($3.10.6)."
14535 */
14536 if (xmlSchemaUnionWildcards(pctxt, type->attributeWildcard,
14537 baseType->attributeWildcard) == -1)
14538 goto exit_failure;
14539 } else {
14540 /*
14541 * (3.2.2.1.1) "If the `complete wildcard` is `absent`,
14542 * then the `base wildcard`."
14543 */
14544 type->attributeWildcard = baseType->attributeWildcard;
14545 }
14546 } else {
14547 /*
14548 * (3.2.2.2) "otherwise (the `base wildcard` is `absent`) the
14549 * `complete wildcard`"
14550 * NOOP
14551 */
14552 }
14553 } else {
14554 /*
14555 * SPEC {attribute wildcard}
14556 * (3.1) "If the <restriction> alternative is chosen, then the
14557 * `complete wildcard`;"
14558 * NOOP
14559 */
14560 }
14561
14562 return (0);
14563
14564exit_failure:
14565 return(-1);
14566}
14567
14580static int
14581xmlSchemaTypeFinalContains(xmlSchemaTypePtr type, int final)
14582{
14583 if (type == NULL)
14584 return (0);
14585 if (type->flags & final)
14586 return (1);
14587 else
14588 return (0);
14589}
14590
14598static xmlSchemaTypeLinkPtr
14599xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type)
14600{
14601 while ((type != NULL) && (type->type == XML_SCHEMA_TYPE_SIMPLE)) {
14602 if (type->memberTypes != NULL)
14603 return (type->memberTypes);
14604 else
14605 type = type->baseType;
14606 }
14607 return (NULL);
14608}
14609
14610#if 0
14620static int
14621xmlSchemaGetParticleTotalRangeMin(xmlSchemaParticlePtr particle)
14622{
14623 if ((particle->children == NULL) ||
14624 (particle->minOccurs == 0))
14625 return (0);
14626 if (particle->children->type == XML_SCHEMA_TYPE_CHOICE) {
14627 int min = -1, cur;
14628 xmlSchemaParticlePtr part =
14629 (xmlSchemaParticlePtr) particle->children->children;
14630
14631 if (part == NULL)
14632 return (0);
14633 while (part != NULL) {
14634 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14635 (part->children->type == XML_SCHEMA_TYPE_ANY))
14636 cur = part->minOccurs;
14637 else
14638 cur = xmlSchemaGetParticleTotalRangeMin(part);
14639 if (cur == 0)
14640 return (0);
14641 if ((min > cur) || (min == -1))
14642 min = cur;
14643 part = (xmlSchemaParticlePtr) part->next;
14644 }
14645 return (particle->minOccurs * min);
14646 } else {
14647 /* <all> and <sequence> */
14648 int sum = 0;
14649 xmlSchemaParticlePtr part =
14650 (xmlSchemaParticlePtr) particle->children->children;
14651
14652 if (part == NULL)
14653 return (0);
14654 do {
14655 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14656 (part->children->type == XML_SCHEMA_TYPE_ANY))
14657 sum += part->minOccurs;
14658 else
14659 sum += xmlSchemaGetParticleTotalRangeMin(part);
14660 part = (xmlSchemaParticlePtr) part->next;
14661 } while (part != NULL);
14662 return (particle->minOccurs * sum);
14663 }
14664}
14665
14675static int
14676xmlSchemaGetParticleTotalRangeMax(xmlSchemaParticlePtr particle)
14677{
14678 if ((particle->children == NULL) ||
14679 (particle->children->children == NULL))
14680 return (0);
14681 if (particle->children->type == XML_SCHEMA_TYPE_CHOICE) {
14682 int max = -1, cur;
14683 xmlSchemaParticlePtr part =
14684 (xmlSchemaParticlePtr) particle->children->children;
14685
14686 for (; part != NULL; part = (xmlSchemaParticlePtr) part->next) {
14687 if (part->children == NULL)
14688 continue;
14689 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14690 (part->children->type == XML_SCHEMA_TYPE_ANY))
14691 cur = part->maxOccurs;
14692 else
14693 cur = xmlSchemaGetParticleTotalRangeMax(part);
14694 if (cur == UNBOUNDED)
14695 return (UNBOUNDED);
14696 if ((max < cur) || (max == -1))
14697 max = cur;
14698 }
14699 /* TODO: Handle overflows? */
14700 return (particle->maxOccurs * max);
14701 } else {
14702 /* <all> and <sequence> */
14703 int sum = 0, cur;
14704 xmlSchemaParticlePtr part =
14705 (xmlSchemaParticlePtr) particle->children->children;
14706
14707 for (; part != NULL; part = (xmlSchemaParticlePtr) part->next) {
14708 if (part->children == NULL)
14709 continue;
14710 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14711 (part->children->type == XML_SCHEMA_TYPE_ANY))
14712 cur = part->maxOccurs;
14713 else
14714 cur = xmlSchemaGetParticleTotalRangeMax(part);
14715 if (cur == UNBOUNDED)
14716 return (UNBOUNDED);
14717 if ((cur > 0) && (particle->maxOccurs == UNBOUNDED))
14718 return (UNBOUNDED);
14719 sum += cur;
14720 }
14721 /* TODO: Handle overflows? */
14722 return (particle->maxOccurs * sum);
14723 }
14724}
14725#endif
14726
14733static int
14734xmlSchemaGetParticleEmptiable(xmlSchemaParticlePtr particle)
14735{
14736 xmlSchemaParticlePtr part;
14737 int emptiable;
14738
14739 if ((particle->children == NULL) || (particle->minOccurs == 0))
14740 return (1);
14741
14742 part = (xmlSchemaParticlePtr) particle->children->children;
14743 if (part == NULL)
14744 return (1);
14745
14746 while (part != NULL) {
14747 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14748 (part->children->type == XML_SCHEMA_TYPE_ANY))
14749 emptiable = (part->minOccurs == 0);
14750 else
14751 emptiable = xmlSchemaGetParticleEmptiable(part);
14752 if (particle->children->type == XML_SCHEMA_TYPE_CHOICE) {
14753 if (emptiable)
14754 return (1);
14755 } else {
14756 /* <all> and <sequence> */
14757 if (!emptiable)
14758 return (0);
14759 }
14760 part = (xmlSchemaParticlePtr) part->next;
14761 }
14762
14763 if (particle->children->type == XML_SCHEMA_TYPE_CHOICE)
14764 return (0);
14765 else
14766 return (1);
14767}
14768
14778static int
14779xmlSchemaIsParticleEmptiable(xmlSchemaParticlePtr particle)
14780{
14781 /*
14782 * SPEC (1) "Its {min occurs} is 0."
14783 */
14784 if ((particle == NULL) || (particle->minOccurs == 0) ||
14785 (particle->children == NULL))
14786 return (1);
14787 /*
14788 * SPEC (2) "Its {term} is a group and the minimum part of the
14789 * effective total range of that group, [...] is 0."
14790 */
14791 if (WXS_IS_MODEL_GROUP(particle->children))
14792 return (xmlSchemaGetParticleEmptiable(particle));
14793 return (0);
14794}
14795
14811static int
14812xmlSchemaCheckCOSSTDerivedOK(xmlSchemaAbstractCtxtPtr actxt,
14813 xmlSchemaTypePtr type,
14814 xmlSchemaTypePtr baseType,
14815 int subset)
14816{
14817 /*
14818 * 1 They are the same type definition.
14819 * TODO: The identity check might have to be more complex than this.
14820 */
14821 if (type == baseType)
14822 return (0);
14823 /*
14824 * 2.1 restriction is not in the subset, or in the {final}
14825 * of its own {base type definition};
14826 *
14827 * NOTE that this will be used also via "xsi:type".
14828 *
14829 * TODO: Revise this, it looks strange. How can the "type"
14830 * not be fixed or *in* fixing?
14831 */
14832 if (WXS_IS_TYPE_NOT_FIXED(type))
14833 if (xmlSchemaTypeFixup(type, actxt) == -1)
14834 return(-1);
14835 if (WXS_IS_TYPE_NOT_FIXED(baseType))
14836 if (xmlSchemaTypeFixup(baseType, actxt) == -1)
14837 return(-1);
14838 if ((subset & SUBSET_RESTRICTION) ||
14839 (xmlSchemaTypeFinalContains(type->baseType,
14840 XML_SCHEMAS_TYPE_FINAL_RESTRICTION))) {
14842 }
14843 /* 2.2 */
14844 if (type->baseType == baseType) {
14845 /*
14846 * 2.2.1 D's `base type definition` is B.
14847 */
14848 return (0);
14849 }
14850 /*
14851 * 2.2.2 D's `base type definition` is not the `ur-type definition`
14852 * and is validly derived from B given the subset, as defined by this
14853 * constraint.
14854 */
14855 if ((! WXS_IS_ANYTYPE(type->baseType)) &&
14856 (xmlSchemaCheckCOSSTDerivedOK(actxt, type->baseType,
14857 baseType, subset) == 0)) {
14858 return (0);
14859 }
14860 /*
14861 * 2.2.3 D's {variety} is list or union and B is the `simple ur-type
14862 * definition`.
14863 */
14864 if (WXS_IS_ANY_SIMPLE_TYPE(baseType) &&
14865 (WXS_IS_LIST(type) || WXS_IS_UNION(type))) {
14866 return (0);
14867 }
14868 /*
14869 * 2.2.4 B's {variety} is union and D is validly derived from a type
14870 * definition in B's {member type definitions} given the subset, as
14871 * defined by this constraint.
14872 *
14873 * NOTE: This seems not to involve built-in types, since there is no
14874 * built-in Union Simple Type.
14875 */
14876 if (WXS_IS_UNION(baseType)) {
14877 xmlSchemaTypeLinkPtr cur;
14878
14879 cur = baseType->memberTypes;
14880 while (cur != NULL) {
14881 if (WXS_IS_TYPE_NOT_FIXED(cur->type))
14882 if (xmlSchemaTypeFixup(cur->type, actxt) == -1)
14883 return(-1);
14884 if (xmlSchemaCheckCOSSTDerivedOK(actxt,
14885 type, cur->type, subset) == 0)
14886 {
14887 /*
14888 * It just has to be validly derived from at least one
14889 * member-type.
14890 */
14891 return (0);
14892 }
14893 cur = cur->next;
14894 }
14895 }
14897}
14898
14911static int
14912xmlSchemaCheckTypeDefCircularInternal(xmlSchemaParserCtxtPtr pctxt,
14913 xmlSchemaTypePtr ctxtType,
14914 xmlSchemaTypePtr ancestor)
14915{
14916 int ret;
14917
14918 if ((ancestor == NULL) || (ancestor->type == XML_SCHEMA_TYPE_BASIC))
14919 return (0);
14920
14921 if (ctxtType == ancestor) {
14922 xmlSchemaPCustomErr(pctxt,
14924 WXS_BASIC_CAST ctxtType, WXS_ITEM_NODE(ctxtType),
14925 "The definition is circular", NULL);
14927 }
14928 if (ancestor->flags & XML_SCHEMAS_TYPE_MARKED) {
14929 /*
14930 * Avoid infinite recursion on circular types not yet checked.
14931 */
14932 return (0);
14933 }
14934 ancestor->flags |= XML_SCHEMAS_TYPE_MARKED;
14935 ret = xmlSchemaCheckTypeDefCircularInternal(pctxt, ctxtType,
14936 ancestor->baseType);
14937 ancestor->flags ^= XML_SCHEMAS_TYPE_MARKED;
14938 return (ret);
14939}
14940
14949static void
14950xmlSchemaCheckTypeDefCircular(xmlSchemaTypePtr item,
14951 xmlSchemaParserCtxtPtr ctxt)
14952{
14953 if ((item == NULL) ||
14954 (item->type == XML_SCHEMA_TYPE_BASIC) ||
14955 (item->baseType == NULL))
14956 return;
14957 xmlSchemaCheckTypeDefCircularInternal(ctxt, item,
14958 item->baseType);
14959}
14960
14961/*
14962* Simple Type Definition Representation OK (src-simple-type) 4
14963*
14964* "4 Circular union type definition is disallowed. That is, if the
14965* <union> alternative is chosen, there must not be any entries in the
14966* memberTypes [attribute] at any depth which resolve to the component
14967* corresponding to the <simpleType>."
14968*
14969* Note that this should work on the *representation* of a component,
14970* thus assumes any union types in the member types not being yet
14971* substituted. At this stage we need the variety of the types
14972* to be already computed.
14973*/
14974static int
14975xmlSchemaCheckUnionTypeDefCircularRecur(xmlSchemaParserCtxtPtr pctxt,
14976 xmlSchemaTypePtr ctxType,
14977 xmlSchemaTypeLinkPtr members)
14978{
14979 xmlSchemaTypeLinkPtr member;
14980 xmlSchemaTypePtr memberType;
14981
14982 member = members;
14983 while (member != NULL) {
14984 memberType = member->type;
14985 while ((memberType != NULL) &&
14986 (memberType->type != XML_SCHEMA_TYPE_BASIC)) {
14987 if (memberType == ctxType) {
14988 xmlSchemaPCustomErr(pctxt,
14990 WXS_BASIC_CAST ctxType, NULL,
14991 "The union type definition is circular", NULL);
14993 }
14994 if ((WXS_IS_UNION(memberType)) &&
14995 ((memberType->flags & XML_SCHEMAS_TYPE_MARKED) == 0))
14996 {
14997 int res;
14998 memberType->flags |= XML_SCHEMAS_TYPE_MARKED;
14999 res = xmlSchemaCheckUnionTypeDefCircularRecur(pctxt,
15000 ctxType,
15001 xmlSchemaGetUnionSimpleTypeMemberTypes(memberType));
15002 memberType->flags ^= XML_SCHEMAS_TYPE_MARKED;
15003 if (res != 0)
15004 return(res);
15005 }
15006 memberType = memberType->baseType;
15007 }
15008 member = member->next;
15009 }
15010 return(0);
15011}
15012
15013static int
15014xmlSchemaCheckUnionTypeDefCircular(xmlSchemaParserCtxtPtr pctxt,
15015 xmlSchemaTypePtr type)
15016{
15017 if (! WXS_IS_UNION(type))
15018 return(0);
15019 return(xmlSchemaCheckUnionTypeDefCircularRecur(pctxt, type,
15020 type->memberTypes));
15021}
15022
15031static void
15032xmlSchemaResolveTypeReferences(xmlSchemaTypePtr typeDef,
15033 xmlSchemaParserCtxtPtr ctxt)
15034{
15035 if (typeDef == NULL)
15036 return;
15037
15038 /*
15039 * Resolve the base type.
15040 */
15041 if (typeDef->baseType == NULL) {
15042 typeDef->baseType = xmlSchemaGetType(ctxt->schema,
15043 typeDef->base, typeDef->baseNs);
15044 if (typeDef->baseType == NULL) {
15045 xmlSchemaPResCompAttrErr(ctxt,
15047 WXS_BASIC_CAST typeDef, typeDef->node,
15048 "base", typeDef->base, typeDef->baseNs,
15049 XML_SCHEMA_TYPE_SIMPLE, NULL);
15050 return;
15051 }
15052 }
15053 if (WXS_IS_SIMPLE(typeDef)) {
15054 if (WXS_IS_UNION(typeDef)) {
15055 /*
15056 * Resolve the memberTypes.
15057 */
15058 xmlSchemaResolveUnionMemberTypes(ctxt, typeDef);
15059 return;
15060 } else if (WXS_IS_LIST(typeDef)) {
15061 /*
15062 * Resolve the itemType.
15063 */
15064 if ((typeDef->subtypes == NULL) && (typeDef->base != NULL)) {
15065
15066 typeDef->subtypes = xmlSchemaGetType(ctxt->schema,
15067 typeDef->base, typeDef->baseNs);
15068
15069 if ((typeDef->subtypes == NULL) ||
15070 (! WXS_IS_SIMPLE(typeDef->subtypes)))
15071 {
15072 typeDef->subtypes = NULL;
15073 xmlSchemaPResCompAttrErr(ctxt,
15075 WXS_BASIC_CAST typeDef, typeDef->node,
15076 "itemType", typeDef->base, typeDef->baseNs,
15077 XML_SCHEMA_TYPE_SIMPLE, NULL);
15078 }
15079 }
15080 return;
15081 }
15082 }
15083 /*
15084 * The ball of letters below means, that if we have a particle
15085 * which has a QName-helper component as its {term}, we want
15086 * to resolve it...
15087 */
15088 else if ((WXS_TYPE_CONTENTTYPE(typeDef) != NULL) &&
15089 ((WXS_TYPE_CONTENTTYPE(typeDef))->type ==
15090 XML_SCHEMA_TYPE_PARTICLE) &&
15091 (WXS_TYPE_PARTICLE_TERM(typeDef) != NULL) &&
15092 ((WXS_TYPE_PARTICLE_TERM(typeDef))->type ==
15093 XML_SCHEMA_EXTRA_QNAMEREF))
15094 {
15095 xmlSchemaQNameRefPtr ref =
15096 WXS_QNAME_CAST WXS_TYPE_PARTICLE_TERM(typeDef);
15097 xmlSchemaModelGroupDefPtr groupDef;
15098
15099 /*
15100 * URGENT TODO: Test this.
15101 */
15102 WXS_TYPE_PARTICLE_TERM(typeDef) = NULL;
15103 /*
15104 * Resolve the MG definition reference.
15105 */
15106 groupDef =
15107 WXS_MODEL_GROUPDEF_CAST xmlSchemaGetNamedComponent(ctxt->schema,
15108 ref->itemType, ref->name, ref->targetNamespace);
15109 if (groupDef == NULL) {
15110 xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
15111 NULL, WXS_ITEM_NODE(WXS_TYPE_PARTICLE(typeDef)),
15112 "ref", ref->name, ref->targetNamespace, ref->itemType,
15113 NULL);
15114 /* Remove the particle. */
15115 WXS_TYPE_CONTENTTYPE(typeDef) = NULL;
15116 } else if (WXS_MODELGROUPDEF_MODEL(groupDef) == NULL)
15117 /* Remove the particle. */
15118 WXS_TYPE_CONTENTTYPE(typeDef) = NULL;
15119 else {
15120 /*
15121 * Assign the MG definition's {model group} to the
15122 * particle's {term}.
15123 */
15124 WXS_TYPE_PARTICLE_TERM(typeDef) = WXS_MODELGROUPDEF_MODEL(groupDef);
15125
15126 if (WXS_MODELGROUPDEF_MODEL(groupDef)->type == XML_SCHEMA_TYPE_ALL) {
15127 /*
15128 * SPEC cos-all-limited (1.2)
15129 * "1.2 the {term} property of a particle with
15130 * {max occurs}=1 which is part of a pair which constitutes
15131 * the {content type} of a complex type definition."
15132 */
15133 if ((WXS_TYPE_PARTICLE(typeDef))->maxOccurs != 1) {
15134 xmlSchemaCustomErr(ACTXT_CAST ctxt,
15135 /* TODO: error code */
15137 WXS_ITEM_NODE(WXS_TYPE_PARTICLE(typeDef)), NULL,
15138 "The particle's {max occurs} must be 1, since the "
15139 "reference resolves to an 'all' model group",
15140 NULL, NULL);
15141 }
15142 }
15143 }
15144 }
15145}
15146
15147
15148
15160static int
15161xmlSchemaCheckSTPropsCorrect(xmlSchemaParserCtxtPtr ctxt,
15162 xmlSchemaTypePtr type)
15163{
15164 xmlSchemaTypePtr baseType = type->baseType;
15165 xmlChar *str = NULL;
15166
15167 /* STATE: error funcs converted. */
15168 /*
15169 * Schema Component Constraint: Simple Type Definition Properties Correct
15170 *
15171 * NOTE: This is somehow redundant, since we actually built a simple type
15172 * to have all the needed information; this acts as an self test.
15173 */
15174 /* Base type: If the datatype has been `derived` by `restriction`
15175 * then the Simple Type Definition component from which it is `derived`,
15176 * otherwise the Simple Type Definition for anySimpleType ($4.1.6).
15177 */
15178 if (baseType == NULL) {
15179 /*
15180 * TODO: Think about: "modulo the impact of Missing
15181 * Sub-components ($5.3)."
15182 */
15183 xmlSchemaPCustomErr(ctxt,
15185 WXS_BASIC_CAST type, NULL,
15186 "No base type existent", NULL);
15188
15189 }
15190 if (! WXS_IS_SIMPLE(baseType)) {
15191 xmlSchemaPCustomErr(ctxt,
15193 WXS_BASIC_CAST type, NULL,
15194 "The base type '%s' is not a simple type",
15195 xmlSchemaGetComponentQName(&str, baseType));
15196 FREE_AND_NULL(str)
15198 }
15199 if ((WXS_IS_LIST(type) || WXS_IS_UNION(type)) &&
15200 (WXS_IS_RESTRICTION(type) == 0) &&
15201 ((! WXS_IS_ANY_SIMPLE_TYPE(baseType)) &&
15202 (baseType->type != XML_SCHEMA_TYPE_SIMPLE))) {
15203 xmlSchemaPCustomErr(ctxt,
15205 WXS_BASIC_CAST type, NULL,
15206 "A type, derived by list or union, must have "
15207 "the simple ur-type definition as base type, not '%s'",
15208 xmlSchemaGetComponentQName(&str, baseType));
15209 FREE_AND_NULL(str)
15211 }
15212 /*
15213 * Variety: One of {atomic, list, union}.
15214 */
15215 if ((! WXS_IS_ATOMIC(type)) && (! WXS_IS_UNION(type)) &&
15216 (! WXS_IS_LIST(type))) {
15217 xmlSchemaPCustomErr(ctxt,
15219 WXS_BASIC_CAST type, NULL,
15220 "The variety is absent", NULL);
15222 }
15223 /* TODO: Finish this. Hmm, is this finished? */
15224
15225 /*
15226 * 3 The {final} of the {base type definition} must not contain restriction.
15227 */
15228 if (xmlSchemaTypeFinalContains(baseType,
15229 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
15230 xmlSchemaPCustomErr(ctxt,
15232 WXS_BASIC_CAST type, NULL,
15233 "The 'final' of its base type '%s' must not contain "
15234 "'restriction'",
15235 xmlSchemaGetComponentQName(&str, baseType));
15236 FREE_AND_NULL(str)
15238 }
15239
15240 /*
15241 * 2 All simple type definitions must be derived ultimately from the `simple
15242 * ur-type definition` (so circular definitions are disallowed). That is, it
15243 * must be possible to reach a built-in primitive datatype or the `simple
15244 * ur-type definition` by repeatedly following the {base type definition}.
15245 *
15246 * NOTE: this is done in xmlSchemaCheckTypeDefCircular().
15247 */
15248 return (0);
15249}
15250
15265static int
15266xmlSchemaCheckCOSSTRestricts(xmlSchemaParserCtxtPtr pctxt,
15267 xmlSchemaTypePtr type)
15268{
15269 xmlChar *str = NULL;
15270
15271 if (type->type != XML_SCHEMA_TYPE_SIMPLE) {
15272 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15273 "given type is not a user-derived simpleType");
15274 return (-1);
15275 }
15276
15277 if (WXS_IS_ATOMIC(type)) {
15278 xmlSchemaTypePtr primitive;
15279 /*
15280 * 1.1 The {base type definition} must be an atomic simple
15281 * type definition or a built-in primitive datatype.
15282 */
15283 if (! WXS_IS_ATOMIC(type->baseType)) {
15284 xmlSchemaPCustomErr(pctxt,
15286 WXS_BASIC_CAST type, NULL,
15287 "The base type '%s' is not an atomic simple type",
15288 xmlSchemaGetComponentQName(&str, type->baseType));
15289 FREE_AND_NULL(str)
15291 }
15292 /* 1.2 The {final} of the {base type definition} must not contain
15293 * restriction.
15294 */
15295 /* OPTIMIZE TODO : This is already done in xmlSchemaCheckStPropsCorrect */
15296 if (xmlSchemaTypeFinalContains(type->baseType,
15297 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
15298 xmlSchemaPCustomErr(pctxt,
15300 WXS_BASIC_CAST type, NULL,
15301 "The final of its base type '%s' must not contain 'restriction'",
15302 xmlSchemaGetComponentQName(&str, type->baseType));
15303 FREE_AND_NULL(str)
15305 }
15306
15307 /*
15308 * 1.3.1 DF must be an allowed constraining facet for the {primitive
15309 * type definition}, as specified in the appropriate subsection of 3.2
15310 * Primitive datatypes.
15311 */
15312 if (type->facets != NULL) {
15313 xmlSchemaFacetPtr facet;
15314 int ok = 1;
15315
15316 primitive = xmlSchemaGetPrimitiveType(type);
15317 if (primitive == NULL) {
15318 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15319 "failed to get primitive type");
15320 return (-1);
15321 }
15322 facet = type->facets;
15323 do {
15324 if (xmlSchemaIsBuiltInTypeFacet(primitive, facet->type) == 0) {
15325 ok = 0;
15326 xmlSchemaPIllegalFacetAtomicErr(pctxt,
15328 type, primitive, facet);
15329 }
15330 facet = facet->next;
15331 } while (facet != NULL);
15332 if (ok == 0)
15334 }
15335 /*
15336 * SPEC (1.3.2) "If there is a facet of the same kind in the {facets}
15337 * of the {base type definition} (call this BF),then the DF's {value}
15338 * must be a valid restriction of BF's {value} as defined in
15339 * [XML Schemas: Datatypes]."
15340 *
15341 * NOTE (1.3.2) Facet derivation constraints are currently handled in
15342 * xmlSchemaDeriveAndValidateFacets()
15343 */
15344 } else if (WXS_IS_LIST(type)) {
15345 xmlSchemaTypePtr itemType = NULL;
15346
15347 itemType = type->subtypes;
15348 if ((itemType == NULL) || (! WXS_IS_SIMPLE(itemType))) {
15349 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15350 "failed to evaluate the item type");
15351 return (-1);
15352 }
15353 if (WXS_IS_TYPE_NOT_FIXED(itemType))
15354 xmlSchemaTypeFixup(itemType, ACTXT_CAST pctxt);
15355 /*
15356 * 2.1 The {item type definition} must have a {variety} of atomic or
15357 * union (in which case all the {member type definitions}
15358 * must be atomic).
15359 */
15360 if ((! WXS_IS_ATOMIC(itemType)) &&
15361 (! WXS_IS_UNION(itemType))) {
15362 xmlSchemaPCustomErr(pctxt,
15364 WXS_BASIC_CAST type, NULL,
15365 "The item type '%s' does not have a variety of atomic or union",
15366 xmlSchemaGetComponentQName(&str, itemType));
15367 FREE_AND_NULL(str)
15369 } else if (WXS_IS_UNION(itemType)) {
15370 xmlSchemaTypeLinkPtr member;
15371
15372 member = itemType->memberTypes;
15373 while (member != NULL) {
15374 if (! WXS_IS_ATOMIC(member->type)) {
15375 xmlSchemaPCustomErr(pctxt,
15377 WXS_BASIC_CAST type, NULL,
15378 "The item type is a union type, but the "
15379 "member type '%s' of this item type is not atomic",
15380 xmlSchemaGetComponentQName(&str, member->type));
15381 FREE_AND_NULL(str)
15383 }
15384 member = member->next;
15385 }
15386 }
15387
15388 if (WXS_IS_ANY_SIMPLE_TYPE(type->baseType)) {
15389 xmlSchemaFacetPtr facet;
15390 /*
15391 * This is the case if we have: <simpleType><list ..
15392 */
15393 /*
15394 * 2.3.1
15395 * 2.3.1.1 The {final} of the {item type definition} must not
15396 * contain list.
15397 */
15398 if (xmlSchemaTypeFinalContains(itemType,
15399 XML_SCHEMAS_TYPE_FINAL_LIST)) {
15400 xmlSchemaPCustomErr(pctxt,
15402 WXS_BASIC_CAST type, NULL,
15403 "The final of its item type '%s' must not contain 'list'",
15404 xmlSchemaGetComponentQName(&str, itemType));
15405 FREE_AND_NULL(str)
15407 }
15408 /*
15409 * 2.3.1.2 The {facets} must only contain the whiteSpace
15410 * facet component.
15411 * OPTIMIZE TODO: the S4S already disallows any facet
15412 * to be specified.
15413 */
15414 if (type->facets != NULL) {
15415 facet = type->facets;
15416 do {
15417 if (facet->type != XML_SCHEMA_FACET_WHITESPACE) {
15418 xmlSchemaPIllegalFacetListUnionErr(pctxt,
15420 type, facet);
15422 }
15423 facet = facet->next;
15424 } while (facet != NULL);
15425 }
15426 /*
15427 * MAYBE TODO: (Hmm, not really) Datatypes states:
15428 * A `list` datatype can be `derived` from an `atomic` datatype
15429 * whose `lexical space` allows space (such as string or anyURI)or
15430 * a `union` datatype any of whose {member type definitions}'s
15431 * `lexical space` allows space.
15432 */
15433 } else {
15434 /*
15435 * This is the case if we have: <simpleType><restriction ...
15436 * I.e. the variety of "list" is inherited.
15437 */
15438 /*
15439 * 2.3.2
15440 * 2.3.2.1 The {base type definition} must have a {variety} of list.
15441 */
15442 if (! WXS_IS_LIST(type->baseType)) {
15443 xmlSchemaPCustomErr(pctxt,
15445 WXS_BASIC_CAST type, NULL,
15446 "The base type '%s' must be a list type",
15447 xmlSchemaGetComponentQName(&str, type->baseType));
15448 FREE_AND_NULL(str)
15450 }
15451 /*
15452 * 2.3.2.2 The {final} of the {base type definition} must not
15453 * contain restriction.
15454 */
15455 if (xmlSchemaTypeFinalContains(type->baseType,
15456 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
15457 xmlSchemaPCustomErr(pctxt,
15459 WXS_BASIC_CAST type, NULL,
15460 "The 'final' of the base type '%s' must not contain 'restriction'",
15461 xmlSchemaGetComponentQName(&str, type->baseType));
15462 FREE_AND_NULL(str)
15464 }
15465 /*
15466 * 2.3.2.3 The {item type definition} must be validly derived
15467 * from the {base type definition}'s {item type definition} given
15468 * the empty set, as defined in Type Derivation OK (Simple) ($3.14.6).
15469 */
15470 {
15471 xmlSchemaTypePtr baseItemType;
15472
15473 baseItemType = type->baseType->subtypes;
15474 if ((baseItemType == NULL) || (! WXS_IS_SIMPLE(baseItemType))) {
15475 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15476 "failed to eval the item type of a base type");
15477 return (-1);
15478 }
15479 if ((itemType != baseItemType) &&
15480 (xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST pctxt, itemType,
15481 baseItemType, 0) != 0)) {
15482 xmlChar *strBIT = NULL, *strBT = NULL;
15483 xmlSchemaPCustomErrExt(pctxt,
15485 WXS_BASIC_CAST type, NULL,
15486 "The item type '%s' is not validly derived from "
15487 "the item type '%s' of the base type '%s'",
15488 xmlSchemaGetComponentQName(&str, itemType),
15489 xmlSchemaGetComponentQName(&strBIT, baseItemType),
15490 xmlSchemaGetComponentQName(&strBT, type->baseType));
15491
15492 FREE_AND_NULL(str)
15493 FREE_AND_NULL(strBIT)
15494 FREE_AND_NULL(strBT)
15496 }
15497 }
15498
15499 if (type->facets != NULL) {
15500 xmlSchemaFacetPtr facet;
15501 int ok = 1;
15502 /*
15503 * 2.3.2.4 Only length, minLength, maxLength, whiteSpace, pattern
15504 * and enumeration facet components are allowed among the {facets}.
15505 */
15506 facet = type->facets;
15507 do {
15508 switch (facet->type) {
15509 case XML_SCHEMA_FACET_LENGTH:
15510 case XML_SCHEMA_FACET_MINLENGTH:
15511 case XML_SCHEMA_FACET_MAXLENGTH:
15512 case XML_SCHEMA_FACET_WHITESPACE:
15513 /*
15514 * TODO: 2.5.1.2 List datatypes
15515 * The value of `whiteSpace` is fixed to the value collapse.
15516 */
15517 case XML_SCHEMA_FACET_PATTERN:
15518 case XML_SCHEMA_FACET_ENUMERATION:
15519 break;
15520 default: {
15521 xmlSchemaPIllegalFacetListUnionErr(pctxt,
15523 type, facet);
15524 /*
15525 * We could return, but it's nicer to report all
15526 * invalid facets.
15527 */
15528 ok = 0;
15529 }
15530 }
15531 facet = facet->next;
15532 } while (facet != NULL);
15533 if (ok == 0)
15535 /*
15536 * SPEC (2.3.2.5) (same as 1.3.2)
15537 *
15538 * NOTE (2.3.2.5) This is currently done in
15539 * xmlSchemaDeriveAndValidateFacets()
15540 */
15541 }
15542 }
15543 } else if (WXS_IS_UNION(type)) {
15544 /*
15545 * 3.1 The {member type definitions} must all have {variety} of
15546 * atomic or list.
15547 */
15548 xmlSchemaTypeLinkPtr member;
15549
15550 member = type->memberTypes;
15551 while (member != NULL) {
15552 if (WXS_IS_TYPE_NOT_FIXED(member->type))
15553 xmlSchemaTypeFixup(member->type, ACTXT_CAST pctxt);
15554
15555 if ((! WXS_IS_ATOMIC(member->type)) &&
15556 (! WXS_IS_LIST(member->type))) {
15557 xmlSchemaPCustomErr(pctxt,
15559 WXS_BASIC_CAST type, NULL,
15560 "The member type '%s' is neither an atomic, nor a list type",
15561 xmlSchemaGetComponentQName(&str, member->type));
15562 FREE_AND_NULL(str)
15564 }
15565 member = member->next;
15566 }
15567 /*
15568 * 3.3.1 If the {base type definition} is the `simple ur-type
15569 * definition`
15570 */
15571 if (type->baseType->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) {
15572 /*
15573 * 3.3.1.1 All of the {member type definitions} must have a
15574 * {final} which does not contain union.
15575 */
15576 member = type->memberTypes;
15577 while (member != NULL) {
15578 if (xmlSchemaTypeFinalContains(member->type,
15579 XML_SCHEMAS_TYPE_FINAL_UNION)) {
15580 xmlSchemaPCustomErr(pctxt,
15582 WXS_BASIC_CAST type, NULL,
15583 "The 'final' of member type '%s' contains 'union'",
15584 xmlSchemaGetComponentQName(&str, member->type));
15585 FREE_AND_NULL(str)
15587 }
15588 member = member->next;
15589 }
15590 /*
15591 * 3.3.1.2 The {facets} must be empty.
15592 */
15593 if (type->facetSet != NULL) {
15594 xmlSchemaPCustomErr(pctxt,
15596 WXS_BASIC_CAST type, NULL,
15597 "No facets allowed", NULL);
15599 }
15600 } else {
15601 /*
15602 * 3.3.2.1 The {base type definition} must have a {variety} of union.
15603 * I.e. the variety of "list" is inherited.
15604 */
15605 if (! WXS_IS_UNION(type->baseType)) {
15606 xmlSchemaPCustomErr(pctxt,
15608 WXS_BASIC_CAST type, NULL,
15609 "The base type '%s' is not a union type",
15610 xmlSchemaGetComponentQName(&str, type->baseType));
15611 FREE_AND_NULL(str)
15613 }
15614 /*
15615 * 3.3.2.2 The {final} of the {base type definition} must not contain restriction.
15616 */
15617 if (xmlSchemaTypeFinalContains(type->baseType,
15618 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
15619 xmlSchemaPCustomErr(pctxt,
15621 WXS_BASIC_CAST type, NULL,
15622 "The 'final' of its base type '%s' must not contain 'restriction'",
15623 xmlSchemaGetComponentQName(&str, type->baseType));
15624 FREE_AND_NULL(str)
15626 }
15627 /*
15628 * 3.3.2.3 The {member type definitions}, in order, must be validly
15629 * derived from the corresponding type definitions in the {base
15630 * type definition}'s {member type definitions} given the empty set,
15631 * as defined in Type Derivation OK (Simple) ($3.14.6).
15632 */
15633 {
15634 xmlSchemaTypeLinkPtr baseMember;
15635
15636 /*
15637 * OPTIMIZE: if the type is restricting, it has no local defined
15638 * member types and inherits the member types of the base type;
15639 * thus a check for equality can be skipped.
15640 */
15641 /*
15642 * Even worse: I cannot see a scenario where a restricting
15643 * union simple type can have other member types as the member
15644 * types of it's base type. This check seems not necessary with
15645 * respect to the derivation process in libxml2.
15646 * But necessary if constructing types with an API.
15647 */
15648 if (type->memberTypes != NULL) {
15649 member = type->memberTypes;
15650 baseMember = xmlSchemaGetUnionSimpleTypeMemberTypes(type->baseType);
15651 if ((member == NULL) && (baseMember != NULL)) {
15652 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15653 "different number of member types in base");
15654 }
15655 while (member != NULL) {
15656 if (baseMember == NULL) {
15657 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15658 "different number of member types in base");
15659 } else if ((member->type != baseMember->type) &&
15660 (xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST pctxt,
15661 member->type, baseMember->type, 0) != 0)) {
15662 xmlChar *strBMT = NULL, *strBT = NULL;
15663
15664 xmlSchemaPCustomErrExt(pctxt,
15666 WXS_BASIC_CAST type, NULL,
15667 "The member type %s is not validly "
15668 "derived from its corresponding member "
15669 "type %s of the base type %s",
15670 xmlSchemaGetComponentQName(&str, member->type),
15671 xmlSchemaGetComponentQName(&strBMT, baseMember->type),
15672 xmlSchemaGetComponentQName(&strBT, type->baseType));
15673 FREE_AND_NULL(str)
15674 FREE_AND_NULL(strBMT)
15675 FREE_AND_NULL(strBT)
15677 }
15678 member = member->next;
15679 if (baseMember != NULL)
15680 baseMember = baseMember->next;
15681 }
15682 }
15683 }
15684 /*
15685 * 3.3.2.4 Only pattern and enumeration facet components are
15686 * allowed among the {facets}.
15687 */
15688 if (type->facets != NULL) {
15689 xmlSchemaFacetPtr facet;
15690 int ok = 1;
15691
15692 facet = type->facets;
15693 do {
15694 if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
15695 (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
15696 xmlSchemaPIllegalFacetListUnionErr(pctxt,
15698 type, facet);
15699 ok = 0;
15700 }
15701 facet = facet->next;
15702 } while (facet != NULL);
15703 if (ok == 0)
15705
15706 }
15707 /*
15708 * SPEC (3.3.2.5) (same as 1.3.2)
15709 *
15710 * NOTE (3.3.2.5) This is currently done in
15711 * xmlSchemaDeriveAndValidateFacets()
15712 */
15713 }
15714 }
15715
15716 return (0);
15717}
15718
15730#if 0
15731static int
15732xmlSchemaCheckSRCSimpleType(xmlSchemaParserCtxtPtr ctxt,
15733 xmlSchemaTypePtr type)
15734{
15735 /*
15736 * src-simple-type.1 The corresponding simple type definition, if any,
15737 * must satisfy the conditions set out in Constraints on Simple Type
15738 * Definition Schema Components ($3.14.6).
15739 */
15740 if (WXS_IS_RESTRICTION(type)) {
15741 /*
15742 * src-simple-type.2 "If the <restriction> alternative is chosen,
15743 * either it must have a base [attribute] or a <simpleType> among its
15744 * [children], but not both."
15745 * NOTE: This is checked in the parse function of <restriction>.
15746 */
15747 /*
15748 *
15749 */
15750 } else if (WXS_IS_LIST(type)) {
15751 /* src-simple-type.3 "If the <list> alternative is chosen, either it must have
15752 * an itemType [attribute] or a <simpleType> among its [children],
15753 * but not both."
15754 *
15755 * NOTE: This is checked in the parse function of <list>.
15756 */
15757 } else if (WXS_IS_UNION(type)) {
15758 /*
15759 * src-simple-type.4 is checked in xmlSchemaCheckUnionTypeDefCircular().
15760 */
15761 }
15762 return (0);
15763}
15764#endif
15765
15766static int
15767xmlSchemaCreateVCtxtOnPCtxt(xmlSchemaParserCtxtPtr ctxt)
15768{
15769 if (ctxt->vctxt == NULL) {
15770 ctxt->vctxt = xmlSchemaNewValidCtxt(NULL);
15771 if (ctxt->vctxt == NULL) {
15772 xmlSchemaPErr(ctxt, NULL,
15774 "Internal error: xmlSchemaCreateVCtxtOnPCtxt, "
15775 "failed to create a temp. validation context.\n",
15776 NULL, NULL);
15777 return (-1);
15778 }
15779 /* TODO: Pass user data. */
15780 xmlSchemaSetValidErrors(ctxt->vctxt,
15781 ctxt->error, ctxt->warning, ctxt->errCtxt);
15782 xmlSchemaSetValidStructuredErrors(ctxt->vctxt,
15783 ctxt->serror, ctxt->errCtxt);
15784 }
15785 return (0);
15786}
15787
15788static int
15789xmlSchemaVCheckCVCSimpleType(xmlSchemaAbstractCtxtPtr actxt,
15790 xmlNodePtr node,
15791 xmlSchemaTypePtr type,
15792 const xmlChar *value,
15793 xmlSchemaValPtr *retVal,
15794 int fireErrors,
15795 int normalize,
15796 int isNormalized);
15797
15814static int
15815xmlSchemaParseCheckCOSValidDefault(xmlSchemaParserCtxtPtr pctxt,
15816 xmlNodePtr node,
15817 xmlSchemaTypePtr type,
15818 const xmlChar *value,
15819 xmlSchemaValPtr *val)
15820{
15821 int ret = 0;
15822
15823 /*
15824 * cos-valid-default:
15825 * Schema Component Constraint: Element Default Valid (Immediate)
15826 * For a string to be a valid default with respect to a type
15827 * definition the appropriate case among the following must be true:
15828 */
15829 if WXS_IS_COMPLEX(type) {
15830 /*
15831 * Complex type.
15832 *
15833 * SPEC (2.1) "its {content type} must be a simple type definition
15834 * or mixed."
15835 * SPEC (2.2.2) "If the {content type} is mixed, then the {content
15836 * type}'s particle must be `emptiable` as defined by
15837 * Particle Emptiable ($3.9.6)."
15838 */
15839 if ((! WXS_HAS_SIMPLE_CONTENT(type)) &&
15840 ((! WXS_HAS_MIXED_CONTENT(type)) || (! WXS_EMPTIABLE(type)))) {
15841 /* NOTE that this covers (2.2.2) as well. */
15842 xmlSchemaPCustomErr(pctxt,
15844 WXS_BASIC_CAST type, type->node,
15845 "For a string to be a valid default, the type definition "
15846 "must be a simple type or a complex type with mixed content "
15847 "and a particle emptiable", NULL);
15849 }
15850 }
15851 /*
15852 * 1 If the type definition is a simple type definition, then the string
15853 * must be `valid` with respect to that definition as defined by String
15854 * Valid ($3.14.4).
15855 *
15856 * AND
15857 *
15858 * 2.2.1 If the {content type} is a simple type definition, then the
15859 * string must be `valid` with respect to that simple type definition
15860 * as defined by String Valid ($3.14.4).
15861 */
15862 if (WXS_IS_SIMPLE(type))
15863 ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST pctxt, node,
15864 type, value, val, 1, 1, 0);
15865 else if (WXS_HAS_SIMPLE_CONTENT(type))
15866 ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST pctxt, node,
15867 type->contentTypeDef, value, val, 1, 1, 0);
15868 else
15869 return (ret);
15870
15871 if (ret < 0) {
15872 PERROR_INT("xmlSchemaParseCheckCOSValidDefault",
15873 "calling xmlSchemaVCheckCVCSimpleType()");
15874 }
15875
15876 return (ret);
15877}
15878
15892static int
15893xmlSchemaCheckCTPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
15894 xmlSchemaTypePtr type)
15895{
15896 /*
15897 * TODO: Correct the error code; XML_SCHEMAP_SRC_CT_1 is used temporarily.
15898 *
15899 * SPEC (1) "The values of the properties of a complex type definition must
15900 * be as described in the property tableau in The Complex Type Definition
15901 * Schema Component ($3.4.1), modulo the impact of Missing
15902 * Sub-components ($5.3)."
15903 */
15904 if ((type->baseType != NULL) &&
15905 (WXS_IS_SIMPLE(type->baseType)) &&
15906 (WXS_IS_EXTENSION(type) == 0)) {
15907 /*
15908 * SPEC (2) "If the {base type definition} is a simple type definition,
15909 * the {derivation method} must be extension."
15910 */
15911 xmlSchemaCustomErr(ACTXT_CAST pctxt,
15913 NULL, WXS_BASIC_CAST type,
15914 "If the base type is a simple type, the derivation method must be "
15915 "'extension'", NULL, NULL);
15916 return (XML_SCHEMAP_SRC_CT_1);
15917 }
15918 /*
15919 * SPEC (3) "Circular definitions are disallowed, except for the `ur-type
15920 * definition`. That is, it must be possible to reach the `ur-type
15921 * definition` by repeatedly following the {base type definition}."
15922 *
15923 * NOTE (3) is done in xmlSchemaCheckTypeDefCircular().
15924 */
15925 /*
15926 * NOTE that (4) and (5) need the following:
15927 * - attribute uses need to be already inherited (apply attr. prohibitions)
15928 * - attribute group references need to be expanded already
15929 * - simple types need to be typefixed already
15930 */
15931 if (type->attrUses &&
15932 (((xmlSchemaItemListPtr) type->attrUses)->nbItems > 1))
15933 {
15934 xmlSchemaItemListPtr uses = (xmlSchemaItemListPtr) type->attrUses;
15935 xmlSchemaAttributeUsePtr use, tmp;
15936 int i, j, hasId = 0;
15937
15938 for (i = uses->nbItems -1; i >= 0; i--) {
15939 use = uses->items[i];
15940
15941 /*
15942 * SPEC ct-props-correct
15943 * (4) "Two distinct attribute declarations in the
15944 * {attribute uses} must not have identical {name}s and
15945 * {target namespace}s."
15946 */
15947 if (i > 0) {
15948 for (j = i -1; j >= 0; j--) {
15949 tmp = uses->items[j];
15950 if ((WXS_ATTRUSE_DECL_NAME(use) ==
15951 WXS_ATTRUSE_DECL_NAME(tmp)) &&
15952 (WXS_ATTRUSE_DECL_TNS(use) ==
15953 WXS_ATTRUSE_DECL_TNS(tmp)))
15954 {
15955 xmlChar *str = NULL;
15956
15957 xmlSchemaCustomErr(ACTXT_CAST pctxt,
15959 NULL, WXS_BASIC_CAST type,
15960 "Duplicate %s",
15961 xmlSchemaGetComponentDesignation(&str, use),
15962 NULL);
15963 FREE_AND_NULL(str);
15964 /*
15965 * Remove the duplicate.
15966 */
15967 if (xmlSchemaItemListRemove(uses, i) == -1)
15968 goto exit_failure;
15969 goto next_use;
15970 }
15971 }
15972 }
15973 /*
15974 * SPEC ct-props-correct
15975 * (5) "Two distinct attribute declarations in the
15976 * {attribute uses} must not have {type definition}s which
15977 * are or are derived from ID."
15978 */
15979 if (WXS_ATTRUSE_TYPEDEF(use) != NULL) {
15980 if (xmlSchemaIsDerivedFromBuiltInType(
15981 WXS_ATTRUSE_TYPEDEF(use), XML_SCHEMAS_ID))
15982 {
15983 if (hasId) {
15984 xmlChar *str = NULL;
15985
15986 xmlSchemaCustomErr(ACTXT_CAST pctxt,
15988 NULL, WXS_BASIC_CAST type,
15989 "There must not exist more than one attribute "
15990 "declaration of type 'xs:ID' "
15991 "(or derived from 'xs:ID'). The %s violates this "
15992 "constraint",
15993 xmlSchemaGetComponentDesignation(&str, use),
15994 NULL);
15995 FREE_AND_NULL(str);
15996 if (xmlSchemaItemListRemove(uses, i) == -1)
15997 goto exit_failure;
15998 }
15999
16000 hasId = 1;
16001 }
16002 }
16003next_use: {}
16004 }
16005 }
16006 return (0);
16007exit_failure:
16008 return(-1);
16009}
16010
16011static int
16012xmlSchemaAreEqualTypes(xmlSchemaTypePtr typeA,
16013 xmlSchemaTypePtr typeB)
16014{
16015 /*
16016 * TODO: This should implement component-identity
16017 * in the future.
16018 */
16019 if ((typeA == NULL) || (typeB == NULL))
16020 return (0);
16021 return (typeA == typeB);
16022}
16023
16039static int
16040xmlSchemaCheckCOSCTDerivedOK(xmlSchemaAbstractCtxtPtr actxt,
16041 xmlSchemaTypePtr type,
16042 xmlSchemaTypePtr baseType,
16043 int set)
16044{
16045 int equal = xmlSchemaAreEqualTypes(type, baseType);
16046 /* TODO: Error codes. */
16047 /*
16048 * SPEC "For a complex type definition (call it D, for derived)
16049 * to be validly derived from a type definition (call this
16050 * B, for base) given a subset of {extension, restriction}
16051 * all of the following must be true:"
16052 */
16053 if (! equal) {
16054 /*
16055 * SPEC (1) "If B and D are not the same type definition, then the
16056 * {derivation method} of D must not be in the subset."
16057 */
16058 if (((set & SUBSET_EXTENSION) && (WXS_IS_EXTENSION(type))) ||
16059 ((set & SUBSET_RESTRICTION) && (WXS_IS_RESTRICTION(type))))
16060 return (1);
16061 } else {
16062 /*
16063 * SPEC (2.1) "B and D must be the same type definition."
16064 */
16065 return (0);
16066 }
16067 /*
16068 * SPEC (2.2) "B must be D's {base type definition}."
16069 */
16070 if (type->baseType == baseType)
16071 return (0);
16072 /*
16073 * SPEC (2.3.1) "D's {base type definition} must not be the `ur-type
16074 * definition`."
16075 */
16076 if (WXS_IS_ANYTYPE(type->baseType))
16077 return (1);
16078
16079 if (WXS_IS_COMPLEX(type->baseType)) {
16080 /*
16081 * SPEC (2.3.2.1) "If D's {base type definition} is complex, then it
16082 * must be validly derived from B given the subset as defined by this
16083 * constraint."
16084 */
16085 return (xmlSchemaCheckCOSCTDerivedOK(actxt, type->baseType,
16086 baseType, set));
16087 } else {
16088 /*
16089 * SPEC (2.3.2.2) "If D's {base type definition} is simple, then it
16090 * must be validly derived from B given the subset as defined in Type
16091 * Derivation OK (Simple) ($3.14.6).
16092 */
16093 return (xmlSchemaCheckCOSSTDerivedOK(actxt, type->baseType,
16094 baseType, set));
16095 }
16096}
16097
16110static int
16111xmlSchemaCheckCOSDerivedOK(xmlSchemaAbstractCtxtPtr actxt,
16112 xmlSchemaTypePtr type,
16113 xmlSchemaTypePtr baseType,
16114 int set)
16115{
16116 if (WXS_IS_SIMPLE(type))
16117 return (xmlSchemaCheckCOSSTDerivedOK(actxt, type, baseType, set));
16118 else
16119 return (xmlSchemaCheckCOSCTDerivedOK(actxt, type, baseType, set));
16120}
16121
16139static int
16140xmlSchemaCheckCOSCTExtends(xmlSchemaParserCtxtPtr ctxt,
16141 xmlSchemaTypePtr type)
16142{
16143 xmlSchemaTypePtr base = type->baseType;
16144 /*
16145 * TODO: Correct the error code; XML_SCHEMAP_COS_CT_EXTENDS_1_1 is used
16146 * temporarily only.
16147 */
16148 /*
16149 * SPEC (1) "If the {base type definition} is a complex type definition,
16150 * then all of the following must be true:"
16151 */
16152 if (WXS_IS_COMPLEX(base)) {
16153 /*
16154 * SPEC (1.1) "The {final} of the {base type definition} must not
16155 * contain extension."
16156 */
16157 if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
16158 xmlSchemaPCustomErr(ctxt,
16160 WXS_BASIC_CAST type, NULL,
16161 "The 'final' of the base type definition "
16162 "contains 'extension'", NULL);
16164 }
16165
16166 /*
16167 * ATTENTION: The constrains (1.2) and (1.3) are not applied,
16168 * since they are automatically satisfied through the
16169 * inheriting mechanism.
16170 * Note that even if redefining components, the inheriting mechanism
16171 * is used.
16172 */
16173#if 0
16174 /*
16175 * SPEC (1.2) "Its {attribute uses} must be a subset of the {attribute
16176 * uses}
16177 * of the complex type definition itself, that is, for every attribute
16178 * use in the {attribute uses} of the {base type definition}, there
16179 * must be an attribute use in the {attribute uses} of the complex
16180 * type definition itself whose {attribute declaration} has the same
16181 * {name}, {target namespace} and {type definition} as its attribute
16182 * declaration"
16183 */
16184 if (base->attrUses != NULL) {
16185 int i, j, found;
16186 xmlSchemaAttributeUsePtr use, buse;
16187
16188 for (i = 0; i < (WXS_LIST_CAST base->attrUses)->nbItems; i ++) {
16189 buse = (WXS_LIST_CAST base->attrUses)->items[i];
16190 found = 0;
16191 if (type->attrUses != NULL) {
16192 use = (WXS_LIST_CAST type->attrUses)->items[j];
16193 for (j = 0; j < (WXS_LIST_CAST type->attrUses)->nbItems; j ++)
16194 {
16195 if ((WXS_ATTRUSE_DECL_NAME(use) ==
16196 WXS_ATTRUSE_DECL_NAME(buse)) &&
16197 (WXS_ATTRUSE_DECL_TNS(use) ==
16198 WXS_ATTRUSE_DECL_TNS(buse)) &&
16199 (WXS_ATTRUSE_TYPEDEF(use) ==
16200 WXS_ATTRUSE_TYPEDEF(buse))
16201 {
16202 found = 1;
16203 break;
16204 }
16205 }
16206 }
16207 if (! found) {
16208 xmlChar *str = NULL;
16209
16210 xmlSchemaCustomErr(ACTXT_CAST ctxt,
16212 NULL, WXS_BASIC_CAST type,
16213 /*
16214 * TODO: The report does not indicate that also the
16215 * type needs to be the same.
16216 */
16217 "This type is missing a matching correspondent "
16218 "for its {base type}'s %s in its {attribute uses}",
16219 xmlSchemaGetComponentDesignation(&str,
16220 buse->children),
16221 NULL);
16222 FREE_AND_NULL(str)
16223 }
16224 }
16225 }
16226 /*
16227 * SPEC (1.3) "If it has an {attribute wildcard}, the complex type
16228 * definition must also have one, and the base type definition's
16229 * {attribute wildcard}'s {namespace constraint} must be a subset
16230 * of the complex type definition's {attribute wildcard}'s {namespace
16231 * constraint}, as defined by Wildcard Subset ($3.10.6)."
16232 */
16233
16234 /*
16235 * MAYBE TODO: Enable if ever needed. But this will be needed only
16236 * if created the type via a schema construction API.
16237 */
16238 if (base->attributeWildcard != NULL) {
16239 if (type->attributeWildcard == NULL) {
16240 xmlChar *str = NULL;
16241
16242 xmlSchemaCustomErr(ACTXT_CAST pctxt,
16244 NULL, type,
16245 "The base %s has an attribute wildcard, "
16246 "but this type is missing an attribute wildcard",
16247 xmlSchemaGetComponentDesignation(&str, base));
16248 FREE_AND_NULL(str)
16249
16250 } else if (xmlSchemaCheckCOSNSSubset(
16251 base->attributeWildcard, type->attributeWildcard))
16252 {
16253 xmlChar *str = NULL;
16254
16255 xmlSchemaCustomErr(ACTXT_CAST pctxt,
16257 NULL, type,
16258 "The attribute wildcard is not a valid "
16259 "superset of the one in the base %s",
16260 xmlSchemaGetComponentDesignation(&str, base));
16261 FREE_AND_NULL(str)
16262 }
16263 }
16264#endif
16265 /*
16266 * SPEC (1.4) "One of the following must be true:"
16267 */
16268 if ((type->contentTypeDef != NULL) &&
16269 (type->contentTypeDef == base->contentTypeDef)) {
16270 /*
16271 * SPEC (1.4.1) "The {content type} of the {base type definition}
16272 * and the {content type} of the complex type definition itself
16273 * must be the same simple type definition"
16274 * PASS
16275 */
16276 } else if ((type->contentType == XML_SCHEMA_CONTENT_EMPTY) &&
16277 (base->contentType == XML_SCHEMA_CONTENT_EMPTY) ) {
16278 /*
16279 * SPEC (1.4.2) "The {content type} of both the {base type
16280 * definition} and the complex type definition itself must
16281 * be empty."
16282 * PASS
16283 */
16284 } else {
16285 /*
16286 * SPEC (1.4.3) "All of the following must be true:"
16287 */
16288 if (type->subtypes == NULL) {
16289 /*
16290 * SPEC 1.4.3.1 The {content type} of the complex type
16291 * definition itself must specify a particle.
16292 */
16293 xmlSchemaPCustomErr(ctxt,
16295 WXS_BASIC_CAST type, NULL,
16296 "The content type must specify a particle", NULL);
16298 }
16299 /*
16300 * SPEC (1.4.3.2) "One of the following must be true:"
16301 */
16302 if (base->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16303 /*
16304 * SPEC (1.4.3.2.1) "The {content type} of the {base type
16305 * definition} must be empty.
16306 * PASS
16307 */
16308 } else {
16309 /*
16310 * SPEC (1.4.3.2.2) "All of the following must be true:"
16311 */
16312 if ((type->contentType != base->contentType) ||
16313 ((type->contentType != XML_SCHEMA_CONTENT_MIXED) &&
16314 (type->contentType != XML_SCHEMA_CONTENT_ELEMENTS))) {
16315 /*
16316 * SPEC (1.4.3.2.2.1) "Both {content type}s must be mixed
16317 * or both must be element-only."
16318 */
16319 xmlSchemaPCustomErr(ctxt,
16321 WXS_BASIC_CAST type, NULL,
16322 "The content type of both, the type and its base "
16323 "type, must either 'mixed' or 'element-only'", NULL);
16325 }
16326 /*
16327 * URGENT TODO SPEC (1.4.3.2.2.2) "The particle of the
16328 * complex type definition must be a `valid extension`
16329 * of the {base type definition}'s particle, as defined
16330 * in Particle Valid (Extension) ($3.9.6)."
16331 *
16332 * NOTE that we won't check "Particle Valid (Extension)",
16333 * since it is ensured by the derivation process in
16334 * xmlSchemaTypeFixup(). We need to implement this when heading
16335 * for a construction API
16336 * TODO: !! This is needed to be checked if redefining a type !!
16337 */
16338 }
16339 /*
16340 * URGENT TODO (1.5)
16341 */
16342 }
16343 } else {
16344 /*
16345 * SPEC (2) "If the {base type definition} is a simple type definition,
16346 * then all of the following must be true:"
16347 */
16348 if (type->contentTypeDef != base) {
16349 /*
16350 * SPEC (2.1) "The {content type} must be the same simple type
16351 * definition."
16352 */
16353 xmlSchemaPCustomErr(ctxt,
16355 WXS_BASIC_CAST type, NULL,
16356 "The content type must be the simple base type", NULL);
16358 }
16359 if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
16360 /*
16361 * SPEC (2.2) "The {final} of the {base type definition} must not
16362 * contain extension"
16363 * NOTE that this is the same as (1.1).
16364 */
16365 xmlSchemaPCustomErr(ctxt,
16367 WXS_BASIC_CAST type, NULL,
16368 "The 'final' of the base type definition "
16369 "contains 'extension'", NULL);
16371 }
16372 }
16373 return (0);
16374}
16375
16396static int
16397xmlSchemaCheckDerivationOKRestriction(xmlSchemaParserCtxtPtr ctxt,
16398 xmlSchemaTypePtr type)
16399{
16400 xmlSchemaTypePtr base;
16401
16402 /*
16403 * TODO: Correct the error code; XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1 is used
16404 * temporarily only.
16405 */
16406 base = type->baseType;
16407 if (! WXS_IS_COMPLEX(base)) {
16408 xmlSchemaCustomErr(ACTXT_CAST ctxt,
16410 type->node, WXS_BASIC_CAST type,
16411 "The base type must be a complex type", NULL, NULL);
16412 return(ctxt->err);
16413 }
16414 if (base->flags & XML_SCHEMAS_TYPE_FINAL_RESTRICTION) {
16415 /*
16416 * SPEC (1) "The {base type definition} must be a complex type
16417 * definition whose {final} does not contain restriction."
16418 */
16419 xmlSchemaCustomErr(ACTXT_CAST ctxt,
16421 type->node, WXS_BASIC_CAST type,
16422 "The 'final' of the base type definition "
16423 "contains 'restriction'", NULL, NULL);
16424 return (ctxt->err);
16425 }
16426 /*
16427 * SPEC (2), (3) and (4)
16428 * Those are handled in a separate function, since the
16429 * same constraints are needed for redefinition of
16430 * attribute groups as well.
16431 */
16432 if (xmlSchemaCheckDerivationOKRestriction2to4(ctxt,
16433 XML_SCHEMA_ACTION_DERIVE,
16434 WXS_BASIC_CAST type, WXS_BASIC_CAST base,
16435 type->attrUses, base->attrUses,
16436 type->attributeWildcard,
16437 base->attributeWildcard) == -1)
16438 {
16439 return(-1);
16440 }
16441 /*
16442 * SPEC (5) "One of the following must be true:"
16443 */
16444 if (base->builtInType == XML_SCHEMAS_ANYTYPE) {
16445 /*
16446 * SPEC (5.1) "The {base type definition} must be the
16447 * `ur-type definition`."
16448 * PASS
16449 */
16450 } else if ((type->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
16451 (type->contentType == XML_SCHEMA_CONTENT_BASIC)) {
16452 /*
16453 * SPEC (5.2.1) "The {content type} of the complex type definition
16454 * must be a simple type definition"
16455 *
16456 * SPEC (5.2.2) "One of the following must be true:"
16457 */
16458 if ((base->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
16459 (base->contentType == XML_SCHEMA_CONTENT_BASIC))
16460 {
16461 int err;
16462 /*
16463 * SPEC (5.2.2.1) "The {content type} of the {base type
16464 * definition} must be a simple type definition from which
16465 * the {content type} is validly derived given the empty
16466 * set as defined in Type Derivation OK (Simple) ($3.14.6)."
16467 *
16468 * ATTENTION TODO: This seems not needed if the type implicitly
16469 * derived from the base type.
16470 *
16471 */
16472 err = xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST ctxt,
16473 type->contentTypeDef, base->contentTypeDef, 0);
16474 if (err != 0) {
16475 xmlChar *strA = NULL, *strB = NULL;
16476
16477 if (err == -1)
16478 return(-1);
16479 xmlSchemaCustomErr(ACTXT_CAST ctxt,
16481 NULL, WXS_BASIC_CAST type,
16482 "The {content type} %s is not validly derived from the "
16483 "base type's {content type} %s",
16484 xmlSchemaGetComponentDesignation(&strA,
16485 type->contentTypeDef),
16486 xmlSchemaGetComponentDesignation(&strB,
16487 base->contentTypeDef));
16488 FREE_AND_NULL(strA);
16489 FREE_AND_NULL(strB);
16490 return(ctxt->err);
16491 }
16492 } else if ((base->contentType == XML_SCHEMA_CONTENT_MIXED) &&
16493 (xmlSchemaIsParticleEmptiable(
16494 (xmlSchemaParticlePtr) base->subtypes))) {
16495 /*
16496 * SPEC (5.2.2.2) "The {base type definition} must be mixed
16497 * and have a particle which is `emptiable` as defined in
16498 * Particle Emptiable ($3.9.6)."
16499 * PASS
16500 */
16501 } else {
16502 xmlSchemaPCustomErr(ctxt,
16504 WXS_BASIC_CAST type, NULL,
16505 "The content type of the base type must be either "
16506 "a simple type or 'mixed' and an emptiable particle", NULL);
16507 return (ctxt->err);
16508 }
16509 } else if (type->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16510 /*
16511 * SPEC (5.3.1) "The {content type} of the complex type itself must
16512 * be empty"
16513 */
16514 if (base->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16515 /*
16516 * SPEC (5.3.2.1) "The {content type} of the {base type
16517 * definition} must also be empty."
16518 * PASS
16519 */
16520 } else if (((base->contentType == XML_SCHEMA_CONTENT_ELEMENTS) ||
16521 (base->contentType == XML_SCHEMA_CONTENT_MIXED)) &&
16522 xmlSchemaIsParticleEmptiable(
16523 (xmlSchemaParticlePtr) base->subtypes)) {
16524 /*
16525 * SPEC (5.3.2.2) "The {content type} of the {base type
16526 * definition} must be elementOnly or mixed and have a particle
16527 * which is `emptiable` as defined in Particle Emptiable ($3.9.6)."
16528 * PASS
16529 */
16530 } else {
16531 xmlSchemaPCustomErr(ctxt,
16533 WXS_BASIC_CAST type, NULL,
16534 "The content type of the base type must be either "
16535 "empty or 'mixed' (or 'elements-only') and an emptiable "
16536 "particle", NULL);
16537 return (ctxt->err);
16538 }
16539 } else if ((type->contentType == XML_SCHEMA_CONTENT_ELEMENTS) ||
16540 WXS_HAS_MIXED_CONTENT(type)) {
16541 /*
16542 * SPEC (5.4.1.1) "The {content type} of the complex type definition
16543 * itself must be element-only"
16544 */
16545 if (WXS_HAS_MIXED_CONTENT(type) && (! WXS_HAS_MIXED_CONTENT(base))) {
16546 /*
16547 * SPEC (5.4.1.2) "The {content type} of the complex type
16548 * definition itself and of the {base type definition} must be
16549 * mixed"
16550 */
16551 xmlSchemaPCustomErr(ctxt,
16553 WXS_BASIC_CAST type, NULL,
16554 "If the content type is 'mixed', then the content type of the "
16555 "base type must also be 'mixed'", NULL);
16556 return (ctxt->err);
16557 }
16558 /*
16559 * SPEC (5.4.2) "The particle of the complex type definition itself
16560 * must be a `valid restriction` of the particle of the {content
16561 * type} of the {base type definition} as defined in Particle Valid
16562 * (Restriction) ($3.9.6).
16563 *
16564 * URGENT TODO: (5.4.2)
16565 */
16566 } else {
16567 xmlSchemaPCustomErr(ctxt,
16569 WXS_BASIC_CAST type, NULL,
16570 "The type is not a valid restriction of its base type", NULL);
16571 return (ctxt->err);
16572 }
16573 return (0);
16574}
16575
16586static int
16587xmlSchemaCheckCTComponent(xmlSchemaParserCtxtPtr ctxt,
16588 xmlSchemaTypePtr type)
16589{
16590 int ret;
16591 /*
16592 * Complex Type Definition Properties Correct
16593 */
16594 ret = xmlSchemaCheckCTPropsCorrect(ctxt, type);
16595 if (ret != 0)
16596 return (ret);
16597 if (WXS_IS_EXTENSION(type))
16598 ret = xmlSchemaCheckCOSCTExtends(ctxt, type);
16599 else
16600 ret = xmlSchemaCheckDerivationOKRestriction(ctxt, type);
16601 return (ret);
16602}
16603
16616static int
16617xmlSchemaCheckSRCCT(xmlSchemaParserCtxtPtr ctxt,
16618 xmlSchemaTypePtr type)
16619{
16620 xmlSchemaTypePtr base;
16621 int ret = 0;
16622
16623 /*
16624 * TODO: Adjust the error codes here, as I used
16625 * XML_SCHEMAP_SRC_CT_1 only yet.
16626 */
16627 base = type->baseType;
16628 if (! WXS_HAS_SIMPLE_CONTENT(type)) {
16629 /*
16630 * 1 If the <complexContent> alternative is chosen, the type definition
16631 * `resolved` to by the `actual value` of the base [attribute]
16632 * must be a complex type definition;
16633 */
16634 if (! WXS_IS_COMPLEX(base)) {
16635 xmlChar *str = NULL;
16636 xmlSchemaPCustomErr(ctxt,
16638 WXS_BASIC_CAST type, type->node,
16639 "If using <complexContent>, the base type is expected to be "
16640 "a complex type. The base type '%s' is a simple type",
16641 xmlSchemaFormatQName(&str, base->targetNamespace,
16642 base->name));
16643 FREE_AND_NULL(str)
16644 return (XML_SCHEMAP_SRC_CT_1);
16645 }
16646 } else {
16647 /*
16648 * SPEC
16649 * 2 If the <simpleContent> alternative is chosen, all of the
16650 * following must be true:
16651 * 2.1 The type definition `resolved` to by the `actual value` of the
16652 * base [attribute] must be one of the following:
16653 */
16654 if (WXS_IS_SIMPLE(base)) {
16655 if (WXS_IS_EXTENSION(type) == 0) {
16656 xmlChar *str = NULL;
16657 /*
16658 * 2.1.3 only if the <extension> alternative is also
16659 * chosen, a simple type definition.
16660 */
16661 /* TODO: Change error code to ..._SRC_CT_2_1_3. */
16662 xmlSchemaPCustomErr(ctxt,
16664 WXS_BASIC_CAST type, NULL,
16665 "If using <simpleContent> and <restriction>, the base "
16666 "type must be a complex type. The base type '%s' is "
16667 "a simple type",
16668 xmlSchemaFormatQName(&str, base->targetNamespace,
16669 base->name));
16670 FREE_AND_NULL(str)
16671 return (XML_SCHEMAP_SRC_CT_1);
16672 }
16673 } else {
16674 /* Base type is a complex type. */
16675 if ((base->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
16676 (base->contentType == XML_SCHEMA_CONTENT_BASIC)) {
16677 /*
16678 * 2.1.1 a complex type definition whose {content type} is a
16679 * simple type definition;
16680 * PASS
16681 */
16682 if (base->contentTypeDef == NULL) {
16683 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
16684 WXS_BASIC_CAST type, NULL,
16685 "Internal error: xmlSchemaCheckSRCCT, "
16686 "'%s', base type has no content type",
16687 type->name);
16688 return (-1);
16689 }
16690 } else if ((base->contentType == XML_SCHEMA_CONTENT_MIXED) &&
16691 (WXS_IS_RESTRICTION(type))) {
16692
16693 /*
16694 * 2.1.2 only if the <restriction> alternative is also
16695 * chosen, a complex type definition whose {content type}
16696 * is mixed and a particle emptiable.
16697 */
16698 if (! xmlSchemaIsParticleEmptiable(
16699 (xmlSchemaParticlePtr) base->subtypes)) {
16701 } else
16702 /*
16703 * Attention: at this point the <simpleType> child is in
16704 * ->contentTypeDef (put there during parsing).
16705 */
16706 if (type->contentTypeDef == NULL) {
16707 xmlChar *str = NULL;
16708 /*
16709 * 2.2 If clause 2.1.2 above is satisfied, then there
16710 * must be a <simpleType> among the [children] of
16711 * <restriction>.
16712 */
16713 /* TODO: Change error code to ..._SRC_CT_2_2. */
16714 xmlSchemaPCustomErr(ctxt,
16716 WXS_BASIC_CAST type, NULL,
16717 "A <simpleType> is expected among the children "
16718 "of <restriction>, if <simpleContent> is used and "
16719 "the base type '%s' is a complex type",
16720 xmlSchemaFormatQName(&str, base->targetNamespace,
16721 base->name));
16722 FREE_AND_NULL(str)
16723 return (XML_SCHEMAP_SRC_CT_1);
16724 }
16725 } else {
16727 }
16728 }
16729 if (ret > 0) {
16730 xmlChar *str = NULL;
16731 if (WXS_IS_RESTRICTION(type)) {
16732 xmlSchemaPCustomErr(ctxt,
16734 WXS_BASIC_CAST type, NULL,
16735 "If <simpleContent> and <restriction> is used, the "
16736 "base type must be a simple type or a complex type with "
16737 "mixed content and particle emptiable. The base type "
16738 "'%s' is none of those",
16739 xmlSchemaFormatQName(&str, base->targetNamespace,
16740 base->name));
16741 } else {
16742 xmlSchemaPCustomErr(ctxt,
16744 WXS_BASIC_CAST type, NULL,
16745 "If <simpleContent> and <extension> is used, the "
16746 "base type must be a simple type. The base type '%s' "
16747 "is a complex type",
16748 xmlSchemaFormatQName(&str, base->targetNamespace,
16749 base->name));
16750 }
16751 FREE_AND_NULL(str)
16752 }
16753 }
16754 /*
16755 * SPEC (3) "The corresponding complex type definition component must
16756 * satisfy the conditions set out in Constraints on Complex Type
16757 * Definition Schema Components ($3.4.6);"
16758 * NOTE (3) will be done in xmlSchemaTypeFixup().
16759 */
16760 /*
16761 * SPEC (4) If clause 2.2.1 or clause 2.2.2 in the correspondence specification
16762 * above for {attribute wildcard} is satisfied, the intensional
16763 * intersection must be expressible, as defined in Attribute Wildcard
16764 * Intersection ($3.10.6).
16765 * NOTE (4) is done in xmlSchemaFixupTypeAttributeUses().
16766 */
16767 return (ret);
16768}
16769
16770#ifdef ENABLE_PARTICLE_RESTRICTION
16785static int
16786xmlSchemaCheckParticleRangeOK(int rmin, int rmax,
16787 int bmin, int bmax)
16788{
16789 if (rmin < bmin)
16790 return (1);
16791 if ((bmax != UNBOUNDED) &&
16792 (rmax > bmax))
16793 return (1);
16794 return (0);
16795}
16796
16815static int
16816xmlSchemaCheckRCaseNameAndTypeOK(xmlSchemaParserCtxtPtr ctxt,
16817 xmlSchemaParticlePtr r,
16818 xmlSchemaParticlePtr b)
16819{
16820 xmlSchemaElementPtr elemR, elemB;
16821
16822 /* TODO: Error codes (rcase-NameAndTypeOK). */
16823 elemR = (xmlSchemaElementPtr) r->children;
16824 elemB = (xmlSchemaElementPtr) b->children;
16825 /*
16826 * SPEC (1) "The declarations' {name}s and {target namespace}s are
16827 * the same."
16828 */
16829 if ((elemR != elemB) &&
16830 ((! xmlStrEqual(elemR->name, elemB->name)) ||
16831 (! xmlStrEqual(elemR->targetNamespace, elemB->targetNamespace))))
16832 return (1);
16833 /*
16834 * SPEC (2) "R's occurrence range is a valid restriction of B's
16835 * occurrence range as defined by Occurrence Range OK ($3.9.6)."
16836 */
16837 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
16838 b->minOccurs, b->maxOccurs) != 0)
16839 return (1);
16840 /*
16841 * SPEC (3.1) "Both B's declaration's {scope} and R's declaration's
16842 * {scope} are global."
16843 */
16844 if (elemR == elemB)
16845 return (0);
16846 /*
16847 * SPEC (3.2.1) "Either B's {nillable} is true or R's {nillable} is false."
16848 */
16849 if (((elemB->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) &&
16850 (elemR->flags & XML_SCHEMAS_ELEM_NILLABLE))
16851 return (1);
16852 /*
16853 * SPEC (3.2.2) "either B's declaration's {value constraint} is absent,
16854 * or is not fixed, or R's declaration's {value constraint} is fixed
16855 * with the same value."
16856 */
16857 if ((elemB->value != NULL) && (elemB->flags & XML_SCHEMAS_ELEM_FIXED) &&
16858 ((elemR->value == NULL) ||
16859 ((elemR->flags & XML_SCHEMAS_ELEM_FIXED) == 0) ||
16860 /* TODO: Equality of the initial value or normalized or canonical? */
16861 (! xmlStrEqual(elemR->value, elemB->value))))
16862 return (1);
16863 /*
16864 * TODO: SPEC (3.2.3) "R's declaration's {identity-constraint
16865 * definitions} is a subset of B's declaration's {identity-constraint
16866 * definitions}, if any."
16867 */
16868 if (elemB->idcs != NULL) {
16869 /* TODO */
16870 }
16871 /*
16872 * SPEC (3.2.4) "R's declaration's {disallowed substitutions} is a
16873 * superset of B's declaration's {disallowed substitutions}."
16874 */
16875 if (((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) &&
16876 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) == 0)) ||
16877 ((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) &&
16878 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) == 0)) ||
16879 ((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION) &&
16880 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION) == 0)))
16881 return (1);
16882 /*
16883 * SPEC (3.2.5) "R's {type definition} is validly derived given
16884 * {extension, list, union} from B's {type definition}"
16885 *
16886 * BADSPEC TODO: What's the point of adding "list" and "union" to the
16887 * set, if the corresponding constraints handle "restriction" and
16888 * "extension" only?
16889 *
16890 */
16891 {
16892 int set = 0;
16893
16894 set |= SUBSET_EXTENSION;
16895 set |= SUBSET_LIST;
16896 set |= SUBSET_UNION;
16897 if (xmlSchemaCheckCOSDerivedOK(ACTXT_CAST ctxt, elemR->subtypes,
16898 elemB->subtypes, set) != 0)
16899 return (1);
16900 }
16901 return (0);
16902}
16903
16920static int
16921xmlSchemaCheckRCaseNSCompat(xmlSchemaParserCtxtPtr ctxt,
16922 xmlSchemaParticlePtr r,
16923 xmlSchemaParticlePtr b)
16924{
16925 /* TODO:Error codes (rcase-NSCompat). */
16926 /*
16927 * SPEC "For an element declaration particle to be a `valid restriction`
16928 * of a wildcard particle all of the following must be true:"
16929 *
16930 * SPEC (1) "The element declaration's {target namespace} is `valid`
16931 * with respect to the wildcard's {namespace constraint} as defined by
16932 * Wildcard allows Namespace Name ($3.10.4)."
16933 */
16934 if (xmlSchemaCheckCVCWildcardNamespace((xmlSchemaWildcardPtr) b->children,
16935 ((xmlSchemaElementPtr) r->children)->targetNamespace) != 0)
16936 return (1);
16937 /*
16938 * SPEC (2) "R's occurrence range is a valid restriction of B's
16939 * occurrence range as defined by Occurrence Range OK ($3.9.6)."
16940 */
16941 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
16942 b->minOccurs, b->maxOccurs) != 0)
16943 return (1);
16944
16945 return (0);
16946}
16947
16964static int
16965xmlSchemaCheckRCaseRecurseAsIfGroup(xmlSchemaParserCtxtPtr ctxt,
16966 xmlSchemaParticlePtr r,
16967 xmlSchemaParticlePtr b)
16968{
16969 /* TODO: Error codes (rcase-RecurseAsIfGroup). */
16970 TODO
16971 return (0);
16972}
16973
16990static int
16991xmlSchemaCheckRCaseNSSubset(xmlSchemaParserCtxtPtr ctxt,
16992 xmlSchemaParticlePtr r,
16993 xmlSchemaParticlePtr b,
16994 int isAnyTypeBase)
16995{
16996 /* TODO: Error codes (rcase-NSSubset). */
16997 /*
16998 * SPEC (1) "R's occurrence range is a valid restriction of B's
16999 * occurrence range as defined by Occurrence Range OK ($3.9.6)."
17000 */
17001 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
17002 b->minOccurs, b->maxOccurs))
17003 return (1);
17004 /*
17005 * SPEC (2) "R's {namespace constraint} must be an intensional subset
17006 * of B's {namespace constraint} as defined by Wildcard Subset ($3.10.6)."
17007 */
17008 if (xmlSchemaCheckCOSNSSubset((xmlSchemaWildcardPtr) r->children,
17009 (xmlSchemaWildcardPtr) b->children))
17010 return (1);
17011 /*
17012 * SPEC (3) "Unless B is the content model wildcard of the `ur-type
17013 * definition`, R's {process contents} must be identical to or stronger
17014 * than B's {process contents}, where strict is stronger than lax is
17015 * stronger than skip."
17016 */
17017 if (! isAnyTypeBase) {
17018 if ( ((xmlSchemaWildcardPtr) r->children)->processContents <
17019 ((xmlSchemaWildcardPtr) b->children)->processContents)
17020 return (1);
17021 }
17022
17023 return (0);
17024}
17025
17040static int
17041xmlSchemaCheckCOSParticleRestrict(xmlSchemaParserCtxtPtr ctxt,
17042 xmlSchemaParticlePtr r,
17043 xmlSchemaParticlePtr b)
17044{
17045 int ret = 0;
17046
17047 /*part = WXS_TYPE_PARTICLE(type);
17048 basePart = WXS_TYPE_PARTICLE(base);
17049 */
17050
17051 TODO
17052
17053 /*
17054 * SPEC (1) "They are the same particle."
17055 */
17056 if (r == b)
17057 return (0);
17058
17059
17060 return (0);
17061}
17062
17063#if 0
17081static int
17082xmlSchemaCheckRCaseNSRecurseCheckCardinality(xmlSchemaParserCtxtPtr ctxt,
17083 xmlSchemaParticlePtr r,
17084 xmlSchemaParticlePtr b)
17085{
17086 xmlSchemaParticlePtr part;
17087 /* TODO: Error codes (rcase-NSRecurseCheckCardinality). */
17088 if ((r->children == NULL) || (r->children->children == NULL))
17089 return (-1);
17090 /*
17091 * SPEC "For a group particle to be a `valid restriction` of a
17092 * wildcard particle..."
17093 *
17094 * SPEC (1) "Every member of the {particles} of the group is a `valid
17095 * restriction` of the wildcard as defined by
17096 * Particle Valid (Restriction) ($3.9.6)."
17097 */
17098 part = (xmlSchemaParticlePtr) r->children->children;
17099 do {
17100 if (xmlSchemaCheckCOSParticleRestrict(ctxt, part, b))
17101 return (1);
17102 part = (xmlSchemaParticlePtr) part->next;
17103 } while (part != NULL);
17104 /*
17105 * SPEC (2) "The effective total range of the group [...] is a
17106 * valid restriction of B's occurrence range as defined by
17107 * Occurrence Range OK ($3.9.6)."
17108 */
17109 if (xmlSchemaCheckParticleRangeOK(
17110 xmlSchemaGetParticleTotalRangeMin(r),
17111 xmlSchemaGetParticleTotalRangeMax(r),
17112 b->minOccurs, b->maxOccurs) != 0)
17113 return (1);
17114 return (0);
17115}
17116#endif
17117
17136static int
17137xmlSchemaCheckRCaseRecurse(xmlSchemaParserCtxtPtr ctxt,
17138 xmlSchemaParticlePtr r,
17139 xmlSchemaParticlePtr b)
17140{
17141 /* xmlSchemaParticlePtr part; */
17142 /* TODO: Error codes (rcase-Recurse). */
17143 if ((r->children == NULL) || (b->children == NULL) ||
17144 (r->children->type != b->children->type))
17145 return (-1);
17146 /*
17147 * SPEC "For an all or sequence group particle to be a `valid
17148 * restriction` of another group particle with the same {compositor}..."
17149 *
17150 * SPEC (1) "R's occurrence range is a valid restriction of B's
17151 * occurrence range as defined by Occurrence Range OK ($3.9.6)."
17152 */
17153 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
17154 b->minOccurs, b->maxOccurs))
17155 return (1);
17156
17157
17158 return (0);
17159}
17160
17161#endif
17162
17163#define FACET_RESTR_MUTUAL_ERR(fac1, fac2) \
17164 xmlSchemaPCustomErrExt(pctxt, \
17165 XML_SCHEMAP_INVALID_FACET_VALUE, \
17166 WXS_BASIC_CAST fac1, fac1->node, \
17167 "It is an error for both '%s' and '%s' to be specified on the "\
17168 "same type definition", \
17169 BAD_CAST xmlSchemaFacetTypeToString(fac1->type), \
17170 BAD_CAST xmlSchemaFacetTypeToString(fac2->type), NULL);
17171
17172#define FACET_RESTR_ERR(fac1, msg) \
17173 xmlSchemaPCustomErr(pctxt, \
17174 XML_SCHEMAP_INVALID_FACET_VALUE, \
17175 WXS_BASIC_CAST fac1, fac1->node, \
17176 msg, NULL);
17177
17178#define FACET_RESTR_FIXED_ERR(fac) \
17179 xmlSchemaPCustomErr(pctxt, \
17180 XML_SCHEMAP_INVALID_FACET_VALUE, \
17181 WXS_BASIC_CAST fac, fac->node, \
17182 "The base type's facet is 'fixed', thus the value must not " \
17183 "differ", NULL);
17184
17185static void
17186xmlSchemaDeriveFacetErr(xmlSchemaParserCtxtPtr pctxt,
17187 xmlSchemaFacetPtr facet1,
17188 xmlSchemaFacetPtr facet2,
17189 int lessGreater,
17190 int orEqual,
17191 int ofBase)
17192{
17193 xmlChar *msg = NULL;
17194
17195 msg = xmlStrdup(BAD_CAST "'");
17196 msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facet1->type));
17197 msg = xmlStrcat(msg, BAD_CAST "' has to be");
17198 if (lessGreater == 0)
17199 msg = xmlStrcat(msg, BAD_CAST " equal to");
17200 if (lessGreater == 1)
17201 msg = xmlStrcat(msg, BAD_CAST " greater than");
17202 else
17203 msg = xmlStrcat(msg, BAD_CAST " less than");
17204
17205 if (orEqual)
17206 msg = xmlStrcat(msg, BAD_CAST " or equal to");
17207 msg = xmlStrcat(msg, BAD_CAST " '");
17208 msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facet2->type));
17209 if (ofBase)
17210 msg = xmlStrcat(msg, BAD_CAST "' of the base type");
17211 else
17212 msg = xmlStrcat(msg, BAD_CAST "'");
17213
17214 xmlSchemaPCustomErr(pctxt,
17216 WXS_BASIC_CAST facet1, NULL,
17217 (const char *) msg, NULL);
17218
17219 if (msg != NULL)
17220 xmlFree(msg);
17221}
17222
17223/*
17224* xmlSchemaDeriveAndValidateFacets:
17225*
17226* Schema Component Constraint: Simple Type Restriction (Facets)
17227* (st-restrict-facets)
17228*/
17229static int
17230xmlSchemaDeriveAndValidateFacets(xmlSchemaParserCtxtPtr pctxt,
17231 xmlSchemaTypePtr type)
17232{
17233 xmlSchemaTypePtr base = type->baseType;
17234 xmlSchemaFacetLinkPtr link, cur, last = NULL;
17235 xmlSchemaFacetPtr facet, bfacet,
17236 flength = NULL, ftotdig = NULL, ffracdig = NULL,
17237 fmaxlen = NULL, fminlen = NULL, /* facets of the current type */
17238 fmininc = NULL, fmaxinc = NULL,
17239 fminexc = NULL, fmaxexc = NULL,
17240 bflength = NULL, bftotdig = NULL, bffracdig = NULL,
17241 bfmaxlen = NULL, bfminlen = NULL, /* facets of the base type */
17242 bfmininc = NULL, bfmaxinc = NULL,
17243 bfminexc = NULL, bfmaxexc = NULL;
17244 int res; /* err = 0, fixedErr; */
17245
17246 /*
17247 * SPEC st-restrict-facets 1:
17248 * "The {variety} of R is the same as that of B."
17249 */
17250 /*
17251 * SPEC st-restrict-facets 2:
17252 * "If {variety} is atomic, the {primitive type definition}
17253 * of R is the same as that of B."
17254 *
17255 * NOTE: we leave 1 & 2 out for now, since this will be
17256 * satisfied by the derivation process.
17257 * CONSTRUCTION TODO: Maybe needed if using a construction API.
17258 */
17259 /*
17260 * SPEC st-restrict-facets 3:
17261 * "The {facets} of R are the union of S and the {facets}
17262 * of B, eliminating duplicates. To eliminate duplicates,
17263 * when a facet of the same kind occurs in both S and the
17264 * {facets} of B, the one in the {facets} of B is not
17265 * included, with the exception of enumeration and pattern
17266 * facets, for which multiple occurrences with distinct values
17267 * are allowed."
17268 */
17269
17270 if ((type->facetSet == NULL) && (base->facetSet == NULL))
17271 return (0);
17272
17273 last = type->facetSet;
17274 if (last != NULL)
17275 while (last->next != NULL)
17276 last = last->next;
17277
17278 for (cur = type->facetSet; cur != NULL; cur = cur->next) {
17279 facet = cur->facet;
17280 switch (facet->type) {
17281 case XML_SCHEMA_FACET_LENGTH:
17282 flength = facet; break;
17283 case XML_SCHEMA_FACET_MINLENGTH:
17284 fminlen = facet; break;
17285 case XML_SCHEMA_FACET_MININCLUSIVE:
17286 fmininc = facet; break;
17287 case XML_SCHEMA_FACET_MINEXCLUSIVE:
17288 fminexc = facet; break;
17289 case XML_SCHEMA_FACET_MAXLENGTH:
17290 fmaxlen = facet; break;
17291 case XML_SCHEMA_FACET_MAXINCLUSIVE:
17292 fmaxinc = facet; break;
17293 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
17294 fmaxexc = facet; break;
17295 case XML_SCHEMA_FACET_TOTALDIGITS:
17296 ftotdig = facet; break;
17297 case XML_SCHEMA_FACET_FRACTIONDIGITS:
17298 ffracdig = facet; break;
17299 default:
17300 break;
17301 }
17302 }
17303 for (cur = base->facetSet; cur != NULL; cur = cur->next) {
17304 facet = cur->facet;
17305 switch (facet->type) {
17306 case XML_SCHEMA_FACET_LENGTH:
17307 bflength = facet; break;
17308 case XML_SCHEMA_FACET_MINLENGTH:
17309 bfminlen = facet; break;
17310 case XML_SCHEMA_FACET_MININCLUSIVE:
17311 bfmininc = facet; break;
17312 case XML_SCHEMA_FACET_MINEXCLUSIVE:
17313 bfminexc = facet; break;
17314 case XML_SCHEMA_FACET_MAXLENGTH:
17315 bfmaxlen = facet; break;
17316 case XML_SCHEMA_FACET_MAXINCLUSIVE:
17317 bfmaxinc = facet; break;
17318 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
17319 bfmaxexc = facet; break;
17320 case XML_SCHEMA_FACET_TOTALDIGITS:
17321 bftotdig = facet; break;
17322 case XML_SCHEMA_FACET_FRACTIONDIGITS:
17323 bffracdig = facet; break;
17324 default:
17325 break;
17326 }
17327 }
17328 /*
17329 * length and minLength or maxLength (2.2) + (3.2)
17330 */
17331 if (flength && (fminlen || fmaxlen)) {
17332 FACET_RESTR_ERR(flength, "It is an error for both 'length' and "
17333 "either of 'minLength' or 'maxLength' to be specified on "
17334 "the same type definition")
17335 }
17336 /*
17337 * Mutual exclusions in the same derivation step.
17338 */
17339 if ((fmaxinc) && (fmaxexc)) {
17340 /*
17341 * SCC "maxInclusive and maxExclusive"
17342 */
17343 FACET_RESTR_MUTUAL_ERR(fmaxinc, fmaxexc)
17344 }
17345 if ((fmininc) && (fminexc)) {
17346 /*
17347 * SCC "minInclusive and minExclusive"
17348 */
17349 FACET_RESTR_MUTUAL_ERR(fmininc, fminexc)
17350 }
17351
17352 if (flength && bflength) {
17353 /*
17354 * SCC "length valid restriction"
17355 * The values have to be equal.
17356 */
17357 res = xmlSchemaCompareValues(flength->val, bflength->val);
17358 if (res == -2)
17359 goto internal_error;
17360 if (res != 0)
17361 xmlSchemaDeriveFacetErr(pctxt, flength, bflength, 0, 0, 1);
17362 if ((res != 0) && (bflength->fixed)) {
17363 FACET_RESTR_FIXED_ERR(flength)
17364 }
17365
17366 }
17367 if (fminlen && bfminlen) {
17368 /*
17369 * SCC "minLength valid restriction"
17370 * minLength >= BASE minLength
17371 */
17372 res = xmlSchemaCompareValues(fminlen->val, bfminlen->val);
17373 if (res == -2)
17374 goto internal_error;
17375 if (res == -1)
17376 xmlSchemaDeriveFacetErr(pctxt, fminlen, bfminlen, 1, 1, 1);
17377 if ((res != 0) && (bfminlen->fixed)) {
17378 FACET_RESTR_FIXED_ERR(fminlen)
17379 }
17380 }
17381 if (fmaxlen && bfmaxlen) {
17382 /*
17383 * SCC "maxLength valid restriction"
17384 * maxLength <= BASE minLength
17385 */
17386 res = xmlSchemaCompareValues(fmaxlen->val, bfmaxlen->val);
17387 if (res == -2)
17388 goto internal_error;
17389 if (res == 1)
17390 xmlSchemaDeriveFacetErr(pctxt, fmaxlen, bfmaxlen, -1, 1, 1);
17391 if ((res != 0) && (bfmaxlen->fixed)) {
17392 FACET_RESTR_FIXED_ERR(fmaxlen)
17393 }
17394 }
17395 /*
17396 * SCC "length and minLength or maxLength"
17397 */
17398 if (! flength)
17399 flength = bflength;
17400 if (flength) {
17401 if (! fminlen)
17402 fminlen = bfminlen;
17403 if (fminlen) {
17404 /* (1.1) length >= minLength */
17405 res = xmlSchemaCompareValues(flength->val, fminlen->val);
17406 if (res == -2)
17407 goto internal_error;
17408 if (res == -1)
17409 xmlSchemaDeriveFacetErr(pctxt, flength, fminlen, 1, 1, 0);
17410 }
17411 if (! fmaxlen)
17412 fmaxlen = bfmaxlen;
17413 if (fmaxlen) {
17414 /* (2.1) length <= maxLength */
17415 res = xmlSchemaCompareValues(flength->val, fmaxlen->val);
17416 if (res == -2)
17417 goto internal_error;
17418 if (res == 1)
17419 xmlSchemaDeriveFacetErr(pctxt, flength, fmaxlen, -1, 1, 0);
17420 }
17421 }
17422 if (fmaxinc) {
17423 /*
17424 * "maxInclusive"
17425 */
17426 if (fmininc) {
17427 /* SCC "maxInclusive >= minInclusive" */
17428 res = xmlSchemaCompareValues(fmaxinc->val, fmininc->val);
17429 if (res == -2)
17430 goto internal_error;
17431 if (res == -1) {
17432 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, fmininc, 1, 1, 0);
17433 }
17434 }
17435 /*
17436 * SCC "maxInclusive valid restriction"
17437 */
17438 if (bfmaxinc) {
17439 /* maxInclusive <= BASE maxInclusive */
17440 res = xmlSchemaCompareValues(fmaxinc->val, bfmaxinc->val);
17441 if (res == -2)
17442 goto internal_error;
17443 if (res == 1)
17444 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmaxinc, -1, 1, 1);
17445 if ((res != 0) && (bfmaxinc->fixed)) {
17446 FACET_RESTR_FIXED_ERR(fmaxinc)
17447 }
17448 }
17449 if (bfmaxexc) {
17450 /* maxInclusive < BASE maxExclusive */
17451 res = xmlSchemaCompareValues(fmaxinc->val, bfmaxexc->val);
17452 if (res == -2)
17453 goto internal_error;
17454 if (res != -1) {
17455 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmaxexc, -1, 0, 1);
17456 }
17457 }
17458 if (bfmininc) {
17459 /* maxInclusive >= BASE minInclusive */
17460 res = xmlSchemaCompareValues(fmaxinc->val, bfmininc->val);
17461 if (res == -2)
17462 goto internal_error;
17463 if (res == -1) {
17464 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmininc, 1, 1, 1);
17465 }
17466 }
17467 if (bfminexc) {
17468 /* maxInclusive > BASE minExclusive */
17469 res = xmlSchemaCompareValues(fmaxinc->val, bfminexc->val);
17470 if (res == -2)
17471 goto internal_error;
17472 if (res != 1) {
17473 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfminexc, 1, 0, 1);
17474 }
17475 }
17476 }
17477 if (fmaxexc) {
17478 /*
17479 * "maxExclusive >= minExclusive"
17480 */
17481 if (fminexc) {
17482 res = xmlSchemaCompareValues(fmaxexc->val, fminexc->val);
17483 if (res == -2)
17484 goto internal_error;
17485 if (res == -1) {
17486 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, fminexc, 1, 1, 0);
17487 }
17488 }
17489 /*
17490 * "maxExclusive valid restriction"
17491 */
17492 if (bfmaxexc) {
17493 /* maxExclusive <= BASE maxExclusive */
17494 res = xmlSchemaCompareValues(fmaxexc->val, bfmaxexc->val);
17495 if (res == -2)
17496 goto internal_error;
17497 if (res == 1) {
17498 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmaxexc, -1, 1, 1);
17499 }
17500 if ((res != 0) && (bfmaxexc->fixed)) {
17501 FACET_RESTR_FIXED_ERR(fmaxexc)
17502 }
17503 }
17504 if (bfmaxinc) {
17505 /* maxExclusive <= BASE maxInclusive */
17506 res = xmlSchemaCompareValues(fmaxexc->val, bfmaxinc->val);
17507 if (res == -2)
17508 goto internal_error;
17509 if (res == 1) {
17510 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmaxinc, -1, 1, 1);
17511 }
17512 }
17513 if (bfmininc) {
17514 /* maxExclusive > BASE minInclusive */
17515 res = xmlSchemaCompareValues(fmaxexc->val, bfmininc->val);
17516 if (res == -2)
17517 goto internal_error;
17518 if (res != 1) {
17519 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmininc, 1, 0, 1);
17520 }
17521 }
17522 if (bfminexc) {
17523 /* maxExclusive > BASE minExclusive */
17524 res = xmlSchemaCompareValues(fmaxexc->val, bfminexc->val);
17525 if (res == -2)
17526 goto internal_error;
17527 if (res != 1) {
17528 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfminexc, 1, 0, 1);
17529 }
17530 }
17531 }
17532 if (fminexc) {
17533 /*
17534 * "minExclusive < maxInclusive"
17535 */
17536 if (fmaxinc) {
17537 res = xmlSchemaCompareValues(fminexc->val, fmaxinc->val);
17538 if (res == -2)
17539 goto internal_error;
17540 if (res != -1) {
17541 xmlSchemaDeriveFacetErr(pctxt, fminexc, fmaxinc, -1, 0, 0);
17542 }
17543 }
17544 /*
17545 * "minExclusive valid restriction"
17546 */
17547 if (bfminexc) {
17548 /* minExclusive >= BASE minExclusive */
17549 res = xmlSchemaCompareValues(fminexc->val, bfminexc->val);
17550 if (res == -2)
17551 goto internal_error;
17552 if (res == -1) {
17553 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfminexc, 1, 1, 1);
17554 }
17555 if ((res != 0) && (bfminexc->fixed)) {
17556 FACET_RESTR_FIXED_ERR(fminexc)
17557 }
17558 }
17559 if (bfmaxinc) {
17560 /* minExclusive <= BASE maxInclusive */
17561 res = xmlSchemaCompareValues(fminexc->val, bfmaxinc->val);
17562 if (res == -2)
17563 goto internal_error;
17564 if (res == 1) {
17565 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmaxinc, -1, 1, 1);
17566 }
17567 }
17568 if (bfmininc) {
17569 /* minExclusive >= BASE minInclusive */
17570 res = xmlSchemaCompareValues(fminexc->val, bfmininc->val);
17571 if (res == -2)
17572 goto internal_error;
17573 if (res == -1) {
17574 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmininc, 1, 1, 1);
17575 }
17576 }
17577 if (bfmaxexc) {
17578 /* minExclusive < BASE maxExclusive */
17579 res = xmlSchemaCompareValues(fminexc->val, bfmaxexc->val);
17580 if (res == -2)
17581 goto internal_error;
17582 if (res != -1) {
17583 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmaxexc, -1, 0, 1);
17584 }
17585 }
17586 }
17587 if (fmininc) {
17588 /*
17589 * "minInclusive < maxExclusive"
17590 */
17591 if (fmaxexc) {
17592 res = xmlSchemaCompareValues(fmininc->val, fmaxexc->val);
17593 if (res == -2)
17594 goto internal_error;
17595 if (res != -1) {
17596 xmlSchemaDeriveFacetErr(pctxt, fmininc, fmaxexc, -1, 0, 0);
17597 }
17598 }
17599 /*
17600 * "minExclusive valid restriction"
17601 */
17602 if (bfmininc) {
17603 /* minInclusive >= BASE minInclusive */
17604 res = xmlSchemaCompareValues(fmininc->val, bfmininc->val);
17605 if (res == -2)
17606 goto internal_error;
17607 if (res == -1) {
17608 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmininc, 1, 1, 1);
17609 }
17610 if ((res != 0) && (bfmininc->fixed)) {
17611 FACET_RESTR_FIXED_ERR(fmininc)
17612 }
17613 }
17614 if (bfmaxinc) {
17615 /* minInclusive <= BASE maxInclusive */
17616 res = xmlSchemaCompareValues(fmininc->val, bfmaxinc->val);
17617 if (res == -2)
17618 goto internal_error;
17619 if (res == 1) {
17620 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmaxinc, -1, 1, 1);
17621 }
17622 }
17623 if (bfminexc) {
17624 /* minInclusive > BASE minExclusive */
17625 res = xmlSchemaCompareValues(fmininc->val, bfminexc->val);
17626 if (res == -2)
17627 goto internal_error;
17628 if (res != 1)
17629 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfminexc, 1, 0, 1);
17630 }
17631 if (bfmaxexc) {
17632 /* minInclusive < BASE maxExclusive */
17633 res = xmlSchemaCompareValues(fmininc->val, bfmaxexc->val);
17634 if (res == -2)
17635 goto internal_error;
17636 if (res != -1)
17637 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmaxexc, -1, 0, 1);
17638 }
17639 }
17640 if (ftotdig && bftotdig) {
17641 /*
17642 * SCC " totalDigits valid restriction"
17643 * totalDigits <= BASE totalDigits
17644 */
17645 res = xmlSchemaCompareValues(ftotdig->val, bftotdig->val);
17646 if (res == -2)
17647 goto internal_error;
17648 if (res == 1)
17649 xmlSchemaDeriveFacetErr(pctxt, ftotdig, bftotdig,
17650 -1, 1, 1);
17651 if ((res != 0) && (bftotdig->fixed)) {
17652 FACET_RESTR_FIXED_ERR(ftotdig)
17653 }
17654 }
17655 if (ffracdig && bffracdig) {
17656 /*
17657 * SCC "fractionDigits valid restriction"
17658 * fractionDigits <= BASE fractionDigits
17659 */
17660 res = xmlSchemaCompareValues(ffracdig->val, bffracdig->val);
17661 if (res == -2)
17662 goto internal_error;
17663 if (res == 1)
17664 xmlSchemaDeriveFacetErr(pctxt, ffracdig, bffracdig,
17665 -1, 1, 1);
17666 if ((res != 0) && (bffracdig->fixed)) {
17667 FACET_RESTR_FIXED_ERR(ffracdig)
17668 }
17669 }
17670 /*
17671 * SCC "fractionDigits less than or equal to totalDigits"
17672 */
17673 if (! ftotdig)
17674 ftotdig = bftotdig;
17675 if (! ffracdig)
17676 ffracdig = bffracdig;
17677 if (ftotdig && ffracdig) {
17678 res = xmlSchemaCompareValues(ffracdig->val, ftotdig->val);
17679 if (res == -2)
17680 goto internal_error;
17681 if (res == 1)
17682 xmlSchemaDeriveFacetErr(pctxt, ffracdig, ftotdig,
17683 -1, 1, 0);
17684 }
17685 /*
17686 * *Enumerations* won' be added here, since only the first set
17687 * of enumerations in the ancestor-or-self axis is used
17688 * for validation, plus we need to use the base type of those
17689 * enumerations for whitespace.
17690 *
17691 * *Patterns*: won't be add here, since they are ORed at
17692 * type level and ANDed at ancestor level. This will
17693 * happen during validation by walking the base axis
17694 * of the type.
17695 */
17696 for (cur = base->facetSet; cur != NULL; cur = cur->next) {
17697 bfacet = cur->facet;
17698 /*
17699 * Special handling of enumerations and patterns.
17700 * TODO: hmm, they should not appear in the set, so remove this.
17701 */
17702 if ((bfacet->type == XML_SCHEMA_FACET_PATTERN) ||
17703 (bfacet->type == XML_SCHEMA_FACET_ENUMERATION))
17704 continue;
17705 /*
17706 * Search for a duplicate facet in the current type.
17707 */
17708 link = type->facetSet;
17709 /* err = 0; */
17710 /* fixedErr = 0; */
17711 while (link != NULL) {
17712 facet = link->facet;
17713 if (facet->type == bfacet->type) {
17714 switch (facet->type) {
17715 case XML_SCHEMA_FACET_WHITESPACE:
17716 /*
17717 * The whitespace must be stronger.
17718 */
17719 if (facet->whitespace < bfacet->whitespace) {
17720 FACET_RESTR_ERR(facet,
17721 "The 'whitespace' value has to be equal to "
17722 "or stronger than the 'whitespace' value of "
17723 "the base type")
17724 }
17725 if ((bfacet->fixed) &&
17726 (facet->whitespace != bfacet->whitespace)) {
17727 FACET_RESTR_FIXED_ERR(facet)
17728 }
17729 break;
17730 default:
17731 break;
17732 }
17733 /* Duplicate found. */
17734 break;
17735 }
17736 link = link->next;
17737 }
17738 /*
17739 * If no duplicate was found: add the base types's facet
17740 * to the set.
17741 */
17742 if (link == NULL) {
17743 link = (xmlSchemaFacetLinkPtr)
17744 xmlMalloc(sizeof(xmlSchemaFacetLink));
17745 if (link == NULL) {
17746 xmlSchemaPErrMemory(pctxt,
17747 "deriving facets, creating a facet link", NULL);
17748 return (-1);
17749 }
17750 link->facet = cur->facet;
17751 link->next = NULL;
17752 if (last == NULL)
17753 type->facetSet = link;
17754 else
17755 last->next = link;
17756 last = link;
17757 }
17758
17759 }
17760
17761 return (0);
17762internal_error:
17763 PERROR_INT("xmlSchemaDeriveAndValidateFacets",
17764 "an error occurred");
17765 return (-1);
17766}
17767
17768static int
17769xmlSchemaFinishMemberTypeDefinitionsProperty(xmlSchemaParserCtxtPtr pctxt,
17770 xmlSchemaTypePtr type)
17771{
17772 xmlSchemaTypeLinkPtr link, lastLink, prevLink, subLink, newLink;
17773 /*
17774 * The actual value is then formed by replacing any union type
17775 * definition in the `explicit members` with the members of their
17776 * {member type definitions}, in order.
17777 *
17778 * TODO: There's a bug entry at
17779 * "http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005JulSep/0287.html"
17780 * which indicates that we'll keep the union types the future.
17781 */
17782 link = type->memberTypes;
17783 while (link != NULL) {
17784
17785 if (WXS_IS_TYPE_NOT_FIXED(link->type))
17786 xmlSchemaTypeFixup(link->type, ACTXT_CAST pctxt);
17787
17788 if (WXS_IS_UNION(link->type)) {
17789 subLink = xmlSchemaGetUnionSimpleTypeMemberTypes(link->type);
17790 if (subLink != NULL) {
17791 link->type = subLink->type;
17792 if (subLink->next != NULL) {
17793 lastLink = link->next;
17794 subLink = subLink->next;
17795 prevLink = link;
17796 while (subLink != NULL) {
17797 newLink = (xmlSchemaTypeLinkPtr)
17798 xmlMalloc(sizeof(xmlSchemaTypeLink));
17799 if (newLink == NULL) {
17800 xmlSchemaPErrMemory(pctxt, "allocating a type link",
17801 NULL);
17802 return (-1);
17803 }
17804 newLink->type = subLink->type;
17805 prevLink->next = newLink;
17806 prevLink = newLink;
17807 newLink->next = lastLink;
17808
17809 subLink = subLink->next;
17810 }
17811 }
17812 }
17813 }
17814 link = link->next;
17815 }
17816 return (0);
17817}
17818
17819static void
17820xmlSchemaTypeFixupOptimFacets(xmlSchemaTypePtr type)
17821{
17822 int has = 0, needVal = 0, normVal = 0;
17823
17824 has = (type->baseType->flags & XML_SCHEMAS_TYPE_HAS_FACETS) ? 1 : 0;
17825 if (has) {
17826 needVal = (type->baseType->flags &
17827 XML_SCHEMAS_TYPE_FACETSNEEDVALUE) ? 1 : 0;
17828 normVal = (type->baseType->flags &
17829 XML_SCHEMAS_TYPE_NORMVALUENEEDED) ? 1 : 0;
17830 }
17831 if (type->facets != NULL) {
17832 xmlSchemaFacetPtr fac;
17833
17834 for (fac = type->facets; fac != NULL; fac = fac->next) {
17835 switch (fac->type) {
17836 case XML_SCHEMA_FACET_WHITESPACE:
17837 break;
17838 case XML_SCHEMA_FACET_PATTERN:
17839 normVal = 1;
17840 has = 1;
17841 break;
17842 case XML_SCHEMA_FACET_ENUMERATION:
17843 needVal = 1;
17844 normVal = 1;
17845 has = 1;
17846 break;
17847 default:
17848 has = 1;
17849 break;
17850 }
17851 }
17852 }
17853 if (normVal)
17854 type->flags |= XML_SCHEMAS_TYPE_NORMVALUENEEDED;
17855 if (needVal)
17856 type->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
17857 if (has)
17858 type->flags |= XML_SCHEMAS_TYPE_HAS_FACETS;
17859
17860 if (has && (! needVal) && WXS_IS_ATOMIC(type)) {
17861 xmlSchemaTypePtr prim = xmlSchemaGetPrimitiveType(type);
17862 /*
17863 * OPTIMIZE VAL TODO: Some facets need a computed value.
17864 */
17865 if ((prim->builtInType != XML_SCHEMAS_ANYSIMPLETYPE) &&
17866 (prim->builtInType != XML_SCHEMAS_STRING)) {
17867 type->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
17868 }
17869 }
17870}
17871
17872static int
17873xmlSchemaTypeFixupWhitespace(xmlSchemaTypePtr type)
17874{
17875
17876
17877 /*
17878 * Evaluate the whitespace-facet value.
17879 */
17880 if (WXS_IS_LIST(type)) {
17881 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
17882 return (0);
17883 } else if (WXS_IS_UNION(type))
17884 return (0);
17885
17886 if (type->facetSet != NULL) {
17887 xmlSchemaFacetLinkPtr lin;
17888
17889 for (lin = type->facetSet; lin != NULL; lin = lin->next) {
17890 if (lin->facet->type == XML_SCHEMA_FACET_WHITESPACE) {
17891 switch (lin->facet->whitespace) {
17892 case XML_SCHEMAS_FACET_PRESERVE:
17893 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE;
17894 break;
17895 case XML_SCHEMAS_FACET_REPLACE:
17896 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_REPLACE;
17897 break;
17898 case XML_SCHEMAS_FACET_COLLAPSE:
17899 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
17900 break;
17901 default:
17902 return (-1);
17903 }
17904 return (0);
17905 }
17906 }
17907 }
17908 /*
17909 * For all `atomic` datatypes other than string (and types `derived`
17910 * by `restriction` from it) the value of whiteSpace is fixed to
17911 * collapse
17912 */
17913 {
17914 xmlSchemaTypePtr anc;
17915
17916 for (anc = type->baseType; anc != NULL &&
17917 anc->builtInType != XML_SCHEMAS_ANYTYPE;
17918 anc = anc->baseType) {
17919
17920 if (anc->type == XML_SCHEMA_TYPE_BASIC) {
17921 if (anc->builtInType == XML_SCHEMAS_NORMSTRING) {
17922 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_REPLACE;
17923
17924 } else if ((anc->builtInType == XML_SCHEMAS_STRING) ||
17925 (anc->builtInType == XML_SCHEMAS_ANYSIMPLETYPE)) {
17926 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE;
17927
17928 } else
17929 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
17930 break;
17931 }
17932 }
17933 }
17934 return (0);
17935}
17936
17937static int
17938xmlSchemaFixupSimpleTypeStageOne(xmlSchemaParserCtxtPtr pctxt,
17939 xmlSchemaTypePtr type)
17940{
17941 if (type->type != XML_SCHEMA_TYPE_SIMPLE)
17942 return(0);
17943 if (! WXS_IS_TYPE_NOT_FIXED_1(type))
17944 return(0);
17945 type->flags |= XML_SCHEMAS_TYPE_FIXUP_1;
17946
17947 if (WXS_IS_LIST(type)) {
17948 /*
17949 * Corresponds to <simpleType><list>...
17950 */
17951 if (type->subtypes == NULL) {
17952 /*
17953 * This one is really needed, so get out.
17954 */
17955 PERROR_INT("xmlSchemaFixupSimpleTypeStageOne",
17956 "list type has no item-type assigned");
17957 return(-1);
17958 }
17959 } else if (WXS_IS_UNION(type)) {
17960 /*
17961 * Corresponds to <simpleType><union>...
17962 */
17963 if (type->memberTypes == NULL) {
17964 /*
17965 * This one is really needed, so get out.
17966 */
17967 PERROR_INT("xmlSchemaFixupSimpleTypeStageOne",
17968 "union type has no member-types assigned");
17969 return(-1);
17970 }
17971 } else {
17972 /*
17973 * Corresponds to <simpleType><restriction>...
17974 */
17975 if (type->baseType == NULL) {
17976 PERROR_INT("xmlSchemaFixupSimpleTypeStageOne",
17977 "type has no base-type assigned");
17978 return(-1);
17979 }
17980 if (WXS_IS_TYPE_NOT_FIXED_1(type->baseType))
17981 if (xmlSchemaFixupSimpleTypeStageOne(pctxt, type->baseType) == -1)
17982 return(-1);
17983 /*
17984 * Variety
17985 * If the <restriction> alternative is chosen, then the
17986 * {variety} of the {base type definition}.
17987 */
17988 if (WXS_IS_ATOMIC(type->baseType))
17989 type->flags |= XML_SCHEMAS_TYPE_VARIETY_ATOMIC;
17990 else if (WXS_IS_LIST(type->baseType)) {
17991 type->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
17992 /*
17993 * Inherit the itemType.
17994 */
17995 type->subtypes = type->baseType->subtypes;
17996 } else if (WXS_IS_UNION(type->baseType)) {
17997 type->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
17998 /*
17999 * NOTE that we won't assign the memberTypes of the base,
18000 * since this will make trouble when freeing them; we will
18001 * use a lookup function to access them instead.
18002 */
18003 }
18004 }
18005 return(0);
18006}
18007
18008/*
18009* 3.14.6 Constraints on Simple Type Definition Schema Components
18010*/
18011static int
18012xmlSchemaFixupSimpleTypeStageTwo(xmlSchemaParserCtxtPtr pctxt,
18013 xmlSchemaTypePtr type)
18014{
18015 int res, olderrs = pctxt->nberrors;
18016
18017 if (type->type != XML_SCHEMA_TYPE_SIMPLE)
18018 return(-1);
18019
18020 if (! WXS_IS_TYPE_NOT_FIXED(type))
18021 return(0);
18022
18023 type->flags |= XML_SCHEMAS_TYPE_INTERNAL_RESOLVED;
18024 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
18025
18026 if (type->baseType == NULL) {
18027 PERROR_INT("xmlSchemaFixupSimpleTypeStageTwo",
18028 "missing baseType");
18029 goto exit_failure;
18030 }
18031 if (WXS_IS_TYPE_NOT_FIXED(type->baseType))
18032 xmlSchemaTypeFixup(type->baseType, ACTXT_CAST pctxt);
18033 /*
18034 * If a member type of a union is a union itself, we need to substitute
18035 * that member type for its member types.
18036 * NOTE that this might change in WXS 1.1; i.e. we will keep the union
18037 * types in WXS 1.1.
18038 */
18039 if ((type->memberTypes != NULL) &&
18040 (xmlSchemaFinishMemberTypeDefinitionsProperty(pctxt, type) == -1))
18041 return(-1);
18042 /*
18043 * SPEC src-simple-type 1
18044 * "The corresponding simple type definition, if any, must satisfy
18045 * the conditions set out in Constraints on Simple Type Definition
18046 * Schema Components ($3.14.6)."
18047 */
18048 /*
18049 * Schema Component Constraint: Simple Type Definition Properties Correct
18050 * (st-props-correct)
18051 */
18052 res = xmlSchemaCheckSTPropsCorrect(pctxt, type);
18053 HFAILURE HERROR
18054 /*
18055 * Schema Component Constraint: Derivation Valid (Restriction, Simple)
18056 * (cos-st-restricts)
18057 */
18058 res = xmlSchemaCheckCOSSTRestricts(pctxt, type);
18059 HFAILURE HERROR
18060 /*
18061 * TODO: Removed the error report, since it got annoying to get an
18062 * extra error report, if anything failed until now.
18063 * Enable this if needed.
18064 *
18065 * xmlSchemaPErr(ctxt, type->node,
18066 * XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
18067 * "Simple type '%s' does not satisfy the constraints "
18068 * "on simple type definitions.\n",
18069 * type->name, NULL);
18070 */
18071 /*
18072 * Schema Component Constraint: Simple Type Restriction (Facets)
18073 * (st-restrict-facets)
18074 */
18075 res = xmlSchemaCheckFacetValues(type, pctxt);
18076 HFAILURE HERROR
18077 if ((type->facetSet != NULL) ||
18078 (type->baseType->facetSet != NULL)) {
18079 res = xmlSchemaDeriveAndValidateFacets(pctxt, type);
18080 HFAILURE HERROR
18081 }
18082 /*
18083 * Whitespace value.
18084 */
18085 res = xmlSchemaTypeFixupWhitespace(type);
18086 HFAILURE HERROR
18087 xmlSchemaTypeFixupOptimFacets(type);
18088
18089exit_error:
18090 if (olderrs != pctxt->nberrors)
18091 return(pctxt->err);
18092 return(0);
18093
18094exit_failure:
18095 return(-1);
18096}
18097
18098static int
18099xmlSchemaFixupComplexType(xmlSchemaParserCtxtPtr pctxt,
18100 xmlSchemaTypePtr type)
18101{
18102 int res = 0, olderrs = pctxt->nberrors;
18103 xmlSchemaTypePtr baseType = type->baseType;
18104
18105 if (! WXS_IS_TYPE_NOT_FIXED(type))
18106 return(0);
18107 type->flags |= XML_SCHEMAS_TYPE_INTERNAL_RESOLVED;
18108 if (baseType == NULL) {
18109 PERROR_INT("xmlSchemaFixupComplexType",
18110 "missing baseType");
18111 goto exit_failure;
18112 }
18113 /*
18114 * Fixup the base type.
18115 */
18116 if (WXS_IS_TYPE_NOT_FIXED(baseType))
18117 xmlSchemaTypeFixup(baseType, ACTXT_CAST pctxt);
18118 if (baseType->flags & XML_SCHEMAS_TYPE_INTERNAL_INVALID) {
18119 /*
18120 * Skip fixup if the base type is invalid.
18121 * TODO: Generate a warning!
18122 */
18123 return(0);
18124 }
18125 /*
18126 * This basically checks if the base type can be derived.
18127 */
18128 res = xmlSchemaCheckSRCCT(pctxt, type);
18129 HFAILURE HERROR
18130 /*
18131 * Fixup the content type.
18132 */
18133 if (type->contentType == XML_SCHEMA_CONTENT_SIMPLE) {
18134 /*
18135 * Corresponds to <complexType><simpleContent>...
18136 */
18137 if ((WXS_IS_COMPLEX(baseType)) &&
18138 (baseType->contentTypeDef != NULL) &&
18139 (WXS_IS_RESTRICTION(type))) {
18140 xmlSchemaTypePtr contentBase, content;
18141#ifdef ENABLE_NAMED_LOCALS
18142 char buf[30];
18143 const xmlChar *tmpname;
18144#endif
18145 /*
18146 * SPEC (1) If <restriction> + base type is <complexType>,
18147 * "whose own {content type} is a simple type..."
18148 */
18149 if (type->contentTypeDef != NULL) {
18150 /*
18151 * SPEC (1.1) "the simple type definition corresponding to the
18152 * <simpleType> among the [children] of <restriction> if there
18153 * is one;"
18154 * Note that this "<simpleType> among the [children]" was put
18155 * into ->contentTypeDef during parsing.
18156 */
18157 contentBase = type->contentTypeDef;
18158 type->contentTypeDef = NULL;
18159 } else {
18160 /*
18161 * (1.2) "...otherwise (<restriction> has no <simpleType>
18162 * among its [children]), the simple type definition which
18163 * is the {content type} of the ... base type."
18164 */
18165 contentBase = baseType->contentTypeDef;
18166 }
18167 /*
18168 * SPEC
18169 * "... a simple type definition which restricts the simple
18170 * type definition identified in clause 1.1 or clause 1.2
18171 * with a set of facet components"
18172 *
18173 * Create the anonymous simple type, which will be the content
18174 * type of the complex type.
18175 */
18176#ifdef ENABLE_NAMED_LOCALS
18177 snprintf(buf, 29, "#scST%d", ++(pctxt->counter));
18178 tmpname = xmlDictLookup(pctxt->dict, BAD_CAST buf, -1);
18179 content = xmlSchemaAddType(pctxt, pctxt->schema,
18180 XML_SCHEMA_TYPE_SIMPLE, tmpname, type->targetNamespace,
18181 type->node, 0);
18182#else
18183 content = xmlSchemaAddType(pctxt, pctxt->schema,
18184 XML_SCHEMA_TYPE_SIMPLE, NULL, type->targetNamespace,
18185 type->node, 0);
18186#endif
18187 if (content == NULL)
18188 goto exit_failure;
18189 /*
18190 * We will use the same node as for the <complexType>
18191 * to have it somehow anchored in the schema doc.
18192 */
18193 content->type = XML_SCHEMA_TYPE_SIMPLE;
18194 content->baseType = contentBase;
18195 /*
18196 * Move the facets, previously anchored on the
18197 * complexType during parsing.
18198 */
18199 content->facets = type->facets;
18200 type->facets = NULL;
18201 content->facetSet = type->facetSet;
18202 type->facetSet = NULL;
18203
18204 type->contentTypeDef = content;
18205 if (WXS_IS_TYPE_NOT_FIXED(contentBase))
18206 xmlSchemaTypeFixup(contentBase, ACTXT_CAST pctxt);
18207 /*
18208 * Fixup the newly created type. We don't need to check
18209 * for circularity here.
18210 */
18211 res = xmlSchemaFixupSimpleTypeStageOne(pctxt, content);
18212 HFAILURE HERROR
18213 res = xmlSchemaFixupSimpleTypeStageTwo(pctxt, content);
18214 HFAILURE HERROR
18215
18216 } else if ((WXS_IS_COMPLEX(baseType)) &&
18217 (baseType->contentType == XML_SCHEMA_CONTENT_MIXED) &&
18218 (WXS_IS_RESTRICTION(type))) {
18219 /*
18220 * SPEC (2) If <restriction> + base is a mixed <complexType> with
18221 * an emptiable particle, then a simple type definition which
18222 * restricts the <restriction>'s <simpleType> child.
18223 */
18224 if ((type->contentTypeDef == NULL) ||
18225 (type->contentTypeDef->baseType == NULL)) {
18226 /*
18227 * TODO: Check if this ever happens.
18228 */
18229 xmlSchemaPCustomErr(pctxt,
18231 WXS_BASIC_CAST type, NULL,
18232 "Internal error: xmlSchemaTypeFixup, "
18233 "complex type '%s': the <simpleContent><restriction> "
18234 "is missing a <simpleType> child, but was not caught "
18235 "by xmlSchemaCheckSRCCT()", type->name);
18236 goto exit_failure;
18237 }
18238 } else if ((WXS_IS_COMPLEX(baseType)) && WXS_IS_EXTENSION(type)) {
18239 /*
18240 * SPEC (3) If <extension> + base is <complexType> with
18241 * <simpleType> content, "...then the {content type} of that
18242 * complex type definition"
18243 */
18244 if (baseType->contentTypeDef == NULL) {
18245 /*
18246 * TODO: Check if this ever happens. xmlSchemaCheckSRCCT
18247 * should have caught this already.
18248 */
18249 xmlSchemaPCustomErr(pctxt,
18251 WXS_BASIC_CAST type, NULL,
18252 "Internal error: xmlSchemaTypeFixup, "
18253 "complex type '%s': the <extension>ed base type is "
18254 "a complex type with no simple content type",
18255 type->name);
18256 goto exit_failure;
18257 }
18258 type->contentTypeDef = baseType->contentTypeDef;
18259 } else if ((WXS_IS_SIMPLE(baseType)) && WXS_IS_EXTENSION(type)) {
18260 /*
18261 * SPEC (4) <extension> + base is <simpleType>
18262 * "... then that simple type definition"
18263 */
18264 type->contentTypeDef = baseType;
18265 } else {
18266 /*
18267 * TODO: Check if this ever happens.
18268 */
18269 xmlSchemaPCustomErr(pctxt,
18271 WXS_BASIC_CAST type, NULL,
18272 "Internal error: xmlSchemaTypeFixup, "
18273 "complex type '%s' with <simpleContent>: unhandled "
18274 "derivation case", type->name);
18275 goto exit_failure;
18276 }
18277 } else {
18278 int dummySequence = 0;
18279 xmlSchemaParticlePtr particle =
18280 (xmlSchemaParticlePtr) type->subtypes;
18281 /*
18282 * Corresponds to <complexType><complexContent>...
18283 *
18284 * NOTE that the effective mixed was already set during parsing of
18285 * <complexType> and <complexContent>; its flag value is
18286 * XML_SCHEMAS_TYPE_MIXED.
18287 *
18288 * Compute the "effective content":
18289 * (2.1.1) + (2.1.2) + (2.1.3)
18290 */
18291 if ((particle == NULL) ||
18292 ((particle->type == XML_SCHEMA_TYPE_PARTICLE) &&
18293 ((particle->children->type == XML_SCHEMA_TYPE_ALL) ||
18294 (particle->children->type == XML_SCHEMA_TYPE_SEQUENCE) ||
18295 ((particle->children->type == XML_SCHEMA_TYPE_CHOICE) &&
18296 (particle->minOccurs == 0))) &&
18297 ( ((xmlSchemaTreeItemPtr) particle->children)->children == NULL))) {
18298 if (type->flags & XML_SCHEMAS_TYPE_MIXED) {
18299 /*
18300 * SPEC (2.1.4) "If the `effective mixed` is true, then
18301 * a particle whose properties are as follows:..."
18302 *
18303 * Empty sequence model group with
18304 * minOccurs/maxOccurs = 1 (i.e. a "particle emptiable").
18305 * NOTE that we sill assign it the <complexType> node to
18306 * somehow anchor it in the doc.
18307 */
18308 if ((particle == NULL) ||
18309 (particle->children->type != XML_SCHEMA_TYPE_SEQUENCE)) {
18310 /*
18311 * Create the particle.
18312 */
18313 particle = xmlSchemaAddParticle(pctxt,
18314 type->node, 1, 1);
18315 if (particle == NULL)
18316 goto exit_failure;
18317 /*
18318 * Create the model group.
18319 */ /* URGENT TODO: avoid adding to pending items. */
18320 particle->children = (xmlSchemaTreeItemPtr)
18321 xmlSchemaAddModelGroup(pctxt, pctxt->schema,
18322 XML_SCHEMA_TYPE_SEQUENCE, type->node);
18323 if (particle->children == NULL)
18324 goto exit_failure;
18325
18326 type->subtypes = (xmlSchemaTypePtr) particle;
18327 }
18328 dummySequence = 1;
18329 type->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
18330 } else {
18331 /*
18332 * SPEC (2.1.5) "otherwise empty"
18333 */
18334 type->contentType = XML_SCHEMA_CONTENT_EMPTY;
18335 }
18336 } else {
18337 /*
18338 * SPEC (2.2) "otherwise the particle corresponding to the
18339 * <all>, <choice>, <group> or <sequence> among the
18340 * [children]."
18341 */
18342 type->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
18343 }
18344 /*
18345 * Compute the "content type".
18346 */
18347 if (WXS_IS_RESTRICTION(type)) {
18348 /*
18349 * SPEC (3.1) "If <restriction>..."
18350 * (3.1.1) + (3.1.2) */
18351 if (type->contentType != XML_SCHEMA_CONTENT_EMPTY) {
18352 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
18353 type->contentType = XML_SCHEMA_CONTENT_MIXED;
18354 }
18355 } else {
18356 /*
18357 * SPEC (3.2) "If <extension>..."
18358 */
18359 if (type->contentType == XML_SCHEMA_CONTENT_EMPTY) {
18360 /*
18361 * SPEC (3.2.1)
18362 * "If the `effective content` is empty, then the
18363 * {content type} of the [...] base ..."
18364 */
18365 type->contentType = baseType->contentType;
18366 type->subtypes = baseType->subtypes;
18367 /*
18368 * Fixes bug #347316:
18369 * This is the case when the base type has a simple
18370 * type definition as content.
18371 */
18372 type->contentTypeDef = baseType->contentTypeDef;
18373 /*
18374 * NOTE that the effective mixed is ignored here.
18375 */
18376 } else if (baseType->contentType == XML_SCHEMA_CONTENT_EMPTY) {
18377 /*
18378 * SPEC (3.2.2)
18379 */
18380 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
18381 type->contentType = XML_SCHEMA_CONTENT_MIXED;
18382 } else {
18383 /*
18384 * SPEC (3.2.3)
18385 */
18386 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
18387 type->contentType = XML_SCHEMA_CONTENT_MIXED;
18388 /*
18389 * "A model group whose {compositor} is sequence and whose
18390 * {particles} are..."
18391 */
18392 if ((WXS_TYPE_PARTICLE(type) != NULL) &&
18393 (WXS_TYPE_PARTICLE_TERM(type) != NULL) &&
18394 ((WXS_TYPE_PARTICLE_TERM(type))->type ==
18395 XML_SCHEMA_TYPE_ALL))
18396 {
18397 /*
18398 * SPEC cos-all-limited (1)
18399 */
18400 xmlSchemaCustomErr(ACTXT_CAST pctxt,
18401 /* TODO: error code */
18403 WXS_ITEM_NODE(type), NULL,
18404 "The type has an 'all' model group in its "
18405 "{content type} and thus cannot be derived from "
18406 "a non-empty type, since this would produce a "
18407 "'sequence' model group containing the 'all' "
18408 "model group; 'all' model groups are not "
18409 "allowed to appear inside other model groups",
18410 NULL, NULL);
18411
18412 } else if ((WXS_TYPE_PARTICLE(baseType) != NULL) &&
18413 (WXS_TYPE_PARTICLE_TERM(baseType) != NULL) &&
18414 ((WXS_TYPE_PARTICLE_TERM(baseType))->type ==
18415 XML_SCHEMA_TYPE_ALL))
18416 {
18417 /*
18418 * SPEC cos-all-limited (1)
18419 */
18420 xmlSchemaCustomErr(ACTXT_CAST pctxt,
18421 /* TODO: error code */
18423 WXS_ITEM_NODE(type), NULL,
18424 "A type cannot be derived by extension from a type "
18425 "which has an 'all' model group in its "
18426 "{content type}, since this would produce a "
18427 "'sequence' model group containing the 'all' "
18428 "model group; 'all' model groups are not "
18429 "allowed to appear inside other model groups",
18430 NULL, NULL);
18431
18432 } else if ((!dummySequence) && (baseType->subtypes != NULL)) {
18433 xmlSchemaTreeItemPtr effectiveContent =
18434 (xmlSchemaTreeItemPtr) type->subtypes;
18435 /*
18436 * Create the particle.
18437 */
18438 particle = xmlSchemaAddParticle(pctxt,
18439 type->node, 1, 1);
18440 if (particle == NULL)
18441 goto exit_failure;
18442 /*
18443 * Create the "sequence" model group.
18444 */
18445 particle->children = (xmlSchemaTreeItemPtr)
18446 xmlSchemaAddModelGroup(pctxt, pctxt->schema,
18447 XML_SCHEMA_TYPE_SEQUENCE, type->node);
18448 if (particle->children == NULL)
18449 goto exit_failure;
18450 WXS_TYPE_CONTENTTYPE(type) = (xmlSchemaTypePtr) particle;
18451 /*
18452 * SPEC "the particle of the {content type} of
18453 * the ... base ..."
18454 * Create a duplicate of the base type's particle
18455 * and assign its "term" to it.
18456 */
18457 particle->children->children =
18458 (xmlSchemaTreeItemPtr) xmlSchemaAddParticle(pctxt,
18459 type->node,
18460 ((xmlSchemaParticlePtr) baseType->subtypes)->minOccurs,
18461 ((xmlSchemaParticlePtr) baseType->subtypes)->maxOccurs);
18462 if (particle->children->children == NULL)
18463 goto exit_failure;
18464 particle = (xmlSchemaParticlePtr)
18465 particle->children->children;
18466 particle->children =
18467 ((xmlSchemaParticlePtr) baseType->subtypes)->children;
18468 /*
18469 * SPEC "followed by the `effective content`."
18470 */
18471 particle->next = effectiveContent;
18472 /*
18473 * This all will result in:
18474 * new-particle
18475 * --> new-sequence(
18476 * new-particle
18477 * --> base-model,
18478 * this-particle
18479 * --> this-model
18480 * )
18481 */
18482 } else {
18483 /*
18484 * This is the case when there is already an empty
18485 * <sequence> with minOccurs==maxOccurs==1.
18486 * Just add the base types's content type.
18487 * NOTE that, although we miss to add an intermediate
18488 * <sequence>, this should produce no difference to
18489 * neither the regex compilation of the content model,
18490 * nor to the complex type constraints.
18491 */
18492 particle->children->children =
18493 (xmlSchemaTreeItemPtr) baseType->subtypes;
18494 }
18495 }
18496 }
18497 }
18498 /*
18499 * Now fixup attribute uses:
18500 * - expand attr. group references
18501 * - intersect attribute wildcards
18502 * - inherit attribute uses of the base type
18503 * - inherit or union attr. wildcards if extending
18504 * - apply attr. use prohibitions if restricting
18505 */
18506 res = xmlSchemaFixupTypeAttributeUses(pctxt, type);
18507 HFAILURE HERROR
18508 /*
18509 * Apply the complex type component constraints; this will not
18510 * check attributes, since this is done in
18511 * xmlSchemaFixupTypeAttributeUses().
18512 */
18513 res = xmlSchemaCheckCTComponent(pctxt, type);
18514 HFAILURE HERROR
18515
18516 if (olderrs != pctxt->nberrors)
18517 return(pctxt->err);
18518 else
18519 return(0);
18520
18521exit_error:
18522 type->flags |= XML_SCHEMAS_TYPE_INTERNAL_INVALID;
18523 return(pctxt->err);
18524
18525exit_failure:
18526 type->flags |= XML_SCHEMAS_TYPE_INTERNAL_INVALID;
18527 return(-1);
18528}
18529
18530
18539static int
18540xmlSchemaTypeFixup(xmlSchemaTypePtr type,
18541 xmlSchemaAbstractCtxtPtr actxt)
18542{
18543 if (type == NULL)
18544 return(0);
18545 if (actxt->type != XML_SCHEMA_CTXT_PARSER) {
18546 AERROR_INT("xmlSchemaTypeFixup",
18547 "this function needs a parser context");
18548 return(-1);
18549 }
18550 if (! WXS_IS_TYPE_NOT_FIXED(type))
18551 return(0);
18552 if (type->type == XML_SCHEMA_TYPE_COMPLEX)
18553 return(xmlSchemaFixupComplexType(PCTXT_CAST actxt, type));
18554 else if (type->type == XML_SCHEMA_TYPE_SIMPLE)
18555 return(xmlSchemaFixupSimpleTypeStageTwo(PCTXT_CAST actxt, type));
18556 return(0);
18557}
18558
18571int
18572xmlSchemaCheckFacet(xmlSchemaFacetPtr facet,
18573 xmlSchemaTypePtr typeDecl,
18574 xmlSchemaParserCtxtPtr pctxt,
18576{
18577 int ret = 0, ctxtGiven;
18578
18579 if ((facet == NULL) || (typeDecl == NULL))
18580 return(-1);
18581 /*
18582 * TODO: will the parser context be given if used from
18583 * the relaxNG module?
18584 */
18585 if (pctxt == NULL)
18586 ctxtGiven = 0;
18587 else
18588 ctxtGiven = 1;
18589
18590 switch (facet->type) {
18591 case XML_SCHEMA_FACET_MININCLUSIVE:
18592 case XML_SCHEMA_FACET_MINEXCLUSIVE:
18593 case XML_SCHEMA_FACET_MAXINCLUSIVE:
18594 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
18595 case XML_SCHEMA_FACET_ENUMERATION: {
18596 /*
18597 * Okay we need to validate the value
18598 * at that point.
18599 */
18600 xmlSchemaTypePtr base;
18601
18602 /* 4.3.5.5 Constraints on enumeration Schema Components
18603 * Schema Component Constraint: enumeration valid restriction
18604 * It is an `error` if any member of {value} is not in the
18605 * `value space` of {base type definition}.
18606 *
18607 * minInclusive, maxInclusive, minExclusive, maxExclusive:
18608 * The value `must` be in the
18609 * `value space` of the `base type`.
18610 */
18611 /*
18612 * This function is intended to deliver a compiled value
18613 * on the facet. In this implementation of XML Schemata the
18614 * type holding a facet, won't be a built-in type.
18615 * Thus to ensure that other API
18616 * calls (relaxng) do work, if the given type is a built-in
18617 * type, we will assume that the given built-in type *is
18618 * already* the base type.
18619 */
18620 if (typeDecl->type != XML_SCHEMA_TYPE_BASIC) {
18621 base = typeDecl->baseType;
18622 if (base == NULL) {
18623 PERROR_INT("xmlSchemaCheckFacet",
18624 "a type user derived type has no base type");
18625 return (-1);
18626 }
18627 } else
18628 base = typeDecl;
18629
18630 if (! ctxtGiven) {
18631 /*
18632 * A context is needed if called from RelaxNG.
18633 */
18634 pctxt = xmlSchemaNewParserCtxt("*");
18635 if (pctxt == NULL)
18636 return (-1);
18637 }
18638 /*
18639 * NOTE: This call does not check the content nodes,
18640 * since they are not available:
18641 * facet->node is just the node holding the facet
18642 * definition, *not* the attribute holding the *value*
18643 * of the facet.
18644 */
18645 ret = xmlSchemaVCheckCVCSimpleType(
18646 ACTXT_CAST pctxt, facet->node, base,
18647 facet->value, &(facet->val), 1, 1, 0);
18648 if (ret != 0) {
18649 if (ret < 0) {
18650 /* No error message for RelaxNG. */
18651 if (ctxtGiven) {
18652 xmlSchemaCustomErr(ACTXT_CAST pctxt,
18653 XML_SCHEMAP_INTERNAL, facet->node, NULL,
18654 "Internal error: xmlSchemaCheckFacet, "
18655 "failed to validate the value '%s' of the "
18656 "facet '%s' against the base type",
18657 facet->value, xmlSchemaFacetTypeToString(facet->type));
18658 }
18659 goto internal_error;
18660 }
18662 /* No error message for RelaxNG. */
18663 if (ctxtGiven) {
18664 xmlChar *str = NULL;
18665
18666 xmlSchemaCustomErr(ACTXT_CAST pctxt,
18667 ret, facet->node, WXS_BASIC_CAST facet,
18668 "The value '%s' of the facet does not validate "
18669 "against the base type '%s'",
18670 facet->value,
18671 xmlSchemaFormatQName(&str,
18672 base->targetNamespace, base->name));
18673 FREE_AND_NULL(str);
18674 }
18675 goto exit;
18676 } else if (facet->val == NULL) {
18677 if (ctxtGiven) {
18678 PERROR_INT("xmlSchemaCheckFacet",
18679 "value was not computed");
18680 }
18681 TODO
18682 }
18683 break;
18684 }
18685 case XML_SCHEMA_FACET_PATTERN:
18686 facet->regexp = xmlRegexpCompile(facet->value);
18687 if (facet->regexp == NULL) {
18689 /* No error message for RelaxNG. */
18690 if (ctxtGiven) {
18691 xmlSchemaCustomErr(ACTXT_CAST pctxt,
18692 ret, facet->node, WXS_BASIC_CAST typeDecl,
18693 "The value '%s' of the facet 'pattern' is not a "
18694 "valid regular expression",
18695 facet->value, NULL);
18696 }
18697 }
18698 break;
18699 case XML_SCHEMA_FACET_TOTALDIGITS:
18700 case XML_SCHEMA_FACET_FRACTIONDIGITS:
18701 case XML_SCHEMA_FACET_LENGTH:
18702 case XML_SCHEMA_FACET_MAXLENGTH:
18703 case XML_SCHEMA_FACET_MINLENGTH:
18704
18705 if (facet->type == XML_SCHEMA_FACET_TOTALDIGITS) {
18706 ret = xmlSchemaValidatePredefinedType(
18707 xmlSchemaGetBuiltInType(XML_SCHEMAS_PINTEGER),
18708 facet->value, &(facet->val));
18709 } else {
18710 ret = xmlSchemaValidatePredefinedType(
18711 xmlSchemaGetBuiltInType(XML_SCHEMAS_NNINTEGER),
18712 facet->value, &(facet->val));
18713 }
18714 if (ret != 0) {
18715 if (ret < 0) {
18716 /* No error message for RelaxNG. */
18717 if (ctxtGiven) {
18718 PERROR_INT("xmlSchemaCheckFacet",
18719 "validating facet value");
18720 }
18721 goto internal_error;
18722 }
18724 /* No error message for RelaxNG. */
18725 if (ctxtGiven) {
18726 /* error code */
18727 xmlSchemaCustomErr4(ACTXT_CAST pctxt,
18728 ret, facet->node, WXS_BASIC_CAST typeDecl,
18729 "The value '%s' of the facet '%s' is not a valid '%s'",
18730 facet->value,
18731 xmlSchemaFacetTypeToString(facet->type),
18732 (facet->type != XML_SCHEMA_FACET_TOTALDIGITS) ?
18733 BAD_CAST "nonNegativeInteger" :
18734 BAD_CAST "positiveInteger",
18735 NULL);
18736 }
18737 }
18738 break;
18739
18740 case XML_SCHEMA_FACET_WHITESPACE:{
18741 if (xmlStrEqual(facet->value, BAD_CAST "preserve")) {
18742 facet->whitespace = XML_SCHEMAS_FACET_PRESERVE;
18743 } else if (xmlStrEqual(facet->value, BAD_CAST "replace")) {
18744 facet->whitespace = XML_SCHEMAS_FACET_REPLACE;
18745 } else if (xmlStrEqual(facet->value, BAD_CAST "collapse")) {
18746 facet->whitespace = XML_SCHEMAS_FACET_COLLAPSE;
18747 } else {
18749 /* No error message for RelaxNG. */
18750 if (ctxtGiven) {
18751 /* error was previously: XML_SCHEMAP_INVALID_WHITE_SPACE */
18752 xmlSchemaCustomErr(ACTXT_CAST pctxt,
18753 ret, facet->node, WXS_BASIC_CAST typeDecl,
18754 "The value '%s' of the facet 'whitespace' is not "
18755 "valid", facet->value, NULL);
18756 }
18757 }
18758 }
18759 default:
18760 break;
18761 }
18762exit:
18763 if ((! ctxtGiven) && (pctxt != NULL))
18764 xmlSchemaFreeParserCtxt(pctxt);
18765 return (ret);
18766internal_error:
18767 if ((! ctxtGiven) && (pctxt != NULL))
18768 xmlSchemaFreeParserCtxt(pctxt);
18769 return (-1);
18770}
18771
18779static int
18780xmlSchemaCheckFacetValues(xmlSchemaTypePtr typeDecl,
18781 xmlSchemaParserCtxtPtr pctxt)
18782{
18783 int res, olderrs = pctxt->nberrors;
18784 const xmlChar *name = typeDecl->name;
18785 /*
18786 * NOTE: It is intended to use the facets list, instead
18787 * of facetSet.
18788 */
18789 if (typeDecl->facets != NULL) {
18790 xmlSchemaFacetPtr facet = typeDecl->facets;
18791
18792 /*
18793 * Temporarily assign the "schema" to the validation context
18794 * of the parser context. This is needed for NOTATION validation.
18795 */
18796 if (pctxt->vctxt == NULL) {
18797 if (xmlSchemaCreateVCtxtOnPCtxt(pctxt) == -1)
18798 return(-1);
18799 }
18800 pctxt->vctxt->schema = pctxt->schema;
18801 while (facet != NULL) {
18802 res = xmlSchemaCheckFacet(facet, typeDecl, pctxt, name);
18803 HFAILURE
18804 facet = facet->next;
18805 }
18806 pctxt->vctxt->schema = NULL;
18807 }
18808 if (olderrs != pctxt->nberrors)
18809 return(pctxt->err);
18810 return(0);
18811exit_failure:
18812 return(-1);
18813}
18814
18827static xmlSchemaTreeItemPtr
18828xmlSchemaGetCircModelGrDefRef(xmlSchemaModelGroupDefPtr groupDef,
18829 xmlSchemaTreeItemPtr particle)
18830{
18831 xmlSchemaTreeItemPtr circ = NULL;
18832 xmlSchemaTreeItemPtr term;
18833 xmlSchemaModelGroupDefPtr gdef;
18834
18835 for (; particle != NULL; particle = particle->next) {
18836 term = particle->children;
18837 if (term == NULL)
18838 continue;
18839 switch (term->type) {
18840 case XML_SCHEMA_TYPE_GROUP:
18841 gdef = (xmlSchemaModelGroupDefPtr) term;
18842 if (gdef == groupDef)
18843 return (particle);
18844 /*
18845 * Mark this model group definition to avoid infinite
18846 * recursion on circular references not yet examined.
18847 */
18848 if (gdef->flags & XML_SCHEMA_MODEL_GROUP_DEF_MARKED)
18849 continue;
18850 if (gdef->children != NULL) {
18851 gdef->flags |= XML_SCHEMA_MODEL_GROUP_DEF_MARKED;
18852 circ = xmlSchemaGetCircModelGrDefRef(groupDef,
18853 gdef->children->children);
18854 gdef->flags ^= XML_SCHEMA_MODEL_GROUP_DEF_MARKED;
18855 if (circ != NULL)
18856 return (circ);
18857 }
18858 break;
18859 case XML_SCHEMA_TYPE_SEQUENCE:
18860 case XML_SCHEMA_TYPE_CHOICE:
18861 case XML_SCHEMA_TYPE_ALL:
18862 circ = xmlSchemaGetCircModelGrDefRef(groupDef, term->children);
18863 if (circ != NULL)
18864 return (circ);
18865 break;
18866 default:
18867 break;
18868 }
18869 }
18870 return (NULL);
18871}
18872
18881static void
18882xmlSchemaCheckGroupDefCircular(xmlSchemaModelGroupDefPtr item,
18883 xmlSchemaParserCtxtPtr ctxt)
18884{
18885 /*
18886 * Schema Component Constraint: Model Group Correct
18887 * 2 Circular groups are disallowed. That is, within the {particles}
18888 * of a group there must not be at any depth a particle whose {term}
18889 * is the group itself.
18890 */
18891 if ((item == NULL) ||
18892 (item->type != XML_SCHEMA_TYPE_GROUP) ||
18893 (item->children == NULL))
18894 return;
18895 {
18896 xmlSchemaTreeItemPtr circ;
18897
18898 circ = xmlSchemaGetCircModelGrDefRef(item, item->children->children);
18899 if (circ != NULL) {
18900 xmlChar *str = NULL;
18901 /*
18902 * TODO: The error report is not adequate: this constraint
18903 * is defined for model groups but not definitions, but since
18904 * there cannot be any circular model groups without a model group
18905 * definition (if not using a construction API), we check those
18906 * definitions only.
18907 */
18908 xmlSchemaPCustomErr(ctxt,
18910 NULL, WXS_ITEM_NODE(circ),
18911 "Circular reference to the model group definition '%s' "
18912 "defined", xmlSchemaFormatQName(&str,
18913 item->targetNamespace, item->name));
18914 FREE_AND_NULL(str)
18915 /*
18916 * NOTE: We will cut the reference to avoid further
18917 * confusion of the processor. This is a fatal error.
18918 */
18919 circ->children = NULL;
18920 }
18921 }
18922}
18923
18938static void
18939xmlSchemaModelGroupToModelGroupDefFixup(
18940 xmlSchemaParserCtxtPtr ctxt ATTRIBUTE_UNUSED,
18941 xmlSchemaModelGroupPtr mg)
18942{
18943 xmlSchemaParticlePtr particle = WXS_MODELGROUP_PARTICLE(mg);
18944
18945 while (particle != NULL) {
18946 if ((WXS_PARTICLE_TERM(particle) == NULL) ||
18947 ((WXS_PARTICLE_TERM(particle))->type !=
18948 XML_SCHEMA_TYPE_GROUP))
18949 {
18950 particle = WXS_PTC_CAST particle->next;
18951 continue;
18952 }
18953 if (WXS_MODELGROUPDEF_MODEL(WXS_PARTICLE_TERM(particle)) == NULL) {
18954 /*
18955 * TODO: Remove the particle.
18956 */
18957 WXS_PARTICLE_TERM(particle) = NULL;
18958 particle = WXS_PTC_CAST particle->next;
18959 continue;
18960 }
18961 /*
18962 * Assign the model group to the {term} of the particle.
18963 */
18964 WXS_PARTICLE_TERM(particle) =
18965 WXS_TREE_CAST WXS_MODELGROUPDEF_MODEL(WXS_PARTICLE_TERM(particle));
18966
18967 particle = WXS_PTC_CAST particle->next;
18968 }
18969}
18970
18981static xmlSchemaQNameRefPtr
18982xmlSchemaCheckAttrGroupCircularRecur(xmlSchemaAttributeGroupPtr ctxtGr,
18983 xmlSchemaItemListPtr list)
18984{
18985 xmlSchemaAttributeGroupPtr gr;
18986 xmlSchemaQNameRefPtr ref, circ;
18987 int i;
18988 /*
18989 * We will search for an attribute group reference which
18990 * references the context attribute group.
18991 */
18992 for (i = 0; i < list->nbItems; i++) {
18993 ref = list->items[i];
18994 if ((ref->type == XML_SCHEMA_EXTRA_QNAMEREF) &&
18995 (ref->itemType == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) &&
18996 (ref->item != NULL))
18997 {
18998 gr = WXS_ATTR_GROUP_CAST ref->item;
18999 if (gr == ctxtGr)
19000 return(ref);
19001 if (gr->flags & XML_SCHEMAS_ATTRGROUP_MARKED)
19002 continue;
19003 /*
19004 * Mark as visited to avoid infinite recursion on
19005 * circular references not yet examined.
19006 */
19007 if ((gr->attrUses) &&
19008 (gr->flags & XML_SCHEMAS_ATTRGROUP_HAS_REFS))
19009 {
19010 gr->flags |= XML_SCHEMAS_ATTRGROUP_MARKED;
19011 circ = xmlSchemaCheckAttrGroupCircularRecur(ctxtGr,
19012 (xmlSchemaItemListPtr) gr->attrUses);
19013 gr->flags ^= XML_SCHEMAS_ATTRGROUP_MARKED;
19014 if (circ != NULL)
19015 return (circ);
19016 }
19017
19018 }
19019 }
19020 return (NULL);
19021}
19022
19031static int
19032xmlSchemaCheckAttrGroupCircular(xmlSchemaAttributeGroupPtr attrGr,
19033 xmlSchemaParserCtxtPtr ctxt)
19034{
19035 /*
19036 * Schema Representation Constraint:
19037 * Attribute Group Definition Representation OK
19038 * 3 Circular group reference is disallowed outside <redefine>.
19039 * That is, unless this element information item's parent is
19040 * <redefine>, then among the [children], if any, there must
19041 * not be an <attributeGroup> with ref [attribute] which resolves
19042 * to the component corresponding to this <attributeGroup>. Indirect
19043 * circularity is also ruled out. That is, when QName resolution
19044 * (Schema Document) ($3.15.3) is applied to a `QName` arising from
19045 * any <attributeGroup>s with a ref [attribute] among the [children],
19046 * it must not be the case that a `QName` is encountered at any depth
19047 * which resolves to the component corresponding to this <attributeGroup>.
19048 */
19049 if (attrGr->attrUses == NULL)
19050 return(0);
19051 else if ((attrGr->flags & XML_SCHEMAS_ATTRGROUP_HAS_REFS) == 0)
19052 return(0);
19053 else {
19054 xmlSchemaQNameRefPtr circ;
19055
19056 circ = xmlSchemaCheckAttrGroupCircularRecur(attrGr,
19057 (xmlSchemaItemListPtr) attrGr->attrUses);
19058 if (circ != NULL) {
19059 xmlChar *str = NULL;
19060 /*
19061 * TODO: Report the referenced attr group as QName.
19062 */
19063 xmlSchemaPCustomErr(ctxt,
19065 NULL, WXS_ITEM_NODE(WXS_BASIC_CAST circ),
19066 "Circular reference to the attribute group '%s' "
19067 "defined", xmlSchemaGetComponentQName(&str, attrGr));
19068 FREE_AND_NULL(str);
19069 /*
19070 * NOTE: We will cut the reference to avoid further
19071 * confusion of the processor.
19072 * BADSPEC TODO: The spec should define how to process in this case.
19073 */
19074 circ->item = NULL;
19075 return(ctxt->err);
19076 }
19077 }
19078 return(0);
19079}
19080
19081static int
19082xmlSchemaAttributeGroupExpandRefs(xmlSchemaParserCtxtPtr pctxt,
19083 xmlSchemaAttributeGroupPtr attrGr);
19084
19099static int
19100xmlSchemaExpandAttributeGroupRefs(xmlSchemaParserCtxtPtr pctxt,
19101 xmlSchemaBasicItemPtr item,
19102 xmlSchemaWildcardPtr *completeWild,
19103 xmlSchemaItemListPtr list,
19104 xmlSchemaItemListPtr prohibs)
19105{
19106 xmlSchemaAttributeGroupPtr gr;
19107 xmlSchemaAttributeUsePtr use;
19108 xmlSchemaItemListPtr sublist;
19109 int i, j;
19110 int created = (*completeWild == NULL) ? 0 : 1;
19111
19112 if (prohibs)
19113 prohibs->nbItems = 0;
19114
19115 for (i = 0; i < list->nbItems; i++) {
19116 use = list->items[i];
19117
19118 if (use->type == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB) {
19119 if (prohibs == NULL) {
19120 PERROR_INT("xmlSchemaExpandAttributeGroupRefs",
19121 "unexpected attr prohibition found");
19122 return(-1);
19123 }
19124 /*
19125 * Remove from attribute uses.
19126 */
19127 if (xmlSchemaItemListRemove(list, i) == -1)
19128 return(-1);
19129 i--;
19130 /*
19131 * Note that duplicate prohibitions were already
19132 * handled at parsing time.
19133 */
19134 /*
19135 * Add to list of prohibitions.
19136 */
19137 xmlSchemaItemListAddSize(prohibs, 2, use);
19138 continue;
19139 }
19140 if ((use->type == XML_SCHEMA_EXTRA_QNAMEREF) &&
19141 ((WXS_QNAME_CAST use)->itemType == XML_SCHEMA_TYPE_ATTRIBUTEGROUP))
19142 {
19143 if ((WXS_QNAME_CAST use)->item == NULL)
19144 return(-1);
19145 gr = WXS_ATTR_GROUP_CAST (WXS_QNAME_CAST use)->item;
19146 /*
19147 * Expand the referenced attr. group.
19148 * TODO: remove this, this is done in a previous step, so
19149 * already done here.
19150 */
19151 if ((gr->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED) == 0) {
19152 if (xmlSchemaAttributeGroupExpandRefs(pctxt, gr) == -1)
19153 return(-1);
19154 }
19155 /*
19156 * Build the 'complete' wildcard; i.e. intersect multiple
19157 * wildcards.
19158 */
19159 if (gr->attributeWildcard != NULL) {
19160 if (*completeWild == NULL) {
19161 *completeWild = gr->attributeWildcard;
19162 } else {
19163 if (! created) {
19164 xmlSchemaWildcardPtr tmpWild;
19165
19166 /*
19167 * Copy the first encountered wildcard as context,
19168 * except for the annotation.
19169 *
19170 * Although the complete wildcard might not correspond
19171 * to any node in the schema, we will anchor it on
19172 * the node of the owner component.
19173 */
19174 tmpWild = xmlSchemaAddWildcard(pctxt, pctxt->schema,
19175 XML_SCHEMA_TYPE_ANY_ATTRIBUTE,
19176 WXS_ITEM_NODE(item));
19177 if (tmpWild == NULL)
19178 return(-1);
19179 if (xmlSchemaCloneWildcardNsConstraints(pctxt,
19180 tmpWild, *completeWild) == -1)
19181 return (-1);
19182 tmpWild->processContents = (*completeWild)->processContents;
19183 *completeWild = tmpWild;
19184 created = 1;
19185 }
19186
19187 if (xmlSchemaIntersectWildcards(pctxt, *completeWild,
19188 gr->attributeWildcard) == -1)
19189 return(-1);
19190 }
19191 }
19192 /*
19193 * Just remove the reference if the referenced group does not
19194 * contain any attribute uses.
19195 */
19196 sublist = ((xmlSchemaItemListPtr) gr->attrUses);
19197 if ((sublist == NULL) || sublist->nbItems == 0) {
19198 if (xmlSchemaItemListRemove(list, i) == -1)
19199 return(-1);
19200 i--;
19201 continue;
19202 }
19203 /*
19204 * Add the attribute uses.
19205 */
19206 list->items[i] = sublist->items[0];
19207 if (sublist->nbItems != 1) {
19208 for (j = 1; j < sublist->nbItems; j++) {
19209 i++;
19210 if (xmlSchemaItemListInsert(list,
19211 sublist->items[j], i) == -1)
19212 return(-1);
19213 }
19214 }
19215 }
19216
19217 }
19218 /*
19219 * Handle pointless prohibitions of declared attributes.
19220 */
19221 if (prohibs && (prohibs->nbItems != 0) && (list->nbItems != 0)) {
19222 xmlSchemaAttributeUseProhibPtr prohib;
19223
19224 for (i = prohibs->nbItems -1; i >= 0; i--) {
19225 prohib = prohibs->items[i];
19226 for (j = 0; j < list->nbItems; j++) {
19227 use = list->items[j];
19228
19229 if ((prohib->name == WXS_ATTRUSE_DECL_NAME(use)) &&
19230 (prohib->targetNamespace == WXS_ATTRUSE_DECL_TNS(use)))
19231 {
19232 xmlChar *str = NULL;
19233
19234 xmlSchemaCustomWarning(ACTXT_CAST pctxt,
19236 prohib->node, NULL,
19237 "Skipping pointless attribute use prohibition "
19238 "'%s', since a corresponding attribute use "
19239 "exists already in the type definition",
19240 xmlSchemaFormatQName(&str,
19241 prohib->targetNamespace, prohib->name),
19242 NULL, NULL);
19243 FREE_AND_NULL(str);
19244 /*
19245 * Remove the prohibition.
19246 */
19247 if (xmlSchemaItemListRemove(prohibs, i) == -1)
19248 return(-1);
19249 break;
19250 }
19251 }
19252 }
19253 }
19254 return(0);
19255}
19256
19269static int
19270xmlSchemaAttributeGroupExpandRefs(xmlSchemaParserCtxtPtr pctxt,
19271 xmlSchemaAttributeGroupPtr attrGr)
19272{
19273 if ((attrGr->attrUses == NULL) ||
19274 (attrGr->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED))
19275 return(0);
19276
19277 attrGr->flags |= XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED;
19278 if (xmlSchemaExpandAttributeGroupRefs(pctxt, WXS_BASIC_CAST attrGr,
19279 &(attrGr->attributeWildcard), attrGr->attrUses, NULL) == -1)
19280 return(-1);
19281 return(0);
19282}
19283
19295static int
19296xmlSchemaCheckAGPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
19297 xmlSchemaAttributeGroupPtr attrGr)
19298{
19299 /*
19300 * SPEC ag-props-correct
19301 * (1) "The values of the properties of an attribute group definition
19302 * must be as described in the property tableau in The Attribute
19303 * Group Definition Schema Component ($3.6.1), modulo the impact of
19304 * Missing Sub-components ($5.3);"
19305 */
19306
19307 if ((attrGr->attrUses != NULL) &&
19308 (WXS_LIST_CAST attrGr->attrUses)->nbItems > 1)
19309 {
19310 xmlSchemaItemListPtr uses = WXS_LIST_CAST attrGr->attrUses;
19311 xmlSchemaAttributeUsePtr use, tmp;
19312 int i, j, hasId = 0;
19313
19314 for (i = uses->nbItems -1; i >= 0; i--) {
19315 use = uses->items[i];
19316 /*
19317 * SPEC ag-props-correct
19318 * (2) "Two distinct members of the {attribute uses} must not have
19319 * {attribute declaration}s both of whose {name}s match and whose
19320 * {target namespace}s are identical."
19321 */
19322 if (i > 0) {
19323 for (j = i -1; j >= 0; j--) {
19324 tmp = uses->items[j];
19325 if ((WXS_ATTRUSE_DECL_NAME(use) ==
19326 WXS_ATTRUSE_DECL_NAME(tmp)) &&
19327 (WXS_ATTRUSE_DECL_TNS(use) ==
19328 WXS_ATTRUSE_DECL_TNS(tmp)))
19329 {
19330 xmlChar *str = NULL;
19331
19332 xmlSchemaCustomErr(ACTXT_CAST pctxt,
19334 attrGr->node, WXS_BASIC_CAST attrGr,
19335 "Duplicate %s",
19336 xmlSchemaGetComponentDesignation(&str, use),
19337 NULL);
19338 FREE_AND_NULL(str);
19339 /*
19340 * Remove the duplicate.
19341 */
19342 if (xmlSchemaItemListRemove(uses, i) == -1)
19343 return(-1);
19344 goto next_use;
19345 }
19346 }
19347 }
19348 /*
19349 * SPEC ag-props-correct
19350 * (3) "Two distinct members of the {attribute uses} must not have
19351 * {attribute declaration}s both of whose {type definition}s are or
19352 * are derived from ID."
19353 * TODO: Does 'derived' include member-types of unions?
19354 */
19355 if (WXS_ATTRUSE_TYPEDEF(use) != NULL) {
19356 if (xmlSchemaIsDerivedFromBuiltInType(
19357 WXS_ATTRUSE_TYPEDEF(use), XML_SCHEMAS_ID))
19358 {
19359 if (hasId) {
19360 xmlChar *str = NULL;
19361
19362 xmlSchemaCustomErr(ACTXT_CAST pctxt,
19364 attrGr->node, WXS_BASIC_CAST attrGr,
19365 "There must not exist more than one attribute "
19366 "declaration of type 'xs:ID' "
19367 "(or derived from 'xs:ID'). The %s violates this "
19368 "constraint",
19369 xmlSchemaGetComponentDesignation(&str, use),
19370 NULL);
19371 FREE_AND_NULL(str);
19372 if (xmlSchemaItemListRemove(uses, i) == -1)
19373 return(-1);
19374 }
19375 hasId = 1;
19376 }
19377 }
19378next_use: {}
19379 }
19380 }
19381 return(0);
19382}
19383
19392static int
19393xmlSchemaResolveAttrGroupReferences(xmlSchemaQNameRefPtr ref,
19394 xmlSchemaParserCtxtPtr ctxt)
19395{
19396 xmlSchemaAttributeGroupPtr group;
19397
19398 if (ref->item != NULL)
19399 return(0);
19400 group = xmlSchemaGetAttributeGroup(ctxt->schema,
19401 ref->name,
19402 ref->targetNamespace);
19403 if (group == NULL) {
19404 xmlSchemaPResCompAttrErr(ctxt,
19406 NULL, ref->node,
19407 "ref", ref->name, ref->targetNamespace,
19408 ref->itemType, NULL);
19409 return(ctxt->err);
19410 }
19411 ref->item = WXS_BASIC_CAST group;
19412 return(0);
19413}
19414
19429static int
19430xmlSchemaCheckAttrPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
19431 xmlSchemaAttributePtr attr)
19432{
19433
19434 /*
19435 * SPEC a-props-correct (1)
19436 * "The values of the properties of an attribute declaration must
19437 * be as described in the property tableau in The Attribute
19438 * Declaration Schema Component ($3.2.1), modulo the impact of
19439 * Missing Sub-components ($5.3)."
19440 */
19441
19442 if (WXS_ATTR_TYPEDEF(attr) == NULL)
19443 return(0);
19444
19445 if (attr->defValue != NULL) {
19446 int ret;
19447
19448 /*
19449 * SPEC a-props-correct (3)
19450 * "If the {type definition} is or is derived from ID then there
19451 * must not be a {value constraint}."
19452 */
19453 if (xmlSchemaIsDerivedFromBuiltInType(
19454 WXS_ATTR_TYPEDEF(attr), XML_SCHEMAS_ID))
19455 {
19456 xmlSchemaCustomErr(ACTXT_CAST pctxt,
19458 NULL, WXS_BASIC_CAST attr,
19459 "Value constraints are not allowed if the type definition "
19460 "is or is derived from xs:ID",
19461 NULL, NULL);
19462 return(pctxt->err);
19463 }
19464 /*
19465 * SPEC a-props-correct (2)
19466 * "if there is a {value constraint}, the canonical lexical
19467 * representation of its value must be `valid` with respect
19468 * to the {type definition} as defined in String Valid ($3.14.4)."
19469 * TODO: Don't care about the *canonical* stuff here, this requirement
19470 * will be removed in WXS 1.1 anyway.
19471 */
19472 ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST pctxt,
19473 attr->node, WXS_ATTR_TYPEDEF(attr),
19474 attr->defValue, &(attr->defVal),
19475 1, 1, 0);
19476 if (ret != 0) {
19477 if (ret < 0) {
19478 PERROR_INT("xmlSchemaCheckAttrPropsCorrect",
19479 "calling xmlSchemaVCheckCVCSimpleType()");
19480 return(-1);
19481 }
19482 xmlSchemaCustomErr(ACTXT_CAST pctxt,
19484 NULL, WXS_BASIC_CAST attr,
19485 "The value of the value constraint is not valid",
19486 NULL, NULL);
19487 return(pctxt->err);
19488 }
19489 }
19490
19491 return(0);
19492}
19493
19494static xmlSchemaElementPtr
19495xmlSchemaCheckSubstGroupCircular(xmlSchemaElementPtr elemDecl,
19496 xmlSchemaElementPtr ancestor)
19497{
19498 xmlSchemaElementPtr ret;
19499
19500 if (WXS_SUBST_HEAD(ancestor) == NULL)
19501 return (NULL);
19502 if (WXS_SUBST_HEAD(ancestor) == elemDecl)
19503 return (ancestor);
19504
19505 if (WXS_SUBST_HEAD(ancestor)->flags & XML_SCHEMAS_ELEM_CIRCULAR)
19506 return (NULL);
19507 WXS_SUBST_HEAD(ancestor)->flags |= XML_SCHEMAS_ELEM_CIRCULAR;
19508 ret = xmlSchemaCheckSubstGroupCircular(elemDecl,
19509 WXS_SUBST_HEAD(ancestor));
19510 WXS_SUBST_HEAD(ancestor)->flags ^= XML_SCHEMAS_ELEM_CIRCULAR;
19511
19512 return (ret);
19513}
19514
19527static int
19528xmlSchemaCheckElemPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
19529 xmlSchemaElementPtr elemDecl)
19530{
19531 int ret = 0;
19532 xmlSchemaTypePtr typeDef = WXS_ELEM_TYPEDEF(elemDecl);
19533 /*
19534 * SPEC (1) "The values of the properties of an element declaration
19535 * must be as described in the property tableau in The Element
19536 * Declaration Schema Component ($3.3.1), modulo the impact of Missing
19537 * Sub-components ($5.3)."
19538 */
19539 if (WXS_SUBST_HEAD(elemDecl) != NULL) {
19540 xmlSchemaElementPtr head = WXS_SUBST_HEAD(elemDecl), circ;
19541
19542 xmlSchemaCheckElementDeclComponent(head, pctxt);
19543 /*
19544 * SPEC (3) "If there is a non-`absent` {substitution group
19545 * affiliation}, then {scope} must be global."
19546 */
19547 if ((elemDecl->flags & XML_SCHEMAS_ELEM_GLOBAL) == 0) {
19548 xmlSchemaPCustomErr(pctxt,
19550 WXS_BASIC_CAST elemDecl, NULL,
19551 "Only global element declarations can have a "
19552 "substitution group affiliation", NULL);
19554 }
19555 /*
19556 * TODO: SPEC (6) "Circular substitution groups are disallowed.
19557 * That is, it must not be possible to return to an element declaration
19558 * by repeatedly following the {substitution group affiliation}
19559 * property."
19560 */
19561 if (head == elemDecl)
19562 circ = head;
19563 else if (WXS_SUBST_HEAD(head) != NULL)
19564 circ = xmlSchemaCheckSubstGroupCircular(head, head);
19565 else
19566 circ = NULL;
19567 if (circ != NULL) {
19568 xmlChar *strA = NULL, *strB = NULL;
19569
19570 xmlSchemaPCustomErrExt(pctxt,
19572 WXS_BASIC_CAST circ, NULL,
19573 "The element declaration '%s' defines a circular "
19574 "substitution group to element declaration '%s'",
19575 xmlSchemaGetComponentQName(&strA, circ),
19576 xmlSchemaGetComponentQName(&strB, head),
19577 NULL);
19578 FREE_AND_NULL(strA)
19579 FREE_AND_NULL(strB)
19581 }
19582 /*
19583 * SPEC (4) "If there is a {substitution group affiliation},
19584 * the {type definition}
19585 * of the element declaration must be validly derived from the {type
19586 * definition} of the {substitution group affiliation}, given the value
19587 * of the {substitution group exclusions} of the {substitution group
19588 * affiliation}, as defined in Type Derivation OK (Complex) ($3.4.6)
19589 * (if the {type definition} is complex) or as defined in
19590 * Type Derivation OK (Simple) ($3.14.6) (if the {type definition} is
19591 * simple)."
19592 *
19593 * NOTE: {substitution group exclusions} means the values of the
19594 * attribute "final".
19595 */
19596
19597 if (typeDef != WXS_ELEM_TYPEDEF(WXS_SUBST_HEAD(elemDecl))) {
19598 int set = 0;
19599
19600 if (head->flags & XML_SCHEMAS_ELEM_FINAL_EXTENSION)
19601 set |= SUBSET_EXTENSION;
19602 if (head->flags & XML_SCHEMAS_ELEM_FINAL_RESTRICTION)
19603 set |= SUBSET_RESTRICTION;
19604
19605 if (xmlSchemaCheckCOSDerivedOK(ACTXT_CAST pctxt, typeDef,
19606 WXS_ELEM_TYPEDEF(head), set) != 0) {
19607 xmlChar *strA = NULL, *strB = NULL, *strC = NULL;
19608
19610 xmlSchemaPCustomErrExt(pctxt,
19612 WXS_BASIC_CAST elemDecl, NULL,
19613 "The type definition '%s' was "
19614 "either rejected by the substitution group "
19615 "affiliation '%s', or not validly derived from its type "
19616 "definition '%s'",
19617 xmlSchemaGetComponentQName(&strA, typeDef),
19618 xmlSchemaGetComponentQName(&strB, head),
19619 xmlSchemaGetComponentQName(&strC, WXS_ELEM_TYPEDEF(head)));
19620 FREE_AND_NULL(strA)
19621 FREE_AND_NULL(strB)
19622 FREE_AND_NULL(strC)
19623 }
19624 }
19625 }
19626 /*
19627 * SPEC (5) "If the {type definition} or {type definition}'s
19628 * {content type}
19629 * is or is derived from ID then there must not be a {value constraint}.
19630 * Note: The use of ID as a type definition for elements goes beyond
19631 * XML 1.0, and should be avoided if backwards compatibility is desired"
19632 */
19633 if ((elemDecl->value != NULL) &&
19634 ((WXS_IS_SIMPLE(typeDef) &&
19635 xmlSchemaIsDerivedFromBuiltInType(typeDef, XML_SCHEMAS_ID)) ||
19636 (WXS_IS_COMPLEX(typeDef) &&
19637 WXS_HAS_SIMPLE_CONTENT(typeDef) &&
19638 xmlSchemaIsDerivedFromBuiltInType(typeDef->contentTypeDef,
19639 XML_SCHEMAS_ID)))) {
19640
19642 xmlSchemaPCustomErr(pctxt,
19644 WXS_BASIC_CAST elemDecl, NULL,
19645 "The type definition (or type definition's content type) is or "
19646 "is derived from ID; value constraints are not allowed in "
19647 "conjunction with such a type definition", NULL);
19648 } else if (elemDecl->value != NULL) {
19649 int vcret;
19650 xmlNodePtr node = NULL;
19651
19652 /*
19653 * SPEC (2) "If there is a {value constraint}, the canonical lexical
19654 * representation of its value must be `valid` with respect to the
19655 * {type definition} as defined in Element Default Valid (Immediate)
19656 * ($3.3.6)."
19657 */
19658 if (typeDef == NULL) {
19659 xmlSchemaPErr(pctxt, elemDecl->node,
19661 "Internal error: xmlSchemaCheckElemPropsCorrect, "
19662 "type is missing... skipping validation of "
19663 "the value constraint", NULL, NULL);
19664 return (-1);
19665 }
19666 if (elemDecl->node != NULL) {
19667 if (elemDecl->flags & XML_SCHEMAS_ELEM_FIXED)
19668 node = (xmlNodePtr) xmlHasProp(elemDecl->node,
19669 BAD_CAST "fixed");
19670 else
19671 node = (xmlNodePtr) xmlHasProp(elemDecl->node,
19672 BAD_CAST "default");
19673 }
19674 vcret = xmlSchemaParseCheckCOSValidDefault(pctxt, node,
19675 typeDef, elemDecl->value, &(elemDecl->defVal));
19676 if (vcret != 0) {
19677 if (vcret < 0) {
19678 PERROR_INT("xmlSchemaElemCheckValConstr",
19679 "failed to validate the value constraint of an "
19680 "element declaration");
19681 return (-1);
19682 }
19683 return (vcret);
19684 }
19685 }
19686
19687 return (ret);
19688}
19689
19709static void
19710xmlSchemaCheckElemSubstGroup(xmlSchemaParserCtxtPtr ctxt,
19711 xmlSchemaElementPtr elemDecl)
19712{
19713 if ((WXS_SUBST_HEAD(elemDecl) == NULL) ||
19714 /* SPEC (1) "Its {abstract} is false." */
19715 (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT))
19716 return;
19717 {
19718 xmlSchemaElementPtr head;
19719 xmlSchemaTypePtr headType, type;
19720 int set, methSet;
19721 /*
19722 * SPEC (2) "It is validly substitutable for HEAD subject to HEAD's
19723 * {disallowed substitutions} as the blocking constraint, as defined in
19724 * Substitution Group OK (Transitive) ($3.3.6)."
19725 */
19726 for (head = WXS_SUBST_HEAD(elemDecl); head != NULL;
19727 head = WXS_SUBST_HEAD(head)) {
19728 set = 0;
19729 methSet = 0;
19730 /*
19731 * The blocking constraints.
19732 */
19733 if (head->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION)
19734 continue;
19735 headType = head->subtypes;
19736 type = elemDecl->subtypes;
19737 if (headType == type)
19738 goto add_member;
19739 if (head->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION)
19740 set |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
19741 if (head->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION)
19742 set |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
19743 /*
19744 * SPEC: Substitution Group OK (Transitive) (2.3)
19745 * "The set of all {derivation method}s involved in the
19746 * derivation of D's {type definition} from C's {type definition}
19747 * does not intersect with the union of the blocking constraint,
19748 * C's {prohibited substitutions} (if C is complex, otherwise the
19749 * empty set) and the {prohibited substitutions} (respectively the
19750 * empty set) of any intermediate {type definition}s in the
19751 * derivation of D's {type definition} from C's {type definition}."
19752 */
19753 /*
19754 * OPTIMIZE TODO: Optimize this a bit, since, if traversing the
19755 * subst.head axis, the methSet does not need to be computed for
19756 * the full depth over and over.
19757 */
19758 /*
19759 * The set of all {derivation method}s involved in the derivation
19760 */
19761 while ((type != NULL) && (type != headType) &&
19762 (type != type->baseType)) {
19763 if ((WXS_IS_EXTENSION(type)) &&
19764 ((methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
19765 methSet |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
19766
19767 if (WXS_IS_RESTRICTION(type) &&
19768 ((methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
19769 methSet |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
19770
19771 type = type->baseType;
19772 }
19773 /*
19774 * The {prohibited substitutions} of all intermediate types +
19775 * the head's type.
19776 */
19777 type = elemDecl->subtypes->baseType;
19778 while (type != NULL) {
19779 if (WXS_IS_COMPLEX(type)) {
19780 if ((type->flags &
19781 XML_SCHEMAS_TYPE_BLOCK_EXTENSION) &&
19782 ((set & XML_SCHEMAS_TYPE_BLOCK_EXTENSION) == 0))
19783 set |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
19784 if ((type->flags &
19785 XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) &&
19786 ((set & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
19787 set |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
19788 } else
19789 break;
19790 if (type == headType)
19791 break;
19792 type = type->baseType;
19793 }
19794 if ((set != 0) &&
19795 (((set & XML_SCHEMAS_TYPE_BLOCK_EXTENSION) &&
19796 (methSet & XML_SCHEMAS_TYPE_BLOCK_EXTENSION)) ||
19797 ((set & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) &&
19798 (methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION)))) {
19799 continue;
19800 }
19801add_member:
19802 xmlSchemaAddElementSubstitutionMember(ctxt, head, elemDecl);
19803 if ((head->flags & XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) == 0)
19804 head->flags |= XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD;
19805 }
19806 }
19807}
19808
19809#ifdef WXS_ELEM_DECL_CONS_ENABLED /* enable when finished */
19819static int
19820xmlSchemaCheckElementDeclConsistent(xmlSchemaParserCtxtPtr pctxt,
19821 xmlSchemaBasicItemPtr ctxtComponent,
19822 xmlSchemaParticlePtr ctxtParticle,
19823 xmlSchemaParticlePtr searchParticle,
19824 xmlSchemaParticlePtr curParticle,
19825 int search)
19826{
19827 return(0);
19828
19829 int ret = 0;
19830 xmlSchemaParticlePtr cur = curParticle;
19831 if (curParticle == NULL) {
19832 return(0);
19833 }
19834 if (WXS_PARTICLE_TERM(curParticle) == NULL) {
19835 /*
19836 * Just return in this case. A missing "term" of the particle
19837 * might arise due to an invalid "term" component.
19838 */
19839 return(0);
19840 }
19841 while (cur != NULL) {
19842 switch (WXS_PARTICLE_TERM(cur)->type) {
19843 case XML_SCHEMA_TYPE_ANY:
19844 break;
19845 case XML_SCHEMA_TYPE_ELEMENT:
19846 if (search == 0) {
19847 ret = xmlSchemaCheckElementDeclConsistent(pctxt,
19848 ctxtComponent, ctxtParticle, cur, ctxtParticle, 1);
19849 if (ret != 0)
19850 return(ret);
19851 } else {
19852 xmlSchemaElementPtr elem =
19853 WXS_ELEM_CAST(WXS_PARTICLE_TERM(cur));
19854 /*
19855 * SPEC Element Declarations Consistent:
19856 * "If the {particles} contains, either directly,
19857 * indirectly (that is, within the {particles} of a
19858 * contained model group, recursively) or `implicitly`
19859 * two or more element declaration particles with
19860 * the same {name} and {target namespace}, then
19861 * all their type definitions must be the same
19862 * top-level definition [...]"
19863 */
19864 if (xmlStrEqual(WXS_PARTICLE_TERM_AS_ELEM(cur)->name,
19865 WXS_PARTICLE_TERM_AS_ELEM(searchParticle)->name) &&
19866 xmlStrEqual(WXS_PARTICLE_TERM_AS_ELEM(cur)->targetNamespace,
19867 WXS_PARTICLE_TERM_AS_ELEM(searchParticle)->targetNamespace))
19868 {
19869 xmlChar *strA = NULL, *strB = NULL;
19870
19871 xmlSchemaCustomErr(ACTXT_CAST pctxt,
19872 /* TODO: error code */
19873 XML_SCHEMAP_COS_NONAMBIG,
19874 WXS_ITEM_NODE(cur), NULL,
19875 "In the content model of %s, there are multiple "
19876 "element declarations for '%s' with different "
19877 "type definitions",
19878 xmlSchemaGetComponentDesignation(&strA,
19879 ctxtComponent),
19880 xmlSchemaFormatQName(&strB,
19881 WXS_PARTICLE_TERM_AS_ELEM(cur)->targetNamespace,
19882 WXS_PARTICLE_TERM_AS_ELEM(cur)->name));
19883 FREE_AND_NULL(strA);
19884 FREE_AND_NULL(strB);
19885 return(XML_SCHEMAP_COS_NONAMBIG);
19886 }
19887 }
19888 break;
19889 case XML_SCHEMA_TYPE_SEQUENCE: {
19890 break;
19891 }
19892 case XML_SCHEMA_TYPE_CHOICE:{
19893 /*
19894 xmlSchemaTreeItemPtr sub;
19895
19896 sub = WXS_PARTICLE_TERM(particle)->children; (xmlSchemaParticlePtr)
19897 while (sub != NULL) {
19898 ret = xmlSchemaCheckElementDeclConsistent(pctxt, ctxtComponent,
19899 ctxtParticle, ctxtElem);
19900 if (ret != 0)
19901 return(ret);
19902 sub = sub->next;
19903 }
19904 */
19905 break;
19906 }
19907 case XML_SCHEMA_TYPE_ALL:
19908 break;
19909 case XML_SCHEMA_TYPE_GROUP:
19910 break;
19911 default:
19912 xmlSchemaInternalErr2(ACTXT_CAST pctxt,
19913 "xmlSchemaCheckElementDeclConsistent",
19914 "found unexpected term of type '%s' in content model",
19915 WXS_ITEM_TYPE_NAME(WXS_PARTICLE_TERM(cur)), NULL);
19916 return(-1);
19917 }
19918 cur = (xmlSchemaParticlePtr) cur->next;
19919 }
19920
19921exit:
19922 return(ret);
19923}
19924#endif
19925
19935static void
19936xmlSchemaCheckElementDeclComponent(xmlSchemaElementPtr elemDecl,
19937 xmlSchemaParserCtxtPtr ctxt)
19938{
19939 if (elemDecl == NULL)
19940 return;
19941 if (elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_CHECKED)
19942 return;
19943 elemDecl->flags |= XML_SCHEMAS_ELEM_INTERNAL_CHECKED;
19944 if (xmlSchemaCheckElemPropsCorrect(ctxt, elemDecl) == 0) {
19945 /*
19946 * Adds substitution group members.
19947 */
19948 xmlSchemaCheckElemSubstGroup(ctxt, elemDecl);
19949 }
19950}
19951
19960static void
19961xmlSchemaResolveModelGroupParticleReferences(
19962 xmlSchemaParserCtxtPtr ctxt,
19963 xmlSchemaModelGroupPtr mg)
19964{
19965 xmlSchemaParticlePtr particle = WXS_MODELGROUP_PARTICLE(mg);
19966 xmlSchemaQNameRefPtr ref;
19967 xmlSchemaBasicItemPtr refItem;
19968
19969 /*
19970 * URGENT TODO: Test this.
19971 */
19972 while (particle != NULL) {
19973 if ((WXS_PARTICLE_TERM(particle) == NULL) ||
19974 ((WXS_PARTICLE_TERM(particle))->type !=
19975 XML_SCHEMA_EXTRA_QNAMEREF))
19976 {
19977 goto next_particle;
19978 }
19979 ref = WXS_QNAME_CAST WXS_PARTICLE_TERM(particle);
19980 /*
19981 * Resolve the reference.
19982 * NULL the {term} by default.
19983 */
19984 particle->children = NULL;
19985
19986 refItem = xmlSchemaGetNamedComponent(ctxt->schema,
19987 ref->itemType, ref->name, ref->targetNamespace);
19988 if (refItem == NULL) {
19989 xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
19990 NULL, WXS_ITEM_NODE(particle), "ref", ref->name,
19991 ref->targetNamespace, ref->itemType, NULL);
19992 /* TODO: remove the particle. */
19993 goto next_particle;
19994 }
19995 if (refItem->type == XML_SCHEMA_TYPE_GROUP) {
19996 if (WXS_MODELGROUPDEF_MODEL(refItem) == NULL)
19997 /* TODO: remove the particle. */
19998 goto next_particle;
19999 /*
20000 * NOTE that we will assign the model group definition
20001 * itself to the "term" of the particle. This will ease
20002 * the check for circular model group definitions. After
20003 * that the "term" will be assigned the model group of the
20004 * model group definition.
20005 */
20006 if ((WXS_MODELGROUPDEF_MODEL(refItem))->type ==
20007 XML_SCHEMA_TYPE_ALL) {
20008 /*
20009 * SPEC cos-all-limited (1)
20010 * SPEC cos-all-limited (1.2)
20011 * "It appears only as the value of one or both of the
20012 * following properties:"
20013 * (1.1) "the {model group} property of a model group
20014 * definition."
20015 * (1.2) "the {term} property of a particle [... of] the "
20016 * {content type} of a complex type definition."
20017 */
20018 xmlSchemaCustomErr(ACTXT_CAST ctxt,
20019 /* TODO: error code */
20021 WXS_ITEM_NODE(particle), NULL,
20022 "A model group definition is referenced, but "
20023 "it contains an 'all' model group, which "
20024 "cannot be contained by model groups",
20025 NULL, NULL);
20026 /* TODO: remove the particle. */
20027 goto next_particle;
20028 }
20029 particle->children = (xmlSchemaTreeItemPtr) refItem;
20030 } else {
20031 /*
20032 * TODO: Are referenced element declarations the only
20033 * other components we expect here?
20034 */
20035 particle->children = (xmlSchemaTreeItemPtr) refItem;
20036 }
20037next_particle:
20038 particle = WXS_PTC_CAST particle->next;
20039 }
20040}
20041
20042static int
20043xmlSchemaAreValuesEqual(xmlSchemaValPtr x,
20044 xmlSchemaValPtr y)
20045{
20046 xmlSchemaTypePtr tx, ty, ptx, pty;
20047 int ret;
20048
20049 while (x != NULL) {
20050 /* Same types. */
20051 tx = xmlSchemaGetBuiltInType(xmlSchemaGetValType(x));
20052 ty = xmlSchemaGetBuiltInType(xmlSchemaGetValType(y));
20053 ptx = xmlSchemaGetPrimitiveType(tx);
20054 pty = xmlSchemaGetPrimitiveType(ty);
20055 /*
20056 * (1) if a datatype T' is `derived` by `restriction` from an
20057 * atomic datatype T then the `value space` of T' is a subset of
20058 * the `value space` of T. */
20059 /*
20060 * (2) if datatypes T' and T'' are `derived` by `restriction`
20061 * from a common atomic ancestor T then the `value space`s of T'
20062 * and T'' may overlap.
20063 */
20064 if (ptx != pty)
20065 return(0);
20066 /*
20067 * We assume computed values to be normalized, so do a fast
20068 * string comparison for string based types.
20069 */
20070 if ((ptx->builtInType == XML_SCHEMAS_STRING) ||
20071 WXS_IS_ANY_SIMPLE_TYPE(ptx)) {
20072 if (! xmlStrEqual(
20073 xmlSchemaValueGetAsString(x),
20074 xmlSchemaValueGetAsString(y)))
20075 return (0);
20076 } else {
20077 ret = xmlSchemaCompareValuesWhtsp(
20078 x, XML_SCHEMA_WHITESPACE_PRESERVE,
20079 y, XML_SCHEMA_WHITESPACE_PRESERVE);
20080 if (ret == -2)
20081 return(-1);
20082 if (ret != 0)
20083 return(0);
20084 }
20085 /*
20086 * Lists.
20087 */
20088 x = xmlSchemaValueGetNext(x);
20089 if (x != NULL) {
20090 y = xmlSchemaValueGetNext(y);
20091 if (y == NULL)
20092 return (0);
20093 } else if (xmlSchemaValueGetNext(y) != NULL)
20094 return (0);
20095 else
20096 return (1);
20097 }
20098 return (0);
20099}
20100
20108static int
20109xmlSchemaResolveAttrUseReferences(xmlSchemaAttributeUsePtr ause,
20110 xmlSchemaParserCtxtPtr ctxt)
20111{
20112 if ((ctxt == NULL) || (ause == NULL))
20113 return(-1);
20114 if ((ause->attrDecl == NULL) ||
20115 (ause->attrDecl->type != XML_SCHEMA_EXTRA_QNAMEREF))
20116 return(0);
20117
20118 {
20119 xmlSchemaQNameRefPtr ref = WXS_QNAME_CAST ause->attrDecl;
20120
20121 /*
20122 * TODO: Evaluate, what errors could occur if the declaration is not
20123 * found.
20124 */
20125 ause->attrDecl = xmlSchemaGetAttributeDecl(ctxt->schema,
20126 ref->name, ref->targetNamespace);
20127 if (ause->attrDecl == NULL) {
20128 xmlSchemaPResCompAttrErr(ctxt,
20130 WXS_BASIC_CAST ause, ause->node,
20131 "ref", ref->name, ref->targetNamespace,
20132 XML_SCHEMA_TYPE_ATTRIBUTE, NULL);
20133 return(ctxt->err);
20134 }
20135 }
20136 return(0);
20137}
20138
20148static int
20149xmlSchemaCheckAttrUsePropsCorrect(xmlSchemaParserCtxtPtr ctxt,
20150 xmlSchemaAttributeUsePtr use)
20151{
20152 if ((ctxt == NULL) || (use == NULL))
20153 return(-1);
20154 if ((use->defValue == NULL) || (WXS_ATTRUSE_DECL(use) == NULL) ||
20155 ((WXS_ATTRUSE_DECL(use))->type != XML_SCHEMA_TYPE_ATTRIBUTE))
20156 return(0);
20157
20158 /*
20159 * SPEC au-props-correct (1)
20160 * "The values of the properties of an attribute use must be as
20161 * described in the property tableau in The Attribute Use Schema
20162 * Component ($3.5.1), modulo the impact of Missing
20163 * Sub-components ($5.3)."
20164 */
20165
20166 if (((WXS_ATTRUSE_DECL(use))->defValue != NULL) &&
20167 ((WXS_ATTRUSE_DECL(use))->flags & XML_SCHEMAS_ATTR_FIXED) &&
20168 ((use->flags & XML_SCHEMA_ATTR_USE_FIXED) == 0))
20169 {
20170 xmlSchemaPCustomErr(ctxt,
20172 WXS_BASIC_CAST use, NULL,
20173 "The attribute declaration has a 'fixed' value constraint "
20174 ", thus the attribute use must also have a 'fixed' value "
20175 "constraint",
20176 NULL);
20177 return(ctxt->err);
20178 }
20179 /*
20180 * Compute and check the value constraint's value.
20181 */
20182 if ((use->defVal != NULL) && (WXS_ATTRUSE_TYPEDEF(use) != NULL)) {
20183 int ret;
20184 /*
20185 * TODO: The spec seems to be missing a check of the
20186 * value constraint of the attribute use. We will do it here.
20187 */
20188 /*
20189 * SPEC a-props-correct (3)
20190 */
20191 if (xmlSchemaIsDerivedFromBuiltInType(
20192 WXS_ATTRUSE_TYPEDEF(use), XML_SCHEMAS_ID))
20193 {
20194 xmlSchemaCustomErr(ACTXT_CAST ctxt,
20196 NULL, WXS_BASIC_CAST use,
20197 "Value constraints are not allowed if the type definition "
20198 "is or is derived from xs:ID",
20199 NULL, NULL);
20200 return(ctxt->err);
20201 }
20202
20203 ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST ctxt,
20204 use->node, WXS_ATTRUSE_TYPEDEF(use),
20205 use->defValue, &(use->defVal),
20206 1, 1, 0);
20207 if (ret != 0) {
20208 if (ret < 0) {
20209 PERROR_INT2("xmlSchemaCheckAttrUsePropsCorrect",
20210 "calling xmlSchemaVCheckCVCSimpleType()");
20211 return(-1);
20212 }
20213 xmlSchemaCustomErr(ACTXT_CAST ctxt,
20215 NULL, WXS_BASIC_CAST use,
20216 "The value of the value constraint is not valid",
20217 NULL, NULL);
20218 return(ctxt->err);
20219 }
20220 }
20221 /*
20222 * SPEC au-props-correct (2)
20223 * "If the {attribute declaration} has a fixed
20224 * {value constraint}, then if the attribute use itself has a
20225 * {value constraint}, it must also be fixed and its value must match
20226 * that of the {attribute declaration}'s {value constraint}."
20227 */
20228 if (((WXS_ATTRUSE_DECL(use))->defVal != NULL) &&
20229 (((WXS_ATTRUSE_DECL(use))->flags & XML_SCHEMA_ATTR_USE_FIXED) == 0))
20230 {
20231 if (! xmlSchemaAreValuesEqual(use->defVal,
20232 (WXS_ATTRUSE_DECL(use))->defVal))
20233 {
20234 xmlSchemaPCustomErr(ctxt,
20236 WXS_BASIC_CAST use, NULL,
20237 "The 'fixed' value constraint of the attribute use "
20238 "must match the attribute declaration's value "
20239 "constraint '%s'",
20240 (WXS_ATTRUSE_DECL(use))->defValue);
20241 }
20242 return(ctxt->err);
20243 }
20244 return(0);
20245}
20246
20247
20248
20249
20257static int
20258xmlSchemaResolveAttrTypeReferences(xmlSchemaAttributePtr item,
20259 xmlSchemaParserCtxtPtr ctxt)
20260{
20261 /*
20262 * The simple type definition corresponding to the <simpleType> element
20263 * information item in the [children], if present, otherwise the simple
20264 * type definition `resolved` to by the `actual value` of the type
20265 * [attribute], if present, otherwise the `simple ur-type definition`.
20266 */
20267 if (item->flags & XML_SCHEMAS_ATTR_INTERNAL_RESOLVED)
20268 return(0);
20269 item->flags |= XML_SCHEMAS_ATTR_INTERNAL_RESOLVED;
20270 if (item->subtypes != NULL)
20271 return(0);
20272 if (item->typeName != NULL) {
20273 xmlSchemaTypePtr type;
20274
20275 type = xmlSchemaGetType(ctxt->schema, item->typeName,
20276 item->typeNs);
20277 if ((type == NULL) || (! WXS_IS_SIMPLE(type))) {
20278 xmlSchemaPResCompAttrErr(ctxt,
20280 WXS_BASIC_CAST item, item->node,
20281 "type", item->typeName, item->typeNs,
20282 XML_SCHEMA_TYPE_SIMPLE, NULL);
20283 return(ctxt->err);
20284 } else
20285 item->subtypes = type;
20286
20287 } else {
20288 /*
20289 * The type defaults to the xs:anySimpleType.
20290 */
20291 item->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
20292 }
20293 return(0);
20294}
20295
20306static int
20307xmlSchemaResolveIDCKeyReferences(xmlSchemaIDCPtr idc,
20308 xmlSchemaParserCtxtPtr pctxt)
20309{
20310 if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF)
20311 return(0);
20312 if (idc->ref->name != NULL) {
20313 idc->ref->item = (xmlSchemaBasicItemPtr)
20314 xmlSchemaGetIDC(pctxt->schema, idc->ref->name,
20315 idc->ref->targetNamespace);
20316 if (idc->ref->item == NULL) {
20317 /*
20318 * TODO: It is actually not an error to fail to resolve
20319 * at this stage. BUT we need to be that strict!
20320 */
20321 xmlSchemaPResCompAttrErr(pctxt,
20323 WXS_BASIC_CAST idc, idc->node,
20324 "refer", idc->ref->name,
20325 idc->ref->targetNamespace,
20326 XML_SCHEMA_TYPE_IDC_KEY, NULL);
20327 return(pctxt->err);
20328 } else if (idc->ref->item->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
20329 /*
20330 * SPEC c-props-correct (1)
20331 */
20332 xmlSchemaCustomErr(ACTXT_CAST pctxt,
20334 NULL, WXS_BASIC_CAST idc,
20335 "The keyref references a keyref",
20336 NULL, NULL);
20337 idc->ref->item = NULL;
20338 return(pctxt->err);
20339 } else {
20340 if (idc->nbFields !=
20341 ((xmlSchemaIDCPtr) idc->ref->item)->nbFields) {
20342 xmlChar *str = NULL;
20343 xmlSchemaIDCPtr refer;
20344
20345 refer = (xmlSchemaIDCPtr) idc->ref->item;
20346 /*
20347 * SPEC c-props-correct(2)
20348 * "If the {identity-constraint category} is keyref,
20349 * the cardinality of the {fields} must equal that of
20350 * the {fields} of the {referenced key}.
20351 */
20352 xmlSchemaCustomErr(ACTXT_CAST pctxt,
20354 NULL, WXS_BASIC_CAST idc,
20355 "The cardinality of the keyref differs from the "
20356 "cardinality of the referenced key/unique '%s'",
20357 xmlSchemaFormatQName(&str, refer->targetNamespace,
20358 refer->name),
20359 NULL);
20360 FREE_AND_NULL(str)
20361 return(pctxt->err);
20362 }
20363 }
20364 }
20365 return(0);
20366}
20367
20368static int
20369xmlSchemaResolveAttrUseProhibReferences(xmlSchemaAttributeUseProhibPtr prohib,
20370 xmlSchemaParserCtxtPtr pctxt)
20371{
20372 if (xmlSchemaGetAttributeDecl(pctxt->schema, prohib->name,
20373 prohib->targetNamespace) == NULL) {
20374
20375 xmlSchemaPResCompAttrErr(pctxt,
20377 NULL, prohib->node,
20378 "ref", prohib->name, prohib->targetNamespace,
20379 XML_SCHEMA_TYPE_ATTRIBUTE, NULL);
20381 }
20382 return(0);
20383}
20384
20385#define WXS_REDEFINED_TYPE(c) \
20386(((xmlSchemaTypePtr) item)->flags & XML_SCHEMAS_TYPE_REDEFINED)
20387
20388#define WXS_REDEFINED_MODEL_GROUP_DEF(c) \
20389(((xmlSchemaModelGroupDefPtr) item)->flags & XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED)
20390
20391#define WXS_REDEFINED_ATTR_GROUP(c) \
20392(((xmlSchemaAttributeGroupPtr) item)->flags & XML_SCHEMAS_ATTRGROUP_REDEFINED)
20393
20394static int
20395xmlSchemaCheckSRCRedefineFirst(xmlSchemaParserCtxtPtr pctxt)
20396{
20397 int err = 0;
20398 xmlSchemaRedefPtr redef = WXS_CONSTRUCTOR(pctxt)->redefs;
20399 xmlSchemaBasicItemPtr prev, item;
20400 int wasRedefined;
20401
20402 if (redef == NULL)
20403 return(0);
20404
20405 do {
20406 item = redef->item;
20407 /*
20408 * First try to locate the redefined component in the
20409 * schema graph starting with the redefined schema.
20410 * NOTE: According to this schema bug entry:
20411 * http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005OctDec/0019.html
20412 * it's not clear if the referenced component needs to originate
20413 * from the <redefine>d schema _document_ or the schema; the latter
20414 * would include all imported and included sub-schemas of the
20415 * <redefine>d schema. Currently the latter approach is used.
20416 * SUPPLEMENT: It seems that the WG moves towards the latter
20417 * approach, so we are doing it right.
20418 *
20419 */
20420 prev = xmlSchemaFindRedefCompInGraph(
20421 redef->targetBucket, item->type,
20422 redef->refName, redef->refTargetNs);
20423 if (prev == NULL) {
20424 xmlChar *str = NULL;
20425 xmlNodePtr node;
20426
20427 /*
20428 * SPEC src-redefine:
20429 * (6.2.1) "The `actual value` of its own name attribute plus
20430 * target namespace must successfully `resolve` to a model
20431 * group definition in I."
20432 * (7.2.1) "The `actual value` of its own name attribute plus
20433 * target namespace must successfully `resolve` to an attribute
20434 * group definition in I."
20435
20436 *
20437 * Note that, if we are redefining with the use of references
20438 * to components, the spec assumes the src-resolve to be used;
20439 * but this won't assure that we search only *inside* the
20440 * redefined schema.
20441 */
20442 if (redef->reference)
20443 node = WXS_ITEM_NODE(redef->reference);
20444 else
20445 node = WXS_ITEM_NODE(item);
20446 xmlSchemaCustomErr(ACTXT_CAST pctxt,
20447 /*
20448 * TODO: error code.
20449 * Probably XML_SCHEMAP_SRC_RESOLVE, if this is using the
20450 * reference kind.
20451 */
20453 "The %s '%s' to be redefined could not be found in "
20454 "the redefined schema",
20455 WXS_ITEM_TYPE_NAME(item),
20456 xmlSchemaFormatQName(&str, redef->refTargetNs,
20457 redef->refName));
20458 FREE_AND_NULL(str);
20459 err = pctxt->err;
20460 redef = redef->next;
20461 continue;
20462 }
20463 /*
20464 * TODO: Obtaining and setting the redefinition state is really
20465 * clumsy.
20466 */
20467 wasRedefined = 0;
20468 switch (item->type) {
20469 case XML_SCHEMA_TYPE_COMPLEX:
20470 case XML_SCHEMA_TYPE_SIMPLE:
20471 if ((WXS_TYPE_CAST prev)->flags &
20472 XML_SCHEMAS_TYPE_REDEFINED)
20473 {
20474 wasRedefined = 1;
20475 break;
20476 }
20477 /* Mark it as redefined. */
20478 (WXS_TYPE_CAST prev)->flags |= XML_SCHEMAS_TYPE_REDEFINED;
20479 /*
20480 * Assign the redefined type to the
20481 * base type of the redefining type.
20482 * TODO: How
20483 */
20484 ((xmlSchemaTypePtr) item)->baseType =
20485 (xmlSchemaTypePtr) prev;
20486 break;
20487 case XML_SCHEMA_TYPE_GROUP:
20488 if ((WXS_MODEL_GROUPDEF_CAST prev)->flags &
20489 XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED)
20490 {
20491 wasRedefined = 1;
20492 break;
20493 }
20494 /* Mark it as redefined. */
20495 (WXS_MODEL_GROUPDEF_CAST prev)->flags |=
20496 XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED;
20497 if (redef->reference != NULL) {
20498 /*
20499 * Overwrite the QName-reference with the
20500 * referenced model group def.
20501 */
20502 (WXS_PTC_CAST redef->reference)->children =
20503 WXS_TREE_CAST prev;
20504 }
20505 redef->target = prev;
20506 break;
20507 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20508 if ((WXS_ATTR_GROUP_CAST prev)->flags &
20509 XML_SCHEMAS_ATTRGROUP_REDEFINED)
20510 {
20511 wasRedefined = 1;
20512 break;
20513 }
20514 (WXS_ATTR_GROUP_CAST prev)->flags |=
20515 XML_SCHEMAS_ATTRGROUP_REDEFINED;
20516 if (redef->reference != NULL) {
20517 /*
20518 * Assign the redefined attribute group to the
20519 * QName-reference component.
20520 * This is the easy case, since we will just
20521 * expand the redefined group.
20522 */
20523 (WXS_QNAME_CAST redef->reference)->item = prev;
20524 redef->target = NULL;
20525 } else {
20526 /*
20527 * This is the complicated case: we need
20528 * to apply src-redefine (7.2.2) at a later
20529 * stage, i.e. when attribute group references
20530 * have been expanded and simple types have
20531 * been fixed.
20532 */
20533 redef->target = prev;
20534 }
20535 break;
20536 default:
20537 PERROR_INT("xmlSchemaResolveRedefReferences",
20538 "Unexpected redefined component type");
20539 return(-1);
20540 }
20541 if (wasRedefined) {
20542 xmlChar *str = NULL;
20543 xmlNodePtr node;
20544
20545 if (redef->reference)
20546 node = WXS_ITEM_NODE(redef->reference);
20547 else
20548 node = WXS_ITEM_NODE(redef->item);
20549
20550 xmlSchemaCustomErr(ACTXT_CAST pctxt,
20551 /* TODO: error code. */
20553 node, NULL,
20554 "The referenced %s was already redefined. Multiple "
20555 "redefinition of the same component is not supported",
20556 xmlSchemaGetComponentDesignation(&str, prev),
20557 NULL);
20558 FREE_AND_NULL(str)
20559 err = pctxt->err;
20560 redef = redef->next;
20561 continue;
20562 }
20563 redef = redef->next;
20564 } while (redef != NULL);
20565
20566 return(err);
20567}
20568
20569static int
20570xmlSchemaCheckSRCRedefineSecond(xmlSchemaParserCtxtPtr pctxt)
20571{
20572 int err = 0;
20573 xmlSchemaRedefPtr redef = WXS_CONSTRUCTOR(pctxt)->redefs;
20574 xmlSchemaBasicItemPtr item;
20575
20576 if (redef == NULL)
20577 return(0);
20578
20579 do {
20580 if (redef->target == NULL) {
20581 redef = redef->next;
20582 continue;
20583 }
20584 item = redef->item;
20585
20586 switch (item->type) {
20587 case XML_SCHEMA_TYPE_SIMPLE:
20588 case XML_SCHEMA_TYPE_COMPLEX:
20589 /*
20590 * Since the spec wants the {name} of the redefined
20591 * type to be 'absent', we'll NULL it.
20592 */
20593 (WXS_TYPE_CAST redef->target)->name = NULL;
20594
20595 /*
20596 * TODO: Seems like there's nothing more to do. The normal
20597 * inheritance mechanism is used. But not 100% sure.
20598 */
20599 break;
20600 case XML_SCHEMA_TYPE_GROUP:
20601 /*
20602 * URGENT TODO:
20603 * SPEC src-redefine:
20604 * (6.2.2) "The {model group} of the model group definition
20605 * which corresponds to it per XML Representation of Model
20606 * Group Definition Schema Components ($3.7.2) must be a
20607 * `valid restriction` of the {model group} of that model
20608 * group definition in I, as defined in Particle Valid
20609 * (Restriction) ($3.9.6)."
20610 */
20611 break;
20612 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20613 /*
20614 * SPEC src-redefine:
20615 * (7.2.2) "The {attribute uses} and {attribute wildcard} of
20616 * the attribute group definition which corresponds to it
20617 * per XML Representation of Attribute Group Definition Schema
20618 * Components ($3.6.2) must be `valid restrictions` of the
20619 * {attribute uses} and {attribute wildcard} of that attribute
20620 * group definition in I, as defined in clause 2, clause 3 and
20621 * clause 4 of Derivation Valid (Restriction, Complex)
20622 * ($3.4.6) (where references to the base type definition are
20623 * understood as references to the attribute group definition
20624 * in I)."
20625 */
20626 err = xmlSchemaCheckDerivationOKRestriction2to4(pctxt,
20627 XML_SCHEMA_ACTION_REDEFINE,
20628 item, redef->target,
20629 (WXS_ATTR_GROUP_CAST item)->attrUses,
20630 (WXS_ATTR_GROUP_CAST redef->target)->attrUses,
20631 (WXS_ATTR_GROUP_CAST item)->attributeWildcard,
20632 (WXS_ATTR_GROUP_CAST redef->target)->attributeWildcard);
20633 if (err == -1)
20634 return(-1);
20635 break;
20636 default:
20637 break;
20638 }
20639 redef = redef->next;
20640 } while (redef != NULL);
20641 return(0);
20642}
20643
20644
20645static int
20646xmlSchemaAddComponents(xmlSchemaParserCtxtPtr pctxt,
20647 xmlSchemaBucketPtr bucket)
20648{
20649 xmlSchemaBasicItemPtr item;
20650 int err;
20652 const xmlChar *name;
20653 int i;
20654
20655#define WXS_GET_GLOBAL_HASH(c, slot) { \
20656 if (WXS_IS_BUCKET_IMPMAIN((c)->type)) \
20657 table = &(WXS_IMPBUCKET((c))->schema->slot); \
20658 else \
20659 table = &(WXS_INCBUCKET((c))->ownerImport->schema->slot); }
20660
20661 /*
20662 * Add global components to the schema's hash tables.
20663 * This is the place where duplicate components will be
20664 * detected.
20665 * TODO: I think normally we should support imports of the
20666 * same namespace from multiple locations. We don't do currently,
20667 * but if we do then according to:
20668 * http://www.w3.org/Bugs/Public/show_bug.cgi?id=2224
20669 * we would need, if imported directly, to import redefined
20670 * components as well to be able to catch clashing components.
20671 * (I hope I'll still know what this means after some months :-()
20672 */
20673 if (bucket == NULL)
20674 return(-1);
20675 if (bucket->flags & XML_SCHEMA_BUCKET_COMPS_ADDED)
20676 return(0);
20677 bucket->flags |= XML_SCHEMA_BUCKET_COMPS_ADDED;
20678
20679 for (i = 0; i < bucket->globals->nbItems; i++) {
20680 item = bucket->globals->items[i];
20681 table = NULL;
20682 switch (item->type) {
20683 case XML_SCHEMA_TYPE_COMPLEX:
20684 case XML_SCHEMA_TYPE_SIMPLE:
20685 if (WXS_REDEFINED_TYPE(item))
20686 continue;
20687 name = (WXS_TYPE_CAST item)->name;
20688 WXS_GET_GLOBAL_HASH(bucket, typeDecl)
20689 break;
20690 case XML_SCHEMA_TYPE_ELEMENT:
20691 name = (WXS_ELEM_CAST item)->name;
20692 WXS_GET_GLOBAL_HASH(bucket, elemDecl)
20693 break;
20694 case XML_SCHEMA_TYPE_ATTRIBUTE:
20695 name = (WXS_ATTR_CAST item)->name;
20696 WXS_GET_GLOBAL_HASH(bucket, attrDecl)
20697 break;
20698 case XML_SCHEMA_TYPE_GROUP:
20699 if (WXS_REDEFINED_MODEL_GROUP_DEF(item))
20700 continue;
20701 name = (WXS_MODEL_GROUPDEF_CAST item)->name;
20702 WXS_GET_GLOBAL_HASH(bucket, groupDecl)
20703 break;
20704 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20705 if (WXS_REDEFINED_ATTR_GROUP(item))
20706 continue;
20707 name = (WXS_ATTR_GROUP_CAST item)->name;
20708 WXS_GET_GLOBAL_HASH(bucket, attrgrpDecl)
20709 break;
20710 case XML_SCHEMA_TYPE_IDC_KEY:
20711 case XML_SCHEMA_TYPE_IDC_UNIQUE:
20712 case XML_SCHEMA_TYPE_IDC_KEYREF:
20713 name = (WXS_IDC_CAST item)->name;
20714 WXS_GET_GLOBAL_HASH(bucket, idcDef)
20715 break;
20716 case XML_SCHEMA_TYPE_NOTATION:
20717 name = ((xmlSchemaNotationPtr) item)->name;
20718 WXS_GET_GLOBAL_HASH(bucket, notaDecl)
20719 break;
20720 default:
20721 PERROR_INT("xmlSchemaAddComponents",
20722 "Unexpected global component type");
20723 continue;
20724 }
20725 if (*table == NULL) {
20726 *table = xmlHashCreateDict(10, pctxt->dict);
20727 if (*table == NULL) {
20728 PERROR_INT("xmlSchemaAddComponents",
20729 "failed to create a component hash table");
20730 return(-1);
20731 }
20732 }
20734 if (err != 0) {
20735 xmlChar *str = NULL;
20736
20737 xmlSchemaCustomErr(ACTXT_CAST pctxt,
20739 WXS_ITEM_NODE(item),
20740 WXS_BASIC_CAST item,
20741 "A global %s '%s' does already exist",
20742 WXS_ITEM_TYPE_NAME(item),
20743 xmlSchemaGetComponentQName(&str, item));
20744 FREE_AND_NULL(str);
20745 }
20746 }
20747 /*
20748 * Process imported/included schemas.
20749 */
20750 if (bucket->relations != NULL) {
20751 xmlSchemaSchemaRelationPtr rel = bucket->relations;
20752 do {
20753 if ((rel->bucket != NULL) &&
20754 ((rel->bucket->flags & XML_SCHEMA_BUCKET_COMPS_ADDED) == 0)) {
20755 if (xmlSchemaAddComponents(pctxt, rel->bucket) == -1)
20756 return(-1);
20757 }
20758 rel = rel->next;
20759 } while (rel != NULL);
20760 }
20761 return(0);
20762}
20763
20764static int
20765xmlSchemaFixupComponents(xmlSchemaParserCtxtPtr pctxt,
20766 xmlSchemaBucketPtr rootBucket)
20767{
20768 xmlSchemaConstructionCtxtPtr con = pctxt->constructor;
20769 xmlSchemaTreeItemPtr item, *items;
20770 int nbItems, i, ret = 0;
20771 xmlSchemaBucketPtr oldbucket = con->bucket;
20772 xmlSchemaElementPtr elemDecl;
20773
20774#define FIXHFAILURE if (pctxt->err == XML_SCHEMAP_INTERNAL) goto exit_failure;
20775
20776 if ((con->pending == NULL) ||
20777 (con->pending->nbItems == 0))
20778 return(0);
20779
20780 /*
20781 * Since xmlSchemaFixupComplexType() will create new particles
20782 * (local components), and those particle components need a bucket
20783 * on the constructor, we'll assure here that the constructor has
20784 * a bucket.
20785 * TODO: Think about storing locals _only_ on the main bucket.
20786 */
20787 if (con->bucket == NULL)
20788 con->bucket = rootBucket;
20789
20790 /* TODO:
20791 * SPEC (src-redefine):
20792 * (6.2) "If it has no such self-reference, then all of the
20793 * following must be true:"
20794
20795 * (6.2.2) The {model group} of the model group definition which
20796 * corresponds to it per XML Representation of Model Group
20797 * Definition Schema Components ($3.7.2) must be a `valid
20798 * restriction` of the {model group} of that model group definition
20799 * in I, as defined in Particle Valid (Restriction) ($3.9.6)."
20800 */
20801 xmlSchemaCheckSRCRedefineFirst(pctxt);
20802
20803 /*
20804 * Add global components to the schemata's hash tables.
20805 */
20806 xmlSchemaAddComponents(pctxt, rootBucket);
20807
20808 pctxt->ctxtType = NULL;
20809 items = (xmlSchemaTreeItemPtr *) con->pending->items;
20810 nbItems = con->pending->nbItems;
20811 /*
20812 * Now that we have parsed *all* the schema document(s) and converted
20813 * them to schema components, we can resolve references, apply component
20814 * constraints, create the FSA from the content model, etc.
20815 */
20816 /*
20817 * Resolve references of..
20818 *
20819 * 1. element declarations:
20820 * - the type definition
20821 * - the substitution group affiliation
20822 * 2. simple/complex types:
20823 * - the base type definition
20824 * - the memberTypes of union types
20825 * - the itemType of list types
20826 * 3. attributes declarations and attribute uses:
20827 * - the type definition
20828 * - if an attribute use, then the attribute declaration
20829 * 4. attribute group references:
20830 * - the attribute group definition
20831 * 5. particles:
20832 * - the term of the particle (e.g. a model group)
20833 * 6. IDC key-references:
20834 * - the referenced IDC 'key' or 'unique' definition
20835 * 7. Attribute prohibitions which had a "ref" attribute.
20836 */
20837 for (i = 0; i < nbItems; i++) {
20838 item = items[i];
20839 switch (item->type) {
20840 case XML_SCHEMA_TYPE_ELEMENT:
20841 xmlSchemaResolveElementReferences(
20842 (xmlSchemaElementPtr) item, pctxt);
20843 FIXHFAILURE;
20844 break;
20845 case XML_SCHEMA_TYPE_COMPLEX:
20846 case XML_SCHEMA_TYPE_SIMPLE:
20847 xmlSchemaResolveTypeReferences(
20848 (xmlSchemaTypePtr) item, pctxt);
20849 FIXHFAILURE;
20850 break;
20851 case XML_SCHEMA_TYPE_ATTRIBUTE:
20852 xmlSchemaResolveAttrTypeReferences(
20853 (xmlSchemaAttributePtr) item, pctxt);
20854 FIXHFAILURE;
20855 break;
20856 case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
20857 xmlSchemaResolveAttrUseReferences(
20858 (xmlSchemaAttributeUsePtr) item, pctxt);
20859 FIXHFAILURE;
20860 break;
20861 case XML_SCHEMA_EXTRA_QNAMEREF:
20862 if ((WXS_QNAME_CAST item)->itemType ==
20863 XML_SCHEMA_TYPE_ATTRIBUTEGROUP)
20864 {
20865 xmlSchemaResolveAttrGroupReferences(
20866 WXS_QNAME_CAST item, pctxt);
20867 }
20868 FIXHFAILURE;
20869 break;
20870 case XML_SCHEMA_TYPE_SEQUENCE:
20871 case XML_SCHEMA_TYPE_CHOICE:
20872 case XML_SCHEMA_TYPE_ALL:
20873 xmlSchemaResolveModelGroupParticleReferences(pctxt,
20874 WXS_MODEL_GROUP_CAST item);
20875 FIXHFAILURE;
20876 break;
20877 case XML_SCHEMA_TYPE_IDC_KEY:
20878 case XML_SCHEMA_TYPE_IDC_UNIQUE:
20879 case XML_SCHEMA_TYPE_IDC_KEYREF:
20880 xmlSchemaResolveIDCKeyReferences(
20881 (xmlSchemaIDCPtr) item, pctxt);
20882 FIXHFAILURE;
20883 break;
20884 case XML_SCHEMA_EXTRA_ATTR_USE_PROHIB:
20885 /*
20886 * Handle attribute prohibition which had a
20887 * "ref" attribute.
20888 */
20889 xmlSchemaResolveAttrUseProhibReferences(
20890 WXS_ATTR_PROHIB_CAST item, pctxt);
20891 FIXHFAILURE;
20892 break;
20893 default:
20894 break;
20895 }
20896 }
20897 if (pctxt->nberrors != 0)
20898 goto exit_error;
20899
20900 /*
20901 * Now that all references are resolved we
20902 * can check for circularity of...
20903 * 1. the base axis of type definitions
20904 * 2. nested model group definitions
20905 * 3. nested attribute group definitions
20906 * TODO: check for circular substitution groups.
20907 */
20908 for (i = 0; i < nbItems; i++) {
20909 item = items[i];
20910 /*
20911 * Let's better stop on the first error here.
20912 */
20913 switch (item->type) {
20914 case XML_SCHEMA_TYPE_COMPLEX:
20915 case XML_SCHEMA_TYPE_SIMPLE:
20916 xmlSchemaCheckTypeDefCircular(
20917 (xmlSchemaTypePtr) item, pctxt);
20918 FIXHFAILURE;
20919 if (pctxt->nberrors != 0)
20920 goto exit_error;
20921 break;
20922 case XML_SCHEMA_TYPE_GROUP:
20923 xmlSchemaCheckGroupDefCircular(
20924 (xmlSchemaModelGroupDefPtr) item, pctxt);
20925 FIXHFAILURE;
20926 if (pctxt->nberrors != 0)
20927 goto exit_error;
20928 break;
20929 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20930 xmlSchemaCheckAttrGroupCircular(
20931 (xmlSchemaAttributeGroupPtr) item, pctxt);
20932 FIXHFAILURE;
20933 if (pctxt->nberrors != 0)
20934 goto exit_error;
20935 break;
20936 default:
20937 break;
20938 }
20939 }
20940 if (pctxt->nberrors != 0)
20941 goto exit_error;
20942 /*
20943 * Model group definition references:
20944 * Such a reference is reflected by a particle at the component
20945 * level. Until now the 'term' of such particles pointed
20946 * to the model group definition; this was done, in order to
20947 * ease circularity checks. Now we need to set the 'term' of
20948 * such particles to the model group of the model group definition.
20949 */
20950 for (i = 0; i < nbItems; i++) {
20951 item = items[i];
20952 switch (item->type) {
20953 case XML_SCHEMA_TYPE_SEQUENCE:
20954 case XML_SCHEMA_TYPE_CHOICE:
20955 xmlSchemaModelGroupToModelGroupDefFixup(pctxt,
20956 WXS_MODEL_GROUP_CAST item);
20957 break;
20958 default:
20959 break;
20960 }
20961 }
20962 if (pctxt->nberrors != 0)
20963 goto exit_error;
20964 /*
20965 * Expand attribute group references of attribute group definitions.
20966 */
20967 for (i = 0; i < nbItems; i++) {
20968 item = items[i];
20969 switch (item->type) {
20970 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20971 if ((! WXS_ATTR_GROUP_EXPANDED(item)) &&
20972 WXS_ATTR_GROUP_HAS_REFS(item))
20973 {
20974 xmlSchemaAttributeGroupExpandRefs(pctxt,
20975 WXS_ATTR_GROUP_CAST item);
20976 FIXHFAILURE;
20977 }
20978 break;
20979 default:
20980 break;
20981 }
20982 }
20983 if (pctxt->nberrors != 0)
20984 goto exit_error;
20985 /*
20986 * First compute the variety of simple types. This is needed as
20987 * a separate step, since otherwise we won't be able to detect
20988 * circular union types in all cases.
20989 */
20990 for (i = 0; i < nbItems; i++) {
20991 item = items[i];
20992 switch (item->type) {
20993 case XML_SCHEMA_TYPE_SIMPLE:
20994 if (WXS_IS_TYPE_NOT_FIXED_1((xmlSchemaTypePtr) item)) {
20995 xmlSchemaFixupSimpleTypeStageOne(pctxt,
20996 (xmlSchemaTypePtr) item);
20997 FIXHFAILURE;
20998 }
20999 break;
21000 default:
21001 break;
21002 }
21003 }
21004 if (pctxt->nberrors != 0)
21005 goto exit_error;
21006 /*
21007 * Detect circular union types. Note that this needs the variety to
21008 * be already computed.
21009 */
21010 for (i = 0; i < nbItems; i++) {
21011 item = items[i];
21012 switch (item->type) {
21013 case XML_SCHEMA_TYPE_SIMPLE:
21014 if (((xmlSchemaTypePtr) item)->memberTypes != NULL) {
21015 xmlSchemaCheckUnionTypeDefCircular(pctxt,
21016 (xmlSchemaTypePtr) item);
21017 FIXHFAILURE;
21018 }
21019 break;
21020 default:
21021 break;
21022 }
21023 }
21024 if (pctxt->nberrors != 0)
21025 goto exit_error;
21026
21027 /*
21028 * Do the complete type fixup for simple types.
21029 */
21030 for (i = 0; i < nbItems; i++) {
21031 item = items[i];
21032 switch (item->type) {
21033 case XML_SCHEMA_TYPE_SIMPLE:
21034 if (WXS_IS_TYPE_NOT_FIXED(WXS_TYPE_CAST item)) {
21035 xmlSchemaFixupSimpleTypeStageTwo(pctxt, WXS_TYPE_CAST item);
21036 FIXHFAILURE;
21037 }
21038 break;
21039 default:
21040 break;
21041 }
21042 }
21043 if (pctxt->nberrors != 0)
21044 goto exit_error;
21045 /*
21046 * At this point we need build and check all simple types.
21047 */
21048 /*
21049 * Apply constraints for attribute declarations.
21050 */
21051 for (i = 0; i < nbItems; i++) {
21052 item = items[i];
21053 switch (item->type) {
21054 case XML_SCHEMA_TYPE_ATTRIBUTE:
21055 xmlSchemaCheckAttrPropsCorrect(pctxt, WXS_ATTR_CAST item);
21056 FIXHFAILURE;
21057 break;
21058 default:
21059 break;
21060 }
21061 }
21062 if (pctxt->nberrors != 0)
21063 goto exit_error;
21064 /*
21065 * Apply constraints for attribute uses.
21066 */
21067 for (i = 0; i < nbItems; i++) {
21068 item = items[i];
21069 switch (item->type) {
21070 case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
21071 if (((xmlSchemaAttributeUsePtr)item)->defValue != NULL) {
21072 xmlSchemaCheckAttrUsePropsCorrect(pctxt,
21073 WXS_ATTR_USE_CAST item);
21074 FIXHFAILURE;
21075 }
21076 break;
21077 default:
21078 break;
21079 }
21080 }
21081 if (pctxt->nberrors != 0)
21082 goto exit_error;
21083
21084 /*
21085 * Apply constraints for attribute group definitions.
21086 */
21087 for (i = 0; i < nbItems; i++) {
21088 item = items[i];
21089 switch (item->type) {
21090 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
21091 if (( (WXS_ATTR_GROUP_CAST item)->attrUses != NULL) &&
21092 ( (WXS_LIST_CAST (WXS_ATTR_GROUP_CAST item)->attrUses)->nbItems > 1))
21093 {
21094 xmlSchemaCheckAGPropsCorrect(pctxt, WXS_ATTR_GROUP_CAST item);
21095 FIXHFAILURE;
21096 }
21097 break;
21098 default:
21099 break;
21100 }
21101 }
21102 if (pctxt->nberrors != 0)
21103 goto exit_error;
21104
21105 /*
21106 * Apply constraints for redefinitions.
21107 */
21108 if (WXS_CONSTRUCTOR(pctxt)->redefs != NULL)
21109 xmlSchemaCheckSRCRedefineSecond(pctxt);
21110 if (pctxt->nberrors != 0)
21111 goto exit_error;
21112
21113 /*
21114 * Complex types are built and checked.
21115 */
21116 for (i = 0; i < nbItems; i++) {
21117 item = con->pending->items[i];
21118 switch (item->type) {
21119 case XML_SCHEMA_TYPE_COMPLEX:
21120 if (WXS_IS_TYPE_NOT_FIXED(WXS_TYPE_CAST item)) {
21121 xmlSchemaFixupComplexType(pctxt, WXS_TYPE_CAST item);
21122 FIXHFAILURE;
21123 }
21124 break;
21125 default:
21126 break;
21127 }
21128 }
21129 if (pctxt->nberrors != 0)
21130 goto exit_error;
21131
21132 /*
21133 * The list could have changed, since xmlSchemaFixupComplexType()
21134 * will create particles and model groups in some cases.
21135 */
21136 items = (xmlSchemaTreeItemPtr *) con->pending->items;
21137 nbItems = con->pending->nbItems;
21138
21139 /*
21140 * Apply some constraints for element declarations.
21141 */
21142 for (i = 0; i < nbItems; i++) {
21143 item = items[i];
21144 switch (item->type) {
21145 case XML_SCHEMA_TYPE_ELEMENT:
21146 elemDecl = (xmlSchemaElementPtr) item;
21147
21148 if ((elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_CHECKED) == 0)
21149 {
21150 xmlSchemaCheckElementDeclComponent(
21151 (xmlSchemaElementPtr) elemDecl, pctxt);
21152 FIXHFAILURE;
21153 }
21154
21155#ifdef WXS_ELEM_DECL_CONS_ENABLED
21156 /*
21157 * Schema Component Constraint: Element Declarations Consistent
21158 * Apply this constraint to local types of element declarations.
21159 */
21160 if ((WXS_ELEM_TYPEDEF(elemDecl) != NULL) &&
21161 (WXS_IS_COMPLEX(WXS_ELEM_TYPEDEF(elemDecl))) &&
21162 (WXS_TYPE_IS_LOCAL(WXS_ELEM_TYPEDEF(elemDecl))))
21163 {
21164 xmlSchemaCheckElementDeclConsistent(pctxt,
21165 WXS_BASIC_CAST elemDecl,
21166 WXS_TYPE_PARTICLE(WXS_ELEM_TYPEDEF(elemDecl)),
21167 NULL, NULL, 0);
21168 }
21169#endif
21170 break;
21171 default:
21172 break;
21173 }
21174 }
21175 if (pctxt->nberrors != 0)
21176 goto exit_error;
21177
21178 /*
21179 * Finally we can build the automaton from the content model of
21180 * complex types.
21181 */
21182
21183 for (i = 0; i < nbItems; i++) {
21184 item = items[i];
21185 switch (item->type) {
21186 case XML_SCHEMA_TYPE_COMPLEX:
21187 xmlSchemaBuildContentModel((xmlSchemaTypePtr) item, pctxt);
21188 /* FIXHFAILURE; */
21189 break;
21190 default:
21191 break;
21192 }
21193 }
21194 if (pctxt->nberrors != 0)
21195 goto exit_error;
21196 /*
21197 * URGENT TODO: cos-element-consistent
21198 */
21199 goto exit;
21200
21201exit_error:
21202 ret = pctxt->err;
21203 goto exit;
21204
21205exit_failure:
21206 ret = -1;
21207
21208exit:
21209 /*
21210 * Reset the constructor. This is needed for XSI acquisition, since
21211 * those items will be processed over and over again for every XSI
21212 * if not cleared here.
21213 */
21214 con->bucket = oldbucket;
21215 con->pending->nbItems = 0;
21216 if (con->substGroups != NULL) {
21217 xmlHashFree(con->substGroups, xmlSchemaSubstGroupFreeEntry);
21218 con->substGroups = NULL;
21219 }
21220 if (con->redefs != NULL) {
21221 xmlSchemaRedefListFree(con->redefs);
21222 con->redefs = NULL;
21223 }
21224 return(ret);
21225}
21236xmlSchemaPtr
21237xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt)
21238{
21239 xmlSchemaPtr mainSchema = NULL;
21240 xmlSchemaBucketPtr bucket = NULL;
21241 int res;
21242
21243 /*
21244 * This one is used if the schema to be parsed was specified via
21245 * the API; i.e. not automatically by the validated instance document.
21246 */
21247
21248 if (xmlSchemaInitTypes() < 0)
21249 return (NULL);
21250
21251 if (ctxt == NULL)
21252 return (NULL);
21253
21254 /* TODO: Init the context. Is this all we need?*/
21255 ctxt->nberrors = 0;
21256 ctxt->err = 0;
21257 ctxt->counter = 0;
21258
21259 /* Create the *main* schema. */
21260 mainSchema = xmlSchemaNewSchema(ctxt);
21261 if (mainSchema == NULL)
21262 goto exit_failure;
21263 /*
21264 * Create the schema constructor.
21265 */
21266 if (ctxt->constructor == NULL) {
21267 ctxt->constructor = xmlSchemaConstructionCtxtCreate(ctxt->dict);
21268 if (ctxt->constructor == NULL)
21269 goto exit_failure;
21270 /* Take ownership of the constructor to be able to free it. */
21271 ctxt->ownsConstructor = 1;
21272 }
21273 ctxt->constructor->mainSchema = mainSchema;
21274 /*
21275 * Locate and add the schema document.
21276 */
21277 res = xmlSchemaAddSchemaDoc(ctxt, XML_SCHEMA_SCHEMA_MAIN,
21278 ctxt->URL, ctxt->doc, ctxt->buffer, ctxt->size, NULL,
21279 NULL, NULL, &bucket);
21280 if (res == -1)
21281 goto exit_failure;
21282 if (res != 0)
21283 goto exit;
21284
21285 if (bucket == NULL) {
21286 /* TODO: Error code, actually we failed to *locate* the schema. */
21287 if (ctxt->URL)
21288 xmlSchemaCustomErr(ACTXT_CAST ctxt, XML_SCHEMAP_FAILED_LOAD,
21289 NULL, NULL,
21290 "Failed to locate the main schema resource at '%s'",
21291 ctxt->URL, NULL);
21292 else
21293 xmlSchemaCustomErr(ACTXT_CAST ctxt, XML_SCHEMAP_FAILED_LOAD,
21294 NULL, NULL,
21295 "Failed to locate the main schema resource",
21296 NULL, NULL);
21297 goto exit;
21298 }
21299 /* Then do the parsing for good. */
21300 if (xmlSchemaParseNewDocWithContext(ctxt, mainSchema, bucket) == -1)
21301 goto exit_failure;
21302 if (ctxt->nberrors != 0)
21303 goto exit;
21304
21305 mainSchema->doc = bucket->doc;
21306 mainSchema->preserve = ctxt->preserve;
21307
21308 ctxt->schema = mainSchema;
21309
21310 if (xmlSchemaFixupComponents(ctxt, WXS_CONSTRUCTOR(ctxt)->mainBucket) == -1)
21311 goto exit_failure;
21312
21313 /*
21314 * TODO: This is not nice, since we cannot distinguish from the
21315 * result if there was an internal error or not.
21316 */
21317exit:
21318 if (ctxt->nberrors != 0) {
21319 if (mainSchema) {
21320 xmlSchemaFree(mainSchema);
21321 mainSchema = NULL;
21322 }
21323 if (ctxt->constructor) {
21324 xmlSchemaConstructionCtxtFree(ctxt->constructor);
21325 ctxt->constructor = NULL;
21326 ctxt->ownsConstructor = 0;
21327 }
21328 }
21329 ctxt->schema = NULL;
21330 return(mainSchema);
21331exit_failure:
21332 /*
21333 * Quite verbose, but should catch internal errors, which were
21334 * not communicated.
21335 */
21336 if (mainSchema) {
21337 xmlSchemaFree(mainSchema);
21338 mainSchema = NULL;
21339 }
21340 if (ctxt->constructor) {
21341 xmlSchemaConstructionCtxtFree(ctxt->constructor);
21342 ctxt->constructor = NULL;
21343 ctxt->ownsConstructor = 0;
21344 }
21345 PERROR_INT2("xmlSchemaParse",
21346 "An internal error occurred");
21347 ctxt->schema = NULL;
21348 return(NULL);
21349}
21350
21360void
21361xmlSchemaSetParserErrors(xmlSchemaParserCtxtPtr ctxt,
21362 xmlSchemaValidityErrorFunc err,
21363 xmlSchemaValidityWarningFunc warn, void *ctx)
21364{
21365 if (ctxt == NULL)
21366 return;
21367 ctxt->error = err;
21368 ctxt->warning = warn;
21369 ctxt->errCtxt = ctx;
21370 if (ctxt->vctxt != NULL)
21371 xmlSchemaSetValidErrors(ctxt->vctxt, err, warn, ctx);
21372}
21373
21382void
21383xmlSchemaSetParserStructuredErrors(xmlSchemaParserCtxtPtr ctxt,
21385 void *ctx)
21386{
21387 if (ctxt == NULL)
21388 return;
21389 ctxt->serror = serror;
21390 ctxt->errCtxt = ctx;
21391 if (ctxt->vctxt != NULL)
21392 xmlSchemaSetValidStructuredErrors(ctxt->vctxt, serror, ctx);
21393}
21394
21406int
21407xmlSchemaGetParserErrors(xmlSchemaParserCtxtPtr ctxt,
21408 xmlSchemaValidityErrorFunc * err,
21409 xmlSchemaValidityWarningFunc * warn, void **ctx)
21410{
21411 if (ctxt == NULL)
21412 return(-1);
21413 if (err != NULL)
21414 *err = ctxt->error;
21415 if (warn != NULL)
21416 *warn = ctxt->warning;
21417 if (ctx != NULL)
21418 *ctx = ctxt->errCtxt;
21419 return(0);
21420}
21421
21431static const xmlChar *
21432xmlSchemaFacetTypeToString(xmlSchemaTypeType type)
21433{
21434 switch (type) {
21435 case XML_SCHEMA_FACET_PATTERN:
21436 return (BAD_CAST "pattern");
21437 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
21438 return (BAD_CAST "maxExclusive");
21439 case XML_SCHEMA_FACET_MAXINCLUSIVE:
21440 return (BAD_CAST "maxInclusive");
21441 case XML_SCHEMA_FACET_MINEXCLUSIVE:
21442 return (BAD_CAST "minExclusive");
21443 case XML_SCHEMA_FACET_MININCLUSIVE:
21444 return (BAD_CAST "minInclusive");
21445 case XML_SCHEMA_FACET_WHITESPACE:
21446 return (BAD_CAST "whiteSpace");
21447 case XML_SCHEMA_FACET_ENUMERATION:
21448 return (BAD_CAST "enumeration");
21449 case XML_SCHEMA_FACET_LENGTH:
21450 return (BAD_CAST "length");
21451 case XML_SCHEMA_FACET_MAXLENGTH:
21452 return (BAD_CAST "maxLength");
21453 case XML_SCHEMA_FACET_MINLENGTH:
21454 return (BAD_CAST "minLength");
21455 case XML_SCHEMA_FACET_TOTALDIGITS:
21456 return (BAD_CAST "totalDigits");
21457 case XML_SCHEMA_FACET_FRACTIONDIGITS:
21458 return (BAD_CAST "fractionDigits");
21459 default:
21460 break;
21461 }
21462 return (BAD_CAST "Internal Error");
21463}
21464
21465static xmlSchemaWhitespaceValueType
21466xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type)
21467{
21468 /*
21469 * The normalization type can be changed only for types which are derived
21470 * from xsd:string.
21471 */
21472 if (type->type == XML_SCHEMA_TYPE_BASIC) {
21473 /*
21474 * Note that we assume a whitespace of preserve for anySimpleType.
21475 */
21476 if ((type->builtInType == XML_SCHEMAS_STRING) ||
21477 (type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE))
21478 return(XML_SCHEMA_WHITESPACE_PRESERVE);
21479 else if (type->builtInType == XML_SCHEMAS_NORMSTRING)
21480 return(XML_SCHEMA_WHITESPACE_REPLACE);
21481 else {
21482 /*
21483 * For all `atomic` datatypes other than string (and types `derived`
21484 * by `restriction` from it) the value of whiteSpace is fixed to
21485 * collapse
21486 * Note that this includes built-in list datatypes.
21487 */
21488 return(XML_SCHEMA_WHITESPACE_COLLAPSE);
21489 }
21490 } else if (WXS_IS_LIST(type)) {
21491 /*
21492 * For list types the facet "whiteSpace" is fixed to "collapse".
21493 */
21494 return (XML_SCHEMA_WHITESPACE_COLLAPSE);
21495 } else if (WXS_IS_UNION(type)) {
21496 return (XML_SCHEMA_WHITESPACE_UNKNOWN);
21497 } else if (WXS_IS_ATOMIC(type)) {
21498 if (type->flags & XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE)
21499 return (XML_SCHEMA_WHITESPACE_PRESERVE);
21500 else if (type->flags & XML_SCHEMAS_TYPE_WHITESPACE_REPLACE)
21501 return (XML_SCHEMA_WHITESPACE_REPLACE);
21502 else
21503 return (XML_SCHEMA_WHITESPACE_COLLAPSE);
21504 }
21505 return (-1);
21506}
21507
21508/************************************************************************
21509 * *
21510 * Simple type validation *
21511 * *
21512 ************************************************************************/
21513
21514
21515/************************************************************************
21516 * *
21517 * DOM Validation code *
21518 * *
21519 ************************************************************************/
21520
21535static int
21536xmlSchemaAssembleByLocation(xmlSchemaValidCtxtPtr vctxt,
21537 xmlSchemaPtr schema,
21538 xmlNodePtr node,
21539 const xmlChar *nsName,
21540 const xmlChar *location)
21541{
21542 int ret = 0;
21543 xmlSchemaParserCtxtPtr pctxt;
21544 xmlSchemaBucketPtr bucket = NULL;
21545
21546 if ((vctxt == NULL) || (schema == NULL))
21547 return (-1);
21548
21549 if (vctxt->pctxt == NULL) {
21550 VERROR_INT("xmlSchemaAssembleByLocation",
21551 "no parser context available");
21552 return(-1);
21553 }
21554 pctxt = vctxt->pctxt;
21555 if (pctxt->constructor == NULL) {
21556 PERROR_INT("xmlSchemaAssembleByLocation",
21557 "no constructor");
21558 return(-1);
21559 }
21560 /*
21561 * Acquire the schema document.
21562 */
21563 location = xmlSchemaBuildAbsoluteURI(pctxt->dict,
21564 location, node);
21565 /*
21566 * Note that we pass XML_SCHEMA_SCHEMA_IMPORT here;
21567 * the process will automatically change this to
21568 * XML_SCHEMA_SCHEMA_MAIN if it is the first schema document.
21569 */
21570 ret = xmlSchemaAddSchemaDoc(pctxt, XML_SCHEMA_SCHEMA_IMPORT,
21571 location, NULL, NULL, 0, node, NULL, nsName,
21572 &bucket);
21573 if (ret != 0)
21574 return(ret);
21575 if (bucket == NULL) {
21576 /*
21577 * Generate a warning that the document could not be located.
21578 */
21579 xmlSchemaCustomWarning(ACTXT_CAST vctxt, XML_SCHEMAV_MISC,
21580 node, NULL,
21581 "The document at location '%s' could not be acquired",
21582 location, NULL, NULL);
21583 return(ret);
21584 }
21585 /*
21586 * The first located schema will be handled as if all other
21587 * schemas imported by XSI were imported by this first schema.
21588 */
21589 if ((bucket != NULL) &&
21590 (WXS_CONSTRUCTOR(pctxt)->bucket == NULL))
21591 WXS_CONSTRUCTOR(pctxt)->bucket = bucket;
21592 /*
21593 * TODO: Is this handled like an import? I.e. is it not an error
21594 * if the schema cannot be located?
21595 */
21596 if ((bucket == NULL) || (! CAN_PARSE_SCHEMA(bucket)))
21597 return(0);
21598 /*
21599 * We will reuse the parser context for every schema imported
21600 * directly via XSI. So reset the context.
21601 */
21602 pctxt->nberrors = 0;
21603 pctxt->err = 0;
21604 pctxt->doc = bucket->doc;
21605
21606 ret = xmlSchemaParseNewDocWithContext(pctxt, schema, bucket);
21607 if (ret == -1) {
21608 pctxt->doc = NULL;
21609 goto exit_failure;
21610 }
21611 /* Paranoid error channelling. */
21612 if ((ret == 0) && (pctxt->nberrors != 0))
21613 ret = pctxt->err;
21614 if (pctxt->nberrors == 0) {
21615 /*
21616 * Only bother to fixup pending components, if there was
21617 * no error yet.
21618 * For every XSI acquired schema (and its sub-schemata) we will
21619 * fixup the components.
21620 */
21621 xmlSchemaFixupComponents(pctxt, bucket);
21622 ret = pctxt->err;
21623 /*
21624 * Not nice, but we need somehow to channel the schema parser
21625 * error to the validation context.
21626 */
21627 if ((ret != 0) && (vctxt->err == 0))
21628 vctxt->err = ret;
21629 vctxt->nberrors += pctxt->nberrors;
21630 } else {
21631 /* Add to validation error sum. */
21632 vctxt->nberrors += pctxt->nberrors;
21633 }
21634 pctxt->doc = NULL;
21635 return(ret);
21636exit_failure:
21637 pctxt->doc = NULL;
21638 return (-1);
21639}
21640
21641static xmlSchemaAttrInfoPtr
21642xmlSchemaGetMetaAttrInfo(xmlSchemaValidCtxtPtr vctxt,
21643 int metaType)
21644{
21645 if (vctxt->nbAttrInfos == 0)
21646 return (NULL);
21647 {
21648 int i;
21649 xmlSchemaAttrInfoPtr iattr;
21650
21651 for (i = 0; i < vctxt->nbAttrInfos; i++) {
21652 iattr = vctxt->attrInfos[i];
21653 if (iattr->metaType == metaType)
21654 return (iattr);
21655 }
21656
21657 }
21658 return (NULL);
21659}
21660
21673static int
21674xmlSchemaAssembleByXSI(xmlSchemaValidCtxtPtr vctxt)
21675{
21676 const xmlChar *cur, *end;
21677 const xmlChar *nsname = NULL, *location;
21678 int ret = 0;
21679 xmlSchemaAttrInfoPtr iattr;
21680
21681 /*
21682 * Parse the value; we will assume an even number of values
21683 * to be given (this is how Xerces and XSV work).
21684 *
21685 * URGENT TODO: !! This needs to work for both
21686 * @noNamespaceSchemaLocation AND @schemaLocation on the same
21687 * element !!
21688 */
21689 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
21690 XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC);
21691 if (iattr == NULL)
21692 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
21693 XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC);
21694 if (iattr == NULL)
21695 return (0);
21696 cur = iattr->value;
21697 do {
21698 /*
21699 * TODO: Move the string parsing mechanism away from here.
21700 */
21701 if (iattr->metaType == XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC) {
21702 /*
21703 * Get the namespace name.
21704 */
21705 while (IS_BLANK_CH(*cur))
21706 cur++;
21707 end = cur;
21708 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
21709 end++;
21710 if (end == cur)
21711 break;
21712 /* TODO: Don't use the schema's dict. */
21713 nsname = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
21714 cur = end;
21715 }
21716 /*
21717 * Get the URI.
21718 */
21719 while (IS_BLANK_CH(*cur))
21720 cur++;
21721 end = cur;
21722 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
21723 end++;
21724 if (end == cur) {
21725 if (iattr->metaType ==
21726 XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC)
21727 {
21728 /*
21729 * If using @schemaLocation then tuples are expected.
21730 * I.e. the namespace name *and* the document's URI.
21731 */
21732 xmlSchemaCustomWarning(ACTXT_CAST vctxt, XML_SCHEMAV_MISC,
21733 iattr->node, NULL,
21734 "The value must consist of tuples: the target namespace "
21735 "name and the document's URI", NULL, NULL, NULL);
21736 }
21737 break;
21738 }
21739 /* TODO: Don't use the schema's dict. */
21740 location = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
21741 cur = end;
21742 ret = xmlSchemaAssembleByLocation(vctxt, vctxt->schema,
21743 iattr->node, nsname, location);
21744 if (ret == -1) {
21745 VERROR_INT("xmlSchemaAssembleByXSI",
21746 "assembling schemata");
21747 return (-1);
21748 }
21749 } while (*cur != 0);
21750 return (ret);
21751}
21752
21753static const xmlChar *
21754xmlSchemaLookupNamespace(xmlSchemaValidCtxtPtr vctxt,
21755 const xmlChar *prefix)
21756{
21757 if (vctxt->sax != NULL) {
21758 int i, j;
21759 xmlSchemaNodeInfoPtr inode;
21760
21761 for (i = vctxt->depth; i >= 0; i--) {
21762 if (vctxt->elemInfos[i]->nbNsBindings != 0) {
21763 inode = vctxt->elemInfos[i];
21764 for (j = 0; j < inode->nbNsBindings * 2; j += 2) {
21765 if (((prefix == NULL) &&
21766 (inode->nsBindings[j] == NULL)) ||
21767 ((prefix != NULL) && xmlStrEqual(prefix,
21768 inode->nsBindings[j]))) {
21769
21770 /*
21771 * Note that the namespace bindings are already
21772 * in a string dict.
21773 */
21774 return (inode->nsBindings[j+1]);
21775 }
21776 }
21777 }
21778 }
21779 return (NULL);
21780#ifdef LIBXML_READER_ENABLED
21781 } else if (vctxt->reader != NULL) {
21782 xmlChar *nsName;
21783
21784 nsName = xmlTextReaderLookupNamespace(vctxt->reader, prefix);
21785 if (nsName != NULL) {
21786 const xmlChar *ret;
21787
21788 ret = xmlDictLookup(vctxt->dict, nsName, -1);
21789 xmlFree(nsName);
21790 return (ret);
21791 } else
21792 return (NULL);
21793#endif
21794 } else {
21795 xmlNsPtr ns;
21796
21797 if ((vctxt->inode->node == NULL) ||
21798 (vctxt->inode->node->doc == NULL)) {
21799 VERROR_INT("xmlSchemaLookupNamespace",
21800 "no node or node's doc available");
21801 return (NULL);
21802 }
21803 ns = xmlSearchNs(vctxt->inode->node->doc,
21804 vctxt->inode->node, prefix);
21805 if (ns != NULL)
21806 return (ns->href);
21807 return (NULL);
21808 }
21809}
21810
21811/*
21812* This one works on the schema of the validation context.
21813*/
21814static int
21815xmlSchemaValidateNotation(xmlSchemaValidCtxtPtr vctxt,
21816 xmlSchemaPtr schema,
21817 xmlNodePtr node,
21818 const xmlChar *value,
21819 xmlSchemaValPtr *val,
21820 int valNeeded)
21821{
21822 int ret;
21823
21824 if (vctxt && (vctxt->schema == NULL)) {
21825 VERROR_INT("xmlSchemaValidateNotation",
21826 "a schema is needed on the validation context");
21827 return (-1);
21828 }
21829 ret = xmlValidateQName(value, 1);
21830 if (ret != 0)
21831 return (ret);
21832 {
21833 xmlChar *localName = NULL;
21834 xmlChar *prefix = NULL;
21835
21836 localName = xmlSplitQName2(value, &prefix);
21837 if (prefix != NULL) {
21838 const xmlChar *nsName = NULL;
21839
21840 if (vctxt != NULL)
21841 nsName = xmlSchemaLookupNamespace(vctxt, BAD_CAST prefix);
21842 else if (node != NULL) {
21843 xmlNsPtr ns = xmlSearchNs(node->doc, node, prefix);
21844 if (ns != NULL)
21845 nsName = ns->href;
21846 } else {
21847 xmlFree(prefix);
21848 xmlFree(localName);
21849 return (1);
21850 }
21851 if (nsName == NULL) {
21852 xmlFree(prefix);
21853 xmlFree(localName);
21854 return (1);
21855 }
21856 if (xmlSchemaGetNotation(schema, localName, nsName) != NULL) {
21857 if ((valNeeded) && (val != NULL)) {
21858 (*val) = xmlSchemaNewNOTATIONValue(xmlStrdup(localName),
21859 xmlStrdup(nsName));
21860 if (*val == NULL)
21861 ret = -1;
21862 }
21863 } else
21864 ret = 1;
21865 xmlFree(prefix);
21866 xmlFree(localName);
21867 } else {
21868 if (xmlSchemaGetNotation(schema, value, NULL) != NULL) {
21869 if (valNeeded && (val != NULL)) {
21870 (*val) = xmlSchemaNewNOTATIONValue(
21872 if (*val == NULL)
21873 ret = -1;
21874 }
21875 } else
21876 return (1);
21877 }
21878 }
21879 return (ret);
21880}
21881
21882static int
21883xmlSchemaVAddNodeQName(xmlSchemaValidCtxtPtr vctxt,
21884 const xmlChar* lname,
21885 const xmlChar* nsname)
21886{
21887 int i;
21888
21889 lname = xmlDictLookup(vctxt->dict, lname, -1);
21890 if (lname == NULL)
21891 return(-1);
21892 if (nsname != NULL) {
21893 nsname = xmlDictLookup(vctxt->dict, nsname, -1);
21894 if (nsname == NULL)
21895 return(-1);
21896 }
21897 for (i = 0; i < vctxt->nodeQNames->nbItems; i += 2) {
21898 if ((vctxt->nodeQNames->items [i] == lname) &&
21899 (vctxt->nodeQNames->items[i +1] == nsname))
21900 /* Already there */
21901 return(i);
21902 }
21903 /* Add new entry. */
21904 i = vctxt->nodeQNames->nbItems;
21905 xmlSchemaItemListAdd(vctxt->nodeQNames, (void *) lname);
21906 xmlSchemaItemListAdd(vctxt->nodeQNames, (void *) nsname);
21907 return(i);
21908}
21909
21910/************************************************************************
21911 * *
21912 * Validation of identity-constraints (IDC) *
21913 * *
21914 ************************************************************************/
21915
21924static void
21925xmlSchemaAugmentIDC(void *payload, void *data,
21927{
21928 xmlSchemaIDCPtr idcDef = (xmlSchemaIDCPtr) payload;
21929 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) data;
21930 xmlSchemaIDCAugPtr aidc;
21931
21932 aidc = (xmlSchemaIDCAugPtr) xmlMalloc(sizeof(xmlSchemaIDCAug));
21933 if (aidc == NULL) {
21934 xmlSchemaVErrMemory(vctxt,
21935 "xmlSchemaAugmentIDC: allocating an augmented IDC definition",
21936 NULL);
21937 return;
21938 }
21939 aidc->keyrefDepth = -1;
21940 aidc->def = idcDef;
21941 aidc->next = NULL;
21942 if (vctxt->aidcs == NULL)
21943 vctxt->aidcs = aidc;
21944 else {
21945 aidc->next = vctxt->aidcs;
21946 vctxt->aidcs = aidc;
21947 }
21948 /*
21949 * Save if we have keyrefs at all.
21950 */
21951 if ((vctxt->hasKeyrefs == 0) &&
21952 (idcDef->type == XML_SCHEMA_TYPE_IDC_KEYREF))
21953 vctxt->hasKeyrefs = 1;
21954}
21955
21962static void
21963xmlSchemaAugmentImportedIDC(void *payload, void *data,
21964 const xmlChar *name ATTRIBUTE_UNUSED) {
21965 xmlSchemaImportPtr imported = (xmlSchemaImportPtr) payload;
21966 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) data;
21967 if (imported->schema->idcDef != NULL) {
21968 xmlHashScan(imported->schema->idcDef, xmlSchemaAugmentIDC, vctxt);
21969 }
21970}
21971
21980static xmlSchemaPSVIIDCBindingPtr
21981xmlSchemaIDCNewBinding(xmlSchemaIDCPtr idcDef)
21982{
21983 xmlSchemaPSVIIDCBindingPtr ret;
21984
21985 ret = (xmlSchemaPSVIIDCBindingPtr) xmlMalloc(
21986 sizeof(xmlSchemaPSVIIDCBinding));
21987 if (ret == NULL) {
21988 xmlSchemaVErrMemory(NULL,
21989 "allocating a PSVI IDC binding item", NULL);
21990 return (NULL);
21991 }
21992 memset(ret, 0, sizeof(xmlSchemaPSVIIDCBinding));
21993 ret->definition = idcDef;
21994 return (ret);
21995}
21996
22008static int
22009xmlSchemaIDCStoreNodeTableItem(xmlSchemaValidCtxtPtr vctxt,
22010 xmlSchemaPSVIIDCNodePtr item)
22011{
22012 /*
22013 * Add to global list.
22014 */
22015 if (vctxt->idcNodes == NULL) {
22016 vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
22017 xmlMalloc(20 * sizeof(xmlSchemaPSVIIDCNodePtr));
22018 if (vctxt->idcNodes == NULL) {
22019 xmlSchemaVErrMemory(vctxt,
22020 "allocating the IDC node table item list", NULL);
22021 return (-1);
22022 }
22023 vctxt->sizeIdcNodes = 20;
22024 } else if (vctxt->sizeIdcNodes <= vctxt->nbIdcNodes) {
22025 vctxt->sizeIdcNodes *= 2;
22026 vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
22027 xmlRealloc(vctxt->idcNodes, vctxt->sizeIdcNodes *
22028 sizeof(xmlSchemaPSVIIDCNodePtr));
22029 if (vctxt->idcNodes == NULL) {
22030 xmlSchemaVErrMemory(vctxt,
22031 "re-allocating the IDC node table item list", NULL);
22032 return (-1);
22033 }
22034 }
22035 vctxt->idcNodes[vctxt->nbIdcNodes++] = item;
22036
22037 return (0);
22038}
22039
22049static int
22050xmlSchemaIDCStoreKey(xmlSchemaValidCtxtPtr vctxt,
22051 xmlSchemaPSVIIDCKeyPtr key)
22052{
22053 /*
22054 * Add to global list.
22055 */
22056 if (vctxt->idcKeys == NULL) {
22057 vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
22058 xmlMalloc(40 * sizeof(xmlSchemaPSVIIDCKeyPtr));
22059 if (vctxt->idcKeys == NULL) {
22060 xmlSchemaVErrMemory(vctxt,
22061 "allocating the IDC key storage list", NULL);
22062 return (-1);
22063 }
22064 vctxt->sizeIdcKeys = 40;
22065 } else if (vctxt->sizeIdcKeys <= vctxt->nbIdcKeys) {
22066 vctxt->sizeIdcKeys *= 2;
22067 vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
22068 xmlRealloc(vctxt->idcKeys, vctxt->sizeIdcKeys *
22069 sizeof(xmlSchemaPSVIIDCKeyPtr));
22070 if (vctxt->idcKeys == NULL) {
22071 xmlSchemaVErrMemory(vctxt,
22072 "re-allocating the IDC key storage list", NULL);
22073 return (-1);
22074 }
22075 }
22076 vctxt->idcKeys[vctxt->nbIdcKeys++] = key;
22077
22078 return (0);
22079}
22080
22090static int
22091xmlSchemaIDCAppendNodeTableItem(xmlSchemaPSVIIDCBindingPtr bind,
22092 xmlSchemaPSVIIDCNodePtr ntItem)
22093{
22094 if (bind->nodeTable == NULL) {
22095 bind->sizeNodes = 10;
22096 bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
22097 xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr));
22098 if (bind->nodeTable == NULL) {
22099 xmlSchemaVErrMemory(NULL,
22100 "allocating an array of IDC node-table items", NULL);
22101 return(-1);
22102 }
22103 } else if (bind->sizeNodes <= bind->nbNodes) {
22104 bind->sizeNodes *= 2;
22105 bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
22106 xmlRealloc(bind->nodeTable, bind->sizeNodes *
22107 sizeof(xmlSchemaPSVIIDCNodePtr));
22108 if (bind->nodeTable == NULL) {
22109 xmlSchemaVErrMemory(NULL,
22110 "re-allocating an array of IDC node-table items", NULL);
22111 return(-1);
22112 }
22113 }
22114 bind->nodeTable[bind->nbNodes++] = ntItem;
22115 return(0);
22116}
22117
22129static xmlSchemaPSVIIDCBindingPtr
22130xmlSchemaIDCAcquireBinding(xmlSchemaValidCtxtPtr vctxt,
22131 xmlSchemaIDCMatcherPtr matcher)
22132{
22133 xmlSchemaNodeInfoPtr ielem;
22134
22135 ielem = vctxt->elemInfos[matcher->depth];
22136
22137 if (ielem->idcTable == NULL) {
22138 ielem->idcTable = xmlSchemaIDCNewBinding(matcher->aidc->def);
22139 if (ielem->idcTable == NULL)
22140 return (NULL);
22141 return(ielem->idcTable);
22142 } else {
22143 xmlSchemaPSVIIDCBindingPtr bind = NULL;
22144
22145 bind = ielem->idcTable;
22146 do {
22147 if (bind->definition == matcher->aidc->def)
22148 return(bind);
22149 if (bind->next == NULL) {
22150 bind->next = xmlSchemaIDCNewBinding(matcher->aidc->def);
22151 if (bind->next == NULL)
22152 return (NULL);
22153 return(bind->next);
22154 }
22155 bind = bind->next;
22156 } while (bind != NULL);
22157 }
22158 return (NULL);
22159}
22160
22161static xmlSchemaItemListPtr
22162xmlSchemaIDCAcquireTargetList(xmlSchemaValidCtxtPtr vctxt ATTRIBUTE_UNUSED,
22163 xmlSchemaIDCMatcherPtr matcher)
22164{
22165 if (matcher->targets == NULL)
22166 matcher->targets = xmlSchemaItemListCreate();
22167 return(matcher->targets);
22168}
22169
22176static void
22177xmlSchemaIDCFreeKey(xmlSchemaPSVIIDCKeyPtr key)
22178{
22179 if (key->val != NULL)
22180 xmlSchemaFreeValue(key->val);
22181 xmlFree(key);
22182}
22183
22190static void
22191xmlSchemaIDCFreeBinding(xmlSchemaPSVIIDCBindingPtr bind)
22192{
22193 if (bind->nodeTable != NULL)
22194 xmlFree(bind->nodeTable);
22195 if (bind->dupls != NULL)
22196 xmlSchemaItemListFree(bind->dupls);
22197 xmlFree(bind);
22198}
22199
22206static void
22207xmlSchemaIDCFreeIDCTable(xmlSchemaPSVIIDCBindingPtr bind)
22208{
22209 xmlSchemaPSVIIDCBindingPtr prev;
22210
22211 while (bind != NULL) {
22212 prev = bind;
22213 bind = bind->next;
22214 xmlSchemaIDCFreeBinding(prev);
22215 }
22216}
22217
22218static void
22219xmlFreeIDCHashEntry (void *payload, const xmlChar *name ATTRIBUTE_UNUSED)
22220{
22221 xmlIDCHashEntryPtr e = payload, n;
22222 while (e) {
22223 n = e->next;
22224 xmlFree(e);
22225 e = n;
22226 }
22227}
22228
22235static void
22236xmlSchemaIDCFreeMatcherList(xmlSchemaIDCMatcherPtr matcher)
22237{
22238 xmlSchemaIDCMatcherPtr next;
22239
22240 while (matcher != NULL) {
22241 next = matcher->next;
22242 if (matcher->keySeqs != NULL) {
22243 int i;
22244 for (i = 0; i < matcher->sizeKeySeqs; i++)
22245 if (matcher->keySeqs[i] != NULL)
22246 xmlFree(matcher->keySeqs[i]);
22247 xmlFree(matcher->keySeqs);
22248 }
22249 if (matcher->targets != NULL) {
22250 if (matcher->idcType == XML_SCHEMA_TYPE_IDC_KEYREF) {
22251 int i;
22252 xmlSchemaPSVIIDCNodePtr idcNode;
22253 /*
22254 * Node-table items for keyrefs are not stored globally
22255 * to the validation context, since they are not bubbled.
22256 * We need to free them here.
22257 */
22258 for (i = 0; i < matcher->targets->nbItems; i++) {
22259 idcNode =
22260 (xmlSchemaPSVIIDCNodePtr) matcher->targets->items[i];
22261 xmlFree(idcNode->keys);
22262 xmlFree(idcNode);
22263 }
22264 }
22265 xmlSchemaItemListFree(matcher->targets);
22266 }
22267 if (matcher->htab != NULL)
22268 xmlHashFree(matcher->htab, xmlFreeIDCHashEntry);
22269 xmlFree(matcher);
22270 matcher = next;
22271 }
22272}
22273
22281static void
22282xmlSchemaIDCReleaseMatcherList(xmlSchemaValidCtxtPtr vctxt,
22283 xmlSchemaIDCMatcherPtr matcher)
22284{
22285 xmlSchemaIDCMatcherPtr next;
22286
22287 while (matcher != NULL) {
22288 next = matcher->next;
22289 if (matcher->keySeqs != NULL) {
22290 int i;
22291 /*
22292 * Don't free the array, but only the content.
22293 */
22294 for (i = 0; i < matcher->sizeKeySeqs; i++)
22295 if (matcher->keySeqs[i] != NULL) {
22296 xmlFree(matcher->keySeqs[i]);
22297 matcher->keySeqs[i] = NULL;
22298 }
22299 }
22300 if (matcher->targets) {
22301 if (matcher->idcType == XML_SCHEMA_TYPE_IDC_KEYREF) {
22302 int i;
22303 xmlSchemaPSVIIDCNodePtr idcNode;
22304 /*
22305 * Node-table items for keyrefs are not stored globally
22306 * to the validation context, since they are not bubbled.
22307 * We need to free them here.
22308 */
22309 for (i = 0; i < matcher->targets->nbItems; i++) {
22310 idcNode =
22311 (xmlSchemaPSVIIDCNodePtr) matcher->targets->items[i];
22312 xmlFree(idcNode->keys);
22313 xmlFree(idcNode);
22314 }
22315 }
22316 xmlSchemaItemListFree(matcher->targets);
22317 matcher->targets = NULL;
22318 }
22319 if (matcher->htab != NULL) {
22320 xmlHashFree(matcher->htab, xmlFreeIDCHashEntry);
22321 matcher->htab = NULL;
22322 }
22323 matcher->next = NULL;
22324 /*
22325 * Cache the matcher.
22326 */
22327 if (vctxt->idcMatcherCache != NULL)
22328 matcher->nextCached = vctxt->idcMatcherCache;
22329 vctxt->idcMatcherCache = matcher;
22330
22331 matcher = next;
22332 }
22333}
22334
22349static int
22350xmlSchemaIDCAddStateObject(xmlSchemaValidCtxtPtr vctxt,
22351 xmlSchemaIDCMatcherPtr matcher,
22352 xmlSchemaIDCSelectPtr sel,
22353 int type)
22354{
22355 xmlSchemaIDCStateObjPtr sto;
22356
22357 /*
22358 * Reuse the state objects from the pool.
22359 */
22360 if (vctxt->xpathStatePool != NULL) {
22361 sto = vctxt->xpathStatePool;
22362 vctxt->xpathStatePool = sto->next;
22363 sto->next = NULL;
22364 } else {
22365 /*
22366 * Create a new state object.
22367 */
22368 sto = (xmlSchemaIDCStateObjPtr) xmlMalloc(sizeof(xmlSchemaIDCStateObj));
22369 if (sto == NULL) {
22370 xmlSchemaVErrMemory(NULL,
22371 "allocating an IDC state object", NULL);
22372 return (-1);
22373 }
22374 memset(sto, 0, sizeof(xmlSchemaIDCStateObj));
22375 }
22376 /*
22377 * Add to global list.
22378 */
22379 if (vctxt->xpathStates != NULL)
22380 sto->next = vctxt->xpathStates;
22381 vctxt->xpathStates = sto;
22382
22383 /*
22384 * Free the old xpath validation context.
22385 */
22386 if (sto->xpathCtxt != NULL)
22387 xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
22388
22389 /*
22390 * Create a new XPath (pattern) validation context.
22391 */
22392 sto->xpathCtxt = (void *) xmlPatternGetStreamCtxt(
22393 (xmlPatternPtr) sel->xpathComp);
22394 if (sto->xpathCtxt == NULL) {
22395 VERROR_INT("xmlSchemaIDCAddStateObject",
22396 "failed to create an XPath validation context");
22397 return (-1);
22398 }
22399 sto->type = type;
22400 sto->depth = vctxt->depth;
22401 sto->matcher = matcher;
22402 sto->sel = sel;
22403 sto->nbHistory = 0;
22404
22405 return (0);
22406}
22407
22418static int
22419xmlSchemaXPathEvaluate(xmlSchemaValidCtxtPtr vctxt,
22420 xmlElementType nodeType)
22421{
22422 xmlSchemaIDCStateObjPtr sto, head = NULL, first;
22423 int res, resolved = 0, depth = vctxt->depth;
22424
22425 if (vctxt->xpathStates == NULL)
22426 return (0);
22427
22428 if (nodeType == XML_ATTRIBUTE_NODE)
22429 depth++;
22430 /*
22431 * Process all active XPath state objects.
22432 */
22433 first = vctxt->xpathStates;
22434 sto = first;
22435 while (sto != head) {
22436 if (nodeType == XML_ELEMENT_NODE)
22437 res = xmlStreamPush((xmlStreamCtxtPtr) sto->xpathCtxt,
22438 vctxt->inode->localName, vctxt->inode->nsName);
22439 else
22440 res = xmlStreamPushAttr((xmlStreamCtxtPtr) sto->xpathCtxt,
22441 vctxt->inode->localName, vctxt->inode->nsName);
22442
22443 if (res == -1) {
22444 VERROR_INT("xmlSchemaXPathEvaluate",
22445 "calling xmlStreamPush()");
22446 return (-1);
22447 }
22448 if (res == 0)
22449 goto next_sto;
22450 /*
22451 * Full match.
22452 */
22453 /*
22454 * Register a match in the state object history.
22455 */
22456 if (sto->history == NULL) {
22457 sto->history = (int *) xmlMalloc(5 * sizeof(int));
22458 if (sto->history == NULL) {
22459 xmlSchemaVErrMemory(NULL,
22460 "allocating the state object history", NULL);
22461 return(-1);
22462 }
22463 sto->sizeHistory = 5;
22464 } else if (sto->sizeHistory <= sto->nbHistory) {
22465 sto->sizeHistory *= 2;
22466 sto->history = (int *) xmlRealloc(sto->history,
22467 sto->sizeHistory * sizeof(int));
22468 if (sto->history == NULL) {
22469 xmlSchemaVErrMemory(NULL,
22470 "re-allocating the state object history", NULL);
22471 return(-1);
22472 }
22473 }
22474 sto->history[sto->nbHistory++] = depth;
22475
22476 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
22477 xmlSchemaIDCSelectPtr sel;
22478 /*
22479 * Activate state objects for the IDC fields of
22480 * the IDC selector.
22481 */
22482 sel = sto->matcher->aidc->def->fields;
22483 while (sel != NULL) {
22484 if (xmlSchemaIDCAddStateObject(vctxt, sto->matcher,
22485 sel, XPATH_STATE_OBJ_TYPE_IDC_FIELD) == -1)
22486 return (-1);
22487 sel = sel->next;
22488 }
22489 } else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
22490 /*
22491 * An IDC key node was found by the IDC field.
22492 */
22493 /*
22494 * Notify that the character value of this node is
22495 * needed.
22496 */
22497 if (resolved == 0) {
22498 if ((vctxt->inode->flags &
22499 XML_SCHEMA_NODE_INFO_VALUE_NEEDED) == 0)
22500 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_VALUE_NEEDED;
22501 }
22502 resolved++;
22503 }
22504next_sto:
22505 if (sto->next == NULL) {
22506 /*
22507 * Evaluate field state objects created on this node as well.
22508 */
22509 head = first;
22510 sto = vctxt->xpathStates;
22511 } else
22512 sto = sto->next;
22513 }
22514 return (resolved);
22515}
22516
22517static const xmlChar *
22518xmlSchemaFormatIDCKeySequence_1(xmlSchemaValidCtxtPtr vctxt,
22519 xmlChar **buf,
22520 xmlSchemaPSVIIDCKeyPtr *seq,
22521 int count, int for_hash)
22522{
22523 int i, res;
22524 xmlChar *value = NULL;
22525
22526 *buf = xmlStrdup(BAD_CAST "[");
22527 for (i = 0; i < count; i++) {
22528 *buf = xmlStrcat(*buf, BAD_CAST "'");
22529 if (!for_hash)
22530 res = xmlSchemaGetCanonValueWhtspExt(seq[i]->val,
22531 xmlSchemaGetWhiteSpaceFacetValue(seq[i]->type),
22532 &value);
22533 else {
22534 res = xmlSchemaGetCanonValueHash(seq[i]->val, &value);
22535 }
22536 if (res == 0)
22538 else {
22539 VERROR_INT("xmlSchemaFormatIDCKeySequence",
22540 "failed to compute a canonical value");
22541 *buf = xmlStrcat(*buf, BAD_CAST "???");
22542 }
22543 if (i < count -1)
22544 *buf = xmlStrcat(*buf, BAD_CAST "', ");
22545 else
22546 *buf = xmlStrcat(*buf, BAD_CAST "'");
22547 if (value != NULL) {
22548 xmlFree(value);
22549 value = NULL;
22550 }
22551 }
22552 *buf = xmlStrcat(*buf, BAD_CAST "]");
22553
22554 return (BAD_CAST *buf);
22555}
22556
22557static const xmlChar *
22558xmlSchemaFormatIDCKeySequence(xmlSchemaValidCtxtPtr vctxt,
22559 xmlChar **buf,
22560 xmlSchemaPSVIIDCKeyPtr *seq,
22561 int count)
22562{
22563 return xmlSchemaFormatIDCKeySequence_1(vctxt, buf, seq, count, 0);
22564}
22565
22566static const xmlChar *
22567xmlSchemaHashKeySequence(xmlSchemaValidCtxtPtr vctxt,
22568 xmlChar **buf,
22569 xmlSchemaPSVIIDCKeyPtr *seq,
22570 int count)
22571{
22572 return xmlSchemaFormatIDCKeySequence_1(vctxt, buf, seq, count, 1);
22573}
22574
22583static int
22584xmlSchemaXPathPop(xmlSchemaValidCtxtPtr vctxt)
22585{
22586 xmlSchemaIDCStateObjPtr sto;
22587 int res;
22588
22589 if (vctxt->xpathStates == NULL)
22590 return(0);
22591 sto = vctxt->xpathStates;
22592 do {
22593 res = xmlStreamPop((xmlStreamCtxtPtr) sto->xpathCtxt);
22594 if (res == -1)
22595 return (-1);
22596 sto = sto->next;
22597 } while (sto != NULL);
22598 return(0);
22599}
22600
22612static int
22613xmlSchemaXPathProcessHistory(xmlSchemaValidCtxtPtr vctxt,
22614 int depth)
22615{
22616 xmlSchemaIDCStateObjPtr sto, nextsto;
22617 int res, matchDepth;
22618 xmlSchemaPSVIIDCKeyPtr key = NULL;
22619 xmlSchemaTypePtr type = vctxt->inode->typeDef, simpleType = NULL;
22620
22621 if (vctxt->xpathStates == NULL)
22622 return (0);
22623 sto = vctxt->xpathStates;
22624
22625 /*
22626 * Evaluate the state objects.
22627 */
22628 while (sto != NULL) {
22629 res = xmlStreamPop((xmlStreamCtxtPtr) sto->xpathCtxt);
22630 if (res == -1) {
22631 VERROR_INT("xmlSchemaXPathProcessHistory",
22632 "calling xmlStreamPop()");
22633 return (-1);
22634 }
22635 if (sto->nbHistory == 0)
22636 goto deregister_check;
22637
22638 matchDepth = sto->history[sto->nbHistory -1];
22639
22640 /*
22641 * Only matches at the current depth are of interest.
22642 */
22643 if (matchDepth != depth) {
22644 sto = sto->next;
22645 continue;
22646 }
22647 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
22648 /*
22649 * NOTE: According to
22650 * http://www.w3.org/Bugs/Public/show_bug.cgi?id=2198
22651 * ... the simple-content of complex types is also allowed.
22652 */
22653
22654 if (WXS_IS_COMPLEX(type)) {
22655 if (WXS_HAS_SIMPLE_CONTENT(type)) {
22656 /*
22657 * Sanity check for complex types with simple content.
22658 */
22659 simpleType = type->contentTypeDef;
22660 if (simpleType == NULL) {
22661 VERROR_INT("xmlSchemaXPathProcessHistory",
22662 "field resolves to a CT with simple content "
22663 "but the CT is missing the ST definition");
22664 return (-1);
22665 }
22666 } else
22667 simpleType = NULL;
22668 } else
22669 simpleType = type;
22670 if (simpleType == NULL) {
22671 xmlChar *str = NULL;
22672
22673 /*
22674 * Not qualified if the field resolves to a node of non
22675 * simple type.
22676 */
22677 xmlSchemaCustomErr(ACTXT_CAST vctxt,
22679 WXS_BASIC_CAST sto->matcher->aidc->def,
22680 "The XPath '%s' of a field of %s does evaluate to a node of "
22681 "non-simple type",
22682 sto->sel->xpath,
22683 xmlSchemaGetIDCDesignation(&str, sto->matcher->aidc->def));
22684 FREE_AND_NULL(str);
22685 sto->nbHistory--;
22686 goto deregister_check;
22687 }
22688
22689 if ((key == NULL) && (vctxt->inode->val == NULL)) {
22690 /*
22691 * Failed to provide the normalized value; maybe
22692 * the value was invalid.
22693 */
22694 VERROR(XML_SCHEMAV_CVC_IDC,
22695 WXS_BASIC_CAST sto->matcher->aidc->def,
22696 "Warning: No precomputed value available, the value "
22697 "was either invalid or something strange happened");
22698 sto->nbHistory--;
22699 goto deregister_check;
22700 } else {
22701 xmlSchemaIDCMatcherPtr matcher = sto->matcher;
22702 xmlSchemaPSVIIDCKeyPtr *keySeq;
22703 int pos, idx;
22704
22705 /*
22706 * The key will be anchored on the matcher's list of
22707 * key-sequences. The position in this list is determined
22708 * by the target node's depth relative to the matcher's
22709 * depth of creation (i.e. the depth of the scope element).
22710 *
22711 * Element Depth Pos List-entries
22712 * <scope> 0 NULL
22713 * <bar> 1 NULL
22714 * <target/> 2 2 target
22715 * <bar>
22716 * </scope>
22717 *
22718 * The size of the list is only dependent on the depth of
22719 * the tree.
22720 * An entry will be NULLed in selector_leave, i.e. when
22721 * we hit the target's
22722 */
22723 pos = sto->depth - matcher->depth;
22724 idx = sto->sel->index;
22725
22726 /*
22727 * Create/grow the array of key-sequences.
22728 */
22729 if (matcher->keySeqs == NULL) {
22730 if (pos > 9)
22731 matcher->sizeKeySeqs = pos * 2;
22732 else
22733 matcher->sizeKeySeqs = 10;
22734 matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
22735 xmlMalloc(matcher->sizeKeySeqs *
22736 sizeof(xmlSchemaPSVIIDCKeyPtr *));
22737 if (matcher->keySeqs == NULL) {
22738 xmlSchemaVErrMemory(NULL,
22739 "allocating an array of key-sequences",
22740 NULL);
22741 return(-1);
22742 }
22743 memset(matcher->keySeqs, 0,
22744 matcher->sizeKeySeqs *
22745 sizeof(xmlSchemaPSVIIDCKeyPtr *));
22746 } else if (pos >= matcher->sizeKeySeqs) {
22747 int i = matcher->sizeKeySeqs;
22748
22749 matcher->sizeKeySeqs = pos * 2;
22750 matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
22751 xmlRealloc(matcher->keySeqs,
22752 matcher->sizeKeySeqs *
22753 sizeof(xmlSchemaPSVIIDCKeyPtr *));
22754 if (matcher->keySeqs == NULL) {
22755 xmlSchemaVErrMemory(NULL,
22756 "reallocating an array of key-sequences",
22757 NULL);
22758 return (-1);
22759 }
22760 /*
22761 * The array needs to be NULLed.
22762 * TODO: Use memset?
22763 */
22764 for (; i < matcher->sizeKeySeqs; i++)
22765 matcher->keySeqs[i] = NULL;
22766 }
22767
22768 /*
22769 * Get/create the key-sequence.
22770 */
22771 keySeq = matcher->keySeqs[pos];
22772 if (keySeq == NULL) {
22773 goto create_sequence;
22774 } else if (keySeq[idx] != NULL) {
22775 xmlChar *str = NULL;
22776 /*
22777 * cvc-identity-constraint:
22778 * 3 For each node in the `target node set` all
22779 * of the {fields}, with that node as the context
22780 * node, evaluate to either an empty node-set or
22781 * a node-set with exactly one member, which must
22782 * have a simple type.
22783 *
22784 * The key was already set; report an error.
22785 */
22786 xmlSchemaCustomErr(ACTXT_CAST vctxt,
22788 WXS_BASIC_CAST matcher->aidc->def,
22789 "The XPath '%s' of a field of %s evaluates to a "
22790 "node-set with more than one member",
22791 sto->sel->xpath,
22792 xmlSchemaGetIDCDesignation(&str, matcher->aidc->def));
22793 FREE_AND_NULL(str);
22794 sto->nbHistory--;
22795 goto deregister_check;
22796 } else
22797 goto create_key;
22798
22799create_sequence:
22800 /*
22801 * Create a key-sequence.
22802 */
22803 keySeq = (xmlSchemaPSVIIDCKeyPtr *) xmlMalloc(
22804 matcher->aidc->def->nbFields *
22805 sizeof(xmlSchemaPSVIIDCKeyPtr));
22806 if (keySeq == NULL) {
22807 xmlSchemaVErrMemory(NULL,
22808 "allocating an IDC key-sequence", NULL);
22809 return(-1);
22810 }
22811 memset(keySeq, 0, matcher->aidc->def->nbFields *
22812 sizeof(xmlSchemaPSVIIDCKeyPtr));
22813 matcher->keySeqs[pos] = keySeq;
22815 /*
22816 * Create a key once per node only.
22817 */
22818 if (key == NULL) {
22819 key = (xmlSchemaPSVIIDCKeyPtr) xmlMalloc(
22820 sizeof(xmlSchemaPSVIIDCKey));
22821 if (key == NULL) {
22822 xmlSchemaVErrMemory(NULL,
22823 "allocating a IDC key", NULL);
22824 xmlFree(keySeq);
22825 matcher->keySeqs[pos] = NULL;
22826 return(-1);
22827 }
22828 /*
22829 * Consume the compiled value.
22830 */
22831 key->type = simpleType;
22832 key->val = vctxt->inode->val;
22833 vctxt->inode->val = NULL;
22834 /*
22835 * Store the key in a global list.
22836 */
22837 if (xmlSchemaIDCStoreKey(vctxt, key) == -1) {
22838 xmlSchemaIDCFreeKey(key);
22839 return (-1);
22840 }
22841 }
22842 keySeq[idx] = key;
22843 }
22844 } else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
22845
22846 xmlSchemaPSVIIDCKeyPtr **keySeq = NULL;
22847 /* xmlSchemaPSVIIDCBindingPtr bind; */
22848 xmlSchemaPSVIIDCNodePtr ntItem;
22849 xmlSchemaIDCMatcherPtr matcher;
22850 xmlSchemaIDCPtr idc;
22851 xmlSchemaItemListPtr targets;
22852 int pos, i, j, nbKeys;
22853 /*
22854 * Here we have the following scenario:
22855 * An IDC 'selector' state object resolved to a target node,
22856 * during the time this target node was in the
22857 * ancestor-or-self axis, the 'field' state object(s) looked
22858 * out for matching nodes to create a key-sequence for this
22859 * target node. Now we are back to this target node and need
22860 * to put the key-sequence, together with the target node
22861 * itself, into the node-table of the corresponding IDC
22862 * binding.
22863 */
22864 matcher = sto->matcher;
22865 idc = matcher->aidc->def;
22866 nbKeys = idc->nbFields;
22867 pos = depth - matcher->depth;
22868 /*
22869 * Check if the matcher has any key-sequences at all, plus
22870 * if it has a key-sequence for the current target node.
22871 */
22872 if ((matcher->keySeqs == NULL) ||
22873 (matcher->sizeKeySeqs <= pos)) {
22874 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
22875 goto selector_key_error;
22876 else
22877 goto selector_leave;
22878 }
22879
22880 keySeq = &(matcher->keySeqs[pos]);
22881 if (*keySeq == NULL) {
22882 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
22883 goto selector_key_error;
22884 else
22885 goto selector_leave;
22886 }
22887
22888 for (i = 0; i < nbKeys; i++) {
22889 if ((*keySeq)[i] == NULL) {
22890 /*
22891 * Not qualified, if not all fields did resolve.
22892 */
22893 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY) {
22894 /*
22895 * All fields of a "key" IDC must resolve.
22896 */
22897 goto selector_key_error;
22898 }
22899 goto selector_leave;
22900 }
22901 }
22902 /*
22903 * All fields did resolve.
22904 */
22905
22906 /*
22907 * 4.1 If the {identity-constraint category} is unique(/key),
22908 * then no two members of the `qualified node set` have
22909 * `key-sequences` whose members are pairwise equal, as
22910 * defined by Equal in [XML Schemas: Datatypes].
22911 *
22912 * Get the IDC binding from the matcher and check for
22913 * duplicate key-sequences.
22914 */
22915#if 0
22916 bind = xmlSchemaIDCAcquireBinding(vctxt, matcher);
22917#endif
22918 targets = xmlSchemaIDCAcquireTargetList(vctxt, matcher);
22919 if ((idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) &&
22920 (targets->nbItems != 0)) {
22921 xmlSchemaPSVIIDCKeyPtr ckey, bkey, *bkeySeq;
22922 xmlIDCHashEntryPtr e;
22923
22924 res = 0;
22925
22926 if (!matcher->htab)
22927 e = NULL;
22928 else {
22929 xmlChar *value = NULL;
22930 xmlSchemaHashKeySequence(vctxt, &value, *keySeq, nbKeys);
22931 e = xmlHashLookup(matcher->htab, value);
22932 FREE_AND_NULL(value);
22933 }
22934
22935 /*
22936 * Compare the key-sequences, key by key.
22937 */
22938 for (;e; e = e->next) {
22939 bkeySeq =
22940 ((xmlSchemaPSVIIDCNodePtr) targets->items[e->index])->keys;
22941 for (j = 0; j < nbKeys; j++) {
22942 ckey = (*keySeq)[j];
22943 bkey = bkeySeq[j];
22944 res = xmlSchemaAreValuesEqual(ckey->val, bkey->val);
22945 if (res == -1) {
22946 return (-1);
22947 } else if (res == 0) {
22948 /*
22949 * One of the keys differs, so the key-sequence
22950 * won't be equal; get out.
22951 */
22952 break;
22953 }
22954 }
22955 if (res == 1) {
22956 /*
22957 * Duplicate key-sequence found.
22958 */
22959 break;
22960 }
22961 }
22962 if (e) {
22963 xmlChar *str = NULL, *strB = NULL;
22964 /*
22965 * TODO: Try to report the key-sequence.
22966 */
22967 xmlSchemaCustomErr(ACTXT_CAST vctxt,
22969 WXS_BASIC_CAST idc,
22970 "Duplicate key-sequence %s in %s",
22971 xmlSchemaFormatIDCKeySequence(vctxt, &str,
22972 (*keySeq), nbKeys),
22973 xmlSchemaGetIDCDesignation(&strB, idc));
22974 FREE_AND_NULL(str);
22975 FREE_AND_NULL(strB);
22976 goto selector_leave;
22977 }
22978 }
22979 /*
22980 * Add a node-table item to the IDC binding.
22981 */
22982 ntItem = (xmlSchemaPSVIIDCNodePtr) xmlMalloc(
22983 sizeof(xmlSchemaPSVIIDCNode));
22984 if (ntItem == NULL) {
22985 xmlSchemaVErrMemory(NULL,
22986 "allocating an IDC node-table item", NULL);
22987 xmlFree(*keySeq);
22988 *keySeq = NULL;
22989 return(-1);
22990 }
22991 memset(ntItem, 0, sizeof(xmlSchemaPSVIIDCNode));
22992
22993 /*
22994 * Store the node-table item in a global list.
22995 */
22996 if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) {
22997 if (xmlSchemaIDCStoreNodeTableItem(vctxt, ntItem) == -1) {
22998 xmlFree(ntItem);
22999 xmlFree(*keySeq);
23000 *keySeq = NULL;
23001 return (-1);
23002 }
23003 ntItem->nodeQNameID = -1;
23004 } else {
23005 /*
23006 * Save a cached QName for this node on the IDC node, to be
23007 * able to report it, even if the node is not saved.
23008 */
23009 ntItem->nodeQNameID = xmlSchemaVAddNodeQName(vctxt,
23010 vctxt->inode->localName, vctxt->inode->nsName);
23011 if (ntItem->nodeQNameID == -1) {
23012 xmlFree(ntItem);
23013 xmlFree(*keySeq);
23014 *keySeq = NULL;
23015 return (-1);
23016 }
23017 }
23018 /*
23019 * Init the node-table item: Save the node, position and
23020 * consume the key-sequence.
23021 */
23022 ntItem->node = vctxt->node;
23023 ntItem->nodeLine = vctxt->inode->nodeLine;
23024 ntItem->keys = *keySeq;
23025 *keySeq = NULL;
23026#if 0
23027 if (xmlSchemaIDCAppendNodeTableItem(bind, ntItem) == -1)
23028#endif
23029 if (xmlSchemaItemListAdd(targets, ntItem) == -1) {
23030 if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
23031 /*
23032 * Free the item, since keyref items won't be
23033 * put on a global list.
23034 */
23035 xmlFree(ntItem->keys);
23036 xmlFree(ntItem);
23037 }
23038 return (-1);
23039 }
23040 if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) {
23041 xmlChar *value = NULL;
23042 xmlIDCHashEntryPtr r, e;
23043 if (!matcher->htab)
23044 matcher->htab = xmlHashCreate(4);
23045 xmlSchemaHashKeySequence(vctxt, &value, ntItem->keys, nbKeys);
23046 e = xmlMalloc(sizeof *e);
23047 e->index = targets->nbItems - 1;
23048 r = xmlHashLookup(matcher->htab, value);
23049 if (r) {
23050 e->next = r->next;
23051 r->next = e;
23052 } else {
23053 e->next = NULL;
23054 xmlHashAddEntry(matcher->htab, value, e);
23055 }
23056 FREE_AND_NULL(value);
23057 }
23058
23059 goto selector_leave;
23060selector_key_error:
23061 {
23062 xmlChar *str = NULL;
23063 /*
23064 * 4.2.1 (KEY) The `target node set` and the
23065 * `qualified node set` are equal, that is, every
23066 * member of the `target node set` is also a member
23067 * of the `qualified node set` and vice versa.
23068 */
23069 xmlSchemaCustomErr(ACTXT_CAST vctxt,
23071 WXS_BASIC_CAST idc,
23072 "Not all fields of %s evaluate to a node",
23073 xmlSchemaGetIDCDesignation(&str, idc), NULL);
23074 FREE_AND_NULL(str);
23075 }
23076selector_leave:
23077 /*
23078 * Free the key-sequence if not added to the IDC table.
23079 */
23080 if ((keySeq != NULL) && (*keySeq != NULL)) {
23081 xmlFree(*keySeq);
23082 *keySeq = NULL;
23083 }
23084 } /* if selector */
23085
23086 sto->nbHistory--;
23087
23088deregister_check:
23089 /*
23090 * Deregister state objects if they reach the depth of creation.
23091 */
23092 if ((sto->nbHistory == 0) && (sto->depth == depth)) {
23093 if (vctxt->xpathStates != sto) {
23094 VERROR_INT("xmlSchemaXPathProcessHistory",
23095 "The state object to be removed is not the first "
23096 "in the list");
23097 }
23098 nextsto = sto->next;
23099 /*
23100 * Unlink from the list of active XPath state objects.
23101 */
23102 vctxt->xpathStates = sto->next;
23103 sto->next = vctxt->xpathStatePool;
23104 /*
23105 * Link it to the pool of reusable state objects.
23106 */
23107 vctxt->xpathStatePool = sto;
23108 sto = nextsto;
23109 } else
23110 sto = sto->next;
23111 } /* while (sto != NULL) */
23112 return (0);
23113}
23114
23125static int
23126xmlSchemaIDCRegisterMatchers(xmlSchemaValidCtxtPtr vctxt,
23127 xmlSchemaElementPtr elemDecl)
23128{
23129 xmlSchemaIDCMatcherPtr matcher, last = NULL;
23130 xmlSchemaIDCPtr idc, refIdc;
23131 xmlSchemaIDCAugPtr aidc;
23132
23133 idc = (xmlSchemaIDCPtr) elemDecl->idcs;
23134 if (idc == NULL)
23135 return (0);
23136
23137 if (vctxt->inode->idcMatchers != NULL) {
23138 VERROR_INT("xmlSchemaIDCRegisterMatchers",
23139 "The chain of IDC matchers is expected to be empty");
23140 return (-1);
23141 }
23142 do {
23143 if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
23144 /*
23145 * Since IDCs bubbles are expensive we need to know the
23146 * depth at which the bubbles should stop; this will be
23147 * the depth of the top-most keyref IDC. If no keyref
23148 * references a key/unique IDC, the keyrefDepth will
23149 * be -1, indicating that no bubbles are needed.
23150 */
23151 refIdc = (xmlSchemaIDCPtr) idc->ref->item;
23152 if (refIdc != NULL) {
23153 /*
23154 * Remember that we have keyrefs on this node.
23155 */
23156 vctxt->inode->hasKeyrefs = 1;
23157 /*
23158 * Lookup the referenced augmented IDC info.
23159 */
23160 aidc = vctxt->aidcs;
23161 while (aidc != NULL) {
23162 if (aidc->def == refIdc)
23163 break;
23164 aidc = aidc->next;
23165 }
23166 if (aidc == NULL) {
23167 VERROR_INT("xmlSchemaIDCRegisterMatchers",
23168 "Could not find an augmented IDC item for an IDC "
23169 "definition");
23170 return (-1);
23171 }
23172 if ((aidc->keyrefDepth == -1) ||
23173 (vctxt->depth < aidc->keyrefDepth))
23174 aidc->keyrefDepth = vctxt->depth;
23175 }
23176 }
23177 /*
23178 * Lookup the augmented IDC item for the IDC definition.
23179 */
23180 aidc = vctxt->aidcs;
23181 while (aidc != NULL) {
23182 if (aidc->def == idc)
23183 break;
23184 aidc = aidc->next;
23185 }
23186 if (aidc == NULL) {
23187 VERROR_INT("xmlSchemaIDCRegisterMatchers",
23188 "Could not find an augmented IDC item for an IDC definition");
23189 return (-1);
23190 }
23191 /*
23192 * Create an IDC matcher for every IDC definition.
23193 */
23194 if (vctxt->idcMatcherCache != NULL) {
23195 /*
23196 * Reuse a cached matcher.
23197 */
23198 matcher = vctxt->idcMatcherCache;
23199 vctxt->idcMatcherCache = matcher->nextCached;
23200 matcher->nextCached = NULL;
23201 } else {
23202 matcher = (xmlSchemaIDCMatcherPtr)
23203 xmlMalloc(sizeof(xmlSchemaIDCMatcher));
23204 if (matcher == NULL) {
23205 xmlSchemaVErrMemory(vctxt,
23206 "allocating an IDC matcher", NULL);
23207 return (-1);
23208 }
23209 memset(matcher, 0, sizeof(xmlSchemaIDCMatcher));
23210 }
23211 if (last == NULL)
23212 vctxt->inode->idcMatchers = matcher;
23213 else
23214 last->next = matcher;
23215 last = matcher;
23216
23217 matcher->type = IDC_MATCHER;
23218 matcher->depth = vctxt->depth;
23219 matcher->aidc = aidc;
23220 matcher->idcType = aidc->def->type;
23221 /*
23222 * Init the automaton state object.
23223 */
23224 if (xmlSchemaIDCAddStateObject(vctxt, matcher,
23225 idc->selector, XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) == -1)
23226 return (-1);
23227
23228 idc = idc->next;
23229 } while (idc != NULL);
23230 return (0);
23231}
23232
23233static int
23234xmlSchemaIDCFillNodeTables(xmlSchemaValidCtxtPtr vctxt,
23235 xmlSchemaNodeInfoPtr ielem)
23236{
23237 xmlSchemaPSVIIDCBindingPtr bind;
23238 int res, i, j, k, nbTargets, nbFields, nbDupls, nbNodeTable;
23239 xmlSchemaPSVIIDCKeyPtr *keys, *ntkeys;
23240 xmlSchemaPSVIIDCNodePtr *targets, *dupls;
23241
23242 xmlSchemaIDCMatcherPtr matcher = ielem->idcMatchers;
23243 /* vctxt->createIDCNodeTables */
23244 while (matcher != NULL) {
23245 /*
23246 * Skip keyref IDCs and empty IDC target-lists.
23247 */
23248 if ((matcher->aidc->def->type == XML_SCHEMA_TYPE_IDC_KEYREF) ||
23249 WXS_ILIST_IS_EMPTY(matcher->targets))
23250 {
23251 matcher = matcher->next;
23252 continue;
23253 }
23254 /*
23255 * If we _want_ the IDC node-table to be created in any case
23256 * then do so. Otherwise create them only if keyrefs need them.
23257 */
23258 if ((! vctxt->createIDCNodeTables) &&
23259 ((matcher->aidc->keyrefDepth == -1) ||
23260 (matcher->aidc->keyrefDepth > vctxt->depth)))
23261 {
23262 matcher = matcher->next;
23263 continue;
23264 }
23265 /*
23266 * Get/create the IDC binding on this element for the IDC definition.
23267 */
23268 bind = xmlSchemaIDCAcquireBinding(vctxt, matcher);
23269 if (bind == NULL)
23270 goto internal_error;
23271
23272 if (! WXS_ILIST_IS_EMPTY(bind->dupls)) {
23273 dupls = (xmlSchemaPSVIIDCNodePtr *) bind->dupls->items;
23274 nbDupls = bind->dupls->nbItems;
23275 } else {
23276 dupls = NULL;
23277 nbDupls = 0;
23278 }
23279 if (bind->nodeTable != NULL) {
23280 nbNodeTable = bind->nbNodes;
23281 } else {
23282 nbNodeTable = 0;
23283 }
23284
23285 if ((nbNodeTable == 0) && (nbDupls == 0)) {
23286 /*
23287 * Transfer all IDC target-nodes to the IDC node-table.
23288 */
23289 bind->nodeTable =
23290 (xmlSchemaPSVIIDCNodePtr *) matcher->targets->items;
23291 bind->sizeNodes = matcher->targets->sizeItems;
23292 bind->nbNodes = matcher->targets->nbItems;
23293
23294 matcher->targets->items = NULL;
23295 matcher->targets->sizeItems = 0;
23296 matcher->targets->nbItems = 0;
23297 if (matcher->htab) {
23298 xmlHashFree(matcher->htab, xmlFreeIDCHashEntry);
23299 matcher->htab = NULL;
23300 }
23301 } else {
23302 /*
23303 * Compare the key-sequences and add to the IDC node-table.
23304 */
23305 nbTargets = matcher->targets->nbItems;
23306 targets = (xmlSchemaPSVIIDCNodePtr *) matcher->targets->items;
23307 nbFields = matcher->aidc->def->nbFields;
23308 i = 0;
23309 do {
23310 keys = targets[i]->keys;
23311 if (nbDupls) {
23312 /*
23313 * Search in already found duplicates first.
23314 */
23315 j = 0;
23316 do {
23317 if (nbFields == 1) {
23318 res = xmlSchemaAreValuesEqual(keys[0]->val,
23319 dupls[j]->keys[0]->val);
23320 if (res == -1)
23321 goto internal_error;
23322 if (res == 1) {
23323 /*
23324 * Equal key-sequence.
23325 */
23326 goto next_target;
23327 }
23328 } else {
23329 res = 0;
23330 ntkeys = dupls[j]->keys;
23331 for (k = 0; k < nbFields; k++) {
23332 res = xmlSchemaAreValuesEqual(keys[k]->val,
23333 ntkeys[k]->val);
23334 if (res == -1)
23335 goto internal_error;
23336 if (res == 0) {
23337 /*
23338 * One of the keys differs.
23339 */
23340 break;
23341 }
23342 }
23343 if (res == 1) {
23344 /*
23345 * Equal key-sequence found.
23346 */
23347 goto next_target;
23348 }
23349 }
23350 j++;
23351 } while (j < nbDupls);
23352 }
23353 if (nbNodeTable) {
23354 j = 0;
23355 do {
23356 if (nbFields == 1) {
23357 res = xmlSchemaAreValuesEqual(keys[0]->val,
23358 bind->nodeTable[j]->keys[0]->val);
23359 if (res == -1)
23360 goto internal_error;
23361 if (res == 0) {
23362 /*
23363 * The key-sequence differs.
23364 */
23365 goto next_node_table_entry;
23366 }
23367 } else {
23368 res = 0;
23369 ntkeys = bind->nodeTable[j]->keys;
23370 for (k = 0; k < nbFields; k++) {
23371 res = xmlSchemaAreValuesEqual(keys[k]->val,
23372 ntkeys[k]->val);
23373 if (res == -1)
23374 goto internal_error;
23375 if (res == 0) {
23376 /*
23377 * One of the keys differs.
23378 */
23379 goto next_node_table_entry;
23380 }
23381 }
23382 }
23383 /*
23384 * Add the duplicate to the list of duplicates.
23385 */
23386 if (bind->dupls == NULL) {
23387 bind->dupls = xmlSchemaItemListCreate();
23388 if (bind->dupls == NULL)
23389 goto internal_error;
23390 }
23391 if (xmlSchemaItemListAdd(bind->dupls, bind->nodeTable[j]) == -1)
23392 goto internal_error;
23393 /*
23394 * Remove the duplicate entry from the IDC node-table.
23395 */
23396 bind->nodeTable[j] = bind->nodeTable[bind->nbNodes -1];
23397 bind->nbNodes--;
23398
23399 goto next_target;
23400
23401next_node_table_entry:
23402 j++;
23403 } while (j < nbNodeTable);
23404 }
23405 /*
23406 * If everything is fine, then add the IDC target-node to
23407 * the IDC node-table.
23408 */
23409 if (xmlSchemaIDCAppendNodeTableItem(bind, targets[i]) == -1)
23410 goto internal_error;
23411
23412next_target:
23413 i++;
23414 } while (i < nbTargets);
23415 }
23416 matcher = matcher->next;
23417 }
23418 return(0);
23419
23420internal_error:
23421 return(-1);
23422}
23423
23435static int
23436xmlSchemaBubbleIDCNodeTables(xmlSchemaValidCtxtPtr vctxt)
23437{
23438 xmlSchemaPSVIIDCBindingPtr bind; /* IDC bindings of the current node. */
23439 xmlSchemaPSVIIDCBindingPtr *parTable, parBind = NULL; /* parent IDC bindings. */
23440 xmlSchemaPSVIIDCNodePtr node, parNode = NULL, *dupls, *parNodes; /* node-table entries. */
23441 xmlSchemaIDCAugPtr aidc;
23442 int i, j, k, ret = 0, nbFields, oldNum, oldDupls;
23443
23444 bind = vctxt->inode->idcTable;
23445 if (bind == NULL) {
23446 /* Fine, no table, no bubbles. */
23447 return (0);
23448 }
23449
23450 parTable = &(vctxt->elemInfos[vctxt->depth -1]->idcTable);
23451 /*
23452 * Walk all bindings; create new or add to existing bindings.
23453 * Remove duplicate key-sequences.
23454 */
23455 while (bind != NULL) {
23456
23457 if ((bind->nbNodes == 0) && WXS_ILIST_IS_EMPTY(bind->dupls))
23458 goto next_binding;
23459 /*
23460 * Check if the key/unique IDC table needs to be bubbled.
23461 */
23462 if (! vctxt->createIDCNodeTables) {
23463 aidc = vctxt->aidcs;
23464 do {
23465 if (aidc->def == bind->definition) {
23466 if ((aidc->keyrefDepth == -1) ||
23467 (aidc->keyrefDepth >= vctxt->depth)) {
23468 goto next_binding;
23469 }
23470 break;
23471 }
23472 aidc = aidc->next;
23473 } while (aidc != NULL);
23474 }
23475
23476 if (parTable != NULL)
23477 parBind = *parTable;
23478 /*
23479 * Search a matching parent binding for the
23480 * IDC definition.
23481 */
23482 while (parBind != NULL) {
23483 if (parBind->definition == bind->definition)
23484 break;
23485 parBind = parBind->next;
23486 }
23487
23488 if (parBind != NULL) {
23489 /*
23490 * Compare every node-table entry of the child node,
23491 * i.e. the key-sequence within, ...
23492 */
23493 oldNum = parBind->nbNodes; /* Skip newly added items. */
23494
23495 if (! WXS_ILIST_IS_EMPTY(parBind->dupls)) {
23496 oldDupls = parBind->dupls->nbItems;
23497 dupls = (xmlSchemaPSVIIDCNodePtr *) parBind->dupls->items;
23498 } else {
23499 dupls = NULL;
23500 oldDupls = 0;
23501 }
23502
23503 parNodes = parBind->nodeTable;
23504 nbFields = bind->definition->nbFields;
23505
23506 for (i = 0; i < bind->nbNodes; i++) {
23507 node = bind->nodeTable[i];
23508 if (node == NULL)
23509 continue;
23510 /*
23511 * ...with every key-sequence of the parent node, already
23512 * evaluated to be a duplicate key-sequence.
23513 */
23514 if (oldDupls) {
23515 j = 0;
23516 while (j < oldDupls) {
23517 if (nbFields == 1) {
23518 ret = xmlSchemaAreValuesEqual(
23519 node->keys[0]->val,
23520 dupls[j]->keys[0]->val);
23521 if (ret == -1)
23522 goto internal_error;
23523 if (ret == 0) {
23524 j++;
23525 continue;
23526 }
23527 } else {
23528 parNode = dupls[j];
23529 for (k = 0; k < nbFields; k++) {
23530 ret = xmlSchemaAreValuesEqual(
23531 node->keys[k]->val,
23532 parNode->keys[k]->val);
23533 if (ret == -1)
23534 goto internal_error;
23535 if (ret == 0)
23536 break;
23537 }
23538 }
23539 if (ret == 1)
23540 /* Duplicate found. */
23541 break;
23542 j++;
23543 }
23544 if (j != oldDupls) {
23545 /* Duplicate found. Skip this entry. */
23546 continue;
23547 }
23548 }
23549 /*
23550 * ... and with every key-sequence of the parent node.
23551 */
23552 if (oldNum) {
23553 j = 0;
23554 while (j < oldNum) {
23555 parNode = parNodes[j];
23556 if (nbFields == 1) {
23557 ret = xmlSchemaAreValuesEqual(
23558 node->keys[0]->val,
23559 parNode->keys[0]->val);
23560 if (ret == -1)
23561 goto internal_error;
23562 if (ret == 0) {
23563 j++;
23564 continue;
23565 }
23566 } else {
23567 for (k = 0; k < nbFields; k++) {
23568 ret = xmlSchemaAreValuesEqual(
23569 node->keys[k]->val,
23570 parNode->keys[k]->val);
23571 if (ret == -1)
23572 goto internal_error;
23573 if (ret == 0)
23574 break;
23575 }
23576 }
23577 if (ret == 1)
23578 /* Duplicate found. */
23579 break;
23580 j++;
23581 }
23582 if (j != oldNum) {
23583 /*
23584 * Handle duplicates. Move the duplicate in
23585 * the parent's node-table to the list of
23586 * duplicates.
23587 */
23588 oldNum--;
23589 parBind->nbNodes--;
23590 /*
23591 * Move last old item to pos of duplicate.
23592 */
23593 parNodes[j] = parNodes[oldNum];
23594
23595 if (parBind->nbNodes != oldNum) {
23596 /*
23597 * If new items exist, move last new item to
23598 * last of old items.
23599 */
23600 parNodes[oldNum] =
23601 parNodes[parBind->nbNodes];
23602 }
23603 if (parBind->dupls == NULL) {
23604 parBind->dupls = xmlSchemaItemListCreate();
23605 if (parBind->dupls == NULL)
23606 goto internal_error;
23607 }
23608 xmlSchemaItemListAdd(parBind->dupls, parNode);
23609 } else {
23610 /*
23611 * Add the node-table entry (node and key-sequence) of
23612 * the child node to the node table of the parent node.
23613 */
23614 if (parBind->nodeTable == NULL) {
23615 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
23616 xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr));
23617 if (parBind->nodeTable == NULL) {
23618 xmlSchemaVErrMemory(NULL,
23619 "allocating IDC list of node-table items", NULL);
23620 goto internal_error;
23621 }
23622 parBind->sizeNodes = 1;
23623 } else if (parBind->nbNodes >= parBind->sizeNodes) {
23624 parBind->sizeNodes *= 2;
23625 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
23626 xmlRealloc(parBind->nodeTable, parBind->sizeNodes *
23627 sizeof(xmlSchemaPSVIIDCNodePtr));
23628 if (parBind->nodeTable == NULL) {
23629 xmlSchemaVErrMemory(NULL,
23630 "re-allocating IDC list of node-table items", NULL);
23631 goto internal_error;
23632 }
23633 }
23634 parNodes = parBind->nodeTable;
23635 /*
23636 * Append the new node-table entry to the 'new node-table
23637 * entries' section.
23638 */
23639 parNodes[parBind->nbNodes++] = node;
23640 }
23641
23642 }
23643
23644 }
23645 } else {
23646 /*
23647 * No binding for the IDC was found: create a new one and
23648 * copy all node-tables.
23649 */
23650 parBind = xmlSchemaIDCNewBinding(bind->definition);
23651 if (parBind == NULL)
23652 goto internal_error;
23653
23654 /*
23655 * TODO: Hmm, how to optimize the initial number of
23656 * allocated entries?
23657 */
23658 if (bind->nbNodes != 0) {
23659 /*
23660 * Add all IDC node-table entries.
23661 */
23662 if (! vctxt->psviExposeIDCNodeTables) {
23663 /*
23664 * Just move the entries.
23665 * NOTE: this is quite save here, since
23666 * all the keyref lookups have already been
23667 * performed.
23668 */
23669 parBind->nodeTable = bind->nodeTable;
23670 bind->nodeTable = NULL;
23671 parBind->sizeNodes = bind->sizeNodes;
23672 bind->sizeNodes = 0;
23673 parBind->nbNodes = bind->nbNodes;
23674 bind->nbNodes = 0;
23675 } else {
23676 /*
23677 * Copy the entries.
23678 */
23679 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
23680 xmlMalloc(bind->nbNodes *
23681 sizeof(xmlSchemaPSVIIDCNodePtr));
23682 if (parBind->nodeTable == NULL) {
23683 xmlSchemaVErrMemory(NULL,
23684 "allocating an array of IDC node-table "
23685 "items", NULL);
23686 xmlSchemaIDCFreeBinding(parBind);
23687 goto internal_error;
23688 }
23689 parBind->sizeNodes = bind->nbNodes;
23690 parBind->nbNodes = bind->nbNodes;
23691 memcpy(parBind->nodeTable, bind->nodeTable,
23692 bind->nbNodes * sizeof(xmlSchemaPSVIIDCNodePtr));
23693 }
23694 }
23695 if (bind->dupls) {
23696 /*
23697 * Move the duplicates.
23698 */
23699 if (parBind->dupls != NULL)
23700 xmlSchemaItemListFree(parBind->dupls);
23701 parBind->dupls = bind->dupls;
23702 bind->dupls = NULL;
23703 }
23704 if (parTable != NULL) {
23705 if (*parTable == NULL)
23706 *parTable = parBind;
23707 else {
23708 parBind->next = *parTable;
23709 *parTable = parBind;
23710 }
23711 }
23712 }
23713
23714next_binding:
23715 bind = bind->next;
23716 }
23717 return (0);
23718
23719internal_error:
23720 return(-1);
23721}
23722
23730static int
23731xmlSchemaCheckCVCIDCKeyRef(xmlSchemaValidCtxtPtr vctxt)
23732{
23733 xmlSchemaIDCMatcherPtr matcher;
23734 xmlSchemaPSVIIDCBindingPtr bind;
23735
23736 matcher = vctxt->inode->idcMatchers;
23737 /*
23738 * Find a keyref.
23739 */
23740 while (matcher != NULL) {
23741 if ((matcher->idcType == XML_SCHEMA_TYPE_IDC_KEYREF) &&
23742 matcher->targets &&
23743 matcher->targets->nbItems)
23744 {
23745 int i, j, k, res, nbFields, hasDupls;
23746 xmlSchemaPSVIIDCKeyPtr *refKeys, *keys;
23747 xmlSchemaPSVIIDCNodePtr refNode = NULL;
23749
23750 nbFields = matcher->aidc->def->nbFields;
23751
23752 /*
23753 * Find the IDC node-table for the referenced IDC key/unique.
23754 */
23755 bind = vctxt->inode->idcTable;
23756 while (bind != NULL) {
23757 if ((xmlSchemaIDCPtr) matcher->aidc->def->ref->item ==
23758 bind->definition)
23759 break;
23760 bind = bind->next;
23761 }
23762 hasDupls = (bind && bind->dupls && bind->dupls->nbItems) ? 1 : 0;
23763 /*
23764 * Search for a matching key-sequences.
23765 */
23766 if (bind) {
23767 table = xmlHashCreate(bind->nbNodes * 2);
23768 for (j = 0; j < bind->nbNodes; j++) {
23769 xmlChar *value;
23770 xmlIDCHashEntryPtr r, e;
23771 keys = bind->nodeTable[j]->keys;
23772 xmlSchemaHashKeySequence(vctxt, &value, keys, nbFields);
23773 e = xmlMalloc(sizeof *e);
23774 e->index = j;
23776 if (r) {
23777 e->next = r->next;
23778 r->next = e;
23779 } else {
23780 e->next = NULL;
23782 }
23783 FREE_AND_NULL(value);
23784 }
23785 }
23786 for (i = 0; i < matcher->targets->nbItems; i++) {
23787 res = 0;
23788 refNode = matcher->targets->items[i];
23789 if (bind != NULL) {
23790 xmlChar *value;
23791 xmlIDCHashEntryPtr e;
23792 refKeys = refNode->keys;
23793 xmlSchemaHashKeySequence(vctxt, &value, refKeys, nbFields);
23795 FREE_AND_NULL(value);
23796 res = 0;
23797 for (;e; e = e->next) {
23798 keys = bind->nodeTable[e->index]->keys;
23799 for (k = 0; k < nbFields; k++) {
23800 res = xmlSchemaAreValuesEqual(keys[k]->val,
23801 refKeys[k]->val);
23802 if (res == 0)
23803 break;
23804 else if (res == -1) {
23805 return (-1);
23806 }
23807 }
23808 if (res == 1) {
23809 /*
23810 * Match found.
23811 */
23812 break;
23813 }
23814 }
23815 if ((res == 0) && hasDupls) {
23816 /*
23817 * Search in duplicates
23818 */
23819 for (j = 0; j < bind->dupls->nbItems; j++) {
23820 keys = ((xmlSchemaPSVIIDCNodePtr)
23821 bind->dupls->items[j])->keys;
23822 for (k = 0; k < nbFields; k++) {
23823 res = xmlSchemaAreValuesEqual(keys[k]->val,
23824 refKeys[k]->val);
23825 if (res == 0)
23826 break;
23827 else if (res == -1) {
23828 return (-1);
23829 }
23830 }
23831 if (res == 1) {
23832 /*
23833 * Match in duplicates found.
23834 */
23835 xmlChar *str = NULL, *strB = NULL;
23836 xmlSchemaKeyrefErr(vctxt,
23837 XML_SCHEMAV_CVC_IDC, refNode,
23838 (xmlSchemaTypePtr) matcher->aidc->def,
23839 "More than one match found for "
23840 "key-sequence %s of keyref '%s'",
23841 xmlSchemaFormatIDCKeySequence(vctxt, &str,
23842 refNode->keys, nbFields),
23843 xmlSchemaGetComponentQName(&strB,
23844 matcher->aidc->def));
23845 FREE_AND_NULL(str);
23846 FREE_AND_NULL(strB);
23847 break;
23848 }
23849 }
23850 }
23851 }
23852
23853 if (res == 0) {
23854 xmlChar *str = NULL, *strB = NULL;
23855 xmlSchemaKeyrefErr(vctxt,
23856 XML_SCHEMAV_CVC_IDC, refNode,
23857 (xmlSchemaTypePtr) matcher->aidc->def,
23858 "No match found for key-sequence %s of keyref '%s'",
23859 xmlSchemaFormatIDCKeySequence(vctxt, &str,
23860 refNode->keys, nbFields),
23861 xmlSchemaGetComponentQName(&strB, matcher->aidc->def));
23862 FREE_AND_NULL(str);
23863 FREE_AND_NULL(strB);
23864 }
23865 }
23866 if (table) {
23867 xmlHashFree(table, xmlFreeIDCHashEntry);
23868 }
23869 }
23870 matcher = matcher->next;
23871 }
23872 /* TODO: Return an error if any error encountered. */
23873 return (0);
23874}
23875
23876/************************************************************************
23877 * *
23878 * XML Reader validation code *
23879 * *
23880 ************************************************************************/
23881
23882static xmlSchemaAttrInfoPtr
23883xmlSchemaGetFreshAttrInfo(xmlSchemaValidCtxtPtr vctxt)
23884{
23885 xmlSchemaAttrInfoPtr iattr;
23886 /*
23887 * Grow/create list of attribute infos.
23888 */
23889 if (vctxt->attrInfos == NULL) {
23890 vctxt->attrInfos = (xmlSchemaAttrInfoPtr *)
23891 xmlMalloc(sizeof(xmlSchemaAttrInfoPtr));
23892 vctxt->sizeAttrInfos = 1;
23893 if (vctxt->attrInfos == NULL) {
23894 xmlSchemaVErrMemory(vctxt,
23895 "allocating attribute info list", NULL);
23896 return (NULL);
23897 }
23898 } else if (vctxt->sizeAttrInfos <= vctxt->nbAttrInfos) {
23899 vctxt->sizeAttrInfos++;
23900 vctxt->attrInfos = (xmlSchemaAttrInfoPtr *)
23901 xmlRealloc(vctxt->attrInfos,
23902 vctxt->sizeAttrInfos * sizeof(xmlSchemaAttrInfoPtr));
23903 if (vctxt->attrInfos == NULL) {
23904 xmlSchemaVErrMemory(vctxt,
23905 "re-allocating attribute info list", NULL);
23906 return (NULL);
23907 }
23908 } else {
23909 iattr = vctxt->attrInfos[vctxt->nbAttrInfos++];
23910 if (iattr->localName != NULL) {
23911 VERROR_INT("xmlSchemaGetFreshAttrInfo",
23912 "attr info not cleared");
23913 return (NULL);
23914 }
23915 iattr->nodeType = XML_ATTRIBUTE_NODE;
23916 return (iattr);
23917 }
23918 /*
23919 * Create an attribute info.
23920 */
23921 iattr = (xmlSchemaAttrInfoPtr)
23922 xmlMalloc(sizeof(xmlSchemaAttrInfo));
23923 if (iattr == NULL) {
23924 xmlSchemaVErrMemory(vctxt, "creating new attribute info", NULL);
23925 return (NULL);
23926 }
23927 memset(iattr, 0, sizeof(xmlSchemaAttrInfo));
23928 iattr->nodeType = XML_ATTRIBUTE_NODE;
23929 vctxt->attrInfos[vctxt->nbAttrInfos++] = iattr;
23930
23931 return (iattr);
23932}
23933
23934static int
23935xmlSchemaValidatorPushAttribute(xmlSchemaValidCtxtPtr vctxt,
23936 xmlNodePtr attrNode,
23937 int nodeLine,
23938 const xmlChar *localName,
23939 const xmlChar *nsName,
23940 int ownedNames,
23941 xmlChar *value,
23942 int ownedValue)
23943{
23944 xmlSchemaAttrInfoPtr attr;
23945
23946 attr = xmlSchemaGetFreshAttrInfo(vctxt);
23947 if (attr == NULL) {
23948 VERROR_INT("xmlSchemaPushAttribute",
23949 "calling xmlSchemaGetFreshAttrInfo()");
23950 return (-1);
23951 }
23952 attr->node = attrNode;
23953 attr->nodeLine = nodeLine;
23954 attr->state = XML_SCHEMAS_ATTR_UNKNOWN;
23955 attr->localName = localName;
23956 attr->nsName = nsName;
23957 if (ownedNames)
23958 attr->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES;
23959 /*
23960 * Evaluate if it's an XSI attribute.
23961 */
23962 if (nsName != NULL) {
23963 if (xmlStrEqual(localName, BAD_CAST "nil")) {
23964 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
23965 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_NIL;
23966 }
23967 } else if (xmlStrEqual(localName, BAD_CAST "type")) {
23968 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
23969 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_TYPE;
23970 }
23971 } else if (xmlStrEqual(localName, BAD_CAST "schemaLocation")) {
23972 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
23973 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC;
23974 }
23975 } else if (xmlStrEqual(localName, BAD_CAST "noNamespaceSchemaLocation")) {
23976 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
23977 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC;
23978 }
23979 } else if (xmlStrEqual(attr->nsName, xmlNamespaceNs)) {
23980 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XMLNS;
23981 }
23982 }
23983 attr->value = value;
23984 if (ownedValue)
23985 attr->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
23986 if (attr->metaType != 0)
23987 attr->state = XML_SCHEMAS_ATTR_META;
23988 return (0);
23989}
23990
23996static void
23997xmlSchemaClearElemInfo(xmlSchemaValidCtxtPtr vctxt,
23998 xmlSchemaNodeInfoPtr ielem)
23999{
24000 ielem->hasKeyrefs = 0;
24001 ielem->appliedXPath = 0;
24002 if (ielem->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES) {
24003 FREE_AND_NULL(ielem->localName);
24004 FREE_AND_NULL(ielem->nsName);
24005 } else {
24006 ielem->localName = NULL;
24007 ielem->nsName = NULL;
24008 }
24009 if (ielem->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
24010 FREE_AND_NULL(ielem->value);
24011 } else {
24012 ielem->value = NULL;
24013 }
24014 if (ielem->val != NULL) {
24015 /*
24016 * PSVI TODO: Be careful not to free it when the value is
24017 * exposed via PSVI.
24018 */
24019 xmlSchemaFreeValue(ielem->val);
24020 ielem->val = NULL;
24021 }
24022 if (ielem->idcMatchers != NULL) {
24023 /*
24024 * REVISIT OPTIMIZE TODO: Use a pool of IDC matchers.
24025 * Does it work?
24026 */
24027 xmlSchemaIDCReleaseMatcherList(vctxt, ielem->idcMatchers);
24028#if 0
24029 xmlSchemaIDCFreeMatcherList(ielem->idcMatchers);
24030#endif
24031 ielem->idcMatchers = NULL;
24032 }
24033 if (ielem->idcTable != NULL) {
24034 /*
24035 * OPTIMIZE TODO: Use a pool of IDC tables??.
24036 */
24037 xmlSchemaIDCFreeIDCTable(ielem->idcTable);
24038 ielem->idcTable = NULL;
24039 }
24040 if (ielem->regexCtxt != NULL) {
24041 xmlRegFreeExecCtxt(ielem->regexCtxt);
24042 ielem->regexCtxt = NULL;
24043 }
24044 if (ielem->nsBindings != NULL) {
24045 xmlFree((xmlChar **)ielem->nsBindings);
24046 ielem->nsBindings = NULL;
24047 ielem->nbNsBindings = 0;
24048 ielem->sizeNsBindings = 0;
24049 }
24050}
24051
24061static xmlSchemaNodeInfoPtr
24062xmlSchemaGetFreshElemInfo(xmlSchemaValidCtxtPtr vctxt)
24063{
24064 xmlSchemaNodeInfoPtr info = NULL;
24065
24066 if (vctxt->depth > vctxt->sizeElemInfos) {
24067 VERROR_INT("xmlSchemaGetFreshElemInfo",
24068 "inconsistent depth encountered");
24069 return (NULL);
24070 }
24071 if (vctxt->elemInfos == NULL) {
24072 vctxt->elemInfos = (xmlSchemaNodeInfoPtr *)
24073 xmlMalloc(10 * sizeof(xmlSchemaNodeInfoPtr));
24074 if (vctxt->elemInfos == NULL) {
24075 xmlSchemaVErrMemory(vctxt,
24076 "allocating the element info array", NULL);
24077 return (NULL);
24078 }
24079 memset(vctxt->elemInfos, 0, 10 * sizeof(xmlSchemaNodeInfoPtr));
24080 vctxt->sizeElemInfos = 10;
24081 } else if (vctxt->sizeElemInfos <= vctxt->depth) {
24082 int i = vctxt->sizeElemInfos;
24083
24084 vctxt->sizeElemInfos *= 2;
24085 vctxt->elemInfos = (xmlSchemaNodeInfoPtr *)
24086 xmlRealloc(vctxt->elemInfos, vctxt->sizeElemInfos *
24087 sizeof(xmlSchemaNodeInfoPtr));
24088 if (vctxt->elemInfos == NULL) {
24089 xmlSchemaVErrMemory(vctxt,
24090 "re-allocating the element info array", NULL);
24091 return (NULL);
24092 }
24093 /*
24094 * We need the new memory to be NULLed.
24095 * TODO: Use memset instead?
24096 */
24097 for (; i < vctxt->sizeElemInfos; i++)
24098 vctxt->elemInfos[i] = NULL;
24099 } else
24100 info = vctxt->elemInfos[vctxt->depth];
24101
24102 if (info == NULL) {
24103 info = (xmlSchemaNodeInfoPtr)
24104 xmlMalloc(sizeof(xmlSchemaNodeInfo));
24105 if (info == NULL) {
24106 xmlSchemaVErrMemory(vctxt,
24107 "allocating an element info", NULL);
24108 return (NULL);
24109 }
24110 vctxt->elemInfos[vctxt->depth] = info;
24111 } else {
24112 if (info->localName != NULL) {
24113 VERROR_INT("xmlSchemaGetFreshElemInfo",
24114 "elem info has not been cleared");
24115 return (NULL);
24116 }
24117 }
24118 memset(info, 0, sizeof(xmlSchemaNodeInfo));
24119 info->nodeType = XML_ELEMENT_NODE;
24120 info->depth = vctxt->depth;
24121
24122 return (info);
24123}
24124
24125#define ACTIVATE_ATTRIBUTE(item) vctxt->inode = (xmlSchemaNodeInfoPtr) item;
24126#define ACTIVATE_ELEM vctxt->inode = vctxt->elemInfos[vctxt->depth];
24127#define ACTIVATE_PARENT_ELEM vctxt->inode = vctxt->elemInfos[vctxt->depth -1];
24128
24129static int
24130xmlSchemaValidateFacets(xmlSchemaAbstractCtxtPtr actxt,
24131 xmlNodePtr node,
24132 xmlSchemaTypePtr type,
24133 xmlSchemaValType valType,
24134 const xmlChar * value,
24135 xmlSchemaValPtr val,
24136 unsigned long length,
24137 int fireErrors)
24138{
24139 int ret, error = 0, found;
24140
24141 xmlSchemaTypePtr tmpType;
24142 xmlSchemaFacetLinkPtr facetLink;
24143 xmlSchemaFacetPtr facet;
24144 unsigned long len = 0;
24145 xmlSchemaWhitespaceValueType ws;
24146
24147 /*
24148 * In Libxml2, derived built-in types have currently no explicit facets.
24149 */
24150 if (type->type == XML_SCHEMA_TYPE_BASIC)
24151 return (0);
24152
24153 /*
24154 * NOTE: Do not jump away, if the facetSet of the given type is
24155 * empty: until now, "pattern" and "enumeration" facets of the
24156 * *base types* need to be checked as well.
24157 */
24158 if (type->facetSet == NULL)
24159 goto pattern_and_enum;
24160
24161 if (! WXS_IS_ATOMIC(type)) {
24162 if (WXS_IS_LIST(type))
24163 goto WXS_IS_LIST;
24164 else
24165 goto pattern_and_enum;
24166 }
24167
24168 /*
24169 * Whitespace handling is only of importance for string-based
24170 * types.
24171 */
24172 tmpType = xmlSchemaGetPrimitiveType(type);
24173 if ((tmpType->builtInType == XML_SCHEMAS_STRING) ||
24174 WXS_IS_ANY_SIMPLE_TYPE(tmpType)) {
24175 ws = xmlSchemaGetWhiteSpaceFacetValue(type);
24176 } else
24177 ws = XML_SCHEMA_WHITESPACE_COLLAPSE;
24178
24179 /*
24180 * If the value was not computed (for string or
24181 * anySimpleType based types), then use the provided
24182 * type.
24183 */
24184 if (val != NULL)
24185 valType = xmlSchemaGetValType(val);
24186
24187 ret = 0;
24188 for (facetLink = type->facetSet; facetLink != NULL;
24189 facetLink = facetLink->next) {
24190 /*
24191 * Skip the pattern "whiteSpace": it is used to
24192 * format the character content beforehand.
24193 */
24194 switch (facetLink->facet->type) {
24195 case XML_SCHEMA_FACET_WHITESPACE:
24196 case XML_SCHEMA_FACET_PATTERN:
24197 case XML_SCHEMA_FACET_ENUMERATION:
24198 continue;
24199 case XML_SCHEMA_FACET_LENGTH:
24200 case XML_SCHEMA_FACET_MINLENGTH:
24201 case XML_SCHEMA_FACET_MAXLENGTH:
24202 ret = xmlSchemaValidateLengthFacetWhtsp(facetLink->facet,
24203 valType, value, val, &len, ws);
24204 break;
24205 default:
24206 ret = xmlSchemaValidateFacetWhtsp(facetLink->facet, ws,
24207 valType, value, val, ws);
24208 break;
24209 }
24210 if (ret < 0) {
24211 AERROR_INT("xmlSchemaValidateFacets",
24212 "validating against a atomic type facet");
24213 return (-1);
24214 } else if (ret > 0) {
24215 if (fireErrors)
24216 xmlSchemaFacetErr(actxt, ret, node,
24217 value, len, type, facetLink->facet, NULL, NULL, NULL);
24218 else
24219 return (ret);
24220 if (error == 0)
24221 error = ret;
24222 }
24223 ret = 0;
24224 }
24225
24226WXS_IS_LIST:
24227 if (! WXS_IS_LIST(type))
24228 goto pattern_and_enum;
24229 /*
24230 * "length", "minLength" and "maxLength" of list types.
24231 */
24232 ret = 0;
24233 for (facetLink = type->facetSet; facetLink != NULL;
24234 facetLink = facetLink->next) {
24235
24236 switch (facetLink->facet->type) {
24237 case XML_SCHEMA_FACET_LENGTH:
24238 case XML_SCHEMA_FACET_MINLENGTH:
24239 case XML_SCHEMA_FACET_MAXLENGTH:
24240 ret = xmlSchemaValidateListSimpleTypeFacet(facetLink->facet,
24241 value, length, NULL);
24242 break;
24243 default:
24244 continue;
24245 }
24246 if (ret < 0) {
24247 AERROR_INT("xmlSchemaValidateFacets",
24248 "validating against a list type facet");
24249 return (-1);
24250 } else if (ret > 0) {
24251 if (fireErrors)
24252 xmlSchemaFacetErr(actxt, ret, node,
24253 value, length, type, facetLink->facet, NULL, NULL, NULL);
24254 else
24255 return (ret);
24256 if (error == 0)
24257 error = ret;
24258 }
24259 ret = 0;
24260 }
24261
24262pattern_and_enum:
24263 found = 0;
24264 /*
24265 * Process enumerations. Facet values are in the value space
24266 * of the defining type's base type. This seems to be a bug in the
24267 * XML Schema 1.0 spec. Use the whitespace type of the base type.
24268 * Only the first set of enumerations in the ancestor-or-self axis
24269 * is used for validation.
24270 */
24271 ret = 0;
24272 tmpType = type;
24273 do {
24274 for (facet = tmpType->facets; facet != NULL; facet = facet->next) {
24275 if (facet->type != XML_SCHEMA_FACET_ENUMERATION)
24276 continue;
24277 found = 1;
24278 ret = xmlSchemaAreValuesEqual(facet->val, val);
24279 if (ret == 1)
24280 break;
24281 else if (ret < 0) {
24282 AERROR_INT("xmlSchemaValidateFacets",
24283 "validating against an enumeration facet");
24284 return (-1);
24285 }
24286 }
24287 if (ret != 0)
24288 break;
24289 /*
24290 * Break on the first set of enumerations. Any additional
24291 * enumerations which might be existent on the ancestors
24292 * of the current type are restricted by this set; thus
24293 * *must* *not* be taken into account.
24294 */
24295 if (found)
24296 break;
24297 tmpType = tmpType->baseType;
24298 } while ((tmpType != NULL) &&
24299 (tmpType->type != XML_SCHEMA_TYPE_BASIC));
24300 if (found && (ret == 0)) {
24302 if (fireErrors) {
24303 xmlSchemaFacetErr(actxt, ret, node,
24304 value, 0, type, NULL, NULL, NULL, NULL);
24305 } else
24306 return (ret);
24307 if (error == 0)
24308 error = ret;
24309 }
24310
24311 /*
24312 * Process patters. Pattern facets are ORed at type level
24313 * and ANDed if derived. Walk the base type axis.
24314 */
24315 tmpType = type;
24316 facet = NULL;
24317 do {
24318 found = 0;
24319 for (facetLink = tmpType->facetSet; facetLink != NULL;
24320 facetLink = facetLink->next) {
24321 if (facetLink->facet->type != XML_SCHEMA_FACET_PATTERN)
24322 continue;
24323 found = 1;
24324 /*
24325 * NOTE that for patterns, @value needs to be the
24326 * normalized value.
24327 */
24328 ret = xmlRegexpExec(facetLink->facet->regexp, value);
24329 if (ret == 1)
24330 break;
24331 else if (ret < 0) {
24332 AERROR_INT("xmlSchemaValidateFacets",
24333 "validating against a pattern facet");
24334 return (-1);
24335 } else {
24336 /*
24337 * Save the last non-validating facet.
24338 */
24339 facet = facetLink->facet;
24340 }
24341 }
24342 if (found && (ret != 1)) {
24344 if (fireErrors) {
24345 xmlSchemaFacetErr(actxt, ret, node,
24346 value, 0, type, facet, NULL, NULL, NULL);
24347 } else
24348 return (ret);
24349 if (error == 0)
24350 error = ret;
24351 break;
24352 }
24353 tmpType = tmpType->baseType;
24354 } while ((tmpType != NULL) && (tmpType->type != XML_SCHEMA_TYPE_BASIC));
24355
24356 return (error);
24357}
24358
24359static xmlChar *
24360xmlSchemaNormalizeValue(xmlSchemaTypePtr type,
24361 const xmlChar *value)
24362{
24363 switch (xmlSchemaGetWhiteSpaceFacetValue(type)) {
24364 case XML_SCHEMA_WHITESPACE_COLLAPSE:
24365 return (xmlSchemaCollapseString(value));
24366 case XML_SCHEMA_WHITESPACE_REPLACE:
24367 return (xmlSchemaWhiteSpaceReplace(value));
24368 default:
24369 return (NULL);
24370 }
24371}
24372
24373static int
24374xmlSchemaValidateQName(xmlSchemaValidCtxtPtr vctxt,
24375 const xmlChar *value,
24376 xmlSchemaValPtr *val,
24377 int valNeeded)
24378{
24379 int ret;
24380 xmlChar *stripped;
24381 const xmlChar *nsName;
24382 xmlChar *local, *prefix = NULL;
24383
24384 ret = xmlValidateQName(value, 1);
24385 if (ret != 0) {
24386 if (ret == -1) {
24387 VERROR_INT("xmlSchemaValidateQName",
24388 "calling xmlValidateQName()");
24389 return (-1);
24390 }
24392 }
24393 /*
24394 * NOTE: xmlSplitQName2 will always return a duplicated
24395 * strings.
24396 */
24397 /* TODO: Export and use xmlSchemaStrip instead */
24398 stripped = xmlSchemaCollapseString(value);
24399 local = xmlSplitQName2(stripped ? stripped : value, &prefix);
24400 xmlFree(stripped);
24401 if (local == NULL)
24403 /*
24404 * OPTIMIZE TODO: Use flags for:
24405 * - is there any namespace binding?
24406 * - is there a default namespace?
24407 */
24408 nsName = xmlSchemaLookupNamespace(vctxt, prefix);
24409
24410 if (prefix != NULL) {
24411 xmlFree(prefix);
24412 /*
24413 * A namespace must be found if the prefix is
24414 * NOT NULL.
24415 */
24416 if (nsName == NULL) {
24418 xmlSchemaCustomErr(ACTXT_CAST vctxt, ret, NULL,
24419 WXS_BASIC_CAST xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
24420 "The QName value '%s' has no "
24421 "corresponding namespace declaration in "
24422 "scope", value, NULL);
24423 if (local != NULL)
24424 xmlFree(local);
24425 return (ret);
24426 }
24427 }
24428 if (valNeeded && val) {
24429 if (nsName != NULL)
24430 *val = xmlSchemaNewQNameValue(
24431 BAD_CAST xmlStrdup(nsName), BAD_CAST local);
24432 else
24433 *val = xmlSchemaNewQNameValue(NULL,
24434 BAD_CAST local);
24435 } else
24436 xmlFree(local);
24437 return (0);
24438}
24439
24440/*
24441* cvc-simple-type
24442*/
24443static int
24444xmlSchemaVCheckCVCSimpleType(xmlSchemaAbstractCtxtPtr actxt,
24445 xmlNodePtr node,
24446 xmlSchemaTypePtr type,
24447 const xmlChar *value,
24448 xmlSchemaValPtr *retVal,
24449 int fireErrors,
24450 int normalize,
24451 int isNormalized)
24452{
24453 int ret = 0, valNeeded = (retVal) ? 1 : 0;
24454 xmlSchemaValPtr val = NULL;
24455 /* xmlSchemaWhitespaceValueType ws; */
24456 xmlChar *normValue = NULL;
24457
24458#define NORMALIZE(atype) \
24459 if ((! isNormalized) && \
24460 (normalize || (type->flags & XML_SCHEMAS_TYPE_NORMVALUENEEDED))) { \
24461 normValue = xmlSchemaNormalizeValue(atype, value); \
24462 if (normValue != NULL) \
24463 value = normValue; \
24464 isNormalized = 1; \
24465 }
24466
24467 if ((retVal != NULL) && (*retVal != NULL)) {
24468 xmlSchemaFreeValue(*retVal);
24469 *retVal = NULL;
24470 }
24471 /*
24472 * 3.14.4 Simple Type Definition Validation Rules
24473 * Validation Rule: String Valid
24474 */
24475 /*
24476 * 1 It is schema-valid with respect to that definition as defined
24477 * by Datatype Valid in [XML Schemas: Datatypes].
24478 */
24479 /*
24480 * 2.1 If The definition is ENTITY or is validly derived from ENTITY given
24481 * the empty set, as defined in Type Derivation OK (Simple) ($3.14.6), then
24482 * the string must be a `declared entity name`.
24483 */
24484 /*
24485 * 2.2 If The definition is ENTITIES or is validly derived from ENTITIES
24486 * given the empty set, as defined in Type Derivation OK (Simple) ($3.14.6),
24487 * then every whitespace-delimited substring of the string must be a `declared
24488 * entity name`.
24489 */
24490 /*
24491 * 2.3 otherwise no further condition applies.
24492 */
24493 if ((! valNeeded) && (type->flags & XML_SCHEMAS_TYPE_FACETSNEEDVALUE))
24494 valNeeded = 1;
24495 if (value == NULL)
24496 value = BAD_CAST "";
24497 if (WXS_IS_ANY_SIMPLE_TYPE(type) || WXS_IS_ATOMIC(type)) {
24498 xmlSchemaTypePtr biType; /* The built-in type. */
24499 /*
24500 * SPEC (1.2.1) "if {variety} is `atomic` then the string must `match`
24501 * a literal in the `lexical space` of {base type definition}"
24502 */
24503 /*
24504 * Whitespace-normalize.
24505 */
24506 NORMALIZE(type);
24507 if (type->type != XML_SCHEMA_TYPE_BASIC) {
24508 /*
24509 * Get the built-in type.
24510 */
24511 biType = type->baseType;
24512 while ((biType != NULL) &&
24513 (biType->type != XML_SCHEMA_TYPE_BASIC))
24514 biType = biType->baseType;
24515
24516 if (biType == NULL) {
24517 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24518 "could not get the built-in type");
24519 goto internal_error;
24520 }
24521 } else
24522 biType = type;
24523 /*
24524 * NOTATIONs need to be processed here, since they need
24525 * to lookup in the hashtable of NOTATION declarations of the schema.
24526 */
24527 if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
24528 switch (biType->builtInType) {
24529 case XML_SCHEMAS_NOTATION:
24530 ret = xmlSchemaValidateNotation(
24531 (xmlSchemaValidCtxtPtr) actxt,
24532 ((xmlSchemaValidCtxtPtr) actxt)->schema,
24533 NULL, value, &val, valNeeded);
24534 break;
24535 case XML_SCHEMAS_QNAME:
24536 ret = xmlSchemaValidateQName((xmlSchemaValidCtxtPtr) actxt,
24537 value, &val, valNeeded);
24538 break;
24539 default:
24540 /* ws = xmlSchemaGetWhiteSpaceFacetValue(type); */
24541 if (valNeeded)
24542 ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24543 value, &val, node);
24544 else
24545 ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24546 value, NULL, node);
24547 break;
24548 }
24549 } else if (actxt->type == XML_SCHEMA_CTXT_PARSER) {
24550 switch (biType->builtInType) {
24551 case XML_SCHEMAS_NOTATION:
24552 ret = xmlSchemaValidateNotation(NULL,
24553 ((xmlSchemaParserCtxtPtr) actxt)->schema, node,
24554 value, &val, valNeeded);
24555 break;
24556 default:
24557 /* ws = xmlSchemaGetWhiteSpaceFacetValue(type); */
24558 if (valNeeded)
24559 ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24560 value, &val, node);
24561 else
24562 ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24563 value, NULL, node);
24564 break;
24565 }
24566 } else {
24567 /*
24568 * Validation via a public API is not implemented yet.
24569 */
24570 TODO
24571 goto internal_error;
24572 }
24573 if (ret != 0) {
24574 if (ret < 0) {
24575 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24576 "validating against a built-in type");
24577 goto internal_error;
24578 }
24579 if (WXS_IS_LIST(type))
24581 else
24583 }
24584 if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
24585 /*
24586 * Check facets.
24587 */
24588 ret = xmlSchemaValidateFacets(actxt, node, type,
24589 (xmlSchemaValType) biType->builtInType, value, val,
24590 0, fireErrors);
24591 if (ret != 0) {
24592 if (ret < 0) {
24593 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24594 "validating facets of atomic simple type");
24595 goto internal_error;
24596 }
24597 if (WXS_IS_LIST(type))
24599 else
24601 }
24602 }
24603 else if (fireErrors && (ret > 0))
24604 xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
24605 } else if (WXS_IS_LIST(type)) {
24606
24607 xmlSchemaTypePtr itemType;
24608 const xmlChar *cur, *end;
24609 xmlChar *tmpValue = NULL;
24610 unsigned long len = 0;
24611 xmlSchemaValPtr prevVal = NULL, curVal = NULL;
24612 /* 1.2.2 if {variety} is `list` then the string must be a sequence
24613 * of white space separated tokens, each of which `match`es a literal
24614 * in the `lexical space` of {item type definition}
24615 */
24616 /*
24617 * Note that XML_SCHEMAS_TYPE_NORMVALUENEEDED will be set if
24618 * the list type has an enum or pattern facet.
24619 */
24620 NORMALIZE(type);
24621 /*
24622 * VAL TODO: Optimize validation of empty values.
24623 * VAL TODO: We do not have computed values for lists.
24624 */
24625 itemType = WXS_LIST_ITEMTYPE(type);
24626 cur = value;
24627 do {
24628 while (IS_BLANK_CH(*cur))
24629 cur++;
24630 end = cur;
24631 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
24632 end++;
24633 if (end == cur)
24634 break;
24635 tmpValue = xmlStrndup(cur, end - cur);
24636 len++;
24637
24638 if (valNeeded)
24639 ret = xmlSchemaVCheckCVCSimpleType(actxt, node, itemType,
24640 tmpValue, &curVal, fireErrors, 0, 1);
24641 else
24642 ret = xmlSchemaVCheckCVCSimpleType(actxt, node, itemType,
24643 tmpValue, NULL, fireErrors, 0, 1);
24644 FREE_AND_NULL(tmpValue);
24645 if (curVal != NULL) {
24646 /*
24647 * Add to list of computed values.
24648 */
24649 if (val == NULL)
24650 val = curVal;
24651 else
24652 xmlSchemaValueAppend(prevVal, curVal);
24653 prevVal = curVal;
24654 curVal = NULL;
24655 }
24656 if (ret != 0) {
24657 if (ret < 0) {
24658 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24659 "validating an item of list simple type");
24660 goto internal_error;
24661 }
24663 break;
24664 }
24665 cur = end;
24666 } while (*cur != 0);
24667 FREE_AND_NULL(tmpValue);
24668 if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
24669 /*
24670 * Apply facets (pattern, enumeration).
24671 */
24672 ret = xmlSchemaValidateFacets(actxt, node, type,
24673 XML_SCHEMAS_UNKNOWN, value, val,
24674 len, fireErrors);
24675 if (ret != 0) {
24676 if (ret < 0) {
24677 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24678 "validating facets of list simple type");
24679 goto internal_error;
24680 }
24682 }
24683 }
24684 if (fireErrors && (ret > 0)) {
24685 /*
24686 * Report the normalized value.
24687 */
24688 normalize = 1;
24689 NORMALIZE(type);
24690 xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
24691 }
24692 } else if (WXS_IS_UNION(type)) {
24693 xmlSchemaTypeLinkPtr memberLink;
24694 /*
24695 * TODO: For all datatypes `derived` by `union` whiteSpace does
24696 * not apply directly; however, the normalization behavior of `union`
24697 * types is controlled by the value of whiteSpace on that one of the
24698 * `memberTypes` against which the `union` is successfully validated.
24699 *
24700 * This means that the value is normalized by the first validating
24701 * member type, then the facets of the union type are applied. This
24702 * needs changing of the value!
24703 */
24704
24705 /*
24706 * 1.2.3 if {variety} is `union` then the string must `match` a
24707 * literal in the `lexical space` of at least one member of
24708 * {member type definitions}
24709 */
24710 memberLink = xmlSchemaGetUnionSimpleTypeMemberTypes(type);
24711 if (memberLink == NULL) {
24712 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24713 "union simple type has no member types");
24714 goto internal_error;
24715 }
24716 /*
24717 * Always normalize union type values, since we currently
24718 * cannot store the whitespace information with the value
24719 * itself; otherwise a later value-comparison would be
24720 * not possible.
24721 */
24722 while (memberLink != NULL) {
24723 if (valNeeded)
24724 ret = xmlSchemaVCheckCVCSimpleType(actxt, node,
24725 memberLink->type, value, &val, 0, 1, 0);
24726 else
24727 ret = xmlSchemaVCheckCVCSimpleType(actxt, node,
24728 memberLink->type, value, NULL, 0, 1, 0);
24729 if (ret <= 0)
24730 break;
24731 memberLink = memberLink->next;
24732 }
24733 if (ret != 0) {
24734 if (ret < 0) {
24735 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24736 "validating members of union simple type");
24737 goto internal_error;
24738 }
24740 }
24741 /*
24742 * Apply facets (pattern, enumeration).
24743 */
24744 if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
24745 /*
24746 * The normalization behavior of `union` types is controlled by
24747 * the value of whiteSpace on that one of the `memberTypes`
24748 * against which the `union` is successfully validated.
24749 */
24750 NORMALIZE(memberLink->type);
24751 ret = xmlSchemaValidateFacets(actxt, node, type,
24752 XML_SCHEMAS_UNKNOWN, value, val,
24753 0, fireErrors);
24754 if (ret != 0) {
24755 if (ret < 0) {
24756 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24757 "validating facets of union simple type");
24758 goto internal_error;
24759 }
24761 }
24762 }
24763 if (fireErrors && (ret > 0))
24764 xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
24765 }
24766
24767 if (normValue != NULL)
24768 xmlFree(normValue);
24769 if (ret == 0) {
24770 if (retVal != NULL)
24771 *retVal = val;
24772 else if (val != NULL)
24773 xmlSchemaFreeValue(val);
24774 } else if (val != NULL)
24775 xmlSchemaFreeValue(val);
24776 return (ret);
24777internal_error:
24778 if (normValue != NULL)
24779 xmlFree(normValue);
24780 if (val != NULL)
24781 xmlSchemaFreeValue(val);
24782 return (-1);
24783}
24784
24785static int
24786xmlSchemaVExpandQName(xmlSchemaValidCtxtPtr vctxt,
24787 const xmlChar *value,
24788 const xmlChar **nsName,
24789 const xmlChar **localName)
24790{
24791 int ret = 0;
24792
24793 if ((nsName == NULL) || (localName == NULL))
24794 return (-1);
24795 *nsName = NULL;
24796 *localName = NULL;
24797
24798 ret = xmlValidateQName(value, 1);
24799 if (ret == -1)
24800 return (-1);
24801 if (ret > 0) {
24802 xmlSchemaSimpleTypeErr(ACTXT_CAST vctxt,
24804 value, xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), 1);
24805 return (1);
24806 }
24807 {
24808 xmlChar *local = NULL;
24809 xmlChar *prefix;
24810
24811 /*
24812 * NOTE: xmlSplitQName2 will return a duplicated
24813 * string.
24814 */
24815 local = xmlSplitQName2(value, &prefix);
24816 if (local == NULL)
24817 *localName = xmlDictLookup(vctxt->dict, value, -1);
24818 else {
24819 *localName = xmlDictLookup(vctxt->dict, local, -1);
24820 xmlFree(local);
24821 }
24822
24823 *nsName = xmlSchemaLookupNamespace(vctxt, prefix);
24824
24825 if (prefix != NULL) {
24826 xmlFree(prefix);
24827 /*
24828 * A namespace must be found if the prefix is NOT NULL.
24829 */
24830 if (*nsName == NULL) {
24831 xmlSchemaCustomErr(ACTXT_CAST vctxt,
24833 WXS_BASIC_CAST xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
24834 "The QName value '%s' has no "
24835 "corresponding namespace declaration in scope",
24836 value, NULL);
24837 return (2);
24838 }
24839 }
24840 }
24841 return (0);
24842}
24843
24844static int
24845xmlSchemaProcessXSIType(xmlSchemaValidCtxtPtr vctxt,
24846 xmlSchemaAttrInfoPtr iattr,
24847 xmlSchemaTypePtr *localType,
24848 xmlSchemaElementPtr elemDecl)
24849{
24850 int ret = 0;
24851 /*
24852 * cvc-elt (3.3.4) : (4)
24853 * AND
24854 * Schema-Validity Assessment (Element) (cvc-assess-elt)
24855 * (1.2.1.2.1) - (1.2.1.2.4)
24856 * Handle 'xsi:type'.
24857 */
24858 if (localType == NULL)
24859 return (-1);
24860 *localType = NULL;
24861 if (iattr == NULL)
24862 return (0);
24863 else {
24864 const xmlChar *nsName = NULL, *local = NULL;
24865 /*
24866 * TODO: We should report a *warning* that the type was overridden
24867 * by the instance.
24868 */
24869 ACTIVATE_ATTRIBUTE(iattr);
24870 /*
24871 * (cvc-elt) (3.3.4) : (4.1)
24872 * (cvc-assess-elt) (1.2.1.2.2)
24873 */
24874 ret = xmlSchemaVExpandQName(vctxt, iattr->value,
24875 &nsName, &local);
24876 if (ret != 0) {
24877 if (ret < 0) {
24878 VERROR_INT("xmlSchemaValidateElementByDeclaration",
24879 "calling xmlSchemaQNameExpand() to validate the "
24880 "attribute 'xsi:type'");
24881 goto internal_error;
24882 }
24883 goto exit;
24884 }
24885 /*
24886 * (cvc-elt) (3.3.4) : (4.2)
24887 * (cvc-assess-elt) (1.2.1.2.3)
24888 */
24889 *localType = xmlSchemaGetType(vctxt->schema, local, nsName);
24890 if (*localType == NULL) {
24891 xmlChar *str = NULL;
24892
24893 xmlSchemaCustomErr(ACTXT_CAST vctxt,
24895 WXS_BASIC_CAST xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
24896 "The QName value '%s' of the xsi:type attribute does not "
24897 "resolve to a type definition",
24898 xmlSchemaFormatQName(&str, nsName, local), NULL);
24899 FREE_AND_NULL(str);
24900 ret = vctxt->err;
24901 goto exit;
24902 }
24903 if (elemDecl != NULL) {
24904 int set = 0;
24905
24906 /*
24907 * SPEC cvc-elt (3.3.4) : (4.3) (Type Derivation OK)
24908 * "The `local type definition` must be validly
24909 * derived from the {type definition} given the union of
24910 * the {disallowed substitutions} and the {type definition}'s
24911 * {prohibited substitutions}, as defined in
24912 * Type Derivation OK (Complex) ($3.4.6)
24913 * (if it is a complex type definition),
24914 * or given {disallowed substitutions} as defined in Type
24915 * Derivation OK (Simple) ($3.14.6) (if it is a simple type
24916 * definition)."
24917 *
24918 * {disallowed substitutions}: the "block" on the element decl.
24919 * {prohibited substitutions}: the "block" on the type def.
24920 */
24921 /*
24922 * OPTIMIZE TODO: We could map types already evaluated
24923 * to be validly derived from other types to avoid checking
24924 * this over and over for the same types.
24925 */
24926 if ((elemDecl->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) ||
24927 (elemDecl->subtypes->flags &
24928 XML_SCHEMAS_TYPE_BLOCK_EXTENSION))
24929 set |= SUBSET_EXTENSION;
24930
24931 if ((elemDecl->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) ||
24932 (elemDecl->subtypes->flags &
24933 XML_SCHEMAS_TYPE_BLOCK_RESTRICTION))
24934 set |= SUBSET_RESTRICTION;
24935
24936 /*
24937 * REMOVED and CHANGED since this produced a parser context
24938 * which adds to the string dict of the schema. So this would
24939 * change the schema and we don't want this. We don't need
24940 * the parser context anymore.
24941 *
24942 * if ((vctxt->pctxt == NULL) &&
24943 * (xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1))
24944 * return (-1);
24945 */
24946
24947 if (xmlSchemaCheckCOSDerivedOK(ACTXT_CAST vctxt, *localType,
24948 elemDecl->subtypes, set) != 0) {
24949 xmlChar *str = NULL;
24950
24951 xmlSchemaCustomErr(ACTXT_CAST vctxt,
24953 "The type definition '%s', specified by xsi:type, is "
24954 "blocked or not validly derived from the type definition "
24955 "of the element declaration",
24956 xmlSchemaFormatQName(&str,
24957 (*localType)->targetNamespace,
24958 (*localType)->name),
24959 NULL);
24960 FREE_AND_NULL(str);
24961 ret = vctxt->err;
24962 *localType = NULL;
24963 }
24964 }
24965 }
24966exit:
24967 ACTIVATE_ELEM;
24968 return (ret);
24969internal_error:
24970 ACTIVATE_ELEM;
24971 return (-1);
24972}
24973
24974static int
24975xmlSchemaValidateElemDecl(xmlSchemaValidCtxtPtr vctxt)
24976{
24977 xmlSchemaElementPtr elemDecl = vctxt->inode->decl;
24978 xmlSchemaTypePtr actualType;
24979
24980 /*
24981 * cvc-elt (3.3.4) : 1
24982 */
24983 if (elemDecl == NULL) {
24985 "No matching declaration available");
24986 return (vctxt->err);
24987 }
24988 actualType = WXS_ELEM_TYPEDEF(elemDecl);
24989 /*
24990 * cvc-elt (3.3.4) : 2
24991 */
24992 if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT) {
24994 "The element declaration is abstract");
24995 return (vctxt->err);
24996 }
24997 if (actualType == NULL) {
24999 "The type definition is absent");
25000 return (XML_SCHEMAV_CVC_TYPE_1);
25001 }
25002 if (vctxt->nbAttrInfos != 0) {
25003 int ret;
25004 xmlSchemaAttrInfoPtr iattr;
25005 /*
25006 * cvc-elt (3.3.4) : 3
25007 * Handle 'xsi:nil'.
25008 */
25009 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
25010 XML_SCHEMA_ATTR_INFO_META_XSI_NIL);
25011 if (iattr) {
25012 ACTIVATE_ATTRIBUTE(iattr);
25013 /*
25014 * Validate the value.
25015 */
25016 ret = xmlSchemaVCheckCVCSimpleType(
25017 ACTXT_CAST vctxt, NULL,
25018 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
25019 iattr->value, &(iattr->val), 1, 0, 0);
25020 ACTIVATE_ELEM;
25021 if (ret < 0) {
25022 VERROR_INT("xmlSchemaValidateElemDecl",
25023 "calling xmlSchemaVCheckCVCSimpleType() to "
25024 "validate the attribute 'xsi:nil'");
25025 return (-1);
25026 }
25027 if (ret == 0) {
25028 if ((elemDecl->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) {
25029 /*
25030 * cvc-elt (3.3.4) : 3.1
25031 */
25033 "The element is not 'nillable'");
25034 /* Does not return an error on purpose. */
25035 } else {
25036 if (xmlSchemaValueGetAsBoolean(iattr->val)) {
25037 /*
25038 * cvc-elt (3.3.4) : 3.2.2
25039 */
25040 if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) &&
25041 (elemDecl->value != NULL)) {
25043 "The element cannot be 'nilled' because "
25044 "there is a fixed value constraint defined "
25045 "for it");
25046 /* Does not return an error on purpose. */
25047 } else
25048 vctxt->inode->flags |=
25049 XML_SCHEMA_ELEM_INFO_NILLED;
25050 }
25051 }
25052 }
25053 }
25054 /*
25055 * cvc-elt (3.3.4) : 4
25056 * Handle 'xsi:type'.
25057 */
25058 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
25059 XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
25060 if (iattr) {
25061 xmlSchemaTypePtr localType = NULL;
25062
25063 ret = xmlSchemaProcessXSIType(vctxt, iattr, &localType,
25064 elemDecl);
25065 if (ret != 0) {
25066 if (ret == -1) {
25067 VERROR_INT("xmlSchemaValidateElemDecl",
25068 "calling xmlSchemaProcessXSIType() to "
25069 "process the attribute 'xsi:type'");
25070 return (-1);
25071 }
25072 /* Does not return an error on purpose. */
25073 }
25074 if (localType != NULL) {
25075 vctxt->inode->flags |= XML_SCHEMA_ELEM_INFO_LOCAL_TYPE;
25076 actualType = localType;
25077 }
25078 }
25079 }
25080 /*
25081 * IDC: Register identity-constraint XPath matchers.
25082 */
25083 if ((elemDecl->idcs != NULL) &&
25084 (xmlSchemaIDCRegisterMatchers(vctxt, elemDecl) == -1))
25085 return (-1);
25086 /*
25087 * No actual type definition.
25088 */
25089 if (actualType == NULL) {
25091 "The type definition is absent");
25092 return (XML_SCHEMAV_CVC_TYPE_1);
25093 }
25094 /*
25095 * Remember the actual type definition.
25096 */
25097 vctxt->inode->typeDef = actualType;
25098
25099 return (0);
25100}
25101
25102static int
25103xmlSchemaVAttributesSimple(xmlSchemaValidCtxtPtr vctxt)
25104{
25105 xmlSchemaAttrInfoPtr iattr;
25106 int ret = 0, i;
25107
25108 /*
25109 * SPEC cvc-type (3.1.1)
25110 * "The attributes of must be empty, excepting those whose namespace
25111 * name is identical to http://www.w3.org/2001/XMLSchema-instance and
25112 * whose local name is one of type, nil, schemaLocation or
25113 * noNamespaceSchemaLocation."
25114 */
25115 if (vctxt->nbAttrInfos == 0)
25116 return (0);
25117 for (i = 0; i < vctxt->nbAttrInfos; i++) {
25118 iattr = vctxt->attrInfos[i];
25119 if (! iattr->metaType) {
25120 ACTIVATE_ATTRIBUTE(iattr)
25121 xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt,
25124 }
25125 }
25126 ACTIVATE_ELEM
25127 return (ret);
25128}
25129
25130/*
25131* Cleanup currently used attribute infos.
25132*/
25133static void
25134xmlSchemaClearAttrInfos(xmlSchemaValidCtxtPtr vctxt)
25135{
25136 int i;
25137 xmlSchemaAttrInfoPtr attr;
25138
25139 if (vctxt->nbAttrInfos == 0)
25140 return;
25141 for (i = 0; i < vctxt->nbAttrInfos; i++) {
25142 attr = vctxt->attrInfos[i];
25143 if (attr->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES) {
25144 if (attr->localName != NULL)
25145 xmlFree((xmlChar *) attr->localName);
25146 if (attr->nsName != NULL)
25147 xmlFree((xmlChar *) attr->nsName);
25148 }
25149 if (attr->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
25150 if (attr->value != NULL)
25151 xmlFree((xmlChar *) attr->value);
25152 }
25153 if (attr->val != NULL) {
25154 xmlSchemaFreeValue(attr->val);
25155 attr->val = NULL;
25156 }
25157 memset(attr, 0, sizeof(xmlSchemaAttrInfo));
25158 }
25159 vctxt->nbAttrInfos = 0;
25160}
25161
25162/*
25163* 3.4.4 Complex Type Definition Validation Rules
25164* Element Locally Valid (Complex Type) (cvc-complex-type)
25165* 3.2.4 Attribute Declaration Validation Rules
25166* Validation Rule: Attribute Locally Valid (cvc-attribute)
25167* Attribute Locally Valid (Use) (cvc-au)
25168*
25169* Only "assessed" attribute information items will be visible to
25170* IDCs. I.e. not "lax" (without declaration) and "skip" wild attributes.
25171*/
25172static int
25173xmlSchemaVAttributesComplex(xmlSchemaValidCtxtPtr vctxt)
25174{
25175 xmlSchemaTypePtr type = vctxt->inode->typeDef;
25176 xmlSchemaItemListPtr attrUseList;
25177 xmlSchemaAttributeUsePtr attrUse = NULL;
25178 xmlSchemaAttributePtr attrDecl = NULL;
25179 xmlSchemaAttrInfoPtr iattr, tmpiattr;
25180 int i, j, found, nbAttrs, nbUses;
25181 int xpathRes = 0, res, wildIDs = 0, fixed;
25182 xmlNodePtr defAttrOwnerElem = NULL;
25183
25184 /*
25185 * SPEC (cvc-attribute)
25186 * (1) "The declaration must not be `absent` (see Missing
25187 * Sub-components ($5.3) for how this can fail to be
25188 * the case)."
25189 * (2) "Its {type definition} must not be absent."
25190 *
25191 * NOTE (1) + (2): This is not handled here, since we currently do not
25192 * allow validation against schemas which have missing sub-components.
25193 *
25194 * SPEC (cvc-complex-type)
25195 * (3) "For each attribute information item in the element information
25196 * item's [attributes] excepting those whose [namespace name] is
25197 * identical to http://www.w3.org/2001/XMLSchema-instance and whose
25198 * [local name] is one of type, nil, schemaLocation or
25199 * noNamespaceSchemaLocation, the appropriate case among the following
25200 * must be true:
25201 *
25202 */
25203 attrUseList = (xmlSchemaItemListPtr) type->attrUses;
25204 /*
25205 * @nbAttrs is the number of attributes present in the instance.
25206 */
25207 nbAttrs = vctxt->nbAttrInfos;
25208 if (attrUseList != NULL)
25209 nbUses = attrUseList->nbItems;
25210 else
25211 nbUses = 0;
25212 for (i = 0; i < nbUses; i++) {
25213 found = 0;
25214 attrUse = attrUseList->items[i];
25215 attrDecl = WXS_ATTRUSE_DECL(attrUse);
25216 for (j = 0; j < nbAttrs; j++) {
25217 iattr = vctxt->attrInfos[j];
25218 /*
25219 * SPEC (cvc-complex-type) (3)
25220 * Skip meta attributes.
25221 */
25222 if (iattr->metaType)
25223 continue;
25224 if (iattr->localName[0] != attrDecl->name[0])
25225 continue;
25226 if (!xmlStrEqual(iattr->localName, attrDecl->name))
25227 continue;
25228 if (!xmlStrEqual(iattr->nsName, attrDecl->targetNamespace))
25229 continue;
25230 found = 1;
25231 /*
25232 * SPEC (cvc-complex-type)
25233 * (3.1) "If there is among the {attribute uses} an attribute
25234 * use with an {attribute declaration} whose {name} matches
25235 * the attribute information item's [local name] and whose
25236 * {target namespace} is identical to the attribute information
25237 * item's [namespace name] (where an `absent` {target namespace}
25238 * is taken to be identical to a [namespace name] with no value),
25239 * then the attribute information must be `valid` with respect
25240 * to that attribute use as per Attribute Locally Valid (Use)
25241 * ($3.5.4). In this case the {attribute declaration} of that
25242 * attribute use is the `context-determined declaration` for the
25243 * attribute information item with respect to Schema-Validity
25244 * Assessment (Attribute) ($3.2.4) and
25245 * Assessment Outcome (Attribute) ($3.2.5).
25246 */
25247 iattr->state = XML_SCHEMAS_ATTR_ASSESSED;
25248 iattr->use = attrUse;
25249 /*
25250 * Context-determined declaration.
25251 */
25252 iattr->decl = attrDecl;
25253 iattr->typeDef = attrDecl->subtypes;
25254 break;
25255 }
25256
25257 if (found)
25258 continue;
25259
25260 if (attrUse->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED) {
25261 /*
25262 * Handle non-existent, required attributes.
25263 *
25264 * SPEC (cvc-complex-type)
25265 * (4) "The {attribute declaration} of each attribute use in
25266 * the {attribute uses} whose {required} is true matches one
25267 * of the attribute information items in the element information
25268 * item's [attributes] as per clause 3.1 above."
25269 */
25270 tmpiattr = xmlSchemaGetFreshAttrInfo(vctxt);
25271 if (tmpiattr == NULL) {
25272 VERROR_INT(
25273 "xmlSchemaVAttributesComplex",
25274 "calling xmlSchemaGetFreshAttrInfo()");
25275 return (-1);
25276 }
25277 tmpiattr->state = XML_SCHEMAS_ATTR_ERR_MISSING;
25278 tmpiattr->use = attrUse;
25279 tmpiattr->decl = attrDecl;
25280 } else if ((attrUse->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
25281 ((attrUse->defValue != NULL) ||
25282 (attrDecl->defValue != NULL))) {
25283 /*
25284 * Handle non-existent, optional, default/fixed attributes.
25285 */
25286 tmpiattr = xmlSchemaGetFreshAttrInfo(vctxt);
25287 if (tmpiattr == NULL) {
25288 VERROR_INT(
25289 "xmlSchemaVAttributesComplex",
25290 "calling xmlSchemaGetFreshAttrInfo()");
25291 return (-1);
25292 }
25293 tmpiattr->state = XML_SCHEMAS_ATTR_DEFAULT;
25294 tmpiattr->use = attrUse;
25295 tmpiattr->decl = attrDecl;
25296 tmpiattr->typeDef = attrDecl->subtypes;
25297 tmpiattr->localName = attrDecl->name;
25298 tmpiattr->nsName = attrDecl->targetNamespace;
25299 }
25300 }
25301
25302 if (vctxt->nbAttrInfos == 0)
25303 return (0);
25304 /*
25305 * Validate against the wildcard.
25306 */
25307 if (type->attributeWildcard != NULL) {
25308 /*
25309 * SPEC (cvc-complex-type)
25310 * (3.2.1) "There must be an {attribute wildcard}."
25311 */
25312 for (i = 0; i < nbAttrs; i++) {
25313 iattr = vctxt->attrInfos[i];
25314 /*
25315 * SPEC (cvc-complex-type) (3)
25316 * Skip meta attributes.
25317 */
25318 if (iattr->state != XML_SCHEMAS_ATTR_UNKNOWN)
25319 continue;
25320 /*
25321 * SPEC (cvc-complex-type)
25322 * (3.2.2) "The attribute information item must be `valid` with
25323 * respect to it as defined in Item Valid (Wildcard) ($3.10.4)."
25324 *
25325 * SPEC Item Valid (Wildcard) (cvc-wildcard)
25326 * "... its [namespace name] must be `valid` with respect to
25327 * the wildcard constraint, as defined in Wildcard allows
25328 * Namespace Name ($3.10.4)."
25329 */
25330 if (xmlSchemaCheckCVCWildcardNamespace(type->attributeWildcard,
25331 iattr->nsName) == 0) {
25332 /*
25333 * Handle processContents.
25334 *
25335 * SPEC (cvc-wildcard):
25336 * processContents | context-determined declaration:
25337 * "strict" "mustFind"
25338 * "lax" "none"
25339 * "skip" "skip"
25340 */
25341 if (type->attributeWildcard->processContents ==
25342 XML_SCHEMAS_ANY_SKIP) {
25343 /*
25344 * context-determined declaration = "skip"
25345 *
25346 * SPEC PSVI Assessment Outcome (Attribute)
25347 * [validity] = "notKnown"
25348 * [validation attempted] = "none"
25349 */
25350 iattr->state = XML_SCHEMAS_ATTR_WILD_SKIP;
25351 continue;
25352 }
25353 /*
25354 * Find an attribute declaration.
25355 */
25356 iattr->decl = xmlSchemaGetAttributeDecl(vctxt->schema,
25357 iattr->localName, iattr->nsName);
25358 if (iattr->decl != NULL) {
25359 iattr->state = XML_SCHEMAS_ATTR_ASSESSED;
25360 /*
25361 * SPEC (cvc-complex-type)
25362 * (5) "Let [Definition:] the wild IDs be the set of
25363 * all attribute information item to which clause 3.2
25364 * applied and whose `validation` resulted in a
25365 * `context-determined declaration` of mustFind or no
25366 * `context-determined declaration` at all, and whose
25367 * [local name] and [namespace name] resolve (as
25368 * defined by QName resolution (Instance) ($3.15.4)) to
25369 * an attribute declaration whose {type definition} is
25370 * or is derived from ID. Then all of the following
25371 * must be true:"
25372 */
25373 iattr->typeDef = WXS_ATTR_TYPEDEF(iattr->decl);
25374 if (xmlSchemaIsDerivedFromBuiltInType(
25375 iattr->typeDef, XML_SCHEMAS_ID)) {
25376 /*
25377 * SPEC (5.1) "There must be no more than one
25378 * item in `wild IDs`."
25379 */
25380 if (wildIDs != 0) {
25381 /* VAL TODO */
25382 iattr->state = XML_SCHEMAS_ATTR_ERR_WILD_DUPLICATE_ID;
25383 TODO
25384 continue;
25385 }
25386 wildIDs++;
25387 /*
25388 * SPEC (cvc-complex-type)
25389 * (5.2) "If `wild IDs` is non-empty, there must not
25390 * be any attribute uses among the {attribute uses}
25391 * whose {attribute declaration}'s {type definition}
25392 * is or is derived from ID."
25393 */
25394 if (attrUseList != NULL) {
25395 for (j = 0; j < attrUseList->nbItems; j++) {
25396 if (xmlSchemaIsDerivedFromBuiltInType(
25397 WXS_ATTRUSE_TYPEDEF(attrUseList->items[j]),
25398 XML_SCHEMAS_ID)) {
25399 /* URGENT VAL TODO: implement */
25400 iattr->state = XML_SCHEMAS_ATTR_ERR_WILD_AND_USE_ID;
25401 TODO
25402 break;
25403 }
25404 }
25405 }
25406 }
25407 } else if (type->attributeWildcard->processContents ==
25408 XML_SCHEMAS_ANY_LAX) {
25409 iattr->state = XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL;
25410 /*
25411 * SPEC PSVI Assessment Outcome (Attribute)
25412 * [validity] = "notKnown"
25413 * [validation attempted] = "none"
25414 */
25415 } else {
25416 iattr->state = XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL;
25417 }
25418 }
25419 }
25420 }
25421
25422 if (vctxt->nbAttrInfos == 0)
25423 return (0);
25424
25425 /*
25426 * Get the owner element; needed for creation of default attributes.
25427 * This fixes bug #341337, reported by David Grohmann.
25428 */
25429 if (vctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) {
25430 xmlSchemaNodeInfoPtr ielem = vctxt->elemInfos[vctxt->depth];
25431 if (ielem && ielem->node && ielem->node->doc)
25432 defAttrOwnerElem = ielem->node;
25433 }
25434 /*
25435 * Validate values, create default attributes, evaluate IDCs.
25436 */
25437 for (i = 0; i < vctxt->nbAttrInfos; i++) {
25438 iattr = vctxt->attrInfos[i];
25439 /*
25440 * VAL TODO: Note that we won't try to resolve IDCs to
25441 * "lax" and "skip" validated attributes. Check what to
25442 * do in this case.
25443 */
25444 if ((iattr->state != XML_SCHEMAS_ATTR_ASSESSED) &&
25445 (iattr->state != XML_SCHEMAS_ATTR_DEFAULT))
25446 continue;
25447 /*
25448 * VAL TODO: What to do if the type definition is missing?
25449 */
25450 if (iattr->typeDef == NULL) {
25451 iattr->state = XML_SCHEMAS_ATTR_ERR_NO_TYPE;
25452 continue;
25453 }
25454
25455 ACTIVATE_ATTRIBUTE(iattr);
25456 fixed = 0;
25457 xpathRes = 0;
25458
25459 if (vctxt->xpathStates != NULL) {
25460 /*
25461 * Evaluate IDCs.
25462 */
25463 xpathRes = xmlSchemaXPathEvaluate(vctxt,
25464 XML_ATTRIBUTE_NODE);
25465 if (xpathRes == -1) {
25466 VERROR_INT("xmlSchemaVAttributesComplex",
25467 "calling xmlSchemaXPathEvaluate()");
25468 goto internal_error;
25469 }
25470 }
25471
25472 if (iattr->state == XML_SCHEMAS_ATTR_DEFAULT) {
25473 /*
25474 * Default/fixed attributes.
25475 * We need the value only if we need to resolve IDCs or
25476 * will create default attributes.
25477 */
25478 if ((xpathRes) || (defAttrOwnerElem)) {
25479 if (iattr->use->defValue != NULL) {
25480 iattr->value = (xmlChar *) iattr->use->defValue;
25481 iattr->val = iattr->use->defVal;
25482 } else {
25483 iattr->value = (xmlChar *) iattr->decl->defValue;
25484 iattr->val = iattr->decl->defVal;
25485 }
25486 /*
25487 * IDCs will consume the precomputed default value,
25488 * so we need to clone it.
25489 */
25490 if (iattr->val == NULL) {
25491 VERROR_INT("xmlSchemaVAttributesComplex",
25492 "default/fixed value on an attribute use was "
25493 "not precomputed");
25494 goto internal_error;
25495 }
25496 iattr->val = xmlSchemaCopyValue(iattr->val);
25497 if (iattr->val == NULL) {
25498 VERROR_INT("xmlSchemaVAttributesComplex",
25499 "calling xmlSchemaCopyValue()");
25500 goto internal_error;
25501 }
25502 }
25503 /*
25504 * PSVI: Add the default attribute to the current element.
25505 * VAL TODO: Should we use the *normalized* value? This currently
25506 * uses the *initial* value.
25507 */
25508
25509 if (defAttrOwnerElem) {
25510 xmlChar *normValue;
25511 const xmlChar *value;
25512
25513 value = iattr->value;
25514 /*
25515 * Normalize the value.
25516 */
25517 normValue = xmlSchemaNormalizeValue(iattr->typeDef,
25518 iattr->value);
25519 if (normValue != NULL)
25520 value = BAD_CAST normValue;
25521
25522 if (iattr->nsName == NULL) {
25523 if (xmlNewProp(defAttrOwnerElem,
25524 iattr->localName, value) == NULL) {
25525 VERROR_INT("xmlSchemaVAttributesComplex",
25526 "calling xmlNewProp()");
25527 if (normValue != NULL)
25528 xmlFree(normValue);
25529 goto internal_error;
25530 }
25531 } else {
25532 xmlNsPtr ns;
25533
25534 ns = xmlSearchNsByHref(defAttrOwnerElem->doc,
25535 defAttrOwnerElem, iattr->nsName);
25536 if (ns == NULL) {
25537 xmlChar prefix[12];
25538 int counter = 0;
25539
25540 /*
25541 * Create a namespace declaration on the validation
25542 * root node if no namespace declaration is in scope.
25543 */
25544 do {
25545 snprintf((char *) prefix, 12, "p%d", counter++);
25546 ns = xmlSearchNs(defAttrOwnerElem->doc,
25547 defAttrOwnerElem, BAD_CAST prefix);
25548 if (counter > 1000) {
25549 VERROR_INT(
25550 "xmlSchemaVAttributesComplex",
25551 "could not compute a ns prefix for a "
25552 "default/fixed attribute");
25553 if (normValue != NULL)
25554 xmlFree(normValue);
25555 goto internal_error;
25556 }
25557 } while (ns != NULL);
25558 ns = xmlNewNs(vctxt->validationRoot,
25559 iattr->nsName, BAD_CAST prefix);
25560 }
25561 /*
25562 * TODO:
25563 * http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005JulSep/0406.html
25564 * If we have QNames: do we need to ensure there's a
25565 * prefix defined for the QName?
25566 */
25567 xmlNewNsProp(defAttrOwnerElem, ns, iattr->localName, value);
25568 }
25569 if (normValue != NULL)
25570 xmlFree(normValue);
25571 }
25572 /*
25573 * Go directly to IDC evaluation.
25574 */
25575 goto eval_idcs;
25576 }
25577 /*
25578 * Validate the value.
25579 */
25580 if (vctxt->value != NULL) {
25581 /*
25582 * Free last computed value; just for safety reasons.
25583 */
25584 xmlSchemaFreeValue(vctxt->value);
25585 vctxt->value = NULL;
25586 }
25587 /*
25588 * Note that the attribute *use* can be unavailable, if
25589 * the attribute was a wild attribute.
25590 */
25591 if ((iattr->decl->flags & XML_SCHEMAS_ATTR_FIXED) ||
25592 ((iattr->use != NULL) &&
25593 (iattr->use->flags & XML_SCHEMAS_ATTR_FIXED)))
25594 fixed = 1;
25595 else
25596 fixed = 0;
25597 /*
25598 * SPEC (cvc-attribute)
25599 * (3) "The item's `normalized value` must be locally `valid`
25600 * with respect to that {type definition} as per
25601 * String Valid ($3.14.4)."
25602 *
25603 * VAL TODO: Do we already have the
25604 * "normalized attribute value" here?
25605 */
25606 if (xpathRes || fixed) {
25607 iattr->flags |= XML_SCHEMA_NODE_INFO_VALUE_NEEDED;
25608 /*
25609 * Request a computed value.
25610 */
25611 res = xmlSchemaVCheckCVCSimpleType(
25612 ACTXT_CAST vctxt,
25613 iattr->node, iattr->typeDef, iattr->value, &(iattr->val),
25614 1, 1, 0);
25615 } else {
25616 res = xmlSchemaVCheckCVCSimpleType(
25617 ACTXT_CAST vctxt,
25618 iattr->node, iattr->typeDef, iattr->value, NULL,
25619 1, 0, 0);
25620 }
25621
25622 if (res != 0) {
25623 if (res == -1) {
25624 VERROR_INT("xmlSchemaVAttributesComplex",
25625 "calling xmlSchemaStreamValidateSimpleTypeValue()");
25626 goto internal_error;
25627 }
25628 iattr->state = XML_SCHEMAS_ATTR_INVALID_VALUE;
25629 /*
25630 * SPEC PSVI Assessment Outcome (Attribute)
25631 * [validity] = "invalid"
25632 */
25633 goto eval_idcs;
25634 }
25635
25636 if (fixed) {
25637 /*
25638 * SPEC Attribute Locally Valid (Use) (cvc-au)
25639 * "For an attribute information item to be `valid`
25640 * with respect to an attribute use its *normalized*
25641 * value must match the *canonical* lexical
25642 * representation of the attribute use's {value
25643 * constraint}value, if it is present and fixed."
25644 *
25645 * VAL TODO: The requirement for the *canonical* value
25646 * will be removed in XML Schema 1.1.
25647 */
25648 /*
25649 * SPEC Attribute Locally Valid (cvc-attribute)
25650 * (4) "The item's *actual* value must match the *value* of
25651 * the {value constraint}, if it is present and fixed."
25652 */
25653 if (iattr->val == NULL) {
25654 /* VAL TODO: A value was not precomputed. */
25655 TODO
25656 goto eval_idcs;
25657 }
25658 if ((iattr->use != NULL) &&
25659 (iattr->use->defValue != NULL)) {
25660 if (iattr->use->defVal == NULL) {
25661 /* VAL TODO: A default value was not precomputed. */
25662 TODO
25663 goto eval_idcs;
25664 }
25665 iattr->vcValue = iattr->use->defValue;
25666 /*
25667 if (xmlSchemaCompareValuesWhtsp(attr->val,
25668 (xmlSchemaWhitespaceValueType) ws,
25669 attr->use->defVal,
25670 (xmlSchemaWhitespaceValueType) ws) != 0) {
25671 */
25672 if (! xmlSchemaAreValuesEqual(iattr->val, iattr->use->defVal))
25673 iattr->state = XML_SCHEMAS_ATTR_ERR_FIXED_VALUE;
25674 } else {
25675 if (iattr->decl->defVal == NULL) {
25676 /* VAL TODO: A default value was not precomputed. */
25677 TODO
25678 goto eval_idcs;
25679 }
25680 iattr->vcValue = iattr->decl->defValue;
25681 /*
25682 if (xmlSchemaCompareValuesWhtsp(attr->val,
25683 (xmlSchemaWhitespaceValueType) ws,
25684 attrDecl->defVal,
25685 (xmlSchemaWhitespaceValueType) ws) != 0) {
25686 */
25687 if (! xmlSchemaAreValuesEqual(iattr->val, iattr->decl->defVal))
25688 iattr->state = XML_SCHEMAS_ATTR_ERR_FIXED_VALUE;
25689 }
25690 /*
25691 * [validity] = "valid"
25692 */
25693 }
25694eval_idcs:
25695 /*
25696 * Evaluate IDCs.
25697 */
25698 if (xpathRes) {
25699 if (xmlSchemaXPathProcessHistory(vctxt,
25700 vctxt->depth +1) == -1) {
25701 VERROR_INT("xmlSchemaVAttributesComplex",
25702 "calling xmlSchemaXPathEvaluate()");
25703 goto internal_error;
25704 }
25705 } else if (vctxt->xpathStates != NULL)
25706 xmlSchemaXPathPop(vctxt);
25707 }
25708
25709 /*
25710 * Report errors.
25711 */
25712 for (i = 0; i < vctxt->nbAttrInfos; i++) {
25713 iattr = vctxt->attrInfos[i];
25714 if ((iattr->state == XML_SCHEMAS_ATTR_META) ||
25715 (iattr->state == XML_SCHEMAS_ATTR_ASSESSED) ||
25716 (iattr->state == XML_SCHEMAS_ATTR_WILD_SKIP) ||
25717 (iattr->state == XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL))
25718 continue;
25719 ACTIVATE_ATTRIBUTE(iattr);
25720 switch (iattr->state) {
25721 case XML_SCHEMAS_ATTR_ERR_MISSING: {
25722 xmlChar *str = NULL;
25723 ACTIVATE_ELEM;
25724 xmlSchemaCustomErr(ACTXT_CAST vctxt,
25726 "The attribute '%s' is required but missing",
25727 xmlSchemaFormatQName(&str,
25728 iattr->decl->targetNamespace,
25729 iattr->decl->name),
25730 NULL);
25731 FREE_AND_NULL(str)
25732 break;
25733 }
25734 case XML_SCHEMAS_ATTR_ERR_NO_TYPE:
25736 "The type definition is absent");
25737 break;
25738 case XML_SCHEMAS_ATTR_ERR_FIXED_VALUE:
25739 xmlSchemaCustomErr(ACTXT_CAST vctxt,
25741 "The value '%s' does not match the fixed "
25742 "value constraint '%s'",
25743 iattr->value, iattr->vcValue);
25744 break;
25745 case XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL:
25747 "No matching global attribute declaration available, but "
25748 "demanded by the strict wildcard");
25749 break;
25750 case XML_SCHEMAS_ATTR_UNKNOWN:
25751 if (iattr->metaType)
25752 break;
25753 /*
25754 * MAYBE VAL TODO: One might report different error messages
25755 * for the following errors.
25756 */
25757 if (type->attributeWildcard == NULL) {
25758 xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt,
25760 } else {
25761 xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt,
25763 }
25764 break;
25765 default:
25766 break;
25767 }
25768 }
25769
25770 ACTIVATE_ELEM;
25771 return (0);
25772internal_error:
25773 ACTIVATE_ELEM;
25774 return (-1);
25775}
25776
25777static int
25778xmlSchemaValidateElemWildcard(xmlSchemaValidCtxtPtr vctxt,
25779 int *skip)
25780{
25781 xmlSchemaWildcardPtr wild = (xmlSchemaWildcardPtr) vctxt->inode->decl;
25782 /*
25783 * The namespace of the element was already identified to be
25784 * matching the wildcard.
25785 */
25786 if ((skip == NULL) || (wild == NULL) ||
25787 (wild->type != XML_SCHEMA_TYPE_ANY)) {
25788 VERROR_INT("xmlSchemaValidateElemWildcard",
25789 "bad arguments");
25790 return (-1);
25791 }
25792 *skip = 0;
25793 if (wild->processContents == XML_SCHEMAS_ANY_SKIP) {
25794 /*
25795 * URGENT VAL TODO: Either we need to position the stream to the
25796 * next sibling, or walk the whole subtree.
25797 */
25798 *skip = 1;
25799 return (0);
25800 }
25801 {
25802 xmlSchemaElementPtr decl = NULL;
25803
25804 decl = xmlSchemaGetElem(vctxt->schema,
25805 vctxt->inode->localName, vctxt->inode->nsName);
25806 if (decl != NULL) {
25807 vctxt->inode->decl = decl;
25808 return (0);
25809 }
25810 }
25811 if (wild->processContents == XML_SCHEMAS_ANY_STRICT) {
25812 /* VAL TODO: Change to proper error code. */
25813 VERROR(XML_SCHEMAV_CVC_ELT_1, NULL, /* WXS_BASIC_CAST wild */
25814 "No matching global element declaration available, but "
25815 "demanded by the strict wildcard");
25816 return (vctxt->err);
25817 }
25818 if (vctxt->nbAttrInfos != 0) {
25819 xmlSchemaAttrInfoPtr iattr;
25820 /*
25821 * SPEC Validation Rule: Schema-Validity Assessment (Element)
25822 * (1.2.1.2.1) - (1.2.1.2.3 )
25823 *
25824 * Use the xsi:type attribute for the type definition.
25825 */
25826 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
25827 XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
25828 if (iattr != NULL) {
25829 if (xmlSchemaProcessXSIType(vctxt, iattr,
25830 &(vctxt->inode->typeDef), NULL) == -1) {
25831 VERROR_INT("xmlSchemaValidateElemWildcard",
25832 "calling xmlSchemaProcessXSIType() to "
25833 "process the attribute 'xsi:nil'");
25834 return (-1);
25835 }
25836 /*
25837 * Don't return an error on purpose.
25838 */
25839 return (0);
25840 }
25841 }
25842 /*
25843 * SPEC Validation Rule: Schema-Validity Assessment (Element)
25844 *
25845 * Fallback to "anyType".
25846 */
25847 vctxt->inode->typeDef =
25848 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
25849 return (0);
25850}
25851
25852/*
25853* xmlSchemaCheckCOSValidDefault:
25854*
25855* This will be called if: not nilled, no content and a default/fixed
25856* value is provided.
25857*/
25858
25859static int
25860xmlSchemaCheckCOSValidDefault(xmlSchemaValidCtxtPtr vctxt,
25861 const xmlChar *value,
25862 xmlSchemaValPtr *val)
25863{
25864 int ret = 0;
25865 xmlSchemaNodeInfoPtr inode = vctxt->inode;
25866
25867 /*
25868 * cos-valid-default:
25869 * Schema Component Constraint: Element Default Valid (Immediate)
25870 * For a string to be a valid default with respect to a type
25871 * definition the appropriate case among the following must be true:
25872 */
25873 if WXS_IS_COMPLEX(inode->typeDef) {
25874 /*
25875 * Complex type.
25876 *
25877 * SPEC (2.1) "its {content type} must be a simple type definition
25878 * or mixed."
25879 * SPEC (2.2.2) "If the {content type} is mixed, then the {content
25880 * type}'s particle must be `emptiable` as defined by
25881 * Particle Emptiable ($3.9.6)."
25882 */
25883 if ((! WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) &&
25884 ((! WXS_HAS_MIXED_CONTENT(inode->typeDef)) ||
25885 (! WXS_EMPTIABLE(inode->typeDef)))) {
25887 /* NOTE that this covers (2.2.2) as well. */
25888 VERROR(ret, NULL,
25889 "For a string to be a valid default, the type definition "
25890 "must be a simple type or a complex type with simple content "
25891 "or mixed content and a particle emptiable");
25892 return(ret);
25893 }
25894 }
25895 /*
25896 * 1 If the type definition is a simple type definition, then the string
25897 * must be `valid` with respect to that definition as defined by String
25898 * Valid ($3.14.4).
25899 *
25900 * AND
25901 *
25902 * 2.2.1 If the {content type} is a simple type definition, then the
25903 * string must be `valid` with respect to that simple type definition
25904 * as defined by String Valid ($3.14.4).
25905 */
25906 if (WXS_IS_SIMPLE(inode->typeDef)) {
25907
25908 ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST vctxt,
25909 NULL, inode->typeDef, value, val, 1, 1, 0);
25910
25911 } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
25912
25913 ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST vctxt,
25914 NULL, inode->typeDef->contentTypeDef, value, val, 1, 1, 0);
25915 }
25916 if (ret < 0) {
25917 VERROR_INT("xmlSchemaCheckCOSValidDefault",
25918 "calling xmlSchemaVCheckCVCSimpleType()");
25919 }
25920 return (ret);
25921}
25922
25923static void
25924xmlSchemaVContentModelCallback(xmlRegExecCtxtPtr exec ATTRIBUTE_UNUSED,
25926 void *transdata, void *inputdata)
25927{
25928 xmlSchemaElementPtr item = (xmlSchemaElementPtr) transdata;
25929 xmlSchemaNodeInfoPtr inode = (xmlSchemaNodeInfoPtr) inputdata;
25930 inode->decl = item;
25931}
25932
25933static int
25934xmlSchemaValidatorPushElem(xmlSchemaValidCtxtPtr vctxt)
25935{
25936 vctxt->inode = xmlSchemaGetFreshElemInfo(vctxt);
25937 if (vctxt->inode == NULL) {
25938 VERROR_INT("xmlSchemaValidatorPushElem",
25939 "calling xmlSchemaGetFreshElemInfo()");
25940 return (-1);
25941 }
25942 vctxt->nbAttrInfos = 0;
25943 return (0);
25944}
25945
25946static int
25947xmlSchemaVCheckINodeDataType(xmlSchemaValidCtxtPtr vctxt,
25948 xmlSchemaNodeInfoPtr inode,
25949 xmlSchemaTypePtr type,
25950 const xmlChar *value)
25951{
25952 if (inode->flags & XML_SCHEMA_NODE_INFO_VALUE_NEEDED)
25953 return (xmlSchemaVCheckCVCSimpleType(
25954 ACTXT_CAST vctxt, NULL,
25955 type, value, &(inode->val), 1, 1, 0));
25956 else
25957 return (xmlSchemaVCheckCVCSimpleType(
25958 ACTXT_CAST vctxt, NULL,
25959 type, value, NULL, 1, 0, 0));
25960}
25961
25962
25963
25964/*
25965* Process END of element.
25966*/
25967static int
25968xmlSchemaValidatorPopElem(xmlSchemaValidCtxtPtr vctxt)
25969{
25970 int ret = 0;
25971 xmlSchemaNodeInfoPtr inode = vctxt->inode;
25972
25973 if (vctxt->nbAttrInfos != 0)
25974 xmlSchemaClearAttrInfos(vctxt);
25975 if (inode->flags & XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED) {
25976 /*
25977 * This element was not expected;
25978 * we will not validate child elements of broken parents.
25979 * Skip validation of all content of the parent.
25980 */
25981 vctxt->skipDepth = vctxt->depth -1;
25982 goto end_elem;
25983 }
25984 if ((inode->typeDef == NULL) ||
25985 (inode->flags & XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE)) {
25986 /*
25987 * 1. the type definition might be missing if the element was
25988 * error prone
25989 * 2. it might be abstract.
25990 */
25991 goto end_elem;
25992 }
25993 /*
25994 * Check the content model.
25995 */
25996 if ((inode->typeDef->contentType == XML_SCHEMA_CONTENT_MIXED) ||
25997 (inode->typeDef->contentType == XML_SCHEMA_CONTENT_ELEMENTS)) {
25998
25999 /*
26000 * Workaround for "anyType".
26001 */
26002 if (inode->typeDef->builtInType == XML_SCHEMAS_ANYTYPE)
26003 goto character_content;
26004
26005 if ((inode->flags & XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT) == 0) {
26006 xmlChar *values[10];
26007 int terminal, nbval = 10, nbneg;
26008
26009 if (inode->regexCtxt == NULL) {
26010 /*
26011 * Create the regex context.
26012 */
26013 inode->regexCtxt =
26014 xmlRegNewExecCtxt(inode->typeDef->contModel,
26015 xmlSchemaVContentModelCallback, vctxt);
26016 if (inode->regexCtxt == NULL) {
26017 VERROR_INT("xmlSchemaValidatorPopElem",
26018 "failed to create a regex context");
26019 goto internal_error;
26020 }
26021 }
26022
26023 /*
26024 * Do not check further content if the node has been nilled
26025 */
26026 if (INODE_NILLED(inode)) {
26027 ret = 0;
26028 goto skip_nilled;
26029 }
26030
26031 /*
26032 * Get hold of the still expected content, since a further
26033 * call to xmlRegExecPushString() will lose this information.
26034 */
26035 xmlRegExecNextValues(inode->regexCtxt,
26036 &nbval, &nbneg, &values[0], &terminal);
26037 ret = xmlRegExecPushString(inode->regexCtxt, NULL, NULL);
26038 if ((ret<0) || ((ret==0) && (!INODE_NILLED(inode)))) {
26039 /*
26040 * Still missing something.
26041 */
26042 ret = 1;
26043 inode->flags |=
26044 XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT;
26045 xmlSchemaComplexTypeErr(ACTXT_CAST vctxt,
26047 "Missing child element(s)",
26048 nbval, nbneg, values);
26049 } else {
26050 /*
26051 * Content model is satisfied.
26052 */
26053 ret = 0;
26054 }
26055
26056 }
26057 }
26058
26059skip_nilled:
26060
26061 if (inode->typeDef->contentType == XML_SCHEMA_CONTENT_ELEMENTS)
26062 goto end_elem;
26063
26064character_content:
26065
26066 if (vctxt->value != NULL) {
26067 xmlSchemaFreeValue(vctxt->value);
26068 vctxt->value = NULL;
26069 }
26070 /*
26071 * Check character content.
26072 */
26073 if (inode->decl == NULL) {
26074 /*
26075 * Speedup if no declaration exists.
26076 */
26077 if (WXS_IS_SIMPLE(inode->typeDef)) {
26078 ret = xmlSchemaVCheckINodeDataType(vctxt,
26079 inode, inode->typeDef, inode->value);
26080 } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
26081 ret = xmlSchemaVCheckINodeDataType(vctxt,
26082 inode, inode->typeDef->contentTypeDef,
26083 inode->value);
26084 }
26085 if (ret < 0) {
26086 VERROR_INT("xmlSchemaValidatorPopElem",
26087 "calling xmlSchemaVCheckCVCSimpleType()");
26088 goto internal_error;
26089 }
26090 goto end_elem;
26091 }
26092 /*
26093 * cvc-elt (3.3.4) : 5
26094 * The appropriate case among the following must be true:
26095 */
26096 /*
26097 * cvc-elt (3.3.4) : 5.1
26098 * If the declaration has a {value constraint},
26099 * the item has neither element nor character [children] and
26100 * clause 3.2 has not applied, then all of the following must be true:
26101 */
26102 if ((inode->decl->value != NULL) &&
26103 (inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY) &&
26104 (! INODE_NILLED(inode))) {
26105 /*
26106 * cvc-elt (3.3.4) : 5.1.1
26107 * If the `actual type definition` is a `local type definition`
26108 * then the canonical lexical representation of the {value constraint}
26109 * value must be a valid default for the `actual type definition` as
26110 * defined in Element Default Valid (Immediate) ($3.3.6).
26111 */
26112 /*
26113 * NOTE: 'local' above means types acquired by xsi:type.
26114 * NOTE: Although the *canonical* value is stated, it is not
26115 * relevant if canonical or not. Additionally XML Schema 1.1
26116 * will removed this requirement as well.
26117 */
26118 if (inode->flags & XML_SCHEMA_ELEM_INFO_LOCAL_TYPE) {
26119
26120 ret = xmlSchemaCheckCOSValidDefault(vctxt,
26121 inode->decl->value, &(inode->val));
26122 if (ret != 0) {
26123 if (ret < 0) {
26124 VERROR_INT("xmlSchemaValidatorPopElem",
26125 "calling xmlSchemaCheckCOSValidDefault()");
26126 goto internal_error;
26127 }
26128 goto end_elem;
26129 }
26130 /*
26131 * Stop here, to avoid redundant validation of the value
26132 * (see following).
26133 */
26134 goto default_psvi;
26135 }
26136 /*
26137 * cvc-elt (3.3.4) : 5.1.2
26138 * The element information item with the canonical lexical
26139 * representation of the {value constraint} value used as its
26140 * `normalized value` must be `valid` with respect to the
26141 * `actual type definition` as defined by Element Locally Valid (Type)
26142 * ($3.3.4).
26143 */
26144 if (WXS_IS_SIMPLE(inode->typeDef)) {
26145 ret = xmlSchemaVCheckINodeDataType(vctxt,
26146 inode, inode->typeDef, inode->decl->value);
26147 } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
26148 ret = xmlSchemaVCheckINodeDataType(vctxt,
26149 inode, inode->typeDef->contentTypeDef,
26150 inode->decl->value);
26151 }
26152 if (ret != 0) {
26153 if (ret < 0) {
26154 VERROR_INT("xmlSchemaValidatorPopElem",
26155 "calling xmlSchemaVCheckCVCSimpleType()");
26156 goto internal_error;
26157 }
26158 goto end_elem;
26159 }
26160
26161default_psvi:
26162 /*
26163 * PSVI: Create a text node on the instance element.
26164 */
26165 if ((vctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) &&
26166 (inode->node != NULL)) {
26167 xmlNodePtr textChild;
26168 xmlChar *normValue;
26169 /*
26170 * VAL TODO: Normalize the value.
26171 */
26172 normValue = xmlSchemaNormalizeValue(inode->typeDef,
26173 inode->decl->value);
26174 if (normValue != NULL) {
26175 textChild = xmlNewDocText(inode->node->doc,
26176 BAD_CAST normValue);
26177 xmlFree(normValue);
26178 } else
26179 textChild = xmlNewDocText(inode->node->doc,
26180 inode->decl->value);
26181 if (textChild == NULL) {
26182 VERROR_INT("xmlSchemaValidatorPopElem",
26183 "calling xmlNewDocText()");
26184 goto internal_error;
26185 } else
26186 xmlAddChild(inode->node, textChild);
26187 }
26188
26189 } else if (! INODE_NILLED(inode)) {
26190 /*
26191 * 5.2.1 The element information item must be `valid` with respect
26192 * to the `actual type definition` as defined by Element Locally
26193 * Valid (Type) ($3.3.4).
26194 */
26195 if (WXS_IS_SIMPLE(inode->typeDef)) {
26196 /*
26197 * SPEC (cvc-type) (3.1)
26198 * "If the type definition is a simple type definition, ..."
26199 * (3.1.3) "If clause 3.2 of Element Locally Valid
26200 * (Element) ($3.3.4) did not apply, then the `normalized value`
26201 * must be `valid` with respect to the type definition as defined
26202 * by String Valid ($3.14.4).
26203 */
26204 ret = xmlSchemaVCheckINodeDataType(vctxt,
26205 inode, inode->typeDef, inode->value);
26206 } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
26207 /*
26208 * SPEC (cvc-type) (3.2) "If the type definition is a complex type
26209 * definition, then the element information item must be
26210 * `valid` with respect to the type definition as per
26211 * Element Locally Valid (Complex Type) ($3.4.4);"
26212 *
26213 * SPEC (cvc-complex-type) (2.2)
26214 * "If the {content type} is a simple type definition, ...
26215 * the `normalized value` of the element information item is
26216 * `valid` with respect to that simple type definition as
26217 * defined by String Valid ($3.14.4)."
26218 */
26219 ret = xmlSchemaVCheckINodeDataType(vctxt,
26220 inode, inode->typeDef->contentTypeDef, inode->value);
26221 }
26222 if (ret != 0) {
26223 if (ret < 0) {
26224 VERROR_INT("xmlSchemaValidatorPopElem",
26225 "calling xmlSchemaVCheckCVCSimpleType()");
26226 goto internal_error;
26227 }
26228 goto end_elem;
26229 }
26230 /*
26231 * 5.2.2 If there is a fixed {value constraint} and clause 3.2 has
26232 * not applied, all of the following must be true:
26233 */
26234 if ((inode->decl->value != NULL) &&
26235 (inode->decl->flags & XML_SCHEMAS_ELEM_FIXED)) {
26236
26237 /*
26238 * TODO: We will need a computed value, when comparison is
26239 * done on computed values.
26240 */
26241 /*
26242 * 5.2.2.1 The element information item must have no element
26243 * information item [children].
26244 */
26245 if (inode->flags &
26246 XML_SCHEMA_ELEM_INFO_HAS_ELEM_CONTENT) {
26248 VERROR(ret, NULL,
26249 "The content must not contain element nodes since "
26250 "there is a fixed value constraint");
26251 goto end_elem;
26252 } else {
26253 /*
26254 * 5.2.2.2 The appropriate case among the following must
26255 * be true:
26256 */
26257 if (WXS_HAS_MIXED_CONTENT(inode->typeDef)) {
26258 /*
26259 * 5.2.2.2.1 If the {content type} of the `actual type
26260 * definition` is mixed, then the *initial value* of the
26261 * item must match the canonical lexical representation
26262 * of the {value constraint} value.
26263 *
26264 * ... the *initial value* of an element information
26265 * item is the string composed of, in order, the
26266 * [character code] of each character information item in
26267 * the [children] of that element information item.
26268 */
26269 if (! xmlStrEqual(inode->value, inode->decl->value)){
26270 /*
26271 * VAL TODO: Report invalid & expected values as well.
26272 * VAL TODO: Implement the canonical stuff.
26273 */
26275 xmlSchemaCustomErr(ACTXT_CAST vctxt,
26276 ret, NULL, NULL,
26277 "The initial value '%s' does not match the fixed "
26278 "value constraint '%s'",
26279 inode->value, inode->decl->value);
26280 goto end_elem;
26281 }
26282 } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
26283 /*
26284 * 5.2.2.2.2 If the {content type} of the `actual type
26285 * definition` is a simple type definition, then the
26286 * *actual value* of the item must match the canonical
26287 * lexical representation of the {value constraint} value.
26288 */
26289 /*
26290 * VAL TODO: *actual value* is the normalized value, impl.
26291 * this.
26292 * VAL TODO: Report invalid & expected values as well.
26293 * VAL TODO: Implement a comparison with the computed values.
26294 */
26295 if (! xmlStrEqual(inode->value,
26296 inode->decl->value)) {
26298 xmlSchemaCustomErr(ACTXT_CAST vctxt,
26299 ret, NULL, NULL,
26300 "The actual value '%s' does not match the fixed "
26301 "value constraint '%s'",
26302 inode->value,
26303 inode->decl->value);
26304 goto end_elem;
26305 }
26306 }
26307 }
26308 }
26309 }
26310
26311end_elem:
26312 if (vctxt->depth < 0) {
26313 /* TODO: raise error? */
26314 return (0);
26315 }
26316 if (vctxt->depth == vctxt->skipDepth)
26317 vctxt->skipDepth = -1;
26318 /*
26319 * Evaluate the history of XPath state objects.
26320 */
26321 if (inode->appliedXPath &&
26322 (xmlSchemaXPathProcessHistory(vctxt, vctxt->depth) == -1))
26323 goto internal_error;
26324 /*
26325 * MAYBE TODO:
26326 * SPEC (6) "The element information item must be `valid` with
26327 * respect to each of the {identity-constraint definitions} as per
26328 * Identity-constraint Satisfied ($3.11.4)."
26329 */
26330 /*
26331 * PSVI TODO: If we expose IDC node-tables via PSVI then the tables
26332 * need to be built in any case.
26333 * We will currently build IDC node-tables and bubble them only if
26334 * keyrefs do exist.
26335 */
26336
26337 /*
26338 * Add the current IDC target-nodes to the IDC node-tables.
26339 */
26340 if ((inode->idcMatchers != NULL) &&
26341 (vctxt->hasKeyrefs || vctxt->createIDCNodeTables))
26342 {
26343 if (xmlSchemaIDCFillNodeTables(vctxt, inode) == -1)
26344 goto internal_error;
26345 }
26346 /*
26347 * Validate IDC keyrefs.
26348 */
26349 if (vctxt->inode->hasKeyrefs)
26350 if (xmlSchemaCheckCVCIDCKeyRef(vctxt) == -1)
26351 goto internal_error;
26352 /*
26353 * Merge/free the IDC table.
26354 */
26355 if (inode->idcTable != NULL) {
26356 if ((vctxt->depth > 0) &&
26357 (vctxt->hasKeyrefs || vctxt->createIDCNodeTables))
26358 {
26359 /*
26360 * Merge the IDC node table with the table of the parent node.
26361 */
26362 if (xmlSchemaBubbleIDCNodeTables(vctxt) == -1)
26363 goto internal_error;
26364 }
26365 }
26366 /*
26367 * Clear the current ielem.
26368 * VAL TODO: Don't free the PSVI IDC tables if they are
26369 * requested for the PSVI.
26370 */
26371 xmlSchemaClearElemInfo(vctxt, inode);
26372 /*
26373 * Skip further processing if we are on the validation root.
26374 */
26375 if (vctxt->depth == 0) {
26376 vctxt->depth--;
26377 vctxt->inode = NULL;
26378 return (0);
26379 }
26380 /*
26381 * Reset the keyrefDepth if needed.
26382 */
26383 if (vctxt->aidcs != NULL) {
26384 xmlSchemaIDCAugPtr aidc = vctxt->aidcs;
26385 do {
26386 if (aidc->keyrefDepth == vctxt->depth) {
26387 /*
26388 * A 'keyrefDepth' of a key/unique IDC matches the current
26389 * depth, this means that we are leaving the scope of the
26390 * top-most keyref IDC which refers to this IDC.
26391 */
26392 aidc->keyrefDepth = -1;
26393 }
26394 aidc = aidc->next;
26395 } while (aidc != NULL);
26396 }
26397 vctxt->depth--;
26398 vctxt->inode = vctxt->elemInfos[vctxt->depth];
26399 /*
26400 * VAL TODO: 7 If the element information item is the `validation root`, it must be
26401 * `valid` per Validation Root Valid (ID/IDREF) ($3.3.4).
26402 */
26403 return (ret);
26404
26405internal_error:
26406 vctxt->err = -1;
26407 return (-1);
26408}
26409
26410/*
26411* 3.4.4 Complex Type Definition Validation Rules
26412* Validation Rule: Element Locally Valid (Complex Type) (cvc-complex-type)
26413*/
26414static int
26415xmlSchemaValidateChildElem(xmlSchemaValidCtxtPtr vctxt)
26416{
26417 xmlSchemaNodeInfoPtr pielem;
26418 xmlSchemaTypePtr ptype;
26419 int ret = 0;
26420
26421 if (vctxt->depth <= 0) {
26422 VERROR_INT("xmlSchemaValidateChildElem",
26423 "not intended for the validation root");
26424 return (-1);
26425 }
26426 pielem = vctxt->elemInfos[vctxt->depth -1];
26427 if (pielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
26428 pielem->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
26429 /*
26430 * Handle 'nilled' elements.
26431 */
26432 if (INODE_NILLED(pielem)) {
26433 /*
26434 * SPEC (cvc-elt) (3.3.4) : (3.2.1)
26435 */
26436 ACTIVATE_PARENT_ELEM;
26438 VERROR(ret, NULL,
26439 "Neither character nor element content is allowed, "
26440 "because the element was 'nilled'");
26441 ACTIVATE_ELEM;
26442 goto unexpected_elem;
26443 }
26444
26445 ptype = pielem->typeDef;
26446
26447 if (ptype->builtInType == XML_SCHEMAS_ANYTYPE) {
26448 /*
26449 * Workaround for "anyType": we have currently no content model
26450 * assigned for "anyType", so handle it explicitly.
26451 * "anyType" has an unbounded, lax "any" wildcard.
26452 */
26453 vctxt->inode->decl = xmlSchemaGetElem(vctxt->schema,
26454 vctxt->inode->localName,
26455 vctxt->inode->nsName);
26456
26457 if (vctxt->inode->decl == NULL) {
26458 xmlSchemaAttrInfoPtr iattr;
26459 /*
26460 * Process "xsi:type".
26461 * SPEC (cvc-assess-elt) (1.2.1.2.1) - (1.2.1.2.3)
26462 */
26463 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
26464 XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
26465 if (iattr != NULL) {
26466 ret = xmlSchemaProcessXSIType(vctxt, iattr,
26467 &(vctxt->inode->typeDef), NULL);
26468 if (ret != 0) {
26469 if (ret == -1) {
26470 VERROR_INT("xmlSchemaValidateChildElem",
26471 "calling xmlSchemaProcessXSIType() to "
26472 "process the attribute 'xsi:nil'");
26473 return (-1);
26474 }
26475 return (ret);
26476 }
26477 } else {
26478 /*
26479 * Fallback to "anyType".
26480 *
26481 * SPEC (cvc-assess-elt)
26482 * "If the item cannot be `strictly assessed`, [...]
26483 * an element information item's schema validity may be laxly
26484 * assessed if its `context-determined declaration` is not
26485 * skip by `validating` with respect to the `ur-type
26486 * definition` as per Element Locally Valid (Type) ($3.3.4)."
26487 */
26488 vctxt->inode->typeDef =
26489 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
26490 }
26491 }
26492 return (0);
26493 }
26494
26495 switch (ptype->contentType) {
26496 case XML_SCHEMA_CONTENT_EMPTY:
26497 /*
26498 * SPEC (2.1) "If the {content type} is empty, then the
26499 * element information item has no character or element
26500 * information item [children]."
26501 */
26502 ACTIVATE_PARENT_ELEM
26504 VERROR(ret, NULL,
26505 "Element content is not allowed, "
26506 "because the content type is empty");
26507 ACTIVATE_ELEM
26508 goto unexpected_elem;
26509 break;
26510
26511 case XML_SCHEMA_CONTENT_MIXED:
26512 case XML_SCHEMA_CONTENT_ELEMENTS: {
26513 xmlRegExecCtxtPtr regexCtxt;
26514 xmlChar *values[10];
26515 int terminal, nbval = 10, nbneg;
26516
26517 /* VAL TODO: Optimized "anyType" validation.*/
26518
26519 if (ptype->contModel == NULL) {
26520 VERROR_INT("xmlSchemaValidateChildElem",
26521 "type has elem content but no content model");
26522 return (-1);
26523 }
26524 /*
26525 * Safety belt for evaluation if the cont. model was already
26526 * examined to be invalid.
26527 */
26528 if (pielem->flags & XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT) {
26529 VERROR_INT("xmlSchemaValidateChildElem",
26530 "validating elem, but elem content is already invalid");
26531 return (-1);
26532 }
26533
26534 regexCtxt = pielem->regexCtxt;
26535 if (regexCtxt == NULL) {
26536 /*
26537 * Create the regex context.
26538 */
26539 regexCtxt = xmlRegNewExecCtxt(ptype->contModel,
26540 xmlSchemaVContentModelCallback, vctxt);
26541 if (regexCtxt == NULL) {
26542 VERROR_INT("xmlSchemaValidateChildElem",
26543 "failed to create a regex context");
26544 return (-1);
26545 }
26546 pielem->regexCtxt = regexCtxt;
26547 }
26548
26549 /*
26550 * SPEC (2.4) "If the {content type} is element-only or mixed,
26551 * then the sequence of the element information item's
26552 * element information item [children], if any, taken in
26553 * order, is `valid` with respect to the {content type}'s
26554 * particle, as defined in Element Sequence Locally Valid
26555 * (Particle) ($3.9.4)."
26556 */
26557 ret = xmlRegExecPushString2(regexCtxt,
26558 vctxt->inode->localName,
26559 vctxt->inode->nsName,
26560 vctxt->inode);
26561 if (vctxt->err == XML_SCHEMAV_INTERNAL) {
26562 VERROR_INT("xmlSchemaValidateChildElem",
26563 "calling xmlRegExecPushString2()");
26564 return (-1);
26565 }
26566 if (ret < 0) {
26567 xmlRegExecErrInfo(regexCtxt, NULL, &nbval, &nbneg,
26568 &values[0], &terminal);
26569 xmlSchemaComplexTypeErr(ACTXT_CAST vctxt,
26571 "This element is not expected",
26572 nbval, nbneg, values);
26573 ret = vctxt->err;
26574 goto unexpected_elem;
26575 } else
26576 ret = 0;
26577 }
26578 break;
26579 case XML_SCHEMA_CONTENT_SIMPLE:
26580 case XML_SCHEMA_CONTENT_BASIC:
26581 ACTIVATE_PARENT_ELEM
26582 if (WXS_IS_COMPLEX(ptype)) {
26583 /*
26584 * SPEC (cvc-complex-type) (2.2)
26585 * "If the {content type} is a simple type definition, then
26586 * the element information item has no element information
26587 * item [children], ..."
26588 */
26590 VERROR(ret, NULL, "Element content is not allowed, "
26591 "because the content type is a simple type definition");
26592 } else {
26593 /*
26594 * SPEC (cvc-type) (3.1.2) "The element information item must
26595 * have no element information item [children]."
26596 */
26598 VERROR(ret, NULL, "Element content is not allowed, "
26599 "because the type definition is simple");
26600 }
26601 ACTIVATE_ELEM
26602 ret = vctxt->err;
26603 goto unexpected_elem;
26604 break;
26605
26606 default:
26607 break;
26608 }
26609 return (ret);
26610unexpected_elem:
26611 /*
26612 * Pop this element and set the skipDepth to skip
26613 * all further content of the parent element.
26614 */
26615 vctxt->skipDepth = vctxt->depth;
26616 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED;
26617 pielem->flags |= XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT;
26618 return (ret);
26619}
26620
26621#define XML_SCHEMA_PUSH_TEXT_PERSIST 1
26622#define XML_SCHEMA_PUSH_TEXT_CREATED 2
26623#define XML_SCHEMA_PUSH_TEXT_VOLATILE 3
26624
26625static int
26626xmlSchemaVPushText(xmlSchemaValidCtxtPtr vctxt,
26627 int nodeType, const xmlChar *value, int len,
26628 int mode, int *consumed)
26629{
26630 /*
26631 * Unfortunately we have to duplicate the text sometimes.
26632 * OPTIMIZE: Maybe we could skip it, if:
26633 * 1. content type is simple
26634 * 2. whitespace is "collapse"
26635 * 3. it consists of whitespace only
26636 *
26637 * Process character content.
26638 */
26639 if (consumed != NULL)
26640 *consumed = 0;
26641 if (INODE_NILLED(vctxt->inode)) {
26642 /*
26643 * SPEC cvc-elt (3.3.4 - 3.2.1)
26644 * "The element information item must have no character or
26645 * element information item [children]."
26646 */
26648 "Neither character nor element content is allowed "
26649 "because the element is 'nilled'");
26650 return (vctxt->err);
26651 }
26652 /*
26653 * SPEC (2.1) "If the {content type} is empty, then the
26654 * element information item has no character or element
26655 * information item [children]."
26656 */
26657 if (vctxt->inode->typeDef->contentType ==
26658 XML_SCHEMA_CONTENT_EMPTY) {
26660 "Character content is not allowed, "
26661 "because the content type is empty");
26662 return (vctxt->err);
26663 }
26664
26665 if (vctxt->inode->typeDef->contentType ==
26666 XML_SCHEMA_CONTENT_ELEMENTS) {
26667 if ((nodeType != XML_TEXT_NODE) ||
26668 (! xmlSchemaIsBlank((xmlChar *) value, len))) {
26669 /*
26670 * SPEC cvc-complex-type (2.3)
26671 * "If the {content type} is element-only, then the
26672 * element information item has no character information
26673 * item [children] other than those whose [character
26674 * code] is defined as a white space in [XML 1.0 (Second
26675 * Edition)]."
26676 */
26678 "Character content other than whitespace is not allowed "
26679 "because the content type is 'element-only'");
26680 return (vctxt->err);
26681 }
26682 return (0);
26683 }
26684
26685 if ((value == NULL) || (value[0] == 0))
26686 return (0);
26687 /*
26688 * Save the value.
26689 * NOTE that even if the content type is *mixed*, we need the
26690 * *initial value* for default/fixed value constraints.
26691 */
26692 if ((vctxt->inode->typeDef->contentType == XML_SCHEMA_CONTENT_MIXED) &&
26693 ((vctxt->inode->decl == NULL) ||
26694 (vctxt->inode->decl->value == NULL)))
26695 return (0);
26696
26697 if (vctxt->inode->value == NULL) {
26698 /*
26699 * Set the value.
26700 */
26701 switch (mode) {
26702 case XML_SCHEMA_PUSH_TEXT_PERSIST:
26703 /*
26704 * When working on a tree.
26705 */
26706 vctxt->inode->value = value;
26707 break;
26708 case XML_SCHEMA_PUSH_TEXT_CREATED:
26709 /*
26710 * When working with the reader.
26711 * The value will be freed by the element info.
26712 */
26713 vctxt->inode->value = value;
26714 if (consumed != NULL)
26715 *consumed = 1;
26716 vctxt->inode->flags |=
26717 XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
26718 break;
26719 case XML_SCHEMA_PUSH_TEXT_VOLATILE:
26720 /*
26721 * When working with SAX.
26722 * The value will be freed by the element info.
26723 */
26724 if (len != -1)
26725 vctxt->inode->value = BAD_CAST xmlStrndup(value, len);
26726 else
26727 vctxt->inode->value = BAD_CAST xmlStrdup(value);
26728 vctxt->inode->flags |=
26729 XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
26730 break;
26731 default:
26732 break;
26733 }
26734 } else {
26735 if (len < 0)
26736 len = xmlStrlen(value);
26737 /*
26738 * Concat the value.
26739 */
26740 if (vctxt->inode->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
26741 vctxt->inode->value = BAD_CAST xmlStrncat(
26742 (xmlChar *) vctxt->inode->value, value, len);
26743 } else {
26744 vctxt->inode->value =
26745 BAD_CAST xmlStrncatNew(vctxt->inode->value, value, len);
26746 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
26747 }
26748 }
26749
26750 return (0);
26751}
26752
26753static int
26754xmlSchemaValidateElem(xmlSchemaValidCtxtPtr vctxt)
26755{
26756 int ret = 0;
26757
26758 if ((vctxt->skipDepth != -1) &&
26759 (vctxt->depth >= vctxt->skipDepth)) {
26760 VERROR_INT("xmlSchemaValidateElem",
26761 "in skip-state");
26762 goto internal_error;
26763 }
26764 if (vctxt->xsiAssemble) {
26765 /*
26766 * We will stop validation if there was an error during
26767 * dynamic schema construction.
26768 * Note that we simply set @skipDepth to 0, this could
26769 * mean that a streaming document via SAX would be
26770 * still read to the end but it won't be validated any more.
26771 * TODO: If we are sure how to stop the validation at once
26772 * for all input scenarios, then this should be changed to
26773 * instantly stop the validation.
26774 */
26775 ret = xmlSchemaAssembleByXSI(vctxt);
26776 if (ret != 0) {
26777 if (ret == -1)
26778 goto internal_error;
26779 vctxt->skipDepth = 0;
26780 return(ret);
26781 }
26782 /*
26783 * Augment the IDC definitions for the main schema and all imported ones
26784 * NOTE: main schema is the first in the imported list
26785 */
26786 xmlHashScan(vctxt->schema->schemasImports, xmlSchemaAugmentImportedIDC,
26787 vctxt);
26788 }
26789 if (vctxt->depth > 0) {
26790 /*
26791 * Validate this element against the content model
26792 * of the parent.
26793 */
26794 ret = xmlSchemaValidateChildElem(vctxt);
26795 if (ret != 0) {
26796 if (ret < 0) {
26797 VERROR_INT("xmlSchemaValidateElem",
26798 "calling xmlSchemaStreamValidateChildElement()");
26799 goto internal_error;
26800 }
26801 goto exit;
26802 }
26803 if (vctxt->depth == vctxt->skipDepth)
26804 goto exit;
26805 if ((vctxt->inode->decl == NULL) &&
26806 (vctxt->inode->typeDef == NULL)) {
26807 VERROR_INT("xmlSchemaValidateElem",
26808 "the child element was valid but neither the "
26809 "declaration nor the type was set");
26810 goto internal_error;
26811 }
26812 } else {
26813 /*
26814 * Get the declaration of the validation root.
26815 */
26816 vctxt->inode->decl = xmlSchemaGetElem(vctxt->schema,
26817 vctxt->inode->localName,
26818 vctxt->inode->nsName);
26819 if (vctxt->inode->decl == NULL) {
26821 VERROR(ret, NULL,
26822 "No matching global declaration available "
26823 "for the validation root");
26824 goto exit;
26825 }
26826 }
26827
26828 if (vctxt->inode->decl == NULL)
26829 goto type_validation;
26830
26831 if (vctxt->inode->decl->type == XML_SCHEMA_TYPE_ANY) {
26832 int skip;
26833 /*
26834 * Wildcards.
26835 */
26836 ret = xmlSchemaValidateElemWildcard(vctxt, &skip);
26837 if (ret != 0) {
26838 if (ret < 0) {
26839 VERROR_INT("xmlSchemaValidateElem",
26840 "calling xmlSchemaValidateElemWildcard()");
26841 goto internal_error;
26842 }
26843 goto exit;
26844 }
26845 if (skip) {
26846 vctxt->skipDepth = vctxt->depth;
26847 goto exit;
26848 }
26849 /*
26850 * The declaration might be set by the wildcard validation,
26851 * when the processContents is "lax" or "strict".
26852 */
26853 if (vctxt->inode->decl->type != XML_SCHEMA_TYPE_ELEMENT) {
26854 /*
26855 * Clear the "decl" field to not confuse further processing.
26856 */
26857 vctxt->inode->decl = NULL;
26858 goto type_validation;
26859 }
26860 }
26861 /*
26862 * Validate against the declaration.
26863 */
26864 ret = xmlSchemaValidateElemDecl(vctxt);
26865 if (ret != 0) {
26866 if (ret < 0) {
26867 VERROR_INT("xmlSchemaValidateElem",
26868 "calling xmlSchemaValidateElemDecl()");
26869 goto internal_error;
26870 }
26871 goto exit;
26872 }
26873 /*
26874 * Validate against the type definition.
26875 */
26876type_validation:
26877
26878 if (vctxt->inode->typeDef == NULL) {
26879 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE;
26881 VERROR(ret, NULL,
26882 "The type definition is absent");
26883 goto exit;
26884 }
26885 if (vctxt->inode->typeDef->flags & XML_SCHEMAS_TYPE_ABSTRACT) {
26886 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE;
26888 VERROR(ret, NULL,
26889 "The type definition is abstract");
26890 goto exit;
26891 }
26892 /*
26893 * Evaluate IDCs. Do it here, since new IDC matchers are registered
26894 * during validation against the declaration. This must be done
26895 * _before_ attribute validation.
26896 */
26897 if (vctxt->xpathStates != NULL) {
26898 ret = xmlSchemaXPathEvaluate(vctxt, XML_ELEMENT_NODE);
26899 vctxt->inode->appliedXPath = 1;
26900 if (ret == -1) {
26901 VERROR_INT("xmlSchemaValidateElem",
26902 "calling xmlSchemaXPathEvaluate()");
26903 goto internal_error;
26904 }
26905 }
26906 /*
26907 * Validate attributes.
26908 */
26909 if (WXS_IS_COMPLEX(vctxt->inode->typeDef)) {
26910 if ((vctxt->nbAttrInfos != 0) ||
26911 (vctxt->inode->typeDef->attrUses != NULL)) {
26912
26913 ret = xmlSchemaVAttributesComplex(vctxt);
26914 }
26915 } else if (vctxt->nbAttrInfos != 0) {
26916
26917 ret = xmlSchemaVAttributesSimple(vctxt);
26918 }
26919 /*
26920 * Clear registered attributes.
26921 */
26922 if (vctxt->nbAttrInfos != 0)
26923 xmlSchemaClearAttrInfos(vctxt);
26924 if (ret == -1) {
26925 VERROR_INT("xmlSchemaValidateElem",
26926 "calling attributes validation");
26927 goto internal_error;
26928 }
26929 /*
26930 * Don't return an error if attributes are invalid on purpose.
26931 */
26932 ret = 0;
26933
26934exit:
26935 if (ret != 0)
26936 vctxt->skipDepth = vctxt->depth;
26937 return (ret);
26938internal_error:
26939 return (-1);
26940}
26941
26942#ifdef XML_SCHEMA_READER_ENABLED
26943static int
26944xmlSchemaVReaderWalk(xmlSchemaValidCtxtPtr vctxt)
26945{
26946 const int WHTSP = 13, SIGN_WHTSP = 14, END_ELEM = 15;
26947 int depth, nodeType, ret = 0, consumed;
26948 xmlSchemaNodeInfoPtr ielem;
26949
26950 vctxt->depth = -1;
26951 ret = xmlTextReaderRead(vctxt->reader);
26952 /*
26953 * Move to the document element.
26954 */
26955 while (ret == 1) {
26956 nodeType = xmlTextReaderNodeType(vctxt->reader);
26957 if (nodeType == XML_ELEMENT_NODE)
26958 goto root_found;
26959 ret = xmlTextReaderRead(vctxt->reader);
26960 }
26961 goto exit;
26962
26963root_found:
26964
26965 do {
26966 depth = xmlTextReaderDepth(vctxt->reader);
26967 nodeType = xmlTextReaderNodeType(vctxt->reader);
26968
26969 if (nodeType == XML_ELEMENT_NODE) {
26970
26971 vctxt->depth++;
26972 if (xmlSchemaValidatorPushElem(vctxt) == -1) {
26973 VERROR_INT("xmlSchemaVReaderWalk",
26974 "calling xmlSchemaValidatorPushElem()");
26975 goto internal_error;
26976 }
26977 ielem = vctxt->inode;
26978 ielem->localName = xmlTextReaderLocalName(vctxt->reader);
26979 ielem->nsName = xmlTextReaderNamespaceUri(vctxt->reader);
26980 ielem->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES;
26981 /*
26982 * Is the element empty?
26983 */
26984 ret = xmlTextReaderIsEmptyElement(vctxt->reader);
26985 if (ret == -1) {
26986 VERROR_INT("xmlSchemaVReaderWalk",
26987 "calling xmlTextReaderIsEmptyElement()");
26988 goto internal_error;
26989 }
26990 if (ret) {
26991 ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
26992 }
26993 /*
26994 * Register attributes.
26995 */
26996 vctxt->nbAttrInfos = 0;
26997 ret = xmlTextReaderMoveToFirstAttribute(vctxt->reader);
26998 if (ret == -1) {
26999 VERROR_INT("xmlSchemaVReaderWalk",
27000 "calling xmlTextReaderMoveToFirstAttribute()");
27001 goto internal_error;
27002 }
27003 if (ret == 1) {
27004 do {
27005 /*
27006 * VAL TODO: How do we know that the reader works on a
27007 * node tree, to be able to pass a node here?
27008 */
27009 if (xmlSchemaValidatorPushAttribute(vctxt, NULL,
27010 (const xmlChar *) xmlTextReaderLocalName(vctxt->reader),
27011 xmlTextReaderNamespaceUri(vctxt->reader), 1,
27012 xmlTextReaderValue(vctxt->reader), 1) == -1) {
27013
27014 VERROR_INT("xmlSchemaVReaderWalk",
27015 "calling xmlSchemaValidatorPushAttribute()");
27016 goto internal_error;
27017 }
27018 ret = xmlTextReaderMoveToNextAttribute(vctxt->reader);
27019 if (ret == -1) {
27020 VERROR_INT("xmlSchemaVReaderWalk",
27021 "calling xmlTextReaderMoveToFirstAttribute()");
27022 goto internal_error;
27023 }
27024 } while (ret == 1);
27025 /*
27026 * Back to element position.
27027 */
27028 ret = xmlTextReaderMoveToElement(vctxt->reader);
27029 if (ret == -1) {
27030 VERROR_INT("xmlSchemaVReaderWalk",
27031 "calling xmlTextReaderMoveToElement()");
27032 goto internal_error;
27033 }
27034 }
27035 /*
27036 * Validate the element.
27037 */
27038 ret= xmlSchemaValidateElem(vctxt);
27039 if (ret != 0) {
27040 if (ret == -1) {
27041 VERROR_INT("xmlSchemaVReaderWalk",
27042 "calling xmlSchemaValidateElem()");
27043 goto internal_error;
27044 }
27045 goto exit;
27046 }
27047 if (vctxt->depth == vctxt->skipDepth) {
27048 int curDepth;
27049 /*
27050 * Skip all content.
27051 */
27052 if ((ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY) == 0) {
27053 ret = xmlTextReaderRead(vctxt->reader);
27054 curDepth = xmlTextReaderDepth(vctxt->reader);
27055 while ((ret == 1) && (curDepth != depth)) {
27056 ret = xmlTextReaderRead(vctxt->reader);
27057 curDepth = xmlTextReaderDepth(vctxt->reader);
27058 }
27059 if (ret < 0) {
27060 /*
27061 * VAL TODO: A reader error occurred; what to do here?
27062 */
27063 ret = 1;
27064 goto exit;
27065 }
27066 }
27067 goto leave_elem;
27068 }
27069 /*
27070 * READER VAL TODO: Is an END_ELEM really never called
27071 * if the elem is empty?
27072 */
27073 if (ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
27074 goto leave_elem;
27075 } else if (nodeType == END_ELEM) {
27076 /*
27077 * Process END of element.
27078 */
27079leave_elem:
27080 ret = xmlSchemaValidatorPopElem(vctxt);
27081 if (ret != 0) {
27082 if (ret < 0) {
27083 VERROR_INT("xmlSchemaVReaderWalk",
27084 "calling xmlSchemaValidatorPopElem()");
27085 goto internal_error;
27086 }
27087 goto exit;
27088 }
27089 if (vctxt->depth >= 0)
27090 ielem = vctxt->inode;
27091 else
27092 ielem = NULL;
27093 } else if ((nodeType == XML_TEXT_NODE) ||
27094 (nodeType == XML_CDATA_SECTION_NODE) ||
27095 (nodeType == WHTSP) ||
27096 (nodeType == SIGN_WHTSP)) {
27097 /*
27098 * Process character content.
27099 */
27100 xmlChar *value;
27101
27102 if ((nodeType == WHTSP) || (nodeType == SIGN_WHTSP))
27103 nodeType = XML_TEXT_NODE;
27104
27105 value = xmlTextReaderValue(vctxt->reader);
27106 ret = xmlSchemaVPushText(vctxt, nodeType, BAD_CAST value,
27107 -1, XML_SCHEMA_PUSH_TEXT_CREATED, &consumed);
27108 if (! consumed)
27109 xmlFree(value);
27110 if (ret == -1) {
27111 VERROR_INT("xmlSchemaVReaderWalk",
27112 "calling xmlSchemaVPushText()");
27113 goto internal_error;
27114 }
27115 } else if ((nodeType == XML_ENTITY_NODE) ||
27116 (nodeType == XML_ENTITY_REF_NODE)) {
27117 /*
27118 * VAL TODO: What to do with entities?
27119 */
27120 TODO
27121 }
27122 /*
27123 * Read next node.
27124 */
27125 ret = xmlTextReaderRead(vctxt->reader);
27126 } while (ret == 1);
27127
27128exit:
27129 return (ret);
27130internal_error:
27131 return (-1);
27132}
27133#endif
27134
27135/************************************************************************
27136 * *
27137 * SAX validation handlers *
27138 * *
27139 ************************************************************************/
27140
27141/*
27142* Process text content.
27143*/
27144static void
27145xmlSchemaSAXHandleText(void *ctx,
27146 const xmlChar * ch,
27147 int len)
27148{
27149 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27150
27151 if (vctxt->depth < 0)
27152 return;
27153 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27154 return;
27155 if (vctxt->inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
27156 vctxt->inode->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
27157 if (xmlSchemaVPushText(vctxt, XML_TEXT_NODE, ch, len,
27158 XML_SCHEMA_PUSH_TEXT_VOLATILE, NULL) == -1) {
27159 VERROR_INT("xmlSchemaSAXHandleCDataSection",
27160 "calling xmlSchemaVPushText()");
27161 vctxt->err = -1;
27162 xmlStopParser(vctxt->parserCtxt);
27163 }
27164}
27165
27166/*
27167* Process CDATA content.
27168*/
27169static void
27170xmlSchemaSAXHandleCDataSection(void *ctx,
27171 const xmlChar * ch,
27172 int len)
27173{
27174 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27175
27176 if (vctxt->depth < 0)
27177 return;
27178 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27179 return;
27180 if (vctxt->inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
27181 vctxt->inode->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
27182 if (xmlSchemaVPushText(vctxt, XML_CDATA_SECTION_NODE, ch, len,
27183 XML_SCHEMA_PUSH_TEXT_VOLATILE, NULL) == -1) {
27184 VERROR_INT("xmlSchemaSAXHandleCDataSection",
27185 "calling xmlSchemaVPushText()");
27186 vctxt->err = -1;
27187 xmlStopParser(vctxt->parserCtxt);
27188 }
27189}
27190
27191static void
27192xmlSchemaSAXHandleReference(void *ctx ATTRIBUTE_UNUSED,
27194{
27195 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27196
27197 if (vctxt->depth < 0)
27198 return;
27199 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27200 return;
27201 /* SAX VAL TODO: What to do here? */
27202 TODO
27203}
27204
27205static void
27206xmlSchemaSAXHandleStartElementNs(void *ctx,
27207 const xmlChar * localname,
27209 const xmlChar * URI,
27210 int nb_namespaces,
27211 const xmlChar ** namespaces,
27212 int nb_attributes,
27213 int nb_defaulted ATTRIBUTE_UNUSED,
27214 const xmlChar ** attributes)
27215{
27216 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27217 int ret;
27218 xmlSchemaNodeInfoPtr ielem;
27219 int i, j;
27220
27221 /*
27222 * SAX VAL TODO: What to do with nb_defaulted?
27223 */
27224 /*
27225 * Skip elements if inside a "skip" wildcard or invalid.
27226 */
27227 vctxt->depth++;
27228 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27229 return;
27230 /*
27231 * Push the element.
27232 */
27233 if (xmlSchemaValidatorPushElem(vctxt) == -1) {
27234 VERROR_INT("xmlSchemaSAXHandleStartElementNs",
27235 "calling xmlSchemaValidatorPushElem()");
27236 goto internal_error;
27237 }
27238 ielem = vctxt->inode;
27239 /*
27240 * TODO: Is this OK?
27241 */
27242 ielem->nodeLine = xmlSAX2GetLineNumber(vctxt->parserCtxt);
27243 ielem->localName = localname;
27244 ielem->nsName = URI;
27245 ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
27246 /*
27247 * Register namespaces on the elem info.
27248 */
27249 if (nb_namespaces != 0) {
27250 /*
27251 * Although the parser builds its own namespace list,
27252 * we have no access to it, so we'll use an own one.
27253 */
27254 for (i = 0, j = 0; i < nb_namespaces; i++, j += 2) {
27255 /*
27256 * Store prefix and namespace name.
27257 */
27258 if (ielem->nsBindings == NULL) {
27259 ielem->nsBindings =
27260 (const xmlChar **) xmlMalloc(10 *
27261 sizeof(const xmlChar *));
27262 if (ielem->nsBindings == NULL) {
27263 xmlSchemaVErrMemory(vctxt,
27264 "allocating namespace bindings for SAX validation",
27265 NULL);
27266 goto internal_error;
27267 }
27268 ielem->nbNsBindings = 0;
27269 ielem->sizeNsBindings = 5;
27270 } else if (ielem->sizeNsBindings <= ielem->nbNsBindings) {
27271 ielem->sizeNsBindings *= 2;
27272 ielem->nsBindings =
27273 (const xmlChar **) xmlRealloc(
27274 (void *) ielem->nsBindings,
27275 ielem->sizeNsBindings * 2 * sizeof(const xmlChar *));
27276 if (ielem->nsBindings == NULL) {
27277 xmlSchemaVErrMemory(vctxt,
27278 "re-allocating namespace bindings for SAX validation",
27279 NULL);
27280 goto internal_error;
27281 }
27282 }
27283
27284 ielem->nsBindings[ielem->nbNsBindings * 2] = namespaces[j];
27285 if (namespaces[j+1][0] == 0) {
27286 /*
27287 * Handle xmlns="".
27288 */
27289 ielem->nsBindings[ielem->nbNsBindings * 2 + 1] = NULL;
27290 } else
27291 ielem->nsBindings[ielem->nbNsBindings * 2 + 1] =
27292 namespaces[j+1];
27293 ielem->nbNsBindings++;
27294 }
27295 }
27296 /*
27297 * Register attributes.
27298 * SAX VAL TODO: We are not adding namespace declaration
27299 * attributes yet.
27300 */
27301 if (nb_attributes != 0) {
27302 int valueLen, k, l;
27303 xmlChar *value;
27304
27305 for (j = 0, i = 0; i < nb_attributes; i++, j += 5) {
27306 /*
27307 * Duplicate the value, changing any &#38; to a literal ampersand.
27308 *
27309 * libxml2 differs from normal SAX here in that it escapes all ampersands
27310 * as &#38; instead of delivering the raw converted string. Changing the
27311 * behavior at this point would break applications that use this API, so
27312 * we are forced to work around it.
27313 */
27314 valueLen = attributes[j+4] - attributes[j+3];
27315 value = xmlMallocAtomic(valueLen + 1);
27316 if (value == NULL) {
27317 xmlSchemaVErrMemory(vctxt,
27318 "allocating string for decoded attribute",
27319 NULL);
27320 goto internal_error;
27321 }
27322 for (k = 0, l = 0; k < valueLen; l++) {
27323 if (k < valueLen - 4 &&
27324 attributes[j+3][k+0] == '&' &&
27325 attributes[j+3][k+1] == '#' &&
27326 attributes[j+3][k+2] == '3' &&
27327 attributes[j+3][k+3] == '8' &&
27328 attributes[j+3][k+4] == ';') {
27329 value[l] = '&';
27330 k += 5;
27331 } else {
27332 value[l] = attributes[j+3][k];
27333 k++;
27334 }
27335 }
27336 value[l] = '\0';
27337 /*
27338 * TODO: Set the node line.
27339 */
27340 ret = xmlSchemaValidatorPushAttribute(vctxt,
27341 NULL, ielem->nodeLine, attributes[j], attributes[j+2], 0,
27342 value, 1);
27343 if (ret == -1) {
27344 VERROR_INT("xmlSchemaSAXHandleStartElementNs",
27345 "calling xmlSchemaValidatorPushAttribute()");
27346 goto internal_error;
27347 }
27348 }
27349 }
27350 /*
27351 * Validate the element.
27352 */
27353 ret = xmlSchemaValidateElem(vctxt);
27354 if (ret != 0) {
27355 if (ret == -1) {
27356 VERROR_INT("xmlSchemaSAXHandleStartElementNs",
27357 "calling xmlSchemaValidateElem()");
27358 goto internal_error;
27359 }
27360 goto exit;
27361 }
27362
27363exit:
27364 return;
27365internal_error:
27366 vctxt->err = -1;
27367 xmlStopParser(vctxt->parserCtxt);
27368 return;
27369}
27370
27371static void
27372xmlSchemaSAXHandleEndElementNs(void *ctx,
27373 const xmlChar * localname ATTRIBUTE_UNUSED,
27375 const xmlChar * URI ATTRIBUTE_UNUSED)
27376{
27377 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27378 int res;
27379
27380 /*
27381 * Skip elements if inside a "skip" wildcard or if invalid.
27382 */
27383 if (vctxt->skipDepth != -1) {
27384 if (vctxt->depth > vctxt->skipDepth) {
27385 vctxt->depth--;
27386 return;
27387 } else
27388 vctxt->skipDepth = -1;
27389 }
27390 /*
27391 * SAX VAL TODO: Just a temporary check.
27392 */
27393 if ((!xmlStrEqual(vctxt->inode->localName, localname)) ||
27394 (!xmlStrEqual(vctxt->inode->nsName, URI))) {
27395 VERROR_INT("xmlSchemaSAXHandleEndElementNs",
27396 "elem pop mismatch");
27397 }
27398 res = xmlSchemaValidatorPopElem(vctxt);
27399 if (res != 0) {
27400 if (res < 0) {
27401 VERROR_INT("xmlSchemaSAXHandleEndElementNs",
27402 "calling xmlSchemaValidatorPopElem()");
27403 goto internal_error;
27404 }
27405 goto exit;
27406 }
27407exit:
27408 return;
27409internal_error:
27410 vctxt->err = -1;
27411 xmlStopParser(vctxt->parserCtxt);
27412 return;
27413}
27414
27415/************************************************************************
27416 * *
27417 * Validation interfaces *
27418 * *
27419 ************************************************************************/
27420
27429xmlSchemaValidCtxtPtr
27430xmlSchemaNewValidCtxt(xmlSchemaPtr schema)
27431{
27432 xmlSchemaValidCtxtPtr ret;
27433
27434 ret = (xmlSchemaValidCtxtPtr) xmlMalloc(sizeof(xmlSchemaValidCtxt));
27435 if (ret == NULL) {
27436 xmlSchemaVErrMemory(NULL, "allocating validation context", NULL);
27437 return (NULL);
27438 }
27439 memset(ret, 0, sizeof(xmlSchemaValidCtxt));
27440 ret->type = XML_SCHEMA_CTXT_VALIDATOR;
27441 ret->dict = xmlDictCreate();
27442 ret->nodeQNames = xmlSchemaItemListCreate();
27443 ret->schema = schema;
27444 return (ret);
27445}
27446
27455void
27456xmlSchemaValidateSetFilename(xmlSchemaValidCtxtPtr vctxt, const char *filename) {
27457 if (vctxt == NULL)
27458 return;
27459 if (vctxt->filename != NULL)
27460 xmlFree(vctxt->filename);
27461 if (filename != NULL)
27462 vctxt->filename = (char *) xmlStrdup((const xmlChar *) filename);
27463 else
27464 vctxt->filename = NULL;
27465}
27466
27474static void
27475xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt)
27476{
27477 if (vctxt == NULL)
27478 return;
27479
27480 /*
27481 * TODO: Should we clear the flags?
27482 * Might be problematic if one reuses the context
27483 * and assumes that the options remain the same.
27484 */
27485 vctxt->flags = 0;
27486 vctxt->validationRoot = NULL;
27487 vctxt->doc = NULL;
27488#ifdef LIBXML_READER_ENABLED
27489 vctxt->reader = NULL;
27490#endif
27491 vctxt->hasKeyrefs = 0;
27492
27493 if (vctxt->value != NULL) {
27494 xmlSchemaFreeValue(vctxt->value);
27495 vctxt->value = NULL;
27496 }
27497 /*
27498 * Augmented IDC information.
27499 */
27500 if (vctxt->aidcs != NULL) {
27501 xmlSchemaIDCAugPtr cur = vctxt->aidcs, next;
27502 do {
27503 next = cur->next;
27504 xmlFree(cur);
27505 cur = next;
27506 } while (cur != NULL);
27507 vctxt->aidcs = NULL;
27508 }
27509
27510 if (vctxt->idcNodes != NULL) {
27511 int i;
27512 xmlSchemaPSVIIDCNodePtr item;
27513
27514 for (i = 0; i < vctxt->nbIdcNodes; i++) {
27515 item = vctxt->idcNodes[i];
27516 xmlFree(item->keys);
27517 xmlFree(item);
27518 }
27519 xmlFree(vctxt->idcNodes);
27520 vctxt->idcNodes = NULL;
27521 vctxt->nbIdcNodes = 0;
27522 vctxt->sizeIdcNodes = 0;
27523 }
27524
27525 if (vctxt->idcKeys != NULL) {
27526 int i;
27527 for (i = 0; i < vctxt->nbIdcKeys; i++)
27528 xmlSchemaIDCFreeKey(vctxt->idcKeys[i]);
27529 xmlFree(vctxt->idcKeys);
27530 vctxt->idcKeys = NULL;
27531 vctxt->nbIdcKeys = 0;
27532 vctxt->sizeIdcKeys = 0;
27533 }
27534
27535 /*
27536 * Note that we won't delete the XPath state pool here.
27537 */
27538 if (vctxt->xpathStates != NULL) {
27539 xmlSchemaFreeIDCStateObjList(vctxt->xpathStates);
27540 vctxt->xpathStates = NULL;
27541 }
27542 /*
27543 * Attribute info.
27544 */
27545 if (vctxt->nbAttrInfos != 0) {
27546 xmlSchemaClearAttrInfos(vctxt);
27547 }
27548 /*
27549 * Element info.
27550 */
27551 if (vctxt->elemInfos != NULL) {
27552 int i;
27553 xmlSchemaNodeInfoPtr ei;
27554
27555 for (i = 0; i < vctxt->sizeElemInfos; i++) {
27556 ei = vctxt->elemInfos[i];
27557 if (ei == NULL)
27558 break;
27559 xmlSchemaClearElemInfo(vctxt, ei);
27560 }
27561 }
27562 xmlSchemaItemListClear(vctxt->nodeQNames);
27563 /* Recreate the dict. */
27564 xmlDictFree(vctxt->dict);
27565 /*
27566 * TODO: Is is save to recreate it? Do we have a scenario
27567 * where the user provides the dict?
27568 */
27569 vctxt->dict = xmlDictCreate();
27570
27571 if (vctxt->filename != NULL) {
27572 xmlFree(vctxt->filename);
27573 vctxt->filename = NULL;
27574 }
27575
27576 /*
27577 * Note that some cleanup functions can move items to the cache,
27578 * so the cache shouldn't be freed too early.
27579 */
27580 if (vctxt->idcMatcherCache != NULL) {
27581 xmlSchemaIDCMatcherPtr matcher = vctxt->idcMatcherCache, tmp;
27582
27583 while (matcher) {
27584 tmp = matcher;
27585 matcher = matcher->nextCached;
27586 xmlSchemaIDCFreeMatcherList(tmp);
27587 }
27588 vctxt->idcMatcherCache = NULL;
27589 }
27590}
27591
27598void
27599xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt)
27600{
27601 if (ctxt == NULL)
27602 return;
27603 if (ctxt->value != NULL)
27604 xmlSchemaFreeValue(ctxt->value);
27605 if (ctxt->pctxt != NULL)
27606 xmlSchemaFreeParserCtxt(ctxt->pctxt);
27607 if (ctxt->idcNodes != NULL) {
27608 int i;
27609 xmlSchemaPSVIIDCNodePtr item;
27610
27611 for (i = 0; i < ctxt->nbIdcNodes; i++) {
27612 item = ctxt->idcNodes[i];
27613 xmlFree(item->keys);
27614 xmlFree(item);
27615 }
27616 xmlFree(ctxt->idcNodes);
27617 }
27618 if (ctxt->idcKeys != NULL) {
27619 int i;
27620 for (i = 0; i < ctxt->nbIdcKeys; i++)
27621 xmlSchemaIDCFreeKey(ctxt->idcKeys[i]);
27622 xmlFree(ctxt->idcKeys);
27623 }
27624
27625 if (ctxt->xpathStates != NULL) {
27626 xmlSchemaFreeIDCStateObjList(ctxt->xpathStates);
27627 ctxt->xpathStates = NULL;
27628 }
27629 if (ctxt->xpathStatePool != NULL) {
27630 xmlSchemaFreeIDCStateObjList(ctxt->xpathStatePool);
27631 ctxt->xpathStatePool = NULL;
27632 }
27633
27634 /*
27635 * Augmented IDC information.
27636 */
27637 if (ctxt->aidcs != NULL) {
27638 xmlSchemaIDCAugPtr cur = ctxt->aidcs, next;
27639 do {
27640 next = cur->next;
27641 xmlFree(cur);
27642 cur = next;
27643 } while (cur != NULL);
27644 }
27645 if (ctxt->attrInfos != NULL) {
27646 int i;
27647 xmlSchemaAttrInfoPtr attr;
27648
27649 /* Just a paranoid call to the cleanup. */
27650 if (ctxt->nbAttrInfos != 0)
27651 xmlSchemaClearAttrInfos(ctxt);
27652 for (i = 0; i < ctxt->sizeAttrInfos; i++) {
27653 attr = ctxt->attrInfos[i];
27654 xmlFree(attr);
27655 }
27656 xmlFree(ctxt->attrInfos);
27657 }
27658 if (ctxt->elemInfos != NULL) {
27659 int i;
27660 xmlSchemaNodeInfoPtr ei;
27661
27662 for (i = 0; i < ctxt->sizeElemInfos; i++) {
27663 ei = ctxt->elemInfos[i];
27664 if (ei == NULL)
27665 break;
27666 xmlSchemaClearElemInfo(ctxt, ei);
27667 xmlFree(ei);
27668 }
27669 xmlFree(ctxt->elemInfos);
27670 }
27671 if (ctxt->nodeQNames != NULL)
27672 xmlSchemaItemListFree(ctxt->nodeQNames);
27673 if (ctxt->dict != NULL)
27674 xmlDictFree(ctxt->dict);
27675 if (ctxt->filename != NULL)
27676 xmlFree(ctxt->filename);
27677 xmlFree(ctxt);
27678}
27679
27689int
27690xmlSchemaIsValid(xmlSchemaValidCtxtPtr ctxt)
27691{
27692 if (ctxt == NULL)
27693 return(-1);
27694 return(ctxt->err == 0);
27695}
27696
27706void
27707xmlSchemaSetValidErrors(xmlSchemaValidCtxtPtr ctxt,
27708 xmlSchemaValidityErrorFunc err,
27709 xmlSchemaValidityWarningFunc warn, void *ctx)
27710{
27711 if (ctxt == NULL)
27712 return;
27713 ctxt->error = err;
27714 ctxt->warning = warn;
27715 ctxt->errCtxt = ctx;
27716 if (ctxt->pctxt != NULL)
27717 xmlSchemaSetParserErrors(ctxt->pctxt, err, warn, ctx);
27718}
27719
27728void
27729xmlSchemaSetValidStructuredErrors(xmlSchemaValidCtxtPtr ctxt,
27730 xmlStructuredErrorFunc serror, void *ctx)
27731{
27732 if (ctxt == NULL)
27733 return;
27734 ctxt->serror = serror;
27735 ctxt->error = NULL;
27736 ctxt->warning = NULL;
27737 ctxt->errCtxt = ctx;
27738 if (ctxt->pctxt != NULL)
27739 xmlSchemaSetParserStructuredErrors(ctxt->pctxt, serror, ctx);
27740}
27741
27753int
27754xmlSchemaGetValidErrors(xmlSchemaValidCtxtPtr ctxt,
27755 xmlSchemaValidityErrorFunc * err,
27756 xmlSchemaValidityWarningFunc * warn, void **ctx)
27757{
27758 if (ctxt == NULL)
27759 return (-1);
27760 if (err != NULL)
27761 *err = ctxt->error;
27762 if (warn != NULL)
27763 *warn = ctxt->warning;
27764 if (ctx != NULL)
27765 *ctx = ctxt->errCtxt;
27766 return (0);
27767}
27768
27769
27780int
27781xmlSchemaSetValidOptions(xmlSchemaValidCtxtPtr ctxt,
27782 int options)
27783
27784{
27785 int i;
27786
27787 if (ctxt == NULL)
27788 return (-1);
27789 /*
27790 * WARNING: Change the start value if adding to the
27791 * xmlSchemaValidOption.
27792 * TODO: Is there an other, more easy to maintain,
27793 * way?
27794 */
27795 for (i = 1; i < (int) sizeof(int) * 8; i++) {
27796 if (options & 1<<i)
27797 return (-1);
27798 }
27799 ctxt->options = options;
27800 return (0);
27801}
27802
27811int
27812xmlSchemaValidCtxtGetOptions(xmlSchemaValidCtxtPtr ctxt)
27813
27814{
27815 if (ctxt == NULL)
27816 return (-1);
27817 else
27818 return (ctxt->options);
27819}
27820
27821static int
27822xmlSchemaVDocWalk(xmlSchemaValidCtxtPtr vctxt)
27823{
27824 xmlAttrPtr attr;
27825 int ret = 0;
27826 xmlSchemaNodeInfoPtr ielem = NULL;
27827 xmlNodePtr node, valRoot;
27828 const xmlChar *nsName;
27829
27830 /* DOC VAL TODO: Move this to the start function. */
27831 if (vctxt->validationRoot != NULL)
27832 valRoot = vctxt->validationRoot;
27833 else
27834 valRoot = xmlDocGetRootElement(vctxt->doc);
27835 if (valRoot == NULL) {
27836 /* VAL TODO: Error code? */
27837 VERROR(1, NULL, "The document has no document element");
27838 return (1);
27839 }
27840 vctxt->depth = -1;
27841 vctxt->validationRoot = valRoot;
27842 node = valRoot;
27843 while (node != NULL) {
27844 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27845 goto next_sibling;
27846 if (node->type == XML_ELEMENT_NODE) {
27847
27848 /*
27849 * Init the node-info.
27850 */
27851 vctxt->depth++;
27852 if (xmlSchemaValidatorPushElem(vctxt) == -1)
27853 goto internal_error;
27854 ielem = vctxt->inode;
27855 ielem->node = node;
27856 ielem->nodeLine = node->line;
27857 ielem->localName = node->name;
27858 if (node->ns != NULL)
27859 ielem->nsName = node->ns->href;
27860 ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
27861 /*
27862 * Register attributes.
27863 * DOC VAL TODO: We do not register namespace declaration
27864 * attributes yet.
27865 */
27866 vctxt->nbAttrInfos = 0;
27867 if (node->properties != NULL) {
27868 attr = node->properties;
27869 do {
27870 if (attr->ns != NULL)
27871 nsName = attr->ns->href;
27872 else
27873 nsName = NULL;
27874 ret = xmlSchemaValidatorPushAttribute(vctxt,
27875 (xmlNodePtr) attr,
27876 /*
27877 * Note that we give it the line number of the
27878 * parent element.
27879 */
27880 ielem->nodeLine,
27881 attr->name, nsName, 0,
27882 xmlNodeListGetString(attr->doc, attr->children, 1), 1);
27883 if (ret == -1) {
27884 VERROR_INT("xmlSchemaDocWalk",
27885 "calling xmlSchemaValidatorPushAttribute()");
27886 goto internal_error;
27887 }
27888 attr = attr->next;
27889 } while (attr);
27890 }
27891 /*
27892 * Validate the element.
27893 */
27894 ret = xmlSchemaValidateElem(vctxt);
27895 if (ret != 0) {
27896 if (ret == -1) {
27897 VERROR_INT("xmlSchemaDocWalk",
27898 "calling xmlSchemaValidateElem()");
27899 goto internal_error;
27900 }
27901 /*
27902 * Don't stop validation; just skip the content
27903 * of this element.
27904 */
27905 goto leave_node;
27906 }
27907 if ((vctxt->skipDepth != -1) &&
27908 (vctxt->depth >= vctxt->skipDepth))
27909 goto leave_node;
27910 } else if ((node->type == XML_TEXT_NODE) ||
27911 (node->type == XML_CDATA_SECTION_NODE)) {
27912 /*
27913 * Process character content.
27914 */
27915 if ((ielem != NULL) && (ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY))
27916 ielem->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
27917 ret = xmlSchemaVPushText(vctxt, node->type, node->content,
27918 -1, XML_SCHEMA_PUSH_TEXT_PERSIST, NULL);
27919 if (ret < 0) {
27920 VERROR_INT("xmlSchemaVDocWalk",
27921 "calling xmlSchemaVPushText()");
27922 goto internal_error;
27923 }
27924 /*
27925 * DOC VAL TODO: Should we skip further validation of the
27926 * element content here?
27927 */
27928 } else if ((node->type == XML_ENTITY_NODE) ||
27929 (node->type == XML_ENTITY_REF_NODE)) {
27930 /*
27931 * DOC VAL TODO: What to do with entities?
27932 */
27933 VERROR_INT("xmlSchemaVDocWalk",
27934 "there is at least one entity reference in the node-tree "
27935 "currently being validated. Processing of entities with "
27936 "this XML Schema processor is not supported (yet). Please "
27937 "substitute entities before validation.");
27938 goto internal_error;
27939 } else {
27940 goto leave_node;
27941 /*
27942 * DOC VAL TODO: XInclude nodes, etc.
27943 */
27944 }
27945 /*
27946 * Walk the doc.
27947 */
27948 if (node->children != NULL) {
27949 node = node->children;
27950 continue;
27951 }
27952leave_node:
27953 if (node->type == XML_ELEMENT_NODE) {
27954 /*
27955 * Leaving the scope of an element.
27956 */
27957 if (node != vctxt->inode->node) {
27958 VERROR_INT("xmlSchemaVDocWalk",
27959 "element position mismatch");
27960 goto internal_error;
27961 }
27962 ret = xmlSchemaValidatorPopElem(vctxt);
27963 if (ret != 0) {
27964 if (ret < 0) {
27965 VERROR_INT("xmlSchemaVDocWalk",
27966 "calling xmlSchemaValidatorPopElem()");
27967 goto internal_error;
27968 }
27969 }
27970 if (node == valRoot)
27971 goto exit;
27972 }
27973next_sibling:
27974 if (node->next != NULL)
27975 node = node->next;
27976 else {
27977 node = node->parent;
27978 goto leave_node;
27979 }
27980 }
27981
27982exit:
27983 return (ret);
27984internal_error:
27985 return (-1);
27986}
27987
27988static int
27989xmlSchemaPreRun(xmlSchemaValidCtxtPtr vctxt) {
27990 /*
27991 * Some initialization.
27992 */
27993 vctxt->err = 0;
27994 vctxt->nberrors = 0;
27995 vctxt->depth = -1;
27996 vctxt->skipDepth = -1;
27997 vctxt->hasKeyrefs = 0;
27998#ifdef ENABLE_IDC_NODE_TABLES_TEST
27999 vctxt->createIDCNodeTables = 1;
28000#else
28001 vctxt->createIDCNodeTables = 0;
28002#endif
28003 /*
28004 * Create a schema + parser if necessary.
28005 */
28006 if (vctxt->schema == NULL) {
28007 xmlSchemaParserCtxtPtr pctxt;
28008
28009 vctxt->xsiAssemble = 1;
28010 /*
28011 * If not schema was given then we will create a schema
28012 * dynamically using XSI schema locations.
28013 *
28014 * Create the schema parser context.
28015 */
28016 if ((vctxt->pctxt == NULL) &&
28017 (xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1))
28018 return (-1);
28019 pctxt = vctxt->pctxt;
28020 pctxt->xsiAssemble = 1;
28021 /*
28022 * Create the schema.
28023 */
28024 vctxt->schema = xmlSchemaNewSchema(pctxt);
28025 if (vctxt->schema == NULL)
28026 return (-1);
28027 /*
28028 * Create the schema construction context.
28029 */
28030 pctxt->constructor = xmlSchemaConstructionCtxtCreate(pctxt->dict);
28031 if (pctxt->constructor == NULL)
28032 return(-1);
28033 pctxt->constructor->mainSchema = vctxt->schema;
28034 /*
28035 * Take ownership of the constructor to be able to free it.
28036 */
28037 pctxt->ownsConstructor = 1;
28038 }
28039 /*
28040 * Augment the IDC definitions for the main schema and all imported ones
28041 * NOTE: main schema if the first in the imported list
28042 */
28043 xmlHashScan(vctxt->schema->schemasImports, xmlSchemaAugmentImportedIDC,
28044 vctxt);
28045
28046 return(0);
28047}
28048
28049static void
28050xmlSchemaPostRun(xmlSchemaValidCtxtPtr vctxt) {
28051 if (vctxt->xsiAssemble) {
28052 if (vctxt->schema != NULL) {
28053 xmlSchemaFree(vctxt->schema);
28054 vctxt->schema = NULL;
28055 }
28056 }
28057 xmlSchemaClearValidCtxt(vctxt);
28058}
28059
28060static int
28061xmlSchemaVStart(xmlSchemaValidCtxtPtr vctxt)
28062{
28063 int ret = 0;
28064
28065 if (xmlSchemaPreRun(vctxt) < 0)
28066 return(-1);
28067
28068 if (vctxt->doc != NULL) {
28069 /*
28070 * Tree validation.
28071 */
28072 ret = xmlSchemaVDocWalk(vctxt);
28073#ifdef LIBXML_READER_ENABLED
28074 } else if (vctxt->reader != NULL) {
28075 /*
28076 * XML Reader validation.
28077 */
28078#ifdef XML_SCHEMA_READER_ENABLED
28079 ret = xmlSchemaVReaderWalk(vctxt);
28080#endif
28081#endif
28082 } else if ((vctxt->sax != NULL) && (vctxt->parserCtxt != NULL)) {
28083 /*
28084 * SAX validation.
28085 */
28086 ret = xmlParseDocument(vctxt->parserCtxt);
28087 } else {
28088 VERROR_INT("xmlSchemaVStart",
28089 "no instance to validate");
28090 ret = -1;
28091 }
28092
28093 xmlSchemaPostRun(vctxt);
28094 if (ret == 0)
28095 ret = vctxt->err;
28096 return (ret);
28097}
28098
28109int
28110xmlSchemaValidateOneElement(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem)
28111{
28112 if ((ctxt == NULL) || (elem == NULL) || (elem->type != XML_ELEMENT_NODE))
28113 return (-1);
28114
28115 if (ctxt->schema == NULL)
28116 return (-1);
28117
28118 ctxt->doc = elem->doc;
28119 ctxt->node = elem;
28120 ctxt->validationRoot = elem;
28121 return(xmlSchemaVStart(ctxt));
28122}
28123
28134int
28135xmlSchemaValidateDoc(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
28136{
28137 if ((ctxt == NULL) || (doc == NULL))
28138 return (-1);
28139
28140 ctxt->doc = doc;
28141 ctxt->node = xmlDocGetRootElement(doc);
28142 if (ctxt->node == NULL) {
28143 xmlSchemaCustomErr(ACTXT_CAST ctxt,
28145 (xmlNodePtr) doc, NULL,
28146 "The document has no document element", NULL, NULL);
28147 return (ctxt->err);
28148 }
28149 ctxt->validationRoot = ctxt->node;
28150 return (xmlSchemaVStart(ctxt));
28151}
28152
28153
28154/************************************************************************
28155 * *
28156 * Function and data for SAX streaming API *
28157 * *
28158 ************************************************************************/
28159typedef struct _xmlSchemaSplitSAXData xmlSchemaSplitSAXData;
28160typedef xmlSchemaSplitSAXData *xmlSchemaSplitSAXDataPtr;
28161
28162struct _xmlSchemaSplitSAXData {
28163 xmlSAXHandlerPtr user_sax;
28164 void *user_data;
28165 xmlSchemaValidCtxtPtr ctxt;
28166 xmlSAXHandlerPtr schemas_sax;
28167};
28168
28169#define XML_SAX_PLUG_MAGIC 0xdc43ba21
28170
28171struct _xmlSchemaSAXPlug {
28172 unsigned int magic;
28173
28174 /* the original callbacks information */
28175 xmlSAXHandlerPtr *user_sax_ptr;
28176 xmlSAXHandlerPtr user_sax;
28177 void **user_data_ptr;
28178 void *user_data;
28179
28180 /* the block plugged back and validation information */
28181 xmlSAXHandler schemas_sax;
28182 xmlSchemaValidCtxtPtr ctxt;
28183};
28184
28185/* All those functions just bounces to the user provided SAX handlers */
28186static void
28187internalSubsetSplit(void *ctx, const xmlChar *name,
28188 const xmlChar *ExternalID, const xmlChar *SystemID)
28189{
28190 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28191 if ((ctxt != NULL) && (ctxt->user_sax !=