Update mojo sdk to rev 1dc8a9a5db73d3718d99917fadf31f5fb2ebad4f
[chromium-blink-merge.git] / third_party / libxml / src / xmlschemas.c
blob8be14d88f0918262db1cde182f2e658b55fa945e
1 /*
2 * schemas.c : implementation of the XML Schema handling and
3 * schema validity checking
5 * See Copyright for the status of this software.
7 * Daniel Veillard <veillard@redhat.com>
8 */
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: ??
20 * URGENT TODO:
21 * - For xsi-driven schema acquisition, augment the IDCs after every
22 * acquisition episode (xmlSchemaAugmentIDC).
24 * NOTES:
25 * - Elimated item creation for: <restriction>, <extension>,
26 * <simpleContent>, <complexContent>, <list>, <union>
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.
34 * CONSTRAINTS:
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.
47 #define IN_LIBXML
48 #include "libxml.h"
50 #ifdef LIBXML_SCHEMAS_ENABLED
52 #include <string.h>
53 #include <libxml/xmlmemory.h>
54 #include <libxml/parser.h>
55 #include <libxml/parserInternals.h>
56 #include <libxml/hash.h>
57 #include <libxml/uri.h>
58 #include <libxml/xmlschemas.h>
59 #include <libxml/schemasInternals.h>
60 #include <libxml/xmlschemastypes.h>
61 #include <libxml/xmlautomata.h>
62 #include <libxml/xmlregexp.h>
63 #include <libxml/dict.h>
64 #include <libxml/encoding.h>
65 #include <libxml/xmlIO.h>
66 #ifdef LIBXML_PATTERN_ENABLED
67 #include <libxml/pattern.h>
68 #endif
69 #ifdef LIBXML_READER_ENABLED
70 #include <libxml/xmlreader.h>
71 #endif
73 /* #define DEBUG 1 */
75 /* #define DEBUG_CONTENT 1 */
77 /* #define DEBUG_TYPE 1 */
79 /* #define DEBUG_CONTENT_REGEXP 1 */
81 /* #define DEBUG_AUTOMATA 1 */
83 /* #define DEBUG_IDC */
85 /* #define DEBUG_IDC_NODE_TABLE */
87 /* #define WXS_ELEM_DECL_CONS_ENABLED */
89 #ifdef DEBUG_IDC
90 #ifndef DEBUG_IDC_NODE_TABLE
91 #define DEBUG_IDC_NODE_TABLE
92 #endif
93 #endif
95 /* #define ENABLE_PARTICLE_RESTRICTION 1 */
97 #define ENABLE_REDEFINE
99 /* #define ENABLE_NAMED_LOCALS */
101 /* #define ENABLE_IDC_NODE_TABLES_TEST */
103 #define DUMP_CONTENT_MODEL
105 #ifdef LIBXML_READER_ENABLED
106 /* #define XML_SCHEMA_READER_ENABLED */
107 #endif
109 #define UNBOUNDED (1 << 30)
110 #define TODO \
111 xmlGenericError(xmlGenericErrorContext, \
112 "Unimplemented block at %s:%d\n", \
113 __FILE__, __LINE__);
115 #define XML_SCHEMAS_NO_NAMESPACE (const xmlChar *) "##"
118 * The XML Schemas namespaces
120 static const xmlChar *xmlSchemaNs = (const xmlChar *)
121 "http://www.w3.org/2001/XMLSchema";
123 static const xmlChar *xmlSchemaInstanceNs = (const xmlChar *)
124 "http://www.w3.org/2001/XMLSchema-instance";
126 static const xmlChar *xmlNamespaceNs = (const xmlChar *)
127 "http://www.w3.org/2000/xmlns/";
130 * Come casting macros.
132 #define ACTXT_CAST (xmlSchemaAbstractCtxtPtr)
133 #define PCTXT_CAST (xmlSchemaParserCtxtPtr)
134 #define VCTXT_CAST (xmlSchemaValidCtxtPtr)
135 #define WXS_BASIC_CAST (xmlSchemaBasicItemPtr)
136 #define WXS_TREE_CAST (xmlSchemaTreeItemPtr)
137 #define WXS_PTC_CAST (xmlSchemaParticlePtr)
138 #define WXS_TYPE_CAST (xmlSchemaTypePtr)
139 #define WXS_ELEM_CAST (xmlSchemaElementPtr)
140 #define WXS_ATTR_GROUP_CAST (xmlSchemaAttributeGroupPtr)
141 #define WXS_ATTR_CAST (xmlSchemaAttributePtr)
142 #define WXS_ATTR_USE_CAST (xmlSchemaAttributeUsePtr)
143 #define WXS_ATTR_PROHIB_CAST (xmlSchemaAttributeUseProhibPtr)
144 #define WXS_MODEL_GROUPDEF_CAST (xmlSchemaModelGroupDefPtr)
145 #define WXS_MODEL_GROUP_CAST (xmlSchemaModelGroupPtr)
146 #define WXS_IDC_CAST (xmlSchemaIDCPtr)
147 #define WXS_QNAME_CAST (xmlSchemaQNameRefPtr)
148 #define WXS_LIST_CAST (xmlSchemaItemListPtr)
151 * Macros to query common properties of components.
153 #define WXS_ITEM_NODE(i) xmlSchemaGetComponentNode(WXS_BASIC_CAST (i))
155 #define WXS_ITEM_TYPE_NAME(i) xmlSchemaGetComponentTypeStr(WXS_BASIC_CAST (i))
157 * Macros for element declarations.
159 #define WXS_ELEM_TYPEDEF(e) (e)->subtypes
161 #define WXS_SUBST_HEAD(item) (item)->refDecl
163 * Macros for attribute declarations.
165 #define WXS_ATTR_TYPEDEF(a) (a)->subtypes
167 * Macros for attribute uses.
169 #define WXS_ATTRUSE_DECL(au) WXS_ATTR_CAST (WXS_ATTR_USE_CAST (au))->attrDecl
171 #define WXS_ATTRUSE_TYPEDEF(au) WXS_ATTR_TYPEDEF(WXS_ATTRUSE_DECL( WXS_ATTR_USE_CAST au))
173 #define WXS_ATTRUSE_DECL_NAME(au) (WXS_ATTRUSE_DECL(au))->name
175 #define WXS_ATTRUSE_DECL_TNS(au) (WXS_ATTRUSE_DECL(au))->targetNamespace
177 * Macros for attribute groups.
179 #define WXS_ATTR_GROUP_HAS_REFS(ag) ((WXS_ATTR_GROUP_CAST (ag))->flags & XML_SCHEMAS_ATTRGROUP_HAS_REFS)
180 #define WXS_ATTR_GROUP_EXPANDED(ag) ((WXS_ATTR_GROUP_CAST (ag))->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED)
182 * Macros for particles.
184 #define WXS_PARTICLE(p) WXS_PTC_CAST (p)
186 #define WXS_PARTICLE_TERM(p) (WXS_PARTICLE(p))->children
188 #define WXS_PARTICLE_TERM_AS_ELEM(p) (WXS_ELEM_CAST WXS_PARTICLE_TERM(p))
190 #define WXS_PARTICLE_MODEL(p) WXS_MODEL_GROUP_CAST WXS_PARTICLE(p)->children
192 * Macros for model groups definitions.
194 #define WXS_MODELGROUPDEF_MODEL(mgd) (WXS_MODEL_GROUP_CAST (mgd))->children
196 * Macros for model groups.
198 #define WXS_IS_MODEL_GROUP(i) \
199 (((i)->type == XML_SCHEMA_TYPE_SEQUENCE) || \
200 ((i)->type == XML_SCHEMA_TYPE_CHOICE) || \
201 ((i)->type == XML_SCHEMA_TYPE_ALL))
203 #define WXS_MODELGROUP_PARTICLE(mg) WXS_PTC_CAST (mg)->children
205 * Macros for schema buckets.
207 #define WXS_IS_BUCKET_INCREDEF(t) (((t) == XML_SCHEMA_SCHEMA_INCLUDE) || \
208 ((t) == XML_SCHEMA_SCHEMA_REDEFINE))
210 #define WXS_IS_BUCKET_IMPMAIN(t) (((t) == XML_SCHEMA_SCHEMA_MAIN) || \
211 ((t) == XML_SCHEMA_SCHEMA_IMPORT))
213 #define WXS_IMPBUCKET(b) ((xmlSchemaImportPtr) (b))
215 #define WXS_INCBUCKET(b) ((xmlSchemaIncludePtr) (b))
217 * Macros for complex/simple types.
219 #define WXS_IS_ANYTYPE(i) \
220 (( (i)->type == XML_SCHEMA_TYPE_BASIC) && \
221 ( (WXS_TYPE_CAST (i))->builtInType == XML_SCHEMAS_ANYTYPE))
223 #define WXS_IS_COMPLEX(i) \
224 (((i)->type == XML_SCHEMA_TYPE_COMPLEX) || \
225 ((i)->builtInType == XML_SCHEMAS_ANYTYPE))
227 #define WXS_IS_SIMPLE(item) \
228 ((item->type == XML_SCHEMA_TYPE_SIMPLE) || \
229 ((item->type == XML_SCHEMA_TYPE_BASIC) && \
230 (item->builtInType != XML_SCHEMAS_ANYTYPE)))
232 #define WXS_IS_ANY_SIMPLE_TYPE(i) \
233 (((i)->type == XML_SCHEMA_TYPE_BASIC) && \
234 ((i)->builtInType == XML_SCHEMAS_ANYSIMPLETYPE))
236 #define WXS_IS_RESTRICTION(t) \
237 ((t)->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION)
239 #define WXS_IS_EXTENSION(t) \
240 ((t)->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION)
242 #define WXS_IS_TYPE_NOT_FIXED(i) \
243 (((i)->type != XML_SCHEMA_TYPE_BASIC) && \
244 (((i)->flags & XML_SCHEMAS_TYPE_INTERNAL_RESOLVED) == 0))
246 #define WXS_IS_TYPE_NOT_FIXED_1(item) \
247 (((item)->type != XML_SCHEMA_TYPE_BASIC) && \
248 (((item)->flags & XML_SCHEMAS_TYPE_FIXUP_1) == 0))
250 #define WXS_TYPE_IS_GLOBAL(t) ((t)->flags & XML_SCHEMAS_TYPE_GLOBAL)
252 #define WXS_TYPE_IS_LOCAL(t) (((t)->flags & XML_SCHEMAS_TYPE_GLOBAL) == 0)
254 * Macros for exclusively for complex types.
256 #define WXS_HAS_COMPLEX_CONTENT(item) \
257 ((item->contentType == XML_SCHEMA_CONTENT_MIXED) || \
258 (item->contentType == XML_SCHEMA_CONTENT_EMPTY) || \
259 (item->contentType == XML_SCHEMA_CONTENT_ELEMENTS))
261 #define WXS_HAS_SIMPLE_CONTENT(item) \
262 ((item->contentType == XML_SCHEMA_CONTENT_SIMPLE) || \
263 (item->contentType == XML_SCHEMA_CONTENT_BASIC))
265 #define WXS_HAS_MIXED_CONTENT(item) \
266 (item->contentType == XML_SCHEMA_CONTENT_MIXED)
268 #define WXS_EMPTIABLE(t) \
269 (xmlSchemaIsParticleEmptiable(WXS_PTC_CAST (t)->subtypes))
271 #define WXS_TYPE_CONTENTTYPE(t) (t)->subtypes
273 #define WXS_TYPE_PARTICLE(t) WXS_PTC_CAST (t)->subtypes
275 #define WXS_TYPE_PARTICLE_TERM(t) WXS_PARTICLE_TERM(WXS_TYPE_PARTICLE(t))
277 * Macros for exclusively for simple types.
279 #define WXS_LIST_ITEMTYPE(t) (t)->subtypes
281 #define WXS_IS_ATOMIC(t) (t->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC)
283 #define WXS_IS_LIST(t) (t->flags & XML_SCHEMAS_TYPE_VARIETY_LIST)
285 #define WXS_IS_UNION(t) (t->flags & XML_SCHEMAS_TYPE_VARIETY_UNION)
287 * Misc parser context macros.
289 #define WXS_CONSTRUCTOR(ctx) (ctx)->constructor
291 #define WXS_HAS_BUCKETS(ctx) \
292 ( (WXS_CONSTRUCTOR((ctx))->buckets != NULL) && \
293 (WXS_CONSTRUCTOR((ctx))->buckets->nbItems > 0) )
295 #define WXS_SUBST_GROUPS(ctx) WXS_CONSTRUCTOR((ctx))->substGroups
297 #define WXS_BUCKET(ctx) WXS_CONSTRUCTOR((ctx))->bucket
299 #define WXS_SCHEMA(ctx) (ctx)->schema
301 #define WXS_ADD_LOCAL(ctx, item) \
302 xmlSchemaAddItemSize(&(WXS_BUCKET(ctx)->locals), 10, item)
304 #define WXS_ADD_GLOBAL(ctx, item) \
305 xmlSchemaAddItemSize(&(WXS_BUCKET(ctx)->globals), 5, item)
307 #define WXS_ADD_PENDING(ctx, item) \
308 xmlSchemaAddItemSize(&((ctx)->constructor->pending), 10, item)
310 * xmlSchemaItemList macros.
312 #define WXS_ILIST_IS_EMPTY(l) ((l == NULL) || ((l)->nbItems == 0))
314 * Misc macros.
316 #define IS_SCHEMA(node, type) \
317 ((node != NULL) && (node->ns != NULL) && \
318 (xmlStrEqual(node->name, (const xmlChar *) type)) && \
319 (xmlStrEqual(node->ns->href, xmlSchemaNs)))
321 #define FREE_AND_NULL(str) if ((str) != NULL) { xmlFree((xmlChar *) (str)); str = NULL; }
324 * Since we put the default/fixed values into the dict, we can
325 * use pointer comparison for those values.
326 * REMOVED: (xmlStrEqual((v1), (v2)))
328 #define WXS_ARE_DEFAULT_STR_EQUAL(v1, v2) ((v1) == (v2))
330 #define INODE_NILLED(item) (item->flags & XML_SCHEMA_ELEM_INFO_NILLED)
332 #define CAN_PARSE_SCHEMA(b) (((b)->doc != NULL) && ((b)->parsed == 0))
334 #define HFAILURE if (res == -1) goto exit_failure;
336 #define HERROR if (res != 0) goto exit_error;
338 #define HSTOP(ctx) if ((ctx)->stop) goto exit;
340 * Some flags used for various schema constraints.
342 #define SUBSET_RESTRICTION 1<<0
343 #define SUBSET_EXTENSION 1<<1
344 #define SUBSET_SUBSTITUTION 1<<2
345 #define SUBSET_LIST 1<<3
346 #define SUBSET_UNION 1<<4
348 typedef struct _xmlSchemaNodeInfo xmlSchemaNodeInfo;
349 typedef xmlSchemaNodeInfo *xmlSchemaNodeInfoPtr;
351 typedef struct _xmlSchemaItemList xmlSchemaItemList;
352 typedef xmlSchemaItemList *xmlSchemaItemListPtr;
353 struct _xmlSchemaItemList {
354 void **items; /* used for dynamic addition of schemata */
355 int nbItems; /* used for dynamic addition of schemata */
356 int sizeItems; /* used for dynamic addition of schemata */
359 #define XML_SCHEMA_CTXT_PARSER 1
360 #define XML_SCHEMA_CTXT_VALIDATOR 2
362 typedef struct _xmlSchemaAbstractCtxt xmlSchemaAbstractCtxt;
363 typedef xmlSchemaAbstractCtxt *xmlSchemaAbstractCtxtPtr;
364 struct _xmlSchemaAbstractCtxt {
365 int type; /* E.g. XML_SCHEMA_CTXT_VALIDATOR */
368 typedef struct _xmlSchemaBucket xmlSchemaBucket;
369 typedef xmlSchemaBucket *xmlSchemaBucketPtr;
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
377 * xmlSchemaSchemaRelation:
379 * Used to create a graph of schema relationships.
381 typedef struct _xmlSchemaSchemaRelation xmlSchemaSchemaRelation;
382 typedef xmlSchemaSchemaRelation *xmlSchemaSchemaRelationPtr;
383 struct _xmlSchemaSchemaRelation {
384 xmlSchemaSchemaRelationPtr next;
385 int type; /* E.g. XML_SCHEMA_SCHEMA_IMPORT */
386 const xmlChar *importNamespace;
387 xmlSchemaBucketPtr bucket;
390 #define XML_SCHEMA_BUCKET_MARKED 1<<0
391 #define XML_SCHEMA_BUCKET_COMPS_ADDED 1<<1
393 struct _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. */
410 * xmlSchemaImport:
411 * (extends xmlSchemaBucket)
413 * Reflects a schema. Holds some information
414 * about the schema and its toplevel components. Duplicate
415 * toplevel components are not checked at this level.
417 typedef struct _xmlSchemaImport xmlSchemaImport;
418 typedef xmlSchemaImport *xmlSchemaImportPtr;
419 struct _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;
426 * For chameleon includes, @targetNamespace will be the
427 * targetNamespace of the including schema.
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;
444 * (extends xmlSchemaBucket)
446 typedef struct _xmlSchemaInclude xmlSchemaInclude;
447 typedef xmlSchemaInclude *xmlSchemaIncludePtr;
448 struct _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. */
463 /* The owning main or import schema bucket. */
464 xmlSchemaImportPtr ownerImport;
468 * xmlSchemaBasicItem:
470 * The abstract base type for schema components.
472 typedef struct _xmlSchemaBasicItem xmlSchemaBasicItem;
473 typedef xmlSchemaBasicItem *xmlSchemaBasicItemPtr;
474 struct _xmlSchemaBasicItem {
475 xmlSchemaTypeType type;
479 * xmlSchemaAnnotItem:
481 * The abstract base type for annotated schema components.
482 * (Extends xmlSchemaBasicItem)
484 typedef struct _xmlSchemaAnnotItem xmlSchemaAnnotItem;
485 typedef xmlSchemaAnnotItem *xmlSchemaAnnotItemPtr;
486 struct _xmlSchemaAnnotItem {
487 xmlSchemaTypeType type;
488 xmlSchemaAnnotPtr annot;
492 * xmlSchemaTreeItem:
494 * The abstract base type for tree-like structured schema components.
495 * (Extends xmlSchemaAnnotItem)
497 typedef struct _xmlSchemaTreeItem xmlSchemaTreeItem;
498 typedef xmlSchemaTreeItem *xmlSchemaTreeItemPtr;
499 struct _xmlSchemaTreeItem {
500 xmlSchemaTypeType type;
501 xmlSchemaAnnotPtr annot;
502 xmlSchemaTreeItemPtr next;
503 xmlSchemaTreeItemPtr children;
507 #define XML_SCHEMA_ATTR_USE_FIXED 1<<0
509 * xmlSchemaAttributeUsePtr:
511 * The abstract base type for tree-like structured schema components.
512 * (Extends xmlSchemaTreeItem)
514 typedef struct _xmlSchemaAttributeUse xmlSchemaAttributeUse;
515 typedef xmlSchemaAttributeUse *xmlSchemaAttributeUsePtr;
516 struct _xmlSchemaAttributeUse {
517 xmlSchemaTypeType type;
518 xmlSchemaAnnotPtr annot;
519 xmlSchemaAttributeUsePtr next; /* The next attr. use. */
521 * The attr. decl. OR a QName-ref. to an attr. decl. OR
522 * a QName-ref. to an attribute group definition.
524 xmlSchemaAttributePtr attrDecl;
526 int flags;
527 xmlNodePtr node;
528 int occurs; /* required, optional */
529 const xmlChar * defValue;
530 xmlSchemaValPtr defVal;
534 * xmlSchemaAttributeUseProhibPtr:
536 * A helper component to reflect attribute prohibitions.
537 * (Extends xmlSchemaBasicItem)
539 typedef struct _xmlSchemaAttributeUseProhib xmlSchemaAttributeUseProhib;
540 typedef xmlSchemaAttributeUseProhib *xmlSchemaAttributeUseProhibPtr;
541 struct _xmlSchemaAttributeUseProhib {
542 xmlSchemaTypeType type; /* == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB */
543 xmlNodePtr node;
544 const xmlChar *name;
545 const xmlChar *targetNamespace;
546 int isRef;
550 * xmlSchemaRedef:
552 typedef struct _xmlSchemaRedef xmlSchemaRedef;
553 typedef xmlSchemaRedef *xmlSchemaRedefPtr;
554 struct _xmlSchemaRedef {
555 xmlSchemaRedefPtr next;
556 xmlSchemaBasicItemPtr item; /* The redefining component. */
557 xmlSchemaBasicItemPtr reference; /* The referencing component. */
558 xmlSchemaBasicItemPtr target; /* The to-be-redefined component. */
559 const xmlChar *refName; /* The name of the to-be-redefined component. */
560 const xmlChar *refTargetNs; /* The target namespace of the
561 to-be-redefined comp. */
562 xmlSchemaBucketPtr targetBucket; /* The redefined schema. */
566 * xmlSchemaConstructionCtxt:
568 typedef struct _xmlSchemaConstructionCtxt xmlSchemaConstructionCtxt;
569 typedef xmlSchemaConstructionCtxt *xmlSchemaConstructionCtxtPtr;
570 struct _xmlSchemaConstructionCtxt {
571 xmlSchemaPtr mainSchema; /* The main schema. */
572 xmlSchemaBucketPtr mainBucket; /* The main schema bucket */
573 xmlDictPtr dict;
574 xmlSchemaItemListPtr buckets; /* List of schema buckets. */
575 /* xmlSchemaItemListPtr relations; */ /* List of schema relations. */
576 xmlSchemaBucketPtr bucket; /* The current schema bucket */
577 xmlSchemaItemListPtr pending; /* All Components of all schemas that
578 need to be fixed. */
579 xmlHashTablePtr substGroups;
580 xmlSchemaRedefPtr redefs;
581 xmlSchemaRedefPtr lastRedef;
584 #define XML_SCHEMAS_PARSE_ERROR 1
585 #define SCHEMAS_PARSE_OPTIONS XML_PARSE_NOENT
587 struct _xmlSchemaParserCtxt {
588 int type;
589 void *errCtxt; /* user specific error context */
590 xmlSchemaValidityErrorFunc error; /* the callback in case of errors */
591 xmlSchemaValidityWarningFunc warning; /* the callback in case of warning */
592 int err;
593 int nberrors;
594 xmlStructuredErrorFunc serror;
596 xmlSchemaConstructionCtxtPtr constructor;
597 int ownsConstructor; /* TODO: Move this to parser *flags*. */
599 /* xmlSchemaPtr topschema; */
600 /* xmlHashTablePtr namespaces; */
602 xmlSchemaPtr schema; /* The main schema in use */
603 int counter;
605 const xmlChar *URL;
606 xmlDocPtr doc;
607 int preserve; /* Whether the doc should be freed */
609 const char *buffer;
610 int size;
613 * Used to build complex element content models
615 xmlAutomataPtr am;
616 xmlAutomataStatePtr start;
617 xmlAutomataStatePtr end;
618 xmlAutomataStatePtr state;
620 xmlDictPtr dict; /* dictionnary for interned string names */
621 xmlSchemaTypePtr ctxtType; /* The current context simple/complex type */
622 int options;
623 xmlSchemaValidCtxtPtr vctxt;
624 int isS4S;
625 int isRedefine;
626 int xsiAssemble;
627 int stop; /* If the parser should stop; i.e. a critical error. */
628 const xmlChar *targetNamespace;
629 xmlSchemaBucketPtr redefined; /* The schema to be redefined. */
631 xmlSchemaRedefPtr redef; /* Used for redefinitions. */
632 int redefCounter; /* Used for redefinitions. */
633 xmlSchemaItemListPtr attrProhibs;
637 * xmlSchemaQNameRef:
639 * A component reference item (not a schema component)
640 * (Extends xmlSchemaBasicItem)
642 typedef struct _xmlSchemaQNameRef xmlSchemaQNameRef;
643 typedef xmlSchemaQNameRef *xmlSchemaQNameRefPtr;
644 struct _xmlSchemaQNameRef {
645 xmlSchemaTypeType type;
646 xmlSchemaBasicItemPtr item; /* The resolved referenced item. */
647 xmlSchemaTypeType itemType;
648 const xmlChar *name;
649 const xmlChar *targetNamespace;
650 xmlNodePtr node;
654 * xmlSchemaParticle:
656 * A particle component.
657 * (Extends xmlSchemaTreeItem)
659 typedef struct _xmlSchemaParticle xmlSchemaParticle;
660 typedef xmlSchemaParticle *xmlSchemaParticlePtr;
661 struct _xmlSchemaParticle {
662 xmlSchemaTypeType type;
663 xmlSchemaAnnotPtr annot;
664 xmlSchemaTreeItemPtr next; /* next particle */
665 xmlSchemaTreeItemPtr children; /* the "term" (e.g. a model group,
666 a group definition, a XML_SCHEMA_EXTRA_QNAMEREF (if a reference),
667 etc.) */
668 int minOccurs;
669 int maxOccurs;
670 xmlNodePtr node;
674 * xmlSchemaModelGroup:
676 * A model group component.
677 * (Extends xmlSchemaTreeItem)
679 typedef struct _xmlSchemaModelGroup xmlSchemaModelGroup;
680 typedef xmlSchemaModelGroup *xmlSchemaModelGroupPtr;
681 struct _xmlSchemaModelGroup {
682 xmlSchemaTypeType type; /* XML_SCHEMA_TYPE_SEQUENCE, XML_SCHEMA_TYPE_CHOICE, XML_SCHEMA_TYPE_ALL */
683 xmlSchemaAnnotPtr annot;
684 xmlSchemaTreeItemPtr next; /* not used */
685 xmlSchemaTreeItemPtr children; /* first particle (OR "element decl" OR "wildcard") */
686 xmlNodePtr node;
689 #define XML_SCHEMA_MODEL_GROUP_DEF_MARKED 1<<0
690 #define XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED 1<<1
692 * xmlSchemaModelGroupDef:
694 * A model group definition component.
695 * (Extends xmlSchemaTreeItem)
697 typedef struct _xmlSchemaModelGroupDef xmlSchemaModelGroupDef;
698 typedef xmlSchemaModelGroupDef *xmlSchemaModelGroupDefPtr;
699 struct _xmlSchemaModelGroupDef {
700 xmlSchemaTypeType type; /* XML_SCHEMA_TYPE_GROUP */
701 xmlSchemaAnnotPtr annot;
702 xmlSchemaTreeItemPtr next; /* not used */
703 xmlSchemaTreeItemPtr children; /* the "model group" */
704 const xmlChar *name;
705 const xmlChar *targetNamespace;
706 xmlNodePtr node;
707 int flags;
710 typedef struct _xmlSchemaIDC xmlSchemaIDC;
711 typedef xmlSchemaIDC *xmlSchemaIDCPtr;
714 * xmlSchemaIDCSelect:
716 * The identity-constraint "field" and "selector" item, holding the
717 * XPath expression.
719 typedef struct _xmlSchemaIDCSelect xmlSchemaIDCSelect;
720 typedef xmlSchemaIDCSelect *xmlSchemaIDCSelectPtr;
721 struct _xmlSchemaIDCSelect {
722 xmlSchemaIDCSelectPtr next;
723 xmlSchemaIDCPtr idc;
724 int index; /* an index position if significant for IDC key-sequences */
725 const xmlChar *xpath; /* the XPath expression */
726 void *xpathComp; /* the compiled XPath expression */
730 * xmlSchemaIDC:
732 * The identity-constraint definition component.
733 * (Extends xmlSchemaAnnotItem)
736 struct _xmlSchemaIDC {
737 xmlSchemaTypeType type;
738 xmlSchemaAnnotPtr annot;
739 xmlSchemaIDCPtr next;
740 xmlNodePtr node;
741 const xmlChar *name;
742 const xmlChar *targetNamespace;
743 xmlSchemaIDCSelectPtr selector;
744 xmlSchemaIDCSelectPtr fields;
745 int nbFields;
746 xmlSchemaQNameRefPtr ref;
750 * xmlSchemaIDCAug:
752 * The augmented IDC information used for validation.
754 typedef struct _xmlSchemaIDCAug xmlSchemaIDCAug;
755 typedef xmlSchemaIDCAug *xmlSchemaIDCAugPtr;
756 struct _xmlSchemaIDCAug {
757 xmlSchemaIDCAugPtr next; /* next in a list */
758 xmlSchemaIDCPtr def; /* the IDC definition */
759 int keyrefDepth; /* the lowest tree level to which IDC
760 tables need to be bubbled upwards */
764 * xmlSchemaPSVIIDCKeySequence:
766 * The key sequence of a node table item.
768 typedef struct _xmlSchemaPSVIIDCKey xmlSchemaPSVIIDCKey;
769 typedef xmlSchemaPSVIIDCKey *xmlSchemaPSVIIDCKeyPtr;
770 struct _xmlSchemaPSVIIDCKey {
771 xmlSchemaTypePtr type;
772 xmlSchemaValPtr val;
776 * xmlSchemaPSVIIDCNode:
778 * The node table item of a node table.
780 typedef struct _xmlSchemaPSVIIDCNode xmlSchemaPSVIIDCNode;
781 typedef xmlSchemaPSVIIDCNode *xmlSchemaPSVIIDCNodePtr;
782 struct _xmlSchemaPSVIIDCNode {
783 xmlNodePtr node;
784 xmlSchemaPSVIIDCKeyPtr *keys;
785 int nodeLine;
786 int nodeQNameID;
791 * xmlSchemaPSVIIDCBinding:
793 * The identity-constraint binding item of the [identity-constraint table].
795 typedef struct _xmlSchemaPSVIIDCBinding xmlSchemaPSVIIDCBinding;
796 typedef xmlSchemaPSVIIDCBinding *xmlSchemaPSVIIDCBindingPtr;
797 struct _xmlSchemaPSVIIDCBinding {
798 xmlSchemaPSVIIDCBindingPtr next; /* next binding of a specific node */
799 xmlSchemaIDCPtr definition; /* the IDC definition */
800 xmlSchemaPSVIIDCNodePtr *nodeTable; /* array of key-sequences */
801 int nbNodes; /* number of entries in the node table */
802 int sizeNodes; /* size of the node table */
803 xmlSchemaItemListPtr dupls;
807 #define XPATH_STATE_OBJ_TYPE_IDC_SELECTOR 1
808 #define XPATH_STATE_OBJ_TYPE_IDC_FIELD 2
810 #define XPATH_STATE_OBJ_MATCHES -2
811 #define XPATH_STATE_OBJ_BLOCKED -3
813 typedef struct _xmlSchemaIDCMatcher xmlSchemaIDCMatcher;
814 typedef xmlSchemaIDCMatcher *xmlSchemaIDCMatcherPtr;
817 * xmlSchemaIDCStateObj:
819 * The state object used to evaluate XPath expressions.
821 typedef struct _xmlSchemaIDCStateObj xmlSchemaIDCStateObj;
822 typedef xmlSchemaIDCStateObj *xmlSchemaIDCStateObjPtr;
823 struct _xmlSchemaIDCStateObj {
824 int type;
825 xmlSchemaIDCStateObjPtr next; /* next if in a list */
826 int depth; /* depth of creation */
827 int *history; /* list of (depth, state-id) tuples */
828 int nbHistory;
829 int sizeHistory;
830 xmlSchemaIDCMatcherPtr matcher; /* the correspondent field/selector
831 matcher */
832 xmlSchemaIDCSelectPtr sel;
833 void *xpathCtxt;
836 #define IDC_MATCHER 0
839 * xmlSchemaIDCMatcher:
841 * Used to evaluate IDC selectors (and fields).
843 struct _xmlSchemaIDCMatcher {
844 int type;
845 int depth; /* the tree depth at creation time */
846 xmlSchemaIDCMatcherPtr next; /* next in the list */
847 xmlSchemaIDCMatcherPtr nextCached; /* next in the cache list */
848 xmlSchemaIDCAugPtr aidc; /* the augmented IDC item */
849 int idcType;
850 xmlSchemaPSVIIDCKeyPtr **keySeqs; /* the key-sequences of the target
851 elements */
852 int sizeKeySeqs;
853 xmlSchemaItemListPtr targets; /* list of target-node
854 (xmlSchemaPSVIIDCNodePtr) entries */
858 * Element info flags.
860 #define XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES 1<<0
861 #define XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES 1<<1
862 #define XML_SCHEMA_ELEM_INFO_NILLED 1<<2
863 #define XML_SCHEMA_ELEM_INFO_LOCAL_TYPE 1<<3
865 #define XML_SCHEMA_NODE_INFO_VALUE_NEEDED 1<<4
866 #define XML_SCHEMA_ELEM_INFO_EMPTY 1<<5
867 #define XML_SCHEMA_ELEM_INFO_HAS_CONTENT 1<<6
869 #define XML_SCHEMA_ELEM_INFO_HAS_ELEM_CONTENT 1<<7
870 #define XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT 1<<8
871 #define XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED 1<<9
872 #define XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE 1<<10
875 * xmlSchemaNodeInfo:
877 * Holds information of an element node.
879 struct _xmlSchemaNodeInfo {
880 int nodeType;
881 xmlNodePtr node;
882 int nodeLine;
883 const xmlChar *localName;
884 const xmlChar *nsName;
885 const xmlChar *value;
886 xmlSchemaValPtr val; /* the pre-computed value if any */
887 xmlSchemaTypePtr typeDef; /* the complex/simple type definition if any */
889 int flags; /* combination of node info flags */
891 int valNeeded;
892 int normVal;
894 xmlSchemaElementPtr decl; /* the element/attribute declaration */
895 int depth;
896 xmlSchemaPSVIIDCBindingPtr idcTable; /* the table of PSVI IDC bindings
897 for the scope element*/
898 xmlSchemaIDCMatcherPtr idcMatchers; /* the IDC matchers for the scope
899 element */
900 xmlRegExecCtxtPtr regexCtxt;
902 const xmlChar **nsBindings; /* Namespace bindings on this element */
903 int nbNsBindings;
904 int sizeNsBindings;
906 int hasKeyrefs;
907 int appliedXPath; /* Indicates that an XPath has been applied. */
910 #define XML_SCHEMAS_ATTR_UNKNOWN 1
911 #define XML_SCHEMAS_ATTR_ASSESSED 2
912 #define XML_SCHEMAS_ATTR_PROHIBITED 3
913 #define XML_SCHEMAS_ATTR_ERR_MISSING 4
914 #define XML_SCHEMAS_ATTR_INVALID_VALUE 5
915 #define XML_SCHEMAS_ATTR_ERR_NO_TYPE 6
916 #define XML_SCHEMAS_ATTR_ERR_FIXED_VALUE 7
917 #define XML_SCHEMAS_ATTR_DEFAULT 8
918 #define XML_SCHEMAS_ATTR_VALIDATE_VALUE 9
919 #define XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL 10
920 #define XML_SCHEMAS_ATTR_HAS_ATTR_USE 11
921 #define XML_SCHEMAS_ATTR_HAS_ATTR_DECL 12
922 #define XML_SCHEMAS_ATTR_WILD_SKIP 13
923 #define XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL 14
924 #define XML_SCHEMAS_ATTR_ERR_WILD_DUPLICATE_ID 15
925 #define XML_SCHEMAS_ATTR_ERR_WILD_AND_USE_ID 16
926 #define XML_SCHEMAS_ATTR_META 17
928 * @metaType values of xmlSchemaAttrInfo.
930 #define XML_SCHEMA_ATTR_INFO_META_XSI_TYPE 1
931 #define XML_SCHEMA_ATTR_INFO_META_XSI_NIL 2
932 #define XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC 3
933 #define XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC 4
934 #define XML_SCHEMA_ATTR_INFO_META_XMLNS 5
936 typedef struct _xmlSchemaAttrInfo xmlSchemaAttrInfo;
937 typedef xmlSchemaAttrInfo *xmlSchemaAttrInfoPtr;
938 struct _xmlSchemaAttrInfo {
939 int nodeType;
940 xmlNodePtr node;
941 int nodeLine;
942 const xmlChar *localName;
943 const xmlChar *nsName;
944 const xmlChar *value;
945 xmlSchemaValPtr val; /* the pre-computed value if any */
946 xmlSchemaTypePtr typeDef; /* the complex/simple type definition if any */
947 int flags; /* combination of node info flags */
949 xmlSchemaAttributePtr decl; /* the attribute declaration */
950 xmlSchemaAttributeUsePtr use; /* the attribute use */
951 int state;
952 int metaType;
953 const xmlChar *vcValue; /* the value constraint value */
954 xmlSchemaNodeInfoPtr parent;
958 #define XML_SCHEMA_VALID_CTXT_FLAG_STREAM 1
960 * xmlSchemaValidCtxt:
962 * A Schemas validation context
964 struct _xmlSchemaValidCtxt {
965 int type;
966 void *errCtxt; /* user specific data block */
967 xmlSchemaValidityErrorFunc error; /* the callback in case of errors */
968 xmlSchemaValidityWarningFunc warning; /* the callback in case of warning */
969 xmlStructuredErrorFunc serror;
971 xmlSchemaPtr schema; /* The schema in use */
972 xmlDocPtr doc;
973 xmlParserInputBufferPtr input;
974 xmlCharEncoding enc;
975 xmlSAXHandlerPtr sax;
976 xmlParserCtxtPtr parserCtxt;
977 void *user_data; /* TODO: What is this for? */
979 int err;
980 int nberrors;
982 xmlNodePtr node;
983 xmlNodePtr cur;
984 /* xmlSchemaTypePtr type; */
986 xmlRegExecCtxtPtr regexp;
987 xmlSchemaValPtr value;
989 int valueWS;
990 int options;
991 xmlNodePtr validationRoot;
992 xmlSchemaParserCtxtPtr pctxt;
993 int xsiAssemble;
995 int depth;
996 xmlSchemaNodeInfoPtr *elemInfos; /* array of element informations */
997 int sizeElemInfos;
998 xmlSchemaNodeInfoPtr inode; /* the current element information */
1000 xmlSchemaIDCAugPtr aidcs; /* a list of augmented IDC informations */
1002 xmlSchemaIDCStateObjPtr xpathStates; /* first active state object. */
1003 xmlSchemaIDCStateObjPtr xpathStatePool; /* first stored state object. */
1004 xmlSchemaIDCMatcherPtr idcMatcherCache; /* Cache for IDC matcher objects. */
1006 xmlSchemaPSVIIDCNodePtr *idcNodes; /* list of all IDC node-table entries*/
1007 int nbIdcNodes;
1008 int sizeIdcNodes;
1010 xmlSchemaPSVIIDCKeyPtr *idcKeys; /* list of all IDC node-table entries */
1011 int nbIdcKeys;
1012 int sizeIdcKeys;
1014 int flags;
1016 xmlDictPtr dict;
1018 #ifdef LIBXML_READER_ENABLED
1019 xmlTextReaderPtr reader;
1020 #endif
1022 xmlSchemaAttrInfoPtr *attrInfos;
1023 int nbAttrInfos;
1024 int sizeAttrInfos;
1026 int skipDepth;
1027 xmlSchemaItemListPtr nodeQNames;
1028 int hasKeyrefs;
1029 int createIDCNodeTables;
1030 int psviExposeIDCNodeTables;
1034 * xmlSchemaSubstGroup:
1038 typedef struct _xmlSchemaSubstGroup xmlSchemaSubstGroup;
1039 typedef xmlSchemaSubstGroup *xmlSchemaSubstGroupPtr;
1040 struct _xmlSchemaSubstGroup {
1041 xmlSchemaElementPtr head;
1042 xmlSchemaItemListPtr members;
1045 /************************************************************************
1047 * Some predeclarations *
1049 ************************************************************************/
1051 static int xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt,
1052 xmlSchemaPtr schema,
1053 xmlNodePtr node);
1054 static int xmlSchemaParseRedefine(xmlSchemaParserCtxtPtr ctxt,
1055 xmlSchemaPtr schema,
1056 xmlNodePtr node);
1057 static int
1058 xmlSchemaTypeFixup(xmlSchemaTypePtr type,
1059 xmlSchemaAbstractCtxtPtr ctxt);
1060 static const xmlChar *
1061 xmlSchemaFacetTypeToString(xmlSchemaTypeType type);
1062 static int
1063 xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1064 xmlNodePtr node);
1065 static int
1066 xmlSchemaCheckFacetValues(xmlSchemaTypePtr typeDecl,
1067 xmlSchemaParserCtxtPtr ctxt);
1068 static void
1069 xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt);
1070 static xmlSchemaWhitespaceValueType
1071 xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type);
1072 static xmlSchemaTreeItemPtr
1073 xmlSchemaParseModelGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1074 xmlNodePtr node, xmlSchemaTypeType type,
1075 int withParticle);
1076 static const xmlChar *
1077 xmlSchemaGetComponentTypeStr(xmlSchemaBasicItemPtr item);
1078 static xmlSchemaTypeLinkPtr
1079 xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type);
1080 static void
1081 xmlSchemaInternalErr(xmlSchemaAbstractCtxtPtr actxt,
1082 const char *funcName,
1083 const char *message);
1084 static int
1085 xmlSchemaCheckCOSSTDerivedOK(xmlSchemaAbstractCtxtPtr ctxt,
1086 xmlSchemaTypePtr type,
1087 xmlSchemaTypePtr baseType,
1088 int subset);
1089 static void
1090 xmlSchemaCheckElementDeclComponent(xmlSchemaElementPtr elemDecl,
1091 xmlSchemaParserCtxtPtr ctxt);
1092 static void
1093 xmlSchemaComponentListFree(xmlSchemaItemListPtr list);
1094 static xmlSchemaQNameRefPtr
1095 xmlSchemaParseAttributeGroupRef(xmlSchemaParserCtxtPtr pctxt,
1096 xmlSchemaPtr schema,
1097 xmlNodePtr node);
1099 /************************************************************************
1101 * Helper functions *
1103 ************************************************************************/
1106 * xmlSchemaItemTypeToStr:
1107 * @type: the type of the schema item
1109 * Returns the component name of a schema item.
1111 static const xmlChar *
1112 xmlSchemaItemTypeToStr(xmlSchemaTypeType type)
1114 switch (type) {
1115 case XML_SCHEMA_TYPE_BASIC:
1116 return(BAD_CAST "simple type definition");
1117 case XML_SCHEMA_TYPE_SIMPLE:
1118 return(BAD_CAST "simple type definition");
1119 case XML_SCHEMA_TYPE_COMPLEX:
1120 return(BAD_CAST "complex type definition");
1121 case XML_SCHEMA_TYPE_ELEMENT:
1122 return(BAD_CAST "element declaration");
1123 case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
1124 return(BAD_CAST "attribute use");
1125 case XML_SCHEMA_TYPE_ATTRIBUTE:
1126 return(BAD_CAST "attribute declaration");
1127 case XML_SCHEMA_TYPE_GROUP:
1128 return(BAD_CAST "model group definition");
1129 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1130 return(BAD_CAST "attribute group definition");
1131 case XML_SCHEMA_TYPE_NOTATION:
1132 return(BAD_CAST "notation declaration");
1133 case XML_SCHEMA_TYPE_SEQUENCE:
1134 return(BAD_CAST "model group (sequence)");
1135 case XML_SCHEMA_TYPE_CHOICE:
1136 return(BAD_CAST "model group (choice)");
1137 case XML_SCHEMA_TYPE_ALL:
1138 return(BAD_CAST "model group (all)");
1139 case XML_SCHEMA_TYPE_PARTICLE:
1140 return(BAD_CAST "particle");
1141 case XML_SCHEMA_TYPE_IDC_UNIQUE:
1142 return(BAD_CAST "unique identity-constraint");
1143 /* return(BAD_CAST "IDC (unique)"); */
1144 case XML_SCHEMA_TYPE_IDC_KEY:
1145 return(BAD_CAST "key identity-constraint");
1146 /* return(BAD_CAST "IDC (key)"); */
1147 case XML_SCHEMA_TYPE_IDC_KEYREF:
1148 return(BAD_CAST "keyref identity-constraint");
1149 /* return(BAD_CAST "IDC (keyref)"); */
1150 case XML_SCHEMA_TYPE_ANY:
1151 return(BAD_CAST "wildcard (any)");
1152 case XML_SCHEMA_EXTRA_QNAMEREF:
1153 return(BAD_CAST "[helper component] QName reference");
1154 case XML_SCHEMA_EXTRA_ATTR_USE_PROHIB:
1155 return(BAD_CAST "[helper component] attribute use prohibition");
1156 default:
1157 return(BAD_CAST "Not a schema component");
1162 * xmlSchemaGetComponentTypeStr:
1163 * @type: the type of the schema item
1165 * Returns the component name of a schema item.
1167 static const xmlChar *
1168 xmlSchemaGetComponentTypeStr(xmlSchemaBasicItemPtr item)
1170 switch (item->type) {
1171 case XML_SCHEMA_TYPE_BASIC:
1172 if (WXS_IS_COMPLEX(WXS_TYPE_CAST item))
1173 return(BAD_CAST "complex type definition");
1174 else
1175 return(BAD_CAST "simple type definition");
1176 default:
1177 return(xmlSchemaItemTypeToStr(item->type));
1182 * xmlSchemaGetComponentNode:
1183 * @item: a schema component
1185 * Returns node associated with the schema component.
1186 * NOTE that such a node need not be available; plus, a component's
1187 * node need not to reflect the component directly, since there is no
1188 * one-to-one relationship between the XML Schema representation and
1189 * the component representation.
1191 static xmlNodePtr
1192 xmlSchemaGetComponentNode(xmlSchemaBasicItemPtr item)
1194 switch (item->type) {
1195 case XML_SCHEMA_TYPE_ELEMENT:
1196 return (((xmlSchemaElementPtr) item)->node);
1197 case XML_SCHEMA_TYPE_ATTRIBUTE:
1198 return (((xmlSchemaAttributePtr) item)->node);
1199 case XML_SCHEMA_TYPE_COMPLEX:
1200 case XML_SCHEMA_TYPE_SIMPLE:
1201 return (((xmlSchemaTypePtr) item)->node);
1202 case XML_SCHEMA_TYPE_ANY:
1203 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
1204 return (((xmlSchemaWildcardPtr) item)->node);
1205 case XML_SCHEMA_TYPE_PARTICLE:
1206 return (((xmlSchemaParticlePtr) item)->node);
1207 case XML_SCHEMA_TYPE_SEQUENCE:
1208 case XML_SCHEMA_TYPE_CHOICE:
1209 case XML_SCHEMA_TYPE_ALL:
1210 return (((xmlSchemaModelGroupPtr) item)->node);
1211 case XML_SCHEMA_TYPE_GROUP:
1212 return (((xmlSchemaModelGroupDefPtr) item)->node);
1213 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1214 return (((xmlSchemaAttributeGroupPtr) item)->node);
1215 case XML_SCHEMA_TYPE_IDC_UNIQUE:
1216 case XML_SCHEMA_TYPE_IDC_KEY:
1217 case XML_SCHEMA_TYPE_IDC_KEYREF:
1218 return (((xmlSchemaIDCPtr) item)->node);
1219 case XML_SCHEMA_EXTRA_QNAMEREF:
1220 return(((xmlSchemaQNameRefPtr) item)->node);
1221 /* TODO: What to do with NOTATIONs?
1222 case XML_SCHEMA_TYPE_NOTATION:
1223 return (((xmlSchemaNotationPtr) item)->node);
1225 case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
1226 return (((xmlSchemaAttributeUsePtr) item)->node);
1227 default:
1228 return (NULL);
1232 #if 0
1234 * xmlSchemaGetNextComponent:
1235 * @item: a schema component
1237 * Returns the next sibling of the schema component.
1239 static xmlSchemaBasicItemPtr
1240 xmlSchemaGetNextComponent(xmlSchemaBasicItemPtr item)
1242 switch (item->type) {
1243 case XML_SCHEMA_TYPE_ELEMENT:
1244 return ((xmlSchemaBasicItemPtr) ((xmlSchemaElementPtr) item)->next);
1245 case XML_SCHEMA_TYPE_ATTRIBUTE:
1246 return ((xmlSchemaBasicItemPtr) ((xmlSchemaAttributePtr) item)->next);
1247 case XML_SCHEMA_TYPE_COMPLEX:
1248 case XML_SCHEMA_TYPE_SIMPLE:
1249 return ((xmlSchemaBasicItemPtr) ((xmlSchemaTypePtr) item)->next);
1250 case XML_SCHEMA_TYPE_ANY:
1251 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
1252 return (NULL);
1253 case XML_SCHEMA_TYPE_PARTICLE:
1254 return ((xmlSchemaBasicItemPtr) ((xmlSchemaParticlePtr) item)->next);
1255 case XML_SCHEMA_TYPE_SEQUENCE:
1256 case XML_SCHEMA_TYPE_CHOICE:
1257 case XML_SCHEMA_TYPE_ALL:
1258 return (NULL);
1259 case XML_SCHEMA_TYPE_GROUP:
1260 return (NULL);
1261 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1262 return ((xmlSchemaBasicItemPtr) ((xmlSchemaAttributeGroupPtr) item)->next);
1263 case XML_SCHEMA_TYPE_IDC_UNIQUE:
1264 case XML_SCHEMA_TYPE_IDC_KEY:
1265 case XML_SCHEMA_TYPE_IDC_KEYREF:
1266 return ((xmlSchemaBasicItemPtr) ((xmlSchemaIDCPtr) item)->next);
1267 default:
1268 return (NULL);
1271 #endif
1275 * xmlSchemaFormatQName:
1276 * @buf: the string buffer
1277 * @namespaceName: the namespace name
1278 * @localName: the local name
1280 * Returns the given QName in the format "{namespaceName}localName" or
1281 * just "localName" if @namespaceName is NULL.
1283 * Returns the localName if @namespaceName is NULL, a formatted
1284 * string otherwise.
1286 static const xmlChar*
1287 xmlSchemaFormatQName(xmlChar **buf,
1288 const xmlChar *namespaceName,
1289 const xmlChar *localName)
1291 FREE_AND_NULL(*buf)
1292 if (namespaceName != NULL) {
1293 *buf = xmlStrdup(BAD_CAST "{");
1294 *buf = xmlStrcat(*buf, namespaceName);
1295 *buf = xmlStrcat(*buf, BAD_CAST "}");
1297 if (localName != NULL) {
1298 if (namespaceName == NULL)
1299 return(localName);
1300 *buf = xmlStrcat(*buf, localName);
1301 } else {
1302 *buf = xmlStrcat(*buf, BAD_CAST "(NULL)");
1304 return ((const xmlChar *) *buf);
1307 static const xmlChar*
1308 xmlSchemaFormatQNameNs(xmlChar **buf, xmlNsPtr ns, const xmlChar *localName)
1310 if (ns != NULL)
1311 return (xmlSchemaFormatQName(buf, ns->href, localName));
1312 else
1313 return (xmlSchemaFormatQName(buf, NULL, localName));
1316 static const xmlChar *
1317 xmlSchemaGetComponentName(xmlSchemaBasicItemPtr item)
1319 switch (item->type) {
1320 case XML_SCHEMA_TYPE_ELEMENT:
1321 return (((xmlSchemaElementPtr) item)->name);
1322 case XML_SCHEMA_TYPE_ATTRIBUTE:
1323 return (((xmlSchemaAttributePtr) item)->name);
1324 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1325 return (((xmlSchemaAttributeGroupPtr) item)->name);
1326 case XML_SCHEMA_TYPE_BASIC:
1327 case XML_SCHEMA_TYPE_SIMPLE:
1328 case XML_SCHEMA_TYPE_COMPLEX:
1329 return (((xmlSchemaTypePtr) item)->name);
1330 case XML_SCHEMA_TYPE_GROUP:
1331 return (((xmlSchemaModelGroupDefPtr) item)->name);
1332 case XML_SCHEMA_TYPE_IDC_KEY:
1333 case XML_SCHEMA_TYPE_IDC_UNIQUE:
1334 case XML_SCHEMA_TYPE_IDC_KEYREF:
1335 return (((xmlSchemaIDCPtr) item)->name);
1336 case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
1337 if (WXS_ATTRUSE_DECL(item) != NULL) {
1338 return(xmlSchemaGetComponentName(
1339 WXS_BASIC_CAST WXS_ATTRUSE_DECL(item)));
1340 } else
1341 return(NULL);
1342 case XML_SCHEMA_EXTRA_QNAMEREF:
1343 return (((xmlSchemaQNameRefPtr) item)->name);
1344 case XML_SCHEMA_TYPE_NOTATION:
1345 return (((xmlSchemaNotationPtr) item)->name);
1346 default:
1348 * Other components cannot have names.
1350 break;
1352 return (NULL);
1355 #define xmlSchemaGetQNameRefName(r) (WXS_QNAME_CAST (r))->name
1356 #define xmlSchemaGetQNameRefTargetNs(r) (WXS_QNAME_CAST (r))->targetNamespace
1358 static const xmlChar *
1359 xmlSchemaGetQNameRefName(void *ref)
1361 return(((xmlSchemaQNameRefPtr) ref)->name);
1364 static const xmlChar *
1365 xmlSchemaGetQNameRefTargetNs(void *ref)
1367 return(((xmlSchemaQNameRefPtr) ref)->targetNamespace);
1371 static const xmlChar *
1372 xmlSchemaGetComponentTargetNs(xmlSchemaBasicItemPtr item)
1374 switch (item->type) {
1375 case XML_SCHEMA_TYPE_ELEMENT:
1376 return (((xmlSchemaElementPtr) item)->targetNamespace);
1377 case XML_SCHEMA_TYPE_ATTRIBUTE:
1378 return (((xmlSchemaAttributePtr) item)->targetNamespace);
1379 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1380 return (((xmlSchemaAttributeGroupPtr) item)->targetNamespace);
1381 case XML_SCHEMA_TYPE_BASIC:
1382 return (BAD_CAST "http://www.w3.org/2001/XMLSchema");
1383 case XML_SCHEMA_TYPE_SIMPLE:
1384 case XML_SCHEMA_TYPE_COMPLEX:
1385 return (((xmlSchemaTypePtr) item)->targetNamespace);
1386 case XML_SCHEMA_TYPE_GROUP:
1387 return (((xmlSchemaModelGroupDefPtr) item)->targetNamespace);
1388 case XML_SCHEMA_TYPE_IDC_KEY:
1389 case XML_SCHEMA_TYPE_IDC_UNIQUE:
1390 case XML_SCHEMA_TYPE_IDC_KEYREF:
1391 return (((xmlSchemaIDCPtr) item)->targetNamespace);
1392 case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
1393 if (WXS_ATTRUSE_DECL(item) != NULL) {
1394 return(xmlSchemaGetComponentTargetNs(
1395 WXS_BASIC_CAST WXS_ATTRUSE_DECL(item)));
1397 /* TODO: Will returning NULL break something? */
1398 break;
1399 case XML_SCHEMA_EXTRA_QNAMEREF:
1400 return (((xmlSchemaQNameRefPtr) item)->targetNamespace);
1401 case XML_SCHEMA_TYPE_NOTATION:
1402 return (((xmlSchemaNotationPtr) item)->targetNamespace);
1403 default:
1405 * Other components cannot have names.
1407 break;
1409 return (NULL);
1412 static const xmlChar*
1413 xmlSchemaGetComponentQName(xmlChar **buf,
1414 void *item)
1416 return (xmlSchemaFormatQName(buf,
1417 xmlSchemaGetComponentTargetNs((xmlSchemaBasicItemPtr) item),
1418 xmlSchemaGetComponentName((xmlSchemaBasicItemPtr) item)));
1421 static const xmlChar*
1422 xmlSchemaGetComponentDesignation(xmlChar **buf, void *item)
1424 xmlChar *str = NULL;
1426 *buf = xmlStrcat(*buf, WXS_ITEM_TYPE_NAME(item));
1427 *buf = xmlStrcat(*buf, BAD_CAST " '");
1428 *buf = xmlStrcat(*buf, xmlSchemaGetComponentQName(&str,
1429 (xmlSchemaBasicItemPtr) item));
1430 *buf = xmlStrcat(*buf, BAD_CAST "'");
1431 FREE_AND_NULL(str);
1432 return(*buf);
1435 static const xmlChar*
1436 xmlSchemaGetIDCDesignation(xmlChar **buf, xmlSchemaIDCPtr idc)
1438 return(xmlSchemaGetComponentDesignation(buf, idc));
1442 * xmlSchemaWildcardPCToString:
1443 * @pc: the type of processContents
1445 * Returns a string representation of the type of
1446 * processContents.
1448 static const xmlChar *
1449 xmlSchemaWildcardPCToString(int pc)
1451 switch (pc) {
1452 case XML_SCHEMAS_ANY_SKIP:
1453 return (BAD_CAST "skip");
1454 case XML_SCHEMAS_ANY_LAX:
1455 return (BAD_CAST "lax");
1456 case XML_SCHEMAS_ANY_STRICT:
1457 return (BAD_CAST "strict");
1458 default:
1459 return (BAD_CAST "invalid process contents");
1464 * xmlSchemaGetCanonValueWhtspExt:
1465 * @val: the precomputed value
1466 * @retValue: the returned value
1467 * @ws: the whitespace type of the value
1469 * Get a the cononical representation of the value.
1470 * The caller has to free the returned retValue.
1472 * Returns 0 if the value could be built and -1 in case of
1473 * API errors or if the value type is not supported yet.
1475 static int
1476 xmlSchemaGetCanonValueWhtspExt(xmlSchemaValPtr val,
1477 xmlSchemaWhitespaceValueType ws,
1478 xmlChar **retValue)
1480 int list;
1481 xmlSchemaValType valType;
1482 const xmlChar *value, *value2 = NULL;
1485 if ((retValue == NULL) || (val == NULL))
1486 return (-1);
1487 list = xmlSchemaValueGetNext(val) ? 1 : 0;
1488 *retValue = NULL;
1489 do {
1490 value = NULL;
1491 valType = xmlSchemaGetValType(val);
1492 switch (valType) {
1493 case XML_SCHEMAS_STRING:
1494 case XML_SCHEMAS_NORMSTRING:
1495 case XML_SCHEMAS_ANYSIMPLETYPE:
1496 value = xmlSchemaValueGetAsString(val);
1497 if (value != NULL) {
1498 if (ws == XML_SCHEMA_WHITESPACE_COLLAPSE)
1499 value2 = xmlSchemaCollapseString(value);
1500 else if (ws == XML_SCHEMA_WHITESPACE_REPLACE)
1501 value2 = xmlSchemaWhiteSpaceReplace(value);
1502 if (value2 != NULL)
1503 value = value2;
1505 break;
1506 default:
1507 if (xmlSchemaGetCanonValue(val, &value2) == -1) {
1508 if (value2 != NULL)
1509 xmlFree((xmlChar *) value2);
1510 goto internal_error;
1512 value = value2;
1514 if (*retValue == NULL)
1515 if (value == NULL) {
1516 if (! list)
1517 *retValue = xmlStrdup(BAD_CAST "");
1518 } else
1519 *retValue = xmlStrdup(value);
1520 else if (value != NULL) {
1521 /* List. */
1522 *retValue = xmlStrcat((xmlChar *) *retValue, BAD_CAST " ");
1523 *retValue = xmlStrcat((xmlChar *) *retValue, value);
1525 FREE_AND_NULL(value2)
1526 val = xmlSchemaValueGetNext(val);
1527 } while (val != NULL);
1529 return (0);
1530 internal_error:
1531 if (*retValue != NULL)
1532 xmlFree((xmlChar *) (*retValue));
1533 if (value2 != NULL)
1534 xmlFree((xmlChar *) value2);
1535 return (-1);
1539 * xmlSchemaFormatItemForReport:
1540 * @buf: the string buffer
1541 * @itemDes: the designation of the item
1542 * @itemName: the name of the item
1543 * @item: the item as an object
1544 * @itemNode: the node of the item
1545 * @local: the local name
1546 * @parsing: if the function is used during the parse
1548 * Returns a representation of the given item used
1549 * for error reports.
1551 * The following order is used to build the resulting
1552 * designation if the arguments are not NULL:
1553 * 1a. If itemDes not NULL -> itemDes
1554 * 1b. If (itemDes not NULL) and (itemName not NULL)
1555 * -> itemDes + itemName
1556 * 2. If the preceding was NULL and (item not NULL) -> item
1557 * 3. If the preceding was NULL and (itemNode not NULL) -> itemNode
1559 * If the itemNode is an attribute node, the name of the attribute
1560 * will be appended to the result.
1562 * Returns the formatted string and sets @buf to the resulting value.
1564 static xmlChar*
1565 xmlSchemaFormatItemForReport(xmlChar **buf,
1566 const xmlChar *itemDes,
1567 xmlSchemaBasicItemPtr item,
1568 xmlNodePtr itemNode)
1570 xmlChar *str = NULL;
1571 int named = 1;
1573 if (*buf != NULL) {
1574 xmlFree(*buf);
1575 *buf = NULL;
1578 if (itemDes != NULL) {
1579 *buf = xmlStrdup(itemDes);
1580 } else if (item != NULL) {
1581 switch (item->type) {
1582 case XML_SCHEMA_TYPE_BASIC: {
1583 xmlSchemaTypePtr type = WXS_TYPE_CAST item;
1585 if (WXS_IS_ATOMIC(type))
1586 *buf = xmlStrdup(BAD_CAST "atomic type 'xs:");
1587 else if (WXS_IS_LIST(type))
1588 *buf = xmlStrdup(BAD_CAST "list type 'xs:");
1589 else if (WXS_IS_UNION(type))
1590 *buf = xmlStrdup(BAD_CAST "union type 'xs:");
1591 else
1592 *buf = xmlStrdup(BAD_CAST "simple type 'xs:");
1593 *buf = xmlStrcat(*buf, type->name);
1594 *buf = xmlStrcat(*buf, BAD_CAST "'");
1596 break;
1597 case XML_SCHEMA_TYPE_SIMPLE: {
1598 xmlSchemaTypePtr type = WXS_TYPE_CAST item;
1600 if (type->flags & XML_SCHEMAS_TYPE_GLOBAL) {
1601 *buf = xmlStrdup(BAD_CAST"");
1602 } else {
1603 *buf = xmlStrdup(BAD_CAST "local ");
1605 if (WXS_IS_ATOMIC(type))
1606 *buf = xmlStrcat(*buf, BAD_CAST "atomic type");
1607 else if (WXS_IS_LIST(type))
1608 *buf = xmlStrcat(*buf, BAD_CAST "list type");
1609 else if (WXS_IS_UNION(type))
1610 *buf = xmlStrcat(*buf, BAD_CAST "union type");
1611 else
1612 *buf = xmlStrcat(*buf, BAD_CAST "simple type");
1613 if (type->flags & XML_SCHEMAS_TYPE_GLOBAL) {
1614 *buf = xmlStrcat(*buf, BAD_CAST " '");
1615 *buf = xmlStrcat(*buf, type->name);
1616 *buf = xmlStrcat(*buf, BAD_CAST "'");
1619 break;
1620 case XML_SCHEMA_TYPE_COMPLEX: {
1621 xmlSchemaTypePtr type = WXS_TYPE_CAST item;
1623 if (type->flags & XML_SCHEMAS_TYPE_GLOBAL)
1624 *buf = xmlStrdup(BAD_CAST "");
1625 else
1626 *buf = xmlStrdup(BAD_CAST "local ");
1627 *buf = xmlStrcat(*buf, BAD_CAST "complex type");
1628 if (type->flags & XML_SCHEMAS_TYPE_GLOBAL) {
1629 *buf = xmlStrcat(*buf, BAD_CAST " '");
1630 *buf = xmlStrcat(*buf, type->name);
1631 *buf = xmlStrcat(*buf, BAD_CAST "'");
1634 break;
1635 case XML_SCHEMA_TYPE_ATTRIBUTE_USE: {
1636 xmlSchemaAttributeUsePtr ause;
1638 ause = WXS_ATTR_USE_CAST item;
1639 *buf = xmlStrdup(BAD_CAST "attribute use ");
1640 if (WXS_ATTRUSE_DECL(ause) != NULL) {
1641 *buf = xmlStrcat(*buf, BAD_CAST "'");
1642 *buf = xmlStrcat(*buf,
1643 xmlSchemaGetComponentQName(&str, WXS_ATTRUSE_DECL(ause)));
1644 FREE_AND_NULL(str)
1645 *buf = xmlStrcat(*buf, BAD_CAST "'");
1646 } else {
1647 *buf = xmlStrcat(*buf, BAD_CAST "(unknown)");
1650 break;
1651 case XML_SCHEMA_TYPE_ATTRIBUTE: {
1652 xmlSchemaAttributePtr attr;
1654 attr = (xmlSchemaAttributePtr) item;
1655 *buf = xmlStrdup(BAD_CAST "attribute decl.");
1656 *buf = xmlStrcat(*buf, BAD_CAST " '");
1657 *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1658 attr->targetNamespace, attr->name));
1659 FREE_AND_NULL(str)
1660 *buf = xmlStrcat(*buf, BAD_CAST "'");
1662 break;
1663 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1664 xmlSchemaGetComponentDesignation(buf, item);
1665 break;
1666 case XML_SCHEMA_TYPE_ELEMENT: {
1667 xmlSchemaElementPtr elem;
1669 elem = (xmlSchemaElementPtr) item;
1670 *buf = xmlStrdup(BAD_CAST "element decl.");
1671 *buf = xmlStrcat(*buf, BAD_CAST " '");
1672 *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1673 elem->targetNamespace, elem->name));
1674 *buf = xmlStrcat(*buf, BAD_CAST "'");
1676 break;
1677 case XML_SCHEMA_TYPE_IDC_UNIQUE:
1678 case XML_SCHEMA_TYPE_IDC_KEY:
1679 case XML_SCHEMA_TYPE_IDC_KEYREF:
1680 if (item->type == XML_SCHEMA_TYPE_IDC_UNIQUE)
1681 *buf = xmlStrdup(BAD_CAST "unique '");
1682 else if (item->type == XML_SCHEMA_TYPE_IDC_KEY)
1683 *buf = xmlStrdup(BAD_CAST "key '");
1684 else
1685 *buf = xmlStrdup(BAD_CAST "keyRef '");
1686 *buf = xmlStrcat(*buf, ((xmlSchemaIDCPtr) item)->name);
1687 *buf = xmlStrcat(*buf, BAD_CAST "'");
1688 break;
1689 case XML_SCHEMA_TYPE_ANY:
1690 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
1691 *buf = xmlStrdup(xmlSchemaWildcardPCToString(
1692 ((xmlSchemaWildcardPtr) item)->processContents));
1693 *buf = xmlStrcat(*buf, BAD_CAST " wildcard");
1694 break;
1695 case XML_SCHEMA_FACET_MININCLUSIVE:
1696 case XML_SCHEMA_FACET_MINEXCLUSIVE:
1697 case XML_SCHEMA_FACET_MAXINCLUSIVE:
1698 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
1699 case XML_SCHEMA_FACET_TOTALDIGITS:
1700 case XML_SCHEMA_FACET_FRACTIONDIGITS:
1701 case XML_SCHEMA_FACET_PATTERN:
1702 case XML_SCHEMA_FACET_ENUMERATION:
1703 case XML_SCHEMA_FACET_WHITESPACE:
1704 case XML_SCHEMA_FACET_LENGTH:
1705 case XML_SCHEMA_FACET_MAXLENGTH:
1706 case XML_SCHEMA_FACET_MINLENGTH:
1707 *buf = xmlStrdup(BAD_CAST "facet '");
1708 *buf = xmlStrcat(*buf, xmlSchemaFacetTypeToString(item->type));
1709 *buf = xmlStrcat(*buf, BAD_CAST "'");
1710 break;
1711 case XML_SCHEMA_TYPE_GROUP: {
1712 *buf = xmlStrdup(BAD_CAST "model group def.");
1713 *buf = xmlStrcat(*buf, BAD_CAST " '");
1714 *buf = xmlStrcat(*buf, xmlSchemaGetComponentQName(&str, item));
1715 *buf = xmlStrcat(*buf, BAD_CAST "'");
1716 FREE_AND_NULL(str)
1718 break;
1719 case XML_SCHEMA_TYPE_SEQUENCE:
1720 case XML_SCHEMA_TYPE_CHOICE:
1721 case XML_SCHEMA_TYPE_ALL:
1722 case XML_SCHEMA_TYPE_PARTICLE:
1723 *buf = xmlStrdup(WXS_ITEM_TYPE_NAME(item));
1724 break;
1725 case XML_SCHEMA_TYPE_NOTATION: {
1726 *buf = xmlStrdup(WXS_ITEM_TYPE_NAME(item));
1727 *buf = xmlStrcat(*buf, BAD_CAST " '");
1728 *buf = xmlStrcat(*buf, xmlSchemaGetComponentQName(&str, item));
1729 *buf = xmlStrcat(*buf, BAD_CAST "'");
1730 FREE_AND_NULL(str);
1732 default:
1733 named = 0;
1735 } else
1736 named = 0;
1738 if ((named == 0) && (itemNode != NULL)) {
1739 xmlNodePtr elem;
1741 if (itemNode->type == XML_ATTRIBUTE_NODE)
1742 elem = itemNode->parent;
1743 else
1744 elem = itemNode;
1745 *buf = xmlStrdup(BAD_CAST "Element '");
1746 if (elem->ns != NULL) {
1747 *buf = xmlStrcat(*buf,
1748 xmlSchemaFormatQName(&str, elem->ns->href, elem->name));
1749 FREE_AND_NULL(str)
1750 } else
1751 *buf = xmlStrcat(*buf, elem->name);
1752 *buf = xmlStrcat(*buf, BAD_CAST "'");
1755 if ((itemNode != NULL) && (itemNode->type == XML_ATTRIBUTE_NODE)) {
1756 *buf = xmlStrcat(*buf, BAD_CAST ", attribute '");
1757 if (itemNode->ns != NULL) {
1758 *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1759 itemNode->ns->href, itemNode->name));
1760 FREE_AND_NULL(str)
1761 } else
1762 *buf = xmlStrcat(*buf, itemNode->name);
1763 *buf = xmlStrcat(*buf, BAD_CAST "'");
1765 FREE_AND_NULL(str)
1767 return (*buf);
1771 * xmlSchemaFormatFacetEnumSet:
1772 * @buf: the string buffer
1773 * @type: the type holding the enumeration facets
1775 * Builds a string consisting of all enumeration elements.
1777 * Returns a string of all enumeration elements.
1779 static const xmlChar *
1780 xmlSchemaFormatFacetEnumSet(xmlSchemaAbstractCtxtPtr actxt,
1781 xmlChar **buf, xmlSchemaTypePtr type)
1783 xmlSchemaFacetPtr facet;
1784 xmlSchemaWhitespaceValueType ws;
1785 xmlChar *value = NULL;
1786 int res, found = 0;
1788 if (*buf != NULL)
1789 xmlFree(*buf);
1790 *buf = NULL;
1792 do {
1794 * Use the whitespace type of the base type.
1796 ws = xmlSchemaGetWhiteSpaceFacetValue(type->baseType);
1797 for (facet = type->facets; facet != NULL; facet = facet->next) {
1798 if (facet->type != XML_SCHEMA_FACET_ENUMERATION)
1799 continue;
1800 found = 1;
1801 res = xmlSchemaGetCanonValueWhtspExt(facet->val,
1802 ws, &value);
1803 if (res == -1) {
1804 xmlSchemaInternalErr(actxt,
1805 "xmlSchemaFormatFacetEnumSet",
1806 "compute the canonical lexical representation");
1807 if (*buf != NULL)
1808 xmlFree(*buf);
1809 *buf = NULL;
1810 return (NULL);
1812 if (*buf == NULL)
1813 *buf = xmlStrdup(BAD_CAST "'");
1814 else
1815 *buf = xmlStrcat(*buf, BAD_CAST ", '");
1816 *buf = xmlStrcat(*buf, BAD_CAST value);
1817 *buf = xmlStrcat(*buf, BAD_CAST "'");
1818 if (value != NULL) {
1819 xmlFree((xmlChar *)value);
1820 value = NULL;
1824 * The enumeration facet of a type restricts the enumeration
1825 * facet of the ancestor type; i.e., such restricted enumerations
1826 * do not belong to the set of the given type. Thus we break
1827 * on the first found enumeration.
1829 if (found)
1830 break;
1831 type = type->baseType;
1832 } while ((type != NULL) && (type->type != XML_SCHEMA_TYPE_BASIC));
1834 return ((const xmlChar *) *buf);
1837 /************************************************************************
1839 * Error functions *
1841 ************************************************************************/
1843 #if 0
1844 static void
1845 xmlSchemaErrMemory(const char *msg)
1847 __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, NULL, NULL,
1848 msg);
1850 #endif
1852 static void
1853 xmlSchemaPSimpleErr(const char *msg)
1855 __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, NULL, NULL,
1856 msg);
1860 * xmlSchemaPErrMemory:
1861 * @node: a context node
1862 * @extra: extra informations
1864 * Handle an out of memory condition
1866 static void
1867 xmlSchemaPErrMemory(xmlSchemaParserCtxtPtr ctxt,
1868 const char *extra, xmlNodePtr node)
1870 if (ctxt != NULL)
1871 ctxt->nberrors++;
1872 __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, node, NULL,
1873 extra);
1877 * xmlSchemaPErr:
1878 * @ctxt: the parsing context
1879 * @node: the context node
1880 * @error: the error code
1881 * @msg: the error message
1882 * @str1: extra data
1883 * @str2: extra data
1885 * Handle a parser error
1887 static void
1888 xmlSchemaPErr(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
1889 const char *msg, const xmlChar * str1, const xmlChar * str2)
1891 xmlGenericErrorFunc channel = NULL;
1892 xmlStructuredErrorFunc schannel = NULL;
1893 void *data = NULL;
1895 if (ctxt != NULL) {
1896 ctxt->nberrors++;
1897 ctxt->err = error;
1898 channel = ctxt->error;
1899 data = ctxt->errCtxt;
1900 schannel = ctxt->serror;
1902 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
1903 error, XML_ERR_ERROR, NULL, 0,
1904 (const char *) str1, (const char *) str2, NULL, 0, 0,
1905 msg, str1, str2);
1909 * xmlSchemaPErr2:
1910 * @ctxt: the parsing context
1911 * @node: the context node
1912 * @node: the current child
1913 * @error: the error code
1914 * @msg: the error message
1915 * @str1: extra data
1916 * @str2: extra data
1918 * Handle a parser error
1920 static void
1921 xmlSchemaPErr2(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
1922 xmlNodePtr child, int error,
1923 const char *msg, const xmlChar * str1, const xmlChar * str2)
1925 if (child != NULL)
1926 xmlSchemaPErr(ctxt, child, error, msg, str1, str2);
1927 else
1928 xmlSchemaPErr(ctxt, node, error, msg, str1, str2);
1933 * xmlSchemaPErrExt:
1934 * @ctxt: the parsing context
1935 * @node: the context node
1936 * @error: the error code
1937 * @strData1: extra data
1938 * @strData2: extra data
1939 * @strData3: extra data
1940 * @msg: the message
1941 * @str1: extra parameter for the message display
1942 * @str2: extra parameter for the message display
1943 * @str3: extra parameter for the message display
1944 * @str4: extra parameter for the message display
1945 * @str5: extra parameter for the message display
1947 * Handle a parser error
1949 static void
1950 xmlSchemaPErrExt(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
1951 const xmlChar * strData1, const xmlChar * strData2,
1952 const xmlChar * strData3, const char *msg, const xmlChar * str1,
1953 const xmlChar * str2, const xmlChar * str3, const xmlChar * str4,
1954 const xmlChar * str5)
1957 xmlGenericErrorFunc channel = NULL;
1958 xmlStructuredErrorFunc schannel = NULL;
1959 void *data = NULL;
1961 if (ctxt != NULL) {
1962 ctxt->nberrors++;
1963 ctxt->err = error;
1964 channel = ctxt->error;
1965 data = ctxt->errCtxt;
1966 schannel = ctxt->serror;
1968 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
1969 error, XML_ERR_ERROR, NULL, 0,
1970 (const char *) strData1, (const char *) strData2,
1971 (const char *) strData3, 0, 0, msg, str1, str2,
1972 str3, str4, str5);
1975 /************************************************************************
1977 * Allround error functions *
1979 ************************************************************************/
1982 * xmlSchemaVTypeErrMemory:
1983 * @node: a context node
1984 * @extra: extra informations
1986 * Handle an out of memory condition
1988 static void
1989 xmlSchemaVErrMemory(xmlSchemaValidCtxtPtr ctxt,
1990 const char *extra, xmlNodePtr node)
1992 if (ctxt != NULL) {
1993 ctxt->nberrors++;
1994 ctxt->err = XML_SCHEMAV_INTERNAL;
1996 __xmlSimpleError(XML_FROM_SCHEMASV, XML_ERR_NO_MEMORY, node, NULL,
1997 extra);
2000 static void
2001 xmlSchemaPSimpleInternalErr(xmlNodePtr node,
2002 const char *msg, const xmlChar *str)
2004 __xmlSimpleError(XML_FROM_SCHEMASP, XML_SCHEMAP_INTERNAL, node,
2005 msg, (const char *) str);
2008 #define WXS_ERROR_TYPE_ERROR 1
2009 #define WXS_ERROR_TYPE_WARNING 2
2011 * xmlSchemaErr3:
2012 * @ctxt: the validation context
2013 * @node: the context node
2014 * @error: the error code
2015 * @msg: the error message
2016 * @str1: extra data
2017 * @str2: extra data
2018 * @str3: extra data
2020 * Handle a validation error
2022 static void
2023 xmlSchemaErr4Line(xmlSchemaAbstractCtxtPtr ctxt,
2024 xmlErrorLevel errorLevel,
2025 int error, xmlNodePtr node, int line, const char *msg,
2026 const xmlChar *str1, const xmlChar *str2,
2027 const xmlChar *str3, const xmlChar *str4)
2029 xmlStructuredErrorFunc schannel = NULL;
2030 xmlGenericErrorFunc channel = NULL;
2031 void *data = NULL;
2033 if (ctxt != NULL) {
2034 if (ctxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
2035 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctxt;
2036 const char *file = NULL;
2037 if (errorLevel != XML_ERR_WARNING) {
2038 vctxt->nberrors++;
2039 vctxt->err = error;
2040 channel = vctxt->error;
2041 } else {
2042 channel = vctxt->warning;
2044 schannel = vctxt->serror;
2045 data = vctxt->errCtxt;
2048 * Error node. If we specify a line number, then
2049 * do not channel any node to the error function.
2051 if (line == 0) {
2052 if ((node == NULL) &&
2053 (vctxt->depth >= 0) &&
2054 (vctxt->inode != NULL)) {
2055 node = vctxt->inode->node;
2058 * Get filename and line if no node-tree.
2060 if ((node == NULL) &&
2061 (vctxt->parserCtxt != NULL) &&
2062 (vctxt->parserCtxt->input != NULL)) {
2063 file = vctxt->parserCtxt->input->filename;
2064 line = vctxt->parserCtxt->input->line;
2066 } else {
2068 * Override the given node's (if any) position
2069 * and channel only the given line number.
2071 node = NULL;
2073 * Get filename.
2075 if (vctxt->doc != NULL)
2076 file = (const char *) vctxt->doc->URL;
2077 else if ((vctxt->parserCtxt != NULL) &&
2078 (vctxt->parserCtxt->input != NULL))
2079 file = vctxt->parserCtxt->input->filename;
2081 __xmlRaiseError(schannel, channel, data, ctxt,
2082 node, XML_FROM_SCHEMASV,
2083 error, errorLevel, file, line,
2084 (const char *) str1, (const char *) str2,
2085 (const char *) str3, 0, 0, msg, str1, str2, str3, str4);
2087 } else if (ctxt->type == XML_SCHEMA_CTXT_PARSER) {
2088 xmlSchemaParserCtxtPtr pctxt = (xmlSchemaParserCtxtPtr) ctxt;
2089 if (errorLevel != XML_ERR_WARNING) {
2090 pctxt->nberrors++;
2091 pctxt->err = error;
2092 channel = pctxt->error;
2093 } else {
2094 channel = pctxt->warning;
2096 schannel = pctxt->serror;
2097 data = pctxt->errCtxt;
2098 __xmlRaiseError(schannel, channel, data, ctxt,
2099 node, XML_FROM_SCHEMASP, error,
2100 errorLevel, NULL, 0,
2101 (const char *) str1, (const char *) str2,
2102 (const char *) str3, 0, 0, msg, str1, str2, str3, str4);
2103 } else {
2104 TODO
2110 * xmlSchemaErr3:
2111 * @ctxt: the validation context
2112 * @node: the context node
2113 * @error: the error code
2114 * @msg: the error message
2115 * @str1: extra data
2116 * @str2: extra data
2117 * @str3: extra data
2119 * Handle a validation error
2121 static void
2122 xmlSchemaErr3(xmlSchemaAbstractCtxtPtr actxt,
2123 int error, xmlNodePtr node, const char *msg,
2124 const xmlChar *str1, const xmlChar *str2, const xmlChar *str3)
2126 xmlSchemaErr4Line(actxt, XML_ERR_ERROR, error, node, 0,
2127 msg, str1, str2, str3, NULL);
2130 static void
2131 xmlSchemaErr4(xmlSchemaAbstractCtxtPtr actxt,
2132 int error, xmlNodePtr node, const char *msg,
2133 const xmlChar *str1, const xmlChar *str2,
2134 const xmlChar *str3, const xmlChar *str4)
2136 xmlSchemaErr4Line(actxt, XML_ERR_ERROR, error, node, 0,
2137 msg, str1, str2, str3, str4);
2140 static void
2141 xmlSchemaErr(xmlSchemaAbstractCtxtPtr actxt,
2142 int error, xmlNodePtr node, const char *msg,
2143 const xmlChar *str1, const xmlChar *str2)
2145 xmlSchemaErr4(actxt, error, node, msg, str1, str2, NULL, NULL);
2148 static xmlChar *
2149 xmlSchemaFormatNodeForError(xmlChar ** msg,
2150 xmlSchemaAbstractCtxtPtr actxt,
2151 xmlNodePtr node)
2153 xmlChar *str = NULL;
2155 *msg = NULL;
2156 if ((node != NULL) &&
2157 (node->type != XML_ELEMENT_NODE) &&
2158 (node->type != XML_ATTRIBUTE_NODE))
2161 * Don't try to format other nodes than element and
2162 * attribute nodes.
2163 * Play save and return an empty string.
2165 *msg = xmlStrdup(BAD_CAST "");
2166 return(*msg);
2168 if (node != NULL) {
2170 * Work on tree nodes.
2172 if (node->type == XML_ATTRIBUTE_NODE) {
2173 xmlNodePtr elem = node->parent;
2175 *msg = xmlStrdup(BAD_CAST "Element '");
2176 if (elem->ns != NULL)
2177 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2178 elem->ns->href, elem->name));
2179 else
2180 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2181 NULL, elem->name));
2182 FREE_AND_NULL(str);
2183 *msg = xmlStrcat(*msg, BAD_CAST "', ");
2184 *msg = xmlStrcat(*msg, BAD_CAST "attribute '");
2185 } else {
2186 *msg = xmlStrdup(BAD_CAST "Element '");
2188 if (node->ns != NULL)
2189 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2190 node->ns->href, node->name));
2191 else
2192 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2193 NULL, node->name));
2194 FREE_AND_NULL(str);
2195 *msg = xmlStrcat(*msg, BAD_CAST "': ");
2196 } else if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
2197 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) actxt;
2199 * Work on node infos.
2201 if (vctxt->inode->nodeType == XML_ATTRIBUTE_NODE) {
2202 xmlSchemaNodeInfoPtr ielem =
2203 vctxt->elemInfos[vctxt->depth];
2205 *msg = xmlStrdup(BAD_CAST "Element '");
2206 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2207 ielem->nsName, ielem->localName));
2208 FREE_AND_NULL(str);
2209 *msg = xmlStrcat(*msg, BAD_CAST "', ");
2210 *msg = xmlStrcat(*msg, BAD_CAST "attribute '");
2211 } else {
2212 *msg = xmlStrdup(BAD_CAST "Element '");
2214 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2215 vctxt->inode->nsName, vctxt->inode->localName));
2216 FREE_AND_NULL(str);
2217 *msg = xmlStrcat(*msg, BAD_CAST "': ");
2218 } else if (actxt->type == XML_SCHEMA_CTXT_PARSER) {
2220 * Hmm, no node while parsing?
2221 * Return an empty string, in case NULL will break something.
2223 *msg = xmlStrdup(BAD_CAST "");
2224 } else {
2225 TODO
2226 return (NULL);
2229 * VAL TODO: The output of the given schema component is currently
2230 * disabled.
2232 #if 0
2233 if ((type != NULL) && (xmlSchemaIsGlobalItem(type))) {
2234 *msg = xmlStrcat(*msg, BAD_CAST " [");
2235 *msg = xmlStrcat(*msg, xmlSchemaFormatItemForReport(&str,
2236 NULL, type, NULL, 0));
2237 FREE_AND_NULL(str)
2238 *msg = xmlStrcat(*msg, BAD_CAST "]");
2240 #endif
2241 return (*msg);
2244 static void
2245 xmlSchemaInternalErr2(xmlSchemaAbstractCtxtPtr actxt,
2246 const char *funcName,
2247 const char *message,
2248 const xmlChar *str1,
2249 const xmlChar *str2)
2251 xmlChar *msg = NULL;
2253 if (actxt == NULL)
2254 return;
2255 msg = xmlStrdup(BAD_CAST "Internal error: ");
2256 msg = xmlStrcat(msg, BAD_CAST funcName);
2257 msg = xmlStrcat(msg, BAD_CAST ", ");
2258 msg = xmlStrcat(msg, BAD_CAST message);
2259 msg = xmlStrcat(msg, BAD_CAST ".\n");
2261 if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR)
2262 xmlSchemaErr(actxt, XML_SCHEMAV_INTERNAL, NULL,
2263 (const char *) msg, str1, str2);
2265 else if (actxt->type == XML_SCHEMA_CTXT_PARSER)
2266 xmlSchemaErr(actxt, XML_SCHEMAP_INTERNAL, NULL,
2267 (const char *) msg, str1, str2);
2269 FREE_AND_NULL(msg)
2272 static void
2273 xmlSchemaInternalErr(xmlSchemaAbstractCtxtPtr actxt,
2274 const char *funcName,
2275 const char *message)
2277 xmlSchemaInternalErr2(actxt, funcName, message, NULL, NULL);
2280 #if 0
2281 static void
2282 xmlSchemaPInternalErr(xmlSchemaParserCtxtPtr pctxt,
2283 const char *funcName,
2284 const char *message,
2285 const xmlChar *str1,
2286 const xmlChar *str2)
2288 xmlSchemaInternalErr2(ACTXT_CAST pctxt, funcName, message,
2289 str1, str2);
2291 #endif
2293 static void
2294 xmlSchemaCustomErr4(xmlSchemaAbstractCtxtPtr actxt,
2295 xmlParserErrors error,
2296 xmlNodePtr node,
2297 xmlSchemaBasicItemPtr item,
2298 const char *message,
2299 const xmlChar *str1, const xmlChar *str2,
2300 const xmlChar *str3, const xmlChar *str4)
2302 xmlChar *msg = NULL;
2304 if ((node == NULL) && (item != NULL) &&
2305 (actxt->type == XML_SCHEMA_CTXT_PARSER)) {
2306 node = WXS_ITEM_NODE(item);
2307 xmlSchemaFormatItemForReport(&msg, NULL, item, NULL);
2308 msg = xmlStrcat(msg, BAD_CAST ": ");
2309 } else
2310 xmlSchemaFormatNodeForError(&msg, actxt, node);
2311 msg = xmlStrcat(msg, (const xmlChar *) message);
2312 msg = xmlStrcat(msg, BAD_CAST ".\n");
2313 xmlSchemaErr4(actxt, error, node,
2314 (const char *) msg, str1, str2, str3, str4);
2315 FREE_AND_NULL(msg)
2318 static void
2319 xmlSchemaCustomErr(xmlSchemaAbstractCtxtPtr actxt,
2320 xmlParserErrors error,
2321 xmlNodePtr node,
2322 xmlSchemaBasicItemPtr item,
2323 const char *message,
2324 const xmlChar *str1,
2325 const xmlChar *str2)
2327 xmlSchemaCustomErr4(actxt, error, node, item,
2328 message, str1, str2, NULL, NULL);
2333 static void
2334 xmlSchemaCustomWarning(xmlSchemaAbstractCtxtPtr actxt,
2335 xmlParserErrors error,
2336 xmlNodePtr node,
2337 xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
2338 const char *message,
2339 const xmlChar *str1,
2340 const xmlChar *str2,
2341 const xmlChar *str3)
2343 xmlChar *msg = NULL;
2345 xmlSchemaFormatNodeForError(&msg, actxt, node);
2346 msg = xmlStrcat(msg, (const xmlChar *) message);
2347 msg = xmlStrcat(msg, BAD_CAST ".\n");
2349 /* URGENT TODO: Set the error code to something sane. */
2350 xmlSchemaErr4Line(actxt, XML_ERR_WARNING, error, node, 0,
2351 (const char *) msg, str1, str2, str3, NULL);
2353 FREE_AND_NULL(msg)
2358 static void
2359 xmlSchemaKeyrefErr(xmlSchemaValidCtxtPtr vctxt,
2360 xmlParserErrors error,
2361 xmlSchemaPSVIIDCNodePtr idcNode,
2362 xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
2363 const char *message,
2364 const xmlChar *str1,
2365 const xmlChar *str2)
2367 xmlChar *msg = NULL, *qname = NULL;
2369 msg = xmlStrdup(BAD_CAST "Element '%s': ");
2370 msg = xmlStrcat(msg, (const xmlChar *) message);
2371 msg = xmlStrcat(msg, BAD_CAST ".\n");
2372 xmlSchemaErr4Line(ACTXT_CAST vctxt, XML_ERR_ERROR,
2373 error, NULL, idcNode->nodeLine, (const char *) msg,
2374 xmlSchemaFormatQName(&qname,
2375 vctxt->nodeQNames->items[idcNode->nodeQNameID +1],
2376 vctxt->nodeQNames->items[idcNode->nodeQNameID]),
2377 str1, str2, NULL);
2378 FREE_AND_NULL(qname);
2379 FREE_AND_NULL(msg);
2382 static int
2383 xmlSchemaEvalErrorNodeType(xmlSchemaAbstractCtxtPtr actxt,
2384 xmlNodePtr node)
2386 if (node != NULL)
2387 return (node->type);
2388 if ((actxt->type == XML_SCHEMA_CTXT_VALIDATOR) &&
2389 (((xmlSchemaValidCtxtPtr) actxt)->inode != NULL))
2390 return ( ((xmlSchemaValidCtxtPtr) actxt)->inode->nodeType);
2391 return (-1);
2394 static int
2395 xmlSchemaIsGlobalItem(xmlSchemaTypePtr item)
2397 switch (item->type) {
2398 case XML_SCHEMA_TYPE_COMPLEX:
2399 case XML_SCHEMA_TYPE_SIMPLE:
2400 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL)
2401 return(1);
2402 break;
2403 case XML_SCHEMA_TYPE_GROUP:
2404 return (1);
2405 case XML_SCHEMA_TYPE_ELEMENT:
2406 if ( ((xmlSchemaElementPtr) item)->flags &
2407 XML_SCHEMAS_ELEM_GLOBAL)
2408 return(1);
2409 break;
2410 case XML_SCHEMA_TYPE_ATTRIBUTE:
2411 if ( ((xmlSchemaAttributePtr) item)->flags &
2412 XML_SCHEMAS_ATTR_GLOBAL)
2413 return(1);
2414 break;
2415 /* Note that attribute groups are always global. */
2416 default:
2417 return(1);
2419 return (0);
2422 static void
2423 xmlSchemaSimpleTypeErr(xmlSchemaAbstractCtxtPtr actxt,
2424 xmlParserErrors error,
2425 xmlNodePtr node,
2426 const xmlChar *value,
2427 xmlSchemaTypePtr type,
2428 int displayValue)
2430 xmlChar *msg = NULL;
2432 xmlSchemaFormatNodeForError(&msg, actxt, node);
2434 if (displayValue || (xmlSchemaEvalErrorNodeType(actxt, node) ==
2435 XML_ATTRIBUTE_NODE))
2436 msg = xmlStrcat(msg, BAD_CAST "'%s' is not a valid value of ");
2437 else
2438 msg = xmlStrcat(msg, BAD_CAST "The character content is not a valid "
2439 "value of ");
2441 if (! xmlSchemaIsGlobalItem(type))
2442 msg = xmlStrcat(msg, BAD_CAST "the local ");
2443 else
2444 msg = xmlStrcat(msg, BAD_CAST "the ");
2446 if (WXS_IS_ATOMIC(type))
2447 msg = xmlStrcat(msg, BAD_CAST "atomic type");
2448 else if (WXS_IS_LIST(type))
2449 msg = xmlStrcat(msg, BAD_CAST "list type");
2450 else if (WXS_IS_UNION(type))
2451 msg = xmlStrcat(msg, BAD_CAST "union type");
2453 if (xmlSchemaIsGlobalItem(type)) {
2454 xmlChar *str = NULL;
2455 msg = xmlStrcat(msg, BAD_CAST " '");
2456 if (type->builtInType != 0) {
2457 msg = xmlStrcat(msg, BAD_CAST "xs:");
2458 msg = xmlStrcat(msg, type->name);
2459 } else
2460 msg = xmlStrcat(msg,
2461 xmlSchemaFormatQName(&str,
2462 type->targetNamespace, type->name));
2463 msg = xmlStrcat(msg, BAD_CAST "'");
2464 FREE_AND_NULL(str);
2466 msg = xmlStrcat(msg, BAD_CAST ".\n");
2467 if (displayValue || (xmlSchemaEvalErrorNodeType(actxt, node) ==
2468 XML_ATTRIBUTE_NODE))
2469 xmlSchemaErr(actxt, error, node, (const char *) msg, value, NULL);
2470 else
2471 xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
2472 FREE_AND_NULL(msg)
2475 static const xmlChar *
2476 xmlSchemaFormatErrorNodeQName(xmlChar ** str,
2477 xmlSchemaNodeInfoPtr ni,
2478 xmlNodePtr node)
2480 if (node != NULL) {
2481 if (node->ns != NULL)
2482 return (xmlSchemaFormatQName(str, node->ns->href, node->name));
2483 else
2484 return (xmlSchemaFormatQName(str, NULL, node->name));
2485 } else if (ni != NULL)
2486 return (xmlSchemaFormatQName(str, ni->nsName, ni->localName));
2487 return (NULL);
2490 static void
2491 xmlSchemaIllegalAttrErr(xmlSchemaAbstractCtxtPtr actxt,
2492 xmlParserErrors error,
2493 xmlSchemaAttrInfoPtr ni,
2494 xmlNodePtr node)
2496 xmlChar *msg = NULL, *str = NULL;
2498 xmlSchemaFormatNodeForError(&msg, actxt, node);
2499 msg = xmlStrcat(msg, BAD_CAST "The attribute '%s' is not allowed.\n");
2500 xmlSchemaErr(actxt, error, node, (const char *) msg,
2501 xmlSchemaFormatErrorNodeQName(&str, (xmlSchemaNodeInfoPtr) ni, node),
2502 NULL);
2503 FREE_AND_NULL(str)
2504 FREE_AND_NULL(msg)
2507 static void
2508 xmlSchemaComplexTypeErr(xmlSchemaAbstractCtxtPtr actxt,
2509 xmlParserErrors error,
2510 xmlNodePtr node,
2511 xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
2512 const char *message,
2513 int nbval,
2514 int nbneg,
2515 xmlChar **values)
2517 xmlChar *str = NULL, *msg = NULL;
2518 xmlChar *localName, *nsName;
2519 const xmlChar *cur, *end;
2520 int i;
2522 xmlSchemaFormatNodeForError(&msg, actxt, node);
2523 msg = xmlStrcat(msg, (const xmlChar *) message);
2524 msg = xmlStrcat(msg, BAD_CAST ".");
2526 * Note that is does not make sense to report that we have a
2527 * wildcard here, since the wildcard might be unfolded into
2528 * multiple transitions.
2530 if (nbval + nbneg > 0) {
2531 if (nbval + nbneg > 1) {
2532 str = xmlStrdup(BAD_CAST " Expected is one of ( ");
2533 } else
2534 str = xmlStrdup(BAD_CAST " Expected is ( ");
2535 nsName = NULL;
2537 for (i = 0; i < nbval + nbneg; i++) {
2538 cur = values[i];
2539 if (cur == NULL)
2540 continue;
2541 if ((cur[0] == 'n') && (cur[1] == 'o') && (cur[2] == 't') &&
2542 (cur[3] == ' ')) {
2543 cur += 4;
2544 str = xmlStrcat(str, BAD_CAST "##other");
2547 * Get the local name.
2549 localName = NULL;
2551 end = cur;
2552 if (*end == '*') {
2553 localName = xmlStrdup(BAD_CAST "*");
2554 end++;
2555 } else {
2556 while ((*end != 0) && (*end != '|'))
2557 end++;
2558 localName = xmlStrncat(localName, BAD_CAST cur, end - cur);
2560 if (*end != 0) {
2561 end++;
2563 * Skip "*|*" if they come with negated expressions, since
2564 * they represent the same negated wildcard.
2566 if ((nbneg == 0) || (*end != '*') || (*localName != '*')) {
2568 * Get the namespace name.
2570 cur = end;
2571 if (*end == '*') {
2572 nsName = xmlStrdup(BAD_CAST "{*}");
2573 } else {
2574 while (*end != 0)
2575 end++;
2577 if (i >= nbval)
2578 nsName = xmlStrdup(BAD_CAST "{##other:");
2579 else
2580 nsName = xmlStrdup(BAD_CAST "{");
2582 nsName = xmlStrncat(nsName, BAD_CAST cur, end - cur);
2583 nsName = xmlStrcat(nsName, BAD_CAST "}");
2585 str = xmlStrcat(str, BAD_CAST nsName);
2586 FREE_AND_NULL(nsName)
2587 } else {
2588 FREE_AND_NULL(localName);
2589 continue;
2592 str = xmlStrcat(str, BAD_CAST localName);
2593 FREE_AND_NULL(localName);
2595 if (i < nbval + nbneg -1)
2596 str = xmlStrcat(str, BAD_CAST ", ");
2598 str = xmlStrcat(str, BAD_CAST " ).\n");
2599 msg = xmlStrcat(msg, BAD_CAST str);
2600 FREE_AND_NULL(str)
2601 } else
2602 msg = xmlStrcat(msg, BAD_CAST "\n");
2603 xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
2604 xmlFree(msg);
2607 static void
2608 xmlSchemaFacetErr(xmlSchemaAbstractCtxtPtr actxt,
2609 xmlParserErrors error,
2610 xmlNodePtr node,
2611 const xmlChar *value,
2612 unsigned long length,
2613 xmlSchemaTypePtr type,
2614 xmlSchemaFacetPtr facet,
2615 const char *message,
2616 const xmlChar *str1,
2617 const xmlChar *str2)
2619 xmlChar *str = NULL, *msg = NULL;
2620 xmlSchemaTypeType facetType;
2621 int nodeType = xmlSchemaEvalErrorNodeType(actxt, node);
2623 xmlSchemaFormatNodeForError(&msg, actxt, node);
2624 if (error == XML_SCHEMAV_CVC_ENUMERATION_VALID) {
2625 facetType = XML_SCHEMA_FACET_ENUMERATION;
2627 * If enumerations are validated, one must not expect the
2628 * facet to be given.
2630 } else
2631 facetType = facet->type;
2632 msg = xmlStrcat(msg, BAD_CAST "[");
2633 msg = xmlStrcat(msg, BAD_CAST "facet '");
2634 msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facetType));
2635 msg = xmlStrcat(msg, BAD_CAST "'] ");
2636 if (message == NULL) {
2638 * Use a default message.
2640 if ((facetType == XML_SCHEMA_FACET_LENGTH) ||
2641 (facetType == XML_SCHEMA_FACET_MINLENGTH) ||
2642 (facetType == XML_SCHEMA_FACET_MAXLENGTH)) {
2644 char len[25], actLen[25];
2646 /* FIXME, TODO: What is the max expected string length of the
2647 * this value?
2649 if (nodeType == XML_ATTRIBUTE_NODE)
2650 msg = xmlStrcat(msg, BAD_CAST "The value '%s' has a length of '%s'; ");
2651 else
2652 msg = xmlStrcat(msg, BAD_CAST "The value has a length of '%s'; ");
2654 snprintf(len, 24, "%lu", xmlSchemaGetFacetValueAsULong(facet));
2655 snprintf(actLen, 24, "%lu", length);
2657 if (facetType == XML_SCHEMA_FACET_LENGTH)
2658 msg = xmlStrcat(msg,
2659 BAD_CAST "this differs from the allowed length of '%s'.\n");
2660 else if (facetType == XML_SCHEMA_FACET_MAXLENGTH)
2661 msg = xmlStrcat(msg,
2662 BAD_CAST "this exceeds the allowed maximum length of '%s'.\n");
2663 else if (facetType == XML_SCHEMA_FACET_MINLENGTH)
2664 msg = xmlStrcat(msg,
2665 BAD_CAST "this underruns the allowed minimum length of '%s'.\n");
2667 if (nodeType == XML_ATTRIBUTE_NODE)
2668 xmlSchemaErr3(actxt, error, node, (const char *) msg,
2669 value, (const xmlChar *) actLen, (const xmlChar *) len);
2670 else
2671 xmlSchemaErr(actxt, error, node, (const char *) msg,
2672 (const xmlChar *) actLen, (const xmlChar *) len);
2674 } else if (facetType == XML_SCHEMA_FACET_ENUMERATION) {
2675 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not an element "
2676 "of the set {%s}.\n");
2677 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2678 xmlSchemaFormatFacetEnumSet(actxt, &str, type));
2679 } else if (facetType == XML_SCHEMA_FACET_PATTERN) {
2680 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not accepted "
2681 "by the pattern '%s'.\n");
2682 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2683 facet->value);
2684 } else if (facetType == XML_SCHEMA_FACET_MININCLUSIVE) {
2685 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is less than the "
2686 "minimum value allowed ('%s').\n");
2687 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2688 facet->value);
2689 } else if (facetType == XML_SCHEMA_FACET_MAXINCLUSIVE) {
2690 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is greater than the "
2691 "maximum value allowed ('%s').\n");
2692 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2693 facet->value);
2694 } else if (facetType == XML_SCHEMA_FACET_MINEXCLUSIVE) {
2695 msg = xmlStrcat(msg, BAD_CAST "The value '%s' must be greater than "
2696 "'%s'.\n");
2697 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2698 facet->value);
2699 } else if (facetType == XML_SCHEMA_FACET_MAXEXCLUSIVE) {
2700 msg = xmlStrcat(msg, BAD_CAST "The value '%s' must be less than "
2701 "'%s'.\n");
2702 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2703 facet->value);
2704 } else if (facetType == XML_SCHEMA_FACET_TOTALDIGITS) {
2705 msg = xmlStrcat(msg, BAD_CAST "The value '%s' has more "
2706 "digits than are allowed ('%s').\n");
2707 xmlSchemaErr(actxt, error, node, (const char*) msg, value,
2708 facet->value);
2709 } else if (facetType == XML_SCHEMA_FACET_FRACTIONDIGITS) {
2710 msg = xmlStrcat(msg, BAD_CAST "The value '%s' has more fractional "
2711 "digits than are allowed ('%s').\n");
2712 xmlSchemaErr(actxt, error, node, (const char*) msg, value,
2713 facet->value);
2714 } else if (nodeType == XML_ATTRIBUTE_NODE) {
2715 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not facet-valid.\n");
2716 xmlSchemaErr(actxt, error, node, (const char *) msg, value, NULL);
2717 } else {
2718 msg = xmlStrcat(msg, BAD_CAST "The value is not facet-valid.\n");
2719 xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
2721 } else {
2722 msg = xmlStrcat(msg, (const xmlChar *) message);
2723 msg = xmlStrcat(msg, BAD_CAST ".\n");
2724 xmlSchemaErr(actxt, error, node, (const char *) msg, str1, str2);
2726 FREE_AND_NULL(str)
2727 xmlFree(msg);
2730 #define VERROR(err, type, msg) \
2731 xmlSchemaCustomErr(ACTXT_CAST vctxt, err, NULL, type, msg, NULL, NULL);
2733 #define VERROR_INT(func, msg) xmlSchemaInternalErr(ACTXT_CAST vctxt, func, msg);
2735 #define PERROR_INT(func, msg) xmlSchemaInternalErr(ACTXT_CAST pctxt, func, msg);
2736 #define PERROR_INT2(func, msg) xmlSchemaInternalErr(ACTXT_CAST ctxt, func, msg);
2738 #define AERROR_INT(func, msg) xmlSchemaInternalErr(actxt, func, msg);
2742 * xmlSchemaPMissingAttrErr:
2743 * @ctxt: the schema validation context
2744 * @ownerDes: the designation of the owner
2745 * @ownerName: the name of the owner
2746 * @ownerItem: the owner as a schema object
2747 * @ownerElem: the owner as an element node
2748 * @node: the parent element node of the missing attribute node
2749 * @type: the corresponding type of the attribute node
2751 * Reports an illegal attribute.
2753 static void
2754 xmlSchemaPMissingAttrErr(xmlSchemaParserCtxtPtr ctxt,
2755 xmlParserErrors error,
2756 xmlSchemaBasicItemPtr ownerItem,
2757 xmlNodePtr ownerElem,
2758 const char *name,
2759 const char *message)
2761 xmlChar *des = NULL;
2763 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
2765 if (message != NULL)
2766 xmlSchemaPErr(ctxt, ownerElem, error, "%s: %s.\n", BAD_CAST des, BAD_CAST message);
2767 else
2768 xmlSchemaPErr(ctxt, ownerElem, error,
2769 "%s: The attribute '%s' is required but missing.\n",
2770 BAD_CAST des, BAD_CAST name);
2771 FREE_AND_NULL(des);
2776 * xmlSchemaPResCompAttrErr:
2777 * @ctxt: the schema validation context
2778 * @error: the error code
2779 * @ownerDes: the designation of the owner
2780 * @ownerItem: the owner as a schema object
2781 * @ownerElem: the owner as an element node
2782 * @name: the name of the attribute holding the QName
2783 * @refName: the referenced local name
2784 * @refURI: the referenced namespace URI
2785 * @message: optional message
2787 * Used to report QName attribute values that failed to resolve
2788 * to schema components.
2790 static void
2791 xmlSchemaPResCompAttrErr(xmlSchemaParserCtxtPtr ctxt,
2792 xmlParserErrors error,
2793 xmlSchemaBasicItemPtr ownerItem,
2794 xmlNodePtr ownerElem,
2795 const char *name,
2796 const xmlChar *refName,
2797 const xmlChar *refURI,
2798 xmlSchemaTypeType refType,
2799 const char *refTypeStr)
2801 xmlChar *des = NULL, *strA = NULL;
2803 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
2804 if (refTypeStr == NULL)
2805 refTypeStr = (const char *) xmlSchemaItemTypeToStr(refType);
2806 xmlSchemaPErrExt(ctxt, ownerElem, error,
2807 NULL, NULL, NULL,
2808 "%s, attribute '%s': The QName value '%s' does not resolve to a(n) "
2809 "%s.\n", BAD_CAST des, BAD_CAST name,
2810 xmlSchemaFormatQName(&strA, refURI, refName),
2811 BAD_CAST refTypeStr, NULL);
2812 FREE_AND_NULL(des)
2813 FREE_AND_NULL(strA)
2817 * xmlSchemaPCustomAttrErr:
2818 * @ctxt: the schema parser context
2819 * @error: the error code
2820 * @ownerDes: the designation of the owner
2821 * @ownerItem: the owner as a schema object
2822 * @attr: the illegal attribute node
2824 * Reports an illegal attribute during the parse.
2826 static void
2827 xmlSchemaPCustomAttrErr(xmlSchemaParserCtxtPtr ctxt,
2828 xmlParserErrors error,
2829 xmlChar **ownerDes,
2830 xmlSchemaBasicItemPtr ownerItem,
2831 xmlAttrPtr attr,
2832 const char *msg)
2834 xmlChar *des = NULL;
2836 if (ownerDes == NULL)
2837 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent);
2838 else if (*ownerDes == NULL) {
2839 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent);
2840 des = *ownerDes;
2841 } else
2842 des = *ownerDes;
2843 if (attr == NULL) {
2844 xmlSchemaPErrExt(ctxt, NULL, error, NULL, NULL, NULL,
2845 "%s, attribute '%s': %s.\n",
2846 BAD_CAST des, (const xmlChar *) "Unknown",
2847 (const xmlChar *) msg, NULL, NULL);
2848 } else {
2849 xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
2850 "%s, attribute '%s': %s.\n",
2851 BAD_CAST des, attr->name, (const xmlChar *) msg, NULL, NULL);
2853 if (ownerDes == NULL)
2854 FREE_AND_NULL(des);
2858 * xmlSchemaPIllegalAttrErr:
2859 * @ctxt: the schema parser context
2860 * @error: the error code
2861 * @ownerDes: the designation of the attribute's owner
2862 * @ownerItem: the attribute's owner item
2863 * @attr: the illegal attribute node
2865 * Reports an illegal attribute during the parse.
2867 static void
2868 xmlSchemaPIllegalAttrErr(xmlSchemaParserCtxtPtr ctxt,
2869 xmlParserErrors error,
2870 xmlSchemaBasicItemPtr ownerComp ATTRIBUTE_UNUSED,
2871 xmlAttrPtr attr)
2873 xmlChar *strA = NULL, *strB = NULL;
2875 xmlSchemaFormatNodeForError(&strA, ACTXT_CAST ctxt, attr->parent);
2876 xmlSchemaErr4(ACTXT_CAST ctxt, error, (xmlNodePtr) attr,
2877 "%sThe attribute '%s' is not allowed.\n", BAD_CAST strA,
2878 xmlSchemaFormatQNameNs(&strB, attr->ns, attr->name),
2879 NULL, NULL);
2880 FREE_AND_NULL(strA);
2881 FREE_AND_NULL(strB);
2885 * xmlSchemaPCustomErr:
2886 * @ctxt: the schema parser context
2887 * @error: the error code
2888 * @itemDes: the designation of the schema item
2889 * @item: the schema item
2890 * @itemElem: the node of the schema item
2891 * @message: the error message
2892 * @str1: an optional param for the error message
2893 * @str2: an optional param for the error message
2894 * @str3: an optional param for the error message
2896 * Reports an error during parsing.
2898 static void
2899 xmlSchemaPCustomErrExt(xmlSchemaParserCtxtPtr ctxt,
2900 xmlParserErrors error,
2901 xmlSchemaBasicItemPtr item,
2902 xmlNodePtr itemElem,
2903 const char *message,
2904 const xmlChar *str1,
2905 const xmlChar *str2,
2906 const xmlChar *str3)
2908 xmlChar *des = NULL, *msg = NULL;
2910 xmlSchemaFormatItemForReport(&des, NULL, item, itemElem);
2911 msg = xmlStrdup(BAD_CAST "%s: ");
2912 msg = xmlStrcat(msg, (const xmlChar *) message);
2913 msg = xmlStrcat(msg, BAD_CAST ".\n");
2914 if ((itemElem == NULL) && (item != NULL))
2915 itemElem = WXS_ITEM_NODE(item);
2916 xmlSchemaPErrExt(ctxt, itemElem, error, NULL, NULL, NULL,
2917 (const char *) msg, BAD_CAST des, str1, str2, str3, NULL);
2918 FREE_AND_NULL(des);
2919 FREE_AND_NULL(msg);
2923 * xmlSchemaPCustomErr:
2924 * @ctxt: the schema parser context
2925 * @error: the error code
2926 * @itemDes: the designation of the schema item
2927 * @item: the schema item
2928 * @itemElem: the node of the schema item
2929 * @message: the error message
2930 * @str1: the optional param for the error message
2932 * Reports an error during parsing.
2934 static void
2935 xmlSchemaPCustomErr(xmlSchemaParserCtxtPtr ctxt,
2936 xmlParserErrors error,
2937 xmlSchemaBasicItemPtr item,
2938 xmlNodePtr itemElem,
2939 const char *message,
2940 const xmlChar *str1)
2942 xmlSchemaPCustomErrExt(ctxt, error, item, itemElem, message,
2943 str1, NULL, NULL);
2947 * xmlSchemaPAttrUseErr:
2948 * @ctxt: the schema parser context
2949 * @error: the error code
2950 * @itemDes: the designation of the schema type
2951 * @item: the schema type
2952 * @itemElem: the node of the schema type
2953 * @attr: the invalid schema attribute
2954 * @message: the error message
2955 * @str1: the optional param for the error message
2957 * Reports an attribute use error during parsing.
2959 static void
2960 xmlSchemaPAttrUseErr4(xmlSchemaParserCtxtPtr ctxt,
2961 xmlParserErrors error,
2962 xmlNodePtr node,
2963 xmlSchemaBasicItemPtr ownerItem,
2964 const xmlSchemaAttributeUsePtr attruse,
2965 const char *message,
2966 const xmlChar *str1, const xmlChar *str2,
2967 const xmlChar *str3,const xmlChar *str4)
2969 xmlChar *str = NULL, *msg = NULL;
2971 xmlSchemaFormatItemForReport(&msg, NULL, ownerItem, NULL);
2972 msg = xmlStrcat(msg, BAD_CAST ", ");
2973 msg = xmlStrcat(msg,
2974 BAD_CAST xmlSchemaFormatItemForReport(&str, NULL,
2975 WXS_BASIC_CAST attruse, NULL));
2976 FREE_AND_NULL(str);
2977 msg = xmlStrcat(msg, BAD_CAST ": ");
2978 msg = xmlStrcat(msg, (const xmlChar *) message);
2979 msg = xmlStrcat(msg, BAD_CAST ".\n");
2980 xmlSchemaErr4(ACTXT_CAST ctxt, error, node,
2981 (const char *) msg, str1, str2, str3, str4);
2982 xmlFree(msg);
2986 * xmlSchemaPIllegalFacetAtomicErr:
2987 * @ctxt: the schema parser context
2988 * @error: the error code
2989 * @type: the schema type
2990 * @baseType: the base type of type
2991 * @facet: the illegal facet
2993 * Reports an illegal facet for atomic simple types.
2995 static void
2996 xmlSchemaPIllegalFacetAtomicErr(xmlSchemaParserCtxtPtr ctxt,
2997 xmlParserErrors error,
2998 xmlSchemaTypePtr type,
2999 xmlSchemaTypePtr baseType,
3000 xmlSchemaFacetPtr facet)
3002 xmlChar *des = NULL, *strT = NULL;
3004 xmlSchemaFormatItemForReport(&des, NULL, WXS_BASIC_CAST type, type->node);
3005 xmlSchemaPErrExt(ctxt, type->node, error, NULL, NULL, NULL,
3006 "%s: The facet '%s' is not allowed on types derived from the "
3007 "type %s.\n",
3008 BAD_CAST des, xmlSchemaFacetTypeToString(facet->type),
3009 xmlSchemaFormatItemForReport(&strT, NULL, WXS_BASIC_CAST baseType, NULL),
3010 NULL, NULL);
3011 FREE_AND_NULL(des);
3012 FREE_AND_NULL(strT);
3016 * xmlSchemaPIllegalFacetListUnionErr:
3017 * @ctxt: the schema parser context
3018 * @error: the error code
3019 * @itemDes: the designation of the schema item involved
3020 * @item: the schema item involved
3021 * @facet: the illegal facet
3023 * Reports an illegal facet for <list> and <union>.
3025 static void
3026 xmlSchemaPIllegalFacetListUnionErr(xmlSchemaParserCtxtPtr ctxt,
3027 xmlParserErrors error,
3028 xmlSchemaTypePtr type,
3029 xmlSchemaFacetPtr facet)
3031 xmlChar *des = NULL;
3033 xmlSchemaFormatItemForReport(&des, NULL, WXS_BASIC_CAST type,
3034 type->node);
3035 xmlSchemaPErr(ctxt, type->node, error,
3036 "%s: The facet '%s' is not allowed.\n",
3037 BAD_CAST des, xmlSchemaFacetTypeToString(facet->type));
3038 FREE_AND_NULL(des);
3042 * xmlSchemaPMutualExclAttrErr:
3043 * @ctxt: the schema validation context
3044 * @error: the error code
3045 * @elemDes: the designation of the parent element node
3046 * @attr: the bad attribute node
3047 * @type: the corresponding type of the attribute node
3049 * Reports an illegal attribute.
3051 static void
3052 xmlSchemaPMutualExclAttrErr(xmlSchemaParserCtxtPtr ctxt,
3053 xmlParserErrors error,
3054 xmlSchemaBasicItemPtr ownerItem,
3055 xmlAttrPtr attr,
3056 const char *name1,
3057 const char *name2)
3059 xmlChar *des = NULL;
3061 xmlSchemaFormatItemForReport(&des, NULL, WXS_BASIC_CAST ownerItem, attr->parent);
3062 xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
3063 "%s: The attributes '%s' and '%s' are mutually exclusive.\n",
3064 BAD_CAST des, BAD_CAST name1, BAD_CAST name2, NULL, NULL);
3065 FREE_AND_NULL(des);
3069 * xmlSchemaPSimpleTypeErr:
3070 * @ctxt: the schema validation context
3071 * @error: the error code
3072 * @type: the type specifier
3073 * @ownerDes: the designation of the owner
3074 * @ownerItem: the schema object if existent
3075 * @node: the validated node
3076 * @value: the validated value
3078 * Reports a simple type validation error.
3079 * TODO: Should this report the value of an element as well?
3081 static void
3082 xmlSchemaPSimpleTypeErr(xmlSchemaParserCtxtPtr ctxt,
3083 xmlParserErrors error,
3084 xmlSchemaBasicItemPtr ownerItem ATTRIBUTE_UNUSED,
3085 xmlNodePtr node,
3086 xmlSchemaTypePtr type,
3087 const char *expected,
3088 const xmlChar *value,
3089 const char *message,
3090 const xmlChar *str1,
3091 const xmlChar *str2)
3093 xmlChar *msg = NULL;
3095 xmlSchemaFormatNodeForError(&msg, ACTXT_CAST ctxt, node);
3096 if (message == NULL) {
3098 * Use default messages.
3100 if (type != NULL) {
3101 if (node->type == XML_ATTRIBUTE_NODE)
3102 msg = xmlStrcat(msg, BAD_CAST "'%s' is not a valid value of ");
3103 else
3104 msg = xmlStrcat(msg, BAD_CAST "The character content is not a "
3105 "valid value of ");
3106 if (! xmlSchemaIsGlobalItem(type))
3107 msg = xmlStrcat(msg, BAD_CAST "the local ");
3108 else
3109 msg = xmlStrcat(msg, BAD_CAST "the ");
3111 if (WXS_IS_ATOMIC(type))
3112 msg = xmlStrcat(msg, BAD_CAST "atomic type");
3113 else if (WXS_IS_LIST(type))
3114 msg = xmlStrcat(msg, BAD_CAST "list type");
3115 else if (WXS_IS_UNION(type))
3116 msg = xmlStrcat(msg, BAD_CAST "union type");
3118 if (xmlSchemaIsGlobalItem(type)) {
3119 xmlChar *str = NULL;
3120 msg = xmlStrcat(msg, BAD_CAST " '");
3121 if (type->builtInType != 0) {
3122 msg = xmlStrcat(msg, BAD_CAST "xs:");
3123 msg = xmlStrcat(msg, type->name);
3124 } else
3125 msg = xmlStrcat(msg,
3126 xmlSchemaFormatQName(&str,
3127 type->targetNamespace, type->name));
3128 msg = xmlStrcat(msg, BAD_CAST "'.");
3129 FREE_AND_NULL(str);
3131 } else {
3132 if (node->type == XML_ATTRIBUTE_NODE)
3133 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not valid.");
3134 else
3135 msg = xmlStrcat(msg, BAD_CAST "The character content is not "
3136 "valid.");
3138 if (expected) {
3139 msg = xmlStrcat(msg, BAD_CAST " Expected is '");
3140 msg = xmlStrcat(msg, BAD_CAST expected);
3141 msg = xmlStrcat(msg, BAD_CAST "'.\n");
3142 } else
3143 msg = xmlStrcat(msg, BAD_CAST "\n");
3144 if (node->type == XML_ATTRIBUTE_NODE)
3145 xmlSchemaPErr(ctxt, node, error, (const char *) msg, value, NULL);
3146 else
3147 xmlSchemaPErr(ctxt, node, error, (const char *) msg, NULL, NULL);
3148 } else {
3149 msg = xmlStrcat(msg, BAD_CAST message);
3150 msg = xmlStrcat(msg, BAD_CAST ".\n");
3151 xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL,
3152 (const char*) msg, str1, str2, NULL, NULL, NULL);
3154 /* Cleanup. */
3155 FREE_AND_NULL(msg)
3159 * xmlSchemaPContentErr:
3160 * @ctxt: the schema parser context
3161 * @error: the error code
3162 * @onwerDes: the designation of the holder of the content
3163 * @ownerItem: the owner item of the holder of the content
3164 * @ownerElem: the node of the holder of the content
3165 * @child: the invalid child node
3166 * @message: the optional error message
3167 * @content: the optional string describing the correct content
3169 * Reports an error concerning the content of a schema element.
3171 static void
3172 xmlSchemaPContentErr(xmlSchemaParserCtxtPtr ctxt,
3173 xmlParserErrors error,
3174 xmlSchemaBasicItemPtr ownerItem,
3175 xmlNodePtr ownerElem,
3176 xmlNodePtr child,
3177 const char *message,
3178 const char *content)
3180 xmlChar *des = NULL;
3182 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
3183 if (message != NULL)
3184 xmlSchemaPErr2(ctxt, ownerElem, child, error,
3185 "%s: %s.\n",
3186 BAD_CAST des, BAD_CAST message);
3187 else {
3188 if (content != NULL) {
3189 xmlSchemaPErr2(ctxt, ownerElem, child, error,
3190 "%s: The content is not valid. Expected is %s.\n",
3191 BAD_CAST des, BAD_CAST content);
3192 } else {
3193 xmlSchemaPErr2(ctxt, ownerElem, child, error,
3194 "%s: The content is not valid.\n",
3195 BAD_CAST des, NULL);
3198 FREE_AND_NULL(des)
3201 /************************************************************************
3203 * Streamable error functions *
3205 ************************************************************************/
3210 /************************************************************************
3212 * Validation helper functions *
3214 ************************************************************************/
3217 /************************************************************************
3219 * Allocation functions *
3221 ************************************************************************/
3224 * xmlSchemaNewSchemaForParserCtxt:
3225 * @ctxt: a schema validation context
3227 * Allocate a new Schema structure.
3229 * Returns the newly allocated structure or NULL in case or error
3231 static xmlSchemaPtr
3232 xmlSchemaNewSchema(xmlSchemaParserCtxtPtr ctxt)
3234 xmlSchemaPtr ret;
3236 ret = (xmlSchemaPtr) xmlMalloc(sizeof(xmlSchema));
3237 if (ret == NULL) {
3238 xmlSchemaPErrMemory(ctxt, "allocating schema", NULL);
3239 return (NULL);
3241 memset(ret, 0, sizeof(xmlSchema));
3242 ret->dict = ctxt->dict;
3243 xmlDictReference(ret->dict);
3245 return (ret);
3249 * xmlSchemaNewFacet:
3251 * Allocate a new Facet structure.
3253 * Returns the newly allocated structure or NULL in case or error
3255 xmlSchemaFacetPtr
3256 xmlSchemaNewFacet(void)
3258 xmlSchemaFacetPtr ret;
3260 ret = (xmlSchemaFacetPtr) xmlMalloc(sizeof(xmlSchemaFacet));
3261 if (ret == NULL) {
3262 return (NULL);
3264 memset(ret, 0, sizeof(xmlSchemaFacet));
3266 return (ret);
3270 * xmlSchemaNewAnnot:
3271 * @ctxt: a schema validation context
3272 * @node: a node
3274 * Allocate a new annotation structure.
3276 * Returns the newly allocated structure or NULL in case or error
3278 static xmlSchemaAnnotPtr
3279 xmlSchemaNewAnnot(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
3281 xmlSchemaAnnotPtr ret;
3283 ret = (xmlSchemaAnnotPtr) xmlMalloc(sizeof(xmlSchemaAnnot));
3284 if (ret == NULL) {
3285 xmlSchemaPErrMemory(ctxt, "allocating annotation", node);
3286 return (NULL);
3288 memset(ret, 0, sizeof(xmlSchemaAnnot));
3289 ret->content = node;
3290 return (ret);
3293 static xmlSchemaItemListPtr
3294 xmlSchemaItemListCreate(void)
3296 xmlSchemaItemListPtr ret;
3298 ret = xmlMalloc(sizeof(xmlSchemaItemList));
3299 if (ret == NULL) {
3300 xmlSchemaPErrMemory(NULL,
3301 "allocating an item list structure", NULL);
3302 return (NULL);
3304 memset(ret, 0, sizeof(xmlSchemaItemList));
3305 return (ret);
3308 static void
3309 xmlSchemaItemListClear(xmlSchemaItemListPtr list)
3311 if (list->items != NULL) {
3312 xmlFree(list->items);
3313 list->items = NULL;
3315 list->nbItems = 0;
3316 list->sizeItems = 0;
3319 static int
3320 xmlSchemaItemListAdd(xmlSchemaItemListPtr list, void *item)
3322 if (list->items == NULL) {
3323 list->items = (void **) xmlMalloc(
3324 20 * sizeof(void *));
3325 if (list->items == NULL) {
3326 xmlSchemaPErrMemory(NULL, "allocating new item list", NULL);
3327 return(-1);
3329 list->sizeItems = 20;
3330 } else if (list->sizeItems <= list->nbItems) {
3331 list->sizeItems *= 2;
3332 list->items = (void **) xmlRealloc(list->items,
3333 list->sizeItems * sizeof(void *));
3334 if (list->items == NULL) {
3335 xmlSchemaPErrMemory(NULL, "growing item list", NULL);
3336 list->sizeItems = 0;
3337 return(-1);
3340 list->items[list->nbItems++] = item;
3341 return(0);
3344 static int
3345 xmlSchemaItemListAddSize(xmlSchemaItemListPtr list,
3346 int initialSize,
3347 void *item)
3349 if (list->items == NULL) {
3350 if (initialSize <= 0)
3351 initialSize = 1;
3352 list->items = (void **) xmlMalloc(
3353 initialSize * sizeof(void *));
3354 if (list->items == NULL) {
3355 xmlSchemaPErrMemory(NULL, "allocating new item list", NULL);
3356 return(-1);
3358 list->sizeItems = initialSize;
3359 } else if (list->sizeItems <= list->nbItems) {
3360 list->sizeItems *= 2;
3361 list->items = (void **) xmlRealloc(list->items,
3362 list->sizeItems * sizeof(void *));
3363 if (list->items == NULL) {
3364 xmlSchemaPErrMemory(NULL, "growing item list", NULL);
3365 list->sizeItems = 0;
3366 return(-1);
3369 list->items[list->nbItems++] = item;
3370 return(0);
3373 static int
3374 xmlSchemaItemListInsert(xmlSchemaItemListPtr list, void *item, int idx)
3376 if (list->items == NULL) {
3377 list->items = (void **) xmlMalloc(
3378 20 * sizeof(void *));
3379 if (list->items == NULL) {
3380 xmlSchemaPErrMemory(NULL, "allocating new item list", NULL);
3381 return(-1);
3383 list->sizeItems = 20;
3384 } else if (list->sizeItems <= list->nbItems) {
3385 list->sizeItems *= 2;
3386 list->items = (void **) xmlRealloc(list->items,
3387 list->sizeItems * sizeof(void *));
3388 if (list->items == NULL) {
3389 xmlSchemaPErrMemory(NULL, "growing item list", NULL);
3390 list->sizeItems = 0;
3391 return(-1);
3395 * Just append if the index is greater/equal than the item count.
3397 if (idx >= list->nbItems) {
3398 list->items[list->nbItems++] = item;
3399 } else {
3400 int i;
3401 for (i = list->nbItems; i > idx; i--)
3402 list->items[i] = list->items[i-1];
3403 list->items[idx] = item;
3404 list->nbItems++;
3406 return(0);
3409 #if 0 /* enable if ever needed */
3410 static int
3411 xmlSchemaItemListInsertSize(xmlSchemaItemListPtr list,
3412 int initialSize,
3413 void *item,
3414 int idx)
3416 if (list->items == NULL) {
3417 if (initialSize <= 0)
3418 initialSize = 1;
3419 list->items = (void **) xmlMalloc(
3420 initialSize * sizeof(void *));
3421 if (list->items == NULL) {
3422 xmlSchemaPErrMemory(NULL, "allocating new item list", NULL);
3423 return(-1);
3425 list->sizeItems = initialSize;
3426 } else if (list->sizeItems <= list->nbItems) {
3427 list->sizeItems *= 2;
3428 list->items = (void **) xmlRealloc(list->items,
3429 list->sizeItems * sizeof(void *));
3430 if (list->items == NULL) {
3431 xmlSchemaPErrMemory(NULL, "growing item list", NULL);
3432 list->sizeItems = 0;
3433 return(-1);
3437 * Just append if the index is greater/equal than the item count.
3439 if (idx >= list->nbItems) {
3440 list->items[list->nbItems++] = item;
3441 } else {
3442 int i;
3443 for (i = list->nbItems; i > idx; i--)
3444 list->items[i] = list->items[i-1];
3445 list->items[idx] = item;
3446 list->nbItems++;
3448 return(0);
3450 #endif
3452 static int
3453 xmlSchemaItemListRemove(xmlSchemaItemListPtr list, int idx)
3455 int i;
3456 if ((list->items == NULL) || (idx >= list->nbItems)) {
3457 xmlSchemaPSimpleErr("Internal error: xmlSchemaItemListRemove, "
3458 "index error.\n");
3459 return(-1);
3462 if (list->nbItems == 1) {
3463 /* TODO: Really free the list? */
3464 xmlFree(list->items);
3465 list->items = NULL;
3466 list->nbItems = 0;
3467 list->sizeItems = 0;
3468 } else if (list->nbItems -1 == idx) {
3469 list->nbItems--;
3470 } else {
3471 for (i = idx; i < list->nbItems -1; i++)
3472 list->items[i] = list->items[i+1];
3473 list->nbItems--;
3475 return(0);
3479 * xmlSchemaItemListFree:
3480 * @annot: a schema type structure
3482 * Deallocate a annotation structure
3484 static void
3485 xmlSchemaItemListFree(xmlSchemaItemListPtr list)
3487 if (list == NULL)
3488 return;
3489 if (list->items != NULL)
3490 xmlFree(list->items);
3491 xmlFree(list);
3494 static void
3495 xmlSchemaBucketFree(xmlSchemaBucketPtr bucket)
3497 if (bucket == NULL)
3498 return;
3499 if (bucket->globals != NULL) {
3500 xmlSchemaComponentListFree(bucket->globals);
3501 xmlSchemaItemListFree(bucket->globals);
3503 if (bucket->locals != NULL) {
3504 xmlSchemaComponentListFree(bucket->locals);
3505 xmlSchemaItemListFree(bucket->locals);
3507 if (bucket->relations != NULL) {
3508 xmlSchemaSchemaRelationPtr prev, cur = bucket->relations;
3509 do {
3510 prev = cur;
3511 cur = cur->next;
3512 xmlFree(prev);
3513 } while (cur != NULL);
3515 if ((! bucket->preserveDoc) && (bucket->doc != NULL)) {
3516 xmlFreeDoc(bucket->doc);
3518 if (bucket->type == XML_SCHEMA_SCHEMA_IMPORT) {
3519 if (WXS_IMPBUCKET(bucket)->schema != NULL)
3520 xmlSchemaFree(WXS_IMPBUCKET(bucket)->schema);
3522 xmlFree(bucket);
3525 static xmlSchemaBucketPtr
3526 xmlSchemaBucketCreate(xmlSchemaParserCtxtPtr pctxt,
3527 int type, const xmlChar *targetNamespace)
3529 xmlSchemaBucketPtr ret;
3530 int size;
3531 xmlSchemaPtr mainSchema;
3533 if (WXS_CONSTRUCTOR(pctxt)->mainSchema == NULL) {
3534 PERROR_INT("xmlSchemaBucketCreate",
3535 "no main schema on constructor");
3536 return(NULL);
3538 mainSchema = WXS_CONSTRUCTOR(pctxt)->mainSchema;
3539 /* Create the schema bucket. */
3540 if (WXS_IS_BUCKET_INCREDEF(type))
3541 size = sizeof(xmlSchemaInclude);
3542 else
3543 size = sizeof(xmlSchemaImport);
3544 ret = (xmlSchemaBucketPtr) xmlMalloc(size);
3545 if (ret == NULL) {
3546 xmlSchemaPErrMemory(NULL, "allocating schema bucket", NULL);
3547 return(NULL);
3549 memset(ret, 0, size);
3550 ret->targetNamespace = targetNamespace;
3551 ret->type = type;
3552 ret->globals = xmlSchemaItemListCreate();
3553 if (ret->globals == NULL) {
3554 xmlFree(ret);
3555 return(NULL);
3557 ret->locals = xmlSchemaItemListCreate();
3558 if (ret->locals == NULL) {
3559 xmlFree(ret);
3560 return(NULL);
3563 * The following will assure that only the first bucket is marked as
3564 * XML_SCHEMA_SCHEMA_MAIN and it points to the *main* schema.
3565 * For each following import buckets an xmlSchema will be created.
3566 * An xmlSchema will be created for every distinct targetNamespace.
3567 * We assign the targetNamespace to the schemata here.
3569 if (! WXS_HAS_BUCKETS(pctxt)) {
3570 if (WXS_IS_BUCKET_INCREDEF(type)) {
3571 PERROR_INT("xmlSchemaBucketCreate",
3572 "first bucket but it's an include or redefine");
3573 xmlSchemaBucketFree(ret);
3574 return(NULL);
3576 /* Force the type to be XML_SCHEMA_SCHEMA_MAIN. */
3577 ret->type = XML_SCHEMA_SCHEMA_MAIN;
3578 /* Point to the *main* schema. */
3579 WXS_CONSTRUCTOR(pctxt)->mainBucket = ret;
3580 WXS_IMPBUCKET(ret)->schema = mainSchema;
3582 * Ensure that the main schema gets a targetNamespace.
3584 mainSchema->targetNamespace = targetNamespace;
3585 } else {
3586 if (type == XML_SCHEMA_SCHEMA_MAIN) {
3587 PERROR_INT("xmlSchemaBucketCreate",
3588 "main bucket but it's not the first one");
3589 xmlSchemaBucketFree(ret);
3590 return(NULL);
3591 } else if (type == XML_SCHEMA_SCHEMA_IMPORT) {
3593 * Create a schema for imports and assign the
3594 * targetNamespace.
3596 WXS_IMPBUCKET(ret)->schema = xmlSchemaNewSchema(pctxt);
3597 if (WXS_IMPBUCKET(ret)->schema == NULL) {
3598 xmlSchemaBucketFree(ret);
3599 return(NULL);
3601 WXS_IMPBUCKET(ret)->schema->targetNamespace = targetNamespace;
3604 if (WXS_IS_BUCKET_IMPMAIN(type)) {
3605 int res;
3607 * Imports go into the "schemasImports" slot of the main *schema*.
3608 * Note that we create an import entry for the main schema as well; i.e.,
3609 * even if there's only one schema, we'll get an import.
3611 if (mainSchema->schemasImports == NULL) {
3612 mainSchema->schemasImports = xmlHashCreateDict(5,
3613 WXS_CONSTRUCTOR(pctxt)->dict);
3614 if (mainSchema->schemasImports == NULL) {
3615 xmlSchemaBucketFree(ret);
3616 return(NULL);
3619 if (targetNamespace == NULL)
3620 res = xmlHashAddEntry(mainSchema->schemasImports,
3621 XML_SCHEMAS_NO_NAMESPACE, ret);
3622 else
3623 res = xmlHashAddEntry(mainSchema->schemasImports,
3624 targetNamespace, ret);
3625 if (res != 0) {
3626 PERROR_INT("xmlSchemaBucketCreate",
3627 "failed to add the schema bucket to the hash");
3628 xmlSchemaBucketFree(ret);
3629 return(NULL);
3631 } else {
3632 /* Set the @ownerImport of an include bucket. */
3633 if (WXS_IS_BUCKET_IMPMAIN(WXS_CONSTRUCTOR(pctxt)->bucket->type))
3634 WXS_INCBUCKET(ret)->ownerImport =
3635 WXS_IMPBUCKET(WXS_CONSTRUCTOR(pctxt)->bucket);
3636 else
3637 WXS_INCBUCKET(ret)->ownerImport =
3638 WXS_INCBUCKET(WXS_CONSTRUCTOR(pctxt)->bucket)->ownerImport;
3640 /* Includes got into the "includes" slot of the *main* schema. */
3641 if (mainSchema->includes == NULL) {
3642 mainSchema->includes = xmlSchemaItemListCreate();
3643 if (mainSchema->includes == NULL) {
3644 xmlSchemaBucketFree(ret);
3645 return(NULL);
3648 xmlSchemaItemListAdd(mainSchema->includes, ret);
3651 * Add to list of all buckets; this is used for lookup
3652 * during schema construction time only.
3654 if (xmlSchemaItemListAdd(WXS_CONSTRUCTOR(pctxt)->buckets, ret) == -1)
3655 return(NULL);
3656 return(ret);
3659 static int
3660 xmlSchemaAddItemSize(xmlSchemaItemListPtr *list, int initialSize, void *item)
3662 if (*list == NULL) {
3663 *list = xmlSchemaItemListCreate();
3664 if (*list == NULL)
3665 return(-1);
3667 xmlSchemaItemListAddSize(*list, initialSize, item);
3668 return(0);
3672 * xmlSchemaFreeAnnot:
3673 * @annot: a schema type structure
3675 * Deallocate a annotation structure
3677 static void
3678 xmlSchemaFreeAnnot(xmlSchemaAnnotPtr annot)
3680 if (annot == NULL)
3681 return;
3682 if (annot->next == NULL) {
3683 xmlFree(annot);
3684 } else {
3685 xmlSchemaAnnotPtr prev;
3687 do {
3688 prev = annot;
3689 annot = annot->next;
3690 xmlFree(prev);
3691 } while (annot != NULL);
3696 * xmlSchemaFreeNotation:
3697 * @schema: a schema notation structure
3699 * Deallocate a Schema Notation structure.
3701 static void
3702 xmlSchemaFreeNotation(xmlSchemaNotationPtr nota)
3704 if (nota == NULL)
3705 return;
3706 xmlFree(nota);
3710 * xmlSchemaFreeAttribute:
3711 * @attr: an attribute declaration
3713 * Deallocates an attribute declaration structure.
3715 static void
3716 xmlSchemaFreeAttribute(xmlSchemaAttributePtr attr)
3718 if (attr == NULL)
3719 return;
3720 if (attr->annot != NULL)
3721 xmlSchemaFreeAnnot(attr->annot);
3722 if (attr->defVal != NULL)
3723 xmlSchemaFreeValue(attr->defVal);
3724 xmlFree(attr);
3728 * xmlSchemaFreeAttributeUse:
3729 * @use: an attribute use
3731 * Deallocates an attribute use structure.
3733 static void
3734 xmlSchemaFreeAttributeUse(xmlSchemaAttributeUsePtr use)
3736 if (use == NULL)
3737 return;
3738 if (use->annot != NULL)
3739 xmlSchemaFreeAnnot(use->annot);
3740 if (use->defVal != NULL)
3741 xmlSchemaFreeValue(use->defVal);
3742 xmlFree(use);
3746 * xmlSchemaFreeAttributeUseProhib:
3747 * @prohib: an attribute use prohibition
3749 * Deallocates an attribute use structure.
3751 static void
3752 xmlSchemaFreeAttributeUseProhib(xmlSchemaAttributeUseProhibPtr prohib)
3754 if (prohib == NULL)
3755 return;
3756 xmlFree(prohib);
3760 * xmlSchemaFreeWildcardNsSet:
3761 * set: a schema wildcard namespace
3763 * Deallocates a list of wildcard constraint structures.
3765 static void
3766 xmlSchemaFreeWildcardNsSet(xmlSchemaWildcardNsPtr set)
3768 xmlSchemaWildcardNsPtr next;
3770 while (set != NULL) {
3771 next = set->next;
3772 xmlFree(set);
3773 set = next;
3778 * xmlSchemaFreeWildcard:
3779 * @wildcard: a wildcard structure
3781 * Deallocates a wildcard structure.
3783 void
3784 xmlSchemaFreeWildcard(xmlSchemaWildcardPtr wildcard)
3786 if (wildcard == NULL)
3787 return;
3788 if (wildcard->annot != NULL)
3789 xmlSchemaFreeAnnot(wildcard->annot);
3790 if (wildcard->nsSet != NULL)
3791 xmlSchemaFreeWildcardNsSet(wildcard->nsSet);
3792 if (wildcard->negNsSet != NULL)
3793 xmlFree(wildcard->negNsSet);
3794 xmlFree(wildcard);
3798 * xmlSchemaFreeAttributeGroup:
3799 * @schema: a schema attribute group structure
3801 * Deallocate a Schema Attribute Group structure.
3803 static void
3804 xmlSchemaFreeAttributeGroup(xmlSchemaAttributeGroupPtr attrGr)
3806 if (attrGr == NULL)
3807 return;
3808 if (attrGr->annot != NULL)
3809 xmlSchemaFreeAnnot(attrGr->annot);
3810 if (attrGr->attrUses != NULL)
3811 xmlSchemaItemListFree(WXS_LIST_CAST attrGr->attrUses);
3812 xmlFree(attrGr);
3816 * xmlSchemaFreeQNameRef:
3817 * @item: a QName reference structure
3819 * Deallocatea a QName reference structure.
3821 static void
3822 xmlSchemaFreeQNameRef(xmlSchemaQNameRefPtr item)
3824 xmlFree(item);
3828 * xmlSchemaFreeTypeLinkList:
3829 * @alink: a type link
3831 * Deallocate a list of types.
3833 static void
3834 xmlSchemaFreeTypeLinkList(xmlSchemaTypeLinkPtr link)
3836 xmlSchemaTypeLinkPtr next;
3838 while (link != NULL) {
3839 next = link->next;
3840 xmlFree(link);
3841 link = next;
3845 static void
3846 xmlSchemaFreeIDCStateObjList(xmlSchemaIDCStateObjPtr sto)
3848 xmlSchemaIDCStateObjPtr next;
3849 while (sto != NULL) {
3850 next = sto->next;
3851 if (sto->history != NULL)
3852 xmlFree(sto->history);
3853 if (sto->xpathCtxt != NULL)
3854 xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
3855 xmlFree(sto);
3856 sto = next;
3861 * xmlSchemaFreeIDC:
3862 * @idc: a identity-constraint definition
3864 * Deallocates an identity-constraint definition.
3866 static void
3867 xmlSchemaFreeIDC(xmlSchemaIDCPtr idcDef)
3869 xmlSchemaIDCSelectPtr cur, prev;
3871 if (idcDef == NULL)
3872 return;
3873 if (idcDef->annot != NULL)
3874 xmlSchemaFreeAnnot(idcDef->annot);
3875 /* Selector */
3876 if (idcDef->selector != NULL) {
3877 if (idcDef->selector->xpathComp != NULL)
3878 xmlFreePattern((xmlPatternPtr) idcDef->selector->xpathComp);
3879 xmlFree(idcDef->selector);
3881 /* Fields */
3882 if (idcDef->fields != NULL) {
3883 cur = idcDef->fields;
3884 do {
3885 prev = cur;
3886 cur = cur->next;
3887 if (prev->xpathComp != NULL)
3888 xmlFreePattern((xmlPatternPtr) prev->xpathComp);
3889 xmlFree(prev);
3890 } while (cur != NULL);
3892 xmlFree(idcDef);
3896 * xmlSchemaFreeElement:
3897 * @schema: a schema element structure
3899 * Deallocate a Schema Element structure.
3901 static void
3902 xmlSchemaFreeElement(xmlSchemaElementPtr elem)
3904 if (elem == NULL)
3905 return;
3906 if (elem->annot != NULL)
3907 xmlSchemaFreeAnnot(elem->annot);
3908 if (elem->contModel != NULL)
3909 xmlRegFreeRegexp(elem->contModel);
3910 if (elem->defVal != NULL)
3911 xmlSchemaFreeValue(elem->defVal);
3912 xmlFree(elem);
3916 * xmlSchemaFreeFacet:
3917 * @facet: a schema facet structure
3919 * Deallocate a Schema Facet structure.
3921 void
3922 xmlSchemaFreeFacet(xmlSchemaFacetPtr facet)
3924 if (facet == NULL)
3925 return;
3926 if (facet->val != NULL)
3927 xmlSchemaFreeValue(facet->val);
3928 if (facet->regexp != NULL)
3929 xmlRegFreeRegexp(facet->regexp);
3930 if (facet->annot != NULL)
3931 xmlSchemaFreeAnnot(facet->annot);
3932 xmlFree(facet);
3936 * xmlSchemaFreeType:
3937 * @type: a schema type structure
3939 * Deallocate a Schema Type structure.
3941 void
3942 xmlSchemaFreeType(xmlSchemaTypePtr type)
3944 if (type == NULL)
3945 return;
3946 if (type->annot != NULL)
3947 xmlSchemaFreeAnnot(type->annot);
3948 if (type->facets != NULL) {
3949 xmlSchemaFacetPtr facet, next;
3951 facet = type->facets;
3952 while (facet != NULL) {
3953 next = facet->next;
3954 xmlSchemaFreeFacet(facet);
3955 facet = next;
3958 if (type->attrUses != NULL)
3959 xmlSchemaItemListFree((xmlSchemaItemListPtr) type->attrUses);
3960 if (type->memberTypes != NULL)
3961 xmlSchemaFreeTypeLinkList(type->memberTypes);
3962 if (type->facetSet != NULL) {
3963 xmlSchemaFacetLinkPtr next, link;
3965 link = type->facetSet;
3966 do {
3967 next = link->next;
3968 xmlFree(link);
3969 link = next;
3970 } while (link != NULL);
3972 if (type->contModel != NULL)
3973 xmlRegFreeRegexp(type->contModel);
3974 xmlFree(type);
3978 * xmlSchemaFreeModelGroupDef:
3979 * @item: a schema model group definition
3981 * Deallocates a schema model group definition.
3983 static void
3984 xmlSchemaFreeModelGroupDef(xmlSchemaModelGroupDefPtr item)
3986 if (item->annot != NULL)
3987 xmlSchemaFreeAnnot(item->annot);
3988 xmlFree(item);
3992 * xmlSchemaFreeModelGroup:
3993 * @item: a schema model group
3995 * Deallocates a schema model group structure.
3997 static void
3998 xmlSchemaFreeModelGroup(xmlSchemaModelGroupPtr item)
4000 if (item->annot != NULL)
4001 xmlSchemaFreeAnnot(item->annot);
4002 xmlFree(item);
4005 static void
4006 xmlSchemaComponentListFree(xmlSchemaItemListPtr list)
4008 if ((list == NULL) || (list->nbItems == 0))
4009 return;
4011 xmlSchemaTreeItemPtr item;
4012 xmlSchemaTreeItemPtr *items = (xmlSchemaTreeItemPtr *) list->items;
4013 int i;
4015 for (i = 0; i < list->nbItems; i++) {
4016 item = items[i];
4017 if (item == NULL)
4018 continue;
4019 switch (item->type) {
4020 case XML_SCHEMA_TYPE_SIMPLE:
4021 case XML_SCHEMA_TYPE_COMPLEX:
4022 xmlSchemaFreeType((xmlSchemaTypePtr) item);
4023 break;
4024 case XML_SCHEMA_TYPE_ATTRIBUTE:
4025 xmlSchemaFreeAttribute((xmlSchemaAttributePtr) item);
4026 break;
4027 case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
4028 xmlSchemaFreeAttributeUse((xmlSchemaAttributeUsePtr) item);
4029 break;
4030 case XML_SCHEMA_EXTRA_ATTR_USE_PROHIB:
4031 xmlSchemaFreeAttributeUseProhib(
4032 (xmlSchemaAttributeUseProhibPtr) item);
4033 break;
4034 case XML_SCHEMA_TYPE_ELEMENT:
4035 xmlSchemaFreeElement((xmlSchemaElementPtr) item);
4036 break;
4037 case XML_SCHEMA_TYPE_PARTICLE:
4038 if (item->annot != NULL)
4039 xmlSchemaFreeAnnot(item->annot);
4040 xmlFree(item);
4041 break;
4042 case XML_SCHEMA_TYPE_SEQUENCE:
4043 case XML_SCHEMA_TYPE_CHOICE:
4044 case XML_SCHEMA_TYPE_ALL:
4045 xmlSchemaFreeModelGroup((xmlSchemaModelGroupPtr) item);
4046 break;
4047 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
4048 xmlSchemaFreeAttributeGroup(
4049 (xmlSchemaAttributeGroupPtr) item);
4050 break;
4051 case XML_SCHEMA_TYPE_GROUP:
4052 xmlSchemaFreeModelGroupDef(
4053 (xmlSchemaModelGroupDefPtr) item);
4054 break;
4055 case XML_SCHEMA_TYPE_ANY:
4056 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
4057 xmlSchemaFreeWildcard((xmlSchemaWildcardPtr) item);
4058 break;
4059 case XML_SCHEMA_TYPE_IDC_KEY:
4060 case XML_SCHEMA_TYPE_IDC_UNIQUE:
4061 case XML_SCHEMA_TYPE_IDC_KEYREF:
4062 xmlSchemaFreeIDC((xmlSchemaIDCPtr) item);
4063 break;
4064 case XML_SCHEMA_TYPE_NOTATION:
4065 xmlSchemaFreeNotation((xmlSchemaNotationPtr) item);
4066 break;
4067 case XML_SCHEMA_EXTRA_QNAMEREF:
4068 xmlSchemaFreeQNameRef((xmlSchemaQNameRefPtr) item);
4069 break;
4070 default: {
4071 /* TODO: This should never be hit. */
4072 xmlSchemaPSimpleInternalErr(NULL,
4073 "Internal error: xmlSchemaComponentListFree, "
4074 "unexpected component type '%s'\n",
4075 (const xmlChar *) WXS_ITEM_TYPE_NAME(item));
4077 break;
4080 list->nbItems = 0;
4085 * xmlSchemaFree:
4086 * @schema: a schema structure
4088 * Deallocate a Schema structure.
4090 void
4091 xmlSchemaFree(xmlSchemaPtr schema)
4093 if (schema == NULL)
4094 return;
4095 /* @volatiles is not used anymore :-/ */
4096 if (schema->volatiles != NULL)
4097 TODO
4099 * Note that those slots are not responsible for freeing
4100 * schema components anymore; this will now be done by
4101 * the schema buckets.
4103 if (schema->notaDecl != NULL)
4104 xmlHashFree(schema->notaDecl, NULL);
4105 if (schema->attrDecl != NULL)
4106 xmlHashFree(schema->attrDecl, NULL);
4107 if (schema->attrgrpDecl != NULL)
4108 xmlHashFree(schema->attrgrpDecl, NULL);
4109 if (schema->elemDecl != NULL)
4110 xmlHashFree(schema->elemDecl, NULL);
4111 if (schema->typeDecl != NULL)
4112 xmlHashFree(schema->typeDecl, NULL);
4113 if (schema->groupDecl != NULL)
4114 xmlHashFree(schema->groupDecl, NULL);
4115 if (schema->idcDef != NULL)
4116 xmlHashFree(schema->idcDef, NULL);
4118 if (schema->schemasImports != NULL)
4119 xmlHashFree(schema->schemasImports,
4120 (xmlHashDeallocator) xmlSchemaBucketFree);
4121 if (schema->includes != NULL) {
4122 xmlSchemaItemListPtr list = (xmlSchemaItemListPtr) schema->includes;
4123 int i;
4124 for (i = 0; i < list->nbItems; i++) {
4125 xmlSchemaBucketFree((xmlSchemaBucketPtr) list->items[i]);
4127 xmlSchemaItemListFree(list);
4129 if (schema->annot != NULL)
4130 xmlSchemaFreeAnnot(schema->annot);
4131 /* Never free the doc here, since this will be done by the buckets. */
4133 xmlDictFree(schema->dict);
4134 xmlFree(schema);
4137 /************************************************************************
4139 * Debug functions *
4141 ************************************************************************/
4143 #ifdef LIBXML_OUTPUT_ENABLED
4145 static void
4146 xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output); /* forward */
4149 * xmlSchemaElementDump:
4150 * @elem: an element
4151 * @output: the file output
4153 * Dump the element
4155 static void
4156 xmlSchemaElementDump(xmlSchemaElementPtr elem, FILE * output,
4157 const xmlChar * name ATTRIBUTE_UNUSED,
4158 const xmlChar * namespace ATTRIBUTE_UNUSED,
4159 const xmlChar * context ATTRIBUTE_UNUSED)
4161 if (elem == NULL)
4162 return;
4165 fprintf(output, "Element");
4166 if (elem->flags & XML_SCHEMAS_ELEM_GLOBAL)
4167 fprintf(output, " (global)");
4168 fprintf(output, ": '%s' ", elem->name);
4169 if (namespace != NULL)
4170 fprintf(output, "ns '%s'", namespace);
4171 fprintf(output, "\n");
4172 #if 0
4173 if ((elem->minOccurs != 1) || (elem->maxOccurs != 1)) {
4174 fprintf(output, " min %d ", elem->minOccurs);
4175 if (elem->maxOccurs >= UNBOUNDED)
4176 fprintf(output, "max: unbounded\n");
4177 else if (elem->maxOccurs != 1)
4178 fprintf(output, "max: %d\n", elem->maxOccurs);
4179 else
4180 fprintf(output, "\n");
4182 #endif
4184 * Misc other properties.
4186 if ((elem->flags & XML_SCHEMAS_ELEM_NILLABLE) ||
4187 (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT) ||
4188 (elem->flags & XML_SCHEMAS_ELEM_FIXED) ||
4189 (elem->flags & XML_SCHEMAS_ELEM_DEFAULT)) {
4190 fprintf(output, " props: ");
4191 if (elem->flags & XML_SCHEMAS_ELEM_FIXED)
4192 fprintf(output, "[fixed] ");
4193 if (elem->flags & XML_SCHEMAS_ELEM_DEFAULT)
4194 fprintf(output, "[default] ");
4195 if (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT)
4196 fprintf(output, "[abstract] ");
4197 if (elem->flags & XML_SCHEMAS_ELEM_NILLABLE)
4198 fprintf(output, "[nillable] ");
4199 fprintf(output, "\n");
4202 * Default/fixed value.
4204 if (elem->value != NULL)
4205 fprintf(output, " value: '%s'\n", elem->value);
4207 * Type.
4209 if (elem->namedType != NULL) {
4210 fprintf(output, " type: '%s' ", elem->namedType);
4211 if (elem->namedTypeNs != NULL)
4212 fprintf(output, "ns '%s'\n", elem->namedTypeNs);
4213 else
4214 fprintf(output, "\n");
4215 } else if (elem->subtypes != NULL) {
4217 * Dump local types.
4219 xmlSchemaTypeDump(elem->subtypes, output);
4222 * Substitution group.
4224 if (elem->substGroup != NULL) {
4225 fprintf(output, " substitutionGroup: '%s' ", elem->substGroup);
4226 if (elem->substGroupNs != NULL)
4227 fprintf(output, "ns '%s'\n", elem->substGroupNs);
4228 else
4229 fprintf(output, "\n");
4234 * xmlSchemaAnnotDump:
4235 * @output: the file output
4236 * @annot: a annotation
4238 * Dump the annotation
4240 static void
4241 xmlSchemaAnnotDump(FILE * output, xmlSchemaAnnotPtr annot)
4243 xmlChar *content;
4245 if (annot == NULL)
4246 return;
4248 content = xmlNodeGetContent(annot->content);
4249 if (content != NULL) {
4250 fprintf(output, " Annot: %s\n", content);
4251 xmlFree(content);
4252 } else
4253 fprintf(output, " Annot: empty\n");
4257 * xmlSchemaContentModelDump:
4258 * @particle: the schema particle
4259 * @output: the file output
4260 * @depth: the depth used for intentation
4262 * Dump a SchemaType structure
4264 static void
4265 xmlSchemaContentModelDump(xmlSchemaParticlePtr particle, FILE * output, int depth)
4267 xmlChar *str = NULL;
4268 xmlSchemaTreeItemPtr term;
4269 char shift[100];
4270 int i;
4272 if (particle == NULL)
4273 return;
4274 for (i = 0;((i < depth) && (i < 25));i++)
4275 shift[2 * i] = shift[2 * i + 1] = ' ';
4276 shift[2 * i] = shift[2 * i + 1] = 0;
4277 fprintf(output, "%s", shift);
4278 if (particle->children == NULL) {
4279 fprintf(output, "MISSING particle term\n");
4280 return;
4282 term = particle->children;
4283 if (term == NULL) {
4284 fprintf(output, "(NULL)");
4285 } else {
4286 switch (term->type) {
4287 case XML_SCHEMA_TYPE_ELEMENT:
4288 fprintf(output, "ELEM '%s'", xmlSchemaFormatQName(&str,
4289 ((xmlSchemaElementPtr)term)->targetNamespace,
4290 ((xmlSchemaElementPtr)term)->name));
4291 FREE_AND_NULL(str);
4292 break;
4293 case XML_SCHEMA_TYPE_SEQUENCE:
4294 fprintf(output, "SEQUENCE");
4295 break;
4296 case XML_SCHEMA_TYPE_CHOICE:
4297 fprintf(output, "CHOICE");
4298 break;
4299 case XML_SCHEMA_TYPE_ALL:
4300 fprintf(output, "ALL");
4301 break;
4302 case XML_SCHEMA_TYPE_ANY:
4303 fprintf(output, "ANY");
4304 break;
4305 default:
4306 fprintf(output, "UNKNOWN\n");
4307 return;
4310 if (particle->minOccurs != 1)
4311 fprintf(output, " min: %d", particle->minOccurs);
4312 if (particle->maxOccurs >= UNBOUNDED)
4313 fprintf(output, " max: unbounded");
4314 else if (particle->maxOccurs != 1)
4315 fprintf(output, " max: %d", particle->maxOccurs);
4316 fprintf(output, "\n");
4317 if (term &&
4318 ((term->type == XML_SCHEMA_TYPE_SEQUENCE) ||
4319 (term->type == XML_SCHEMA_TYPE_CHOICE) ||
4320 (term->type == XML_SCHEMA_TYPE_ALL)) &&
4321 (term->children != NULL)) {
4322 xmlSchemaContentModelDump((xmlSchemaParticlePtr) term->children,
4323 output, depth +1);
4325 if (particle->next != NULL)
4326 xmlSchemaContentModelDump((xmlSchemaParticlePtr) particle->next,
4327 output, depth);
4331 * xmlSchemaAttrUsesDump:
4332 * @uses: attribute uses list
4333 * @output: the file output
4335 * Dumps a list of attribute use components.
4337 static void
4338 xmlSchemaAttrUsesDump(xmlSchemaItemListPtr uses, FILE * output)
4340 xmlSchemaAttributeUsePtr use;
4341 xmlSchemaAttributeUseProhibPtr prohib;
4342 xmlSchemaQNameRefPtr ref;
4343 const xmlChar *name, *tns;
4344 xmlChar *str = NULL;
4345 int i;
4347 if ((uses == NULL) || (uses->nbItems == 0))
4348 return;
4350 fprintf(output, " attributes:\n");
4351 for (i = 0; i < uses->nbItems; i++) {
4352 use = uses->items[i];
4353 if (use->type == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB) {
4354 fprintf(output, " [prohibition] ");
4355 prohib = (xmlSchemaAttributeUseProhibPtr) use;
4356 name = prohib->name;
4357 tns = prohib->targetNamespace;
4358 } else if (use->type == XML_SCHEMA_EXTRA_QNAMEREF) {
4359 fprintf(output, " [reference] ");
4360 ref = (xmlSchemaQNameRefPtr) use;
4361 name = ref->name;
4362 tns = ref->targetNamespace;
4363 } else {
4364 fprintf(output, " [use] ");
4365 name = WXS_ATTRUSE_DECL_NAME(use);
4366 tns = WXS_ATTRUSE_DECL_TNS(use);
4368 fprintf(output, "'%s'\n",
4369 (const char *) xmlSchemaFormatQName(&str, tns, name));
4370 FREE_AND_NULL(str);
4375 * xmlSchemaTypeDump:
4376 * @output: the file output
4377 * @type: a type structure
4379 * Dump a SchemaType structure
4381 static void
4382 xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output)
4384 if (type == NULL) {
4385 fprintf(output, "Type: NULL\n");
4386 return;
4388 fprintf(output, "Type: ");
4389 if (type->name != NULL)
4390 fprintf(output, "'%s' ", type->name);
4391 else
4392 fprintf(output, "(no name) ");
4393 if (type->targetNamespace != NULL)
4394 fprintf(output, "ns '%s' ", type->targetNamespace);
4395 switch (type->type) {
4396 case XML_SCHEMA_TYPE_BASIC:
4397 fprintf(output, "[basic] ");
4398 break;
4399 case XML_SCHEMA_TYPE_SIMPLE:
4400 fprintf(output, "[simple] ");
4401 break;
4402 case XML_SCHEMA_TYPE_COMPLEX:
4403 fprintf(output, "[complex] ");
4404 break;
4405 case XML_SCHEMA_TYPE_SEQUENCE:
4406 fprintf(output, "[sequence] ");
4407 break;
4408 case XML_SCHEMA_TYPE_CHOICE:
4409 fprintf(output, "[choice] ");
4410 break;
4411 case XML_SCHEMA_TYPE_ALL:
4412 fprintf(output, "[all] ");
4413 break;
4414 case XML_SCHEMA_TYPE_UR:
4415 fprintf(output, "[ur] ");
4416 break;
4417 case XML_SCHEMA_TYPE_RESTRICTION:
4418 fprintf(output, "[restriction] ");
4419 break;
4420 case XML_SCHEMA_TYPE_EXTENSION:
4421 fprintf(output, "[extension] ");
4422 break;
4423 default:
4424 fprintf(output, "[unknown type %d] ", type->type);
4425 break;
4427 fprintf(output, "content: ");
4428 switch (type->contentType) {
4429 case XML_SCHEMA_CONTENT_UNKNOWN:
4430 fprintf(output, "[unknown] ");
4431 break;
4432 case XML_SCHEMA_CONTENT_EMPTY:
4433 fprintf(output, "[empty] ");
4434 break;
4435 case XML_SCHEMA_CONTENT_ELEMENTS:
4436 fprintf(output, "[element] ");
4437 break;
4438 case XML_SCHEMA_CONTENT_MIXED:
4439 fprintf(output, "[mixed] ");
4440 break;
4441 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
4442 /* not used. */
4443 break;
4444 case XML_SCHEMA_CONTENT_BASIC:
4445 fprintf(output, "[basic] ");
4446 break;
4447 case XML_SCHEMA_CONTENT_SIMPLE:
4448 fprintf(output, "[simple] ");
4449 break;
4450 case XML_SCHEMA_CONTENT_ANY:
4451 fprintf(output, "[any] ");
4452 break;
4454 fprintf(output, "\n");
4455 if (type->base != NULL) {
4456 fprintf(output, " base type: '%s'", type->base);
4457 if (type->baseNs != NULL)
4458 fprintf(output, " ns '%s'\n", type->baseNs);
4459 else
4460 fprintf(output, "\n");
4462 if (type->attrUses != NULL)
4463 xmlSchemaAttrUsesDump(type->attrUses, output);
4464 if (type->annot != NULL)
4465 xmlSchemaAnnotDump(output, type->annot);
4466 #ifdef DUMP_CONTENT_MODEL
4467 if ((type->type == XML_SCHEMA_TYPE_COMPLEX) &&
4468 (type->subtypes != NULL)) {
4469 xmlSchemaContentModelDump((xmlSchemaParticlePtr) type->subtypes,
4470 output, 1);
4472 #endif
4476 * xmlSchemaDump:
4477 * @output: the file output
4478 * @schema: a schema structure
4480 * Dump a Schema structure.
4482 void
4483 xmlSchemaDump(FILE * output, xmlSchemaPtr schema)
4485 if (output == NULL)
4486 return;
4487 if (schema == NULL) {
4488 fprintf(output, "Schemas: NULL\n");
4489 return;
4491 fprintf(output, "Schemas: ");
4492 if (schema->name != NULL)
4493 fprintf(output, "%s, ", schema->name);
4494 else
4495 fprintf(output, "no name, ");
4496 if (schema->targetNamespace != NULL)
4497 fprintf(output, "%s", (const char *) schema->targetNamespace);
4498 else
4499 fprintf(output, "no target namespace");
4500 fprintf(output, "\n");
4501 if (schema->annot != NULL)
4502 xmlSchemaAnnotDump(output, schema->annot);
4503 xmlHashScan(schema->typeDecl, (xmlHashScanner) xmlSchemaTypeDump,
4504 output);
4505 xmlHashScanFull(schema->elemDecl,
4506 (xmlHashScannerFull) xmlSchemaElementDump, output);
4509 #ifdef DEBUG_IDC_NODE_TABLE
4511 * xmlSchemaDebugDumpIDCTable:
4512 * @vctxt: the WXS validation context
4514 * Displays the current IDC table for debug purposes.
4516 static void
4517 xmlSchemaDebugDumpIDCTable(FILE * output,
4518 const xmlChar *namespaceName,
4519 const xmlChar *localName,
4520 xmlSchemaPSVIIDCBindingPtr bind)
4522 xmlChar *str = NULL;
4523 const xmlChar *value;
4524 xmlSchemaPSVIIDCNodePtr tab;
4525 xmlSchemaPSVIIDCKeyPtr key;
4526 int i, j, res;
4528 fprintf(output, "IDC: TABLES on '%s'\n",
4529 xmlSchemaFormatQName(&str, namespaceName, localName));
4530 FREE_AND_NULL(str)
4532 if (bind == NULL)
4533 return;
4534 do {
4535 fprintf(output, "IDC: BINDING '%s' (%d)\n",
4536 xmlSchemaGetComponentQName(&str,
4537 bind->definition), bind->nbNodes);
4538 FREE_AND_NULL(str)
4539 for (i = 0; i < bind->nbNodes; i++) {
4540 tab = bind->nodeTable[i];
4541 fprintf(output, " ( ");
4542 for (j = 0; j < bind->definition->nbFields; j++) {
4543 key = tab->keys[j];
4544 if ((key != NULL) && (key->val != NULL)) {
4545 res = xmlSchemaGetCanonValue(key->val, &value);
4546 if (res >= 0)
4547 fprintf(output, "'%s' ", value);
4548 else
4549 fprintf(output, "CANON-VALUE-FAILED ");
4550 if (res == 0)
4551 FREE_AND_NULL(value)
4552 } else if (key != NULL)
4553 fprintf(output, "(no val), ");
4554 else
4555 fprintf(output, "(key missing), ");
4557 fprintf(output, ")\n");
4559 if (bind->dupls && bind->dupls->nbItems) {
4560 fprintf(output, "IDC: dupls (%d):\n", bind->dupls->nbItems);
4561 for (i = 0; i < bind->dupls->nbItems; i++) {
4562 tab = bind->dupls->items[i];
4563 fprintf(output, " ( ");
4564 for (j = 0; j < bind->definition->nbFields; j++) {
4565 key = tab->keys[j];
4566 if ((key != NULL) && (key->val != NULL)) {
4567 res = xmlSchemaGetCanonValue(key->val, &value);
4568 if (res >= 0)
4569 fprintf(output, "'%s' ", value);
4570 else
4571 fprintf(output, "CANON-VALUE-FAILED ");
4572 if (res == 0)
4573 FREE_AND_NULL(value)
4574 } else if (key != NULL)
4575 fprintf(output, "(no val), ");
4576 else
4577 fprintf(output, "(key missing), ");
4579 fprintf(output, ")\n");
4582 bind = bind->next;
4583 } while (bind != NULL);
4585 #endif /* DEBUG_IDC */
4586 #endif /* LIBXML_OUTPUT_ENABLED */
4588 /************************************************************************
4590 * Utilities *
4592 ************************************************************************/
4595 * xmlSchemaGetPropNode:
4596 * @node: the element node
4597 * @name: the name of the attribute
4599 * Seeks an attribute with a name of @name in
4600 * no namespace.
4602 * Returns the attribute or NULL if not present.
4604 static xmlAttrPtr
4605 xmlSchemaGetPropNode(xmlNodePtr node, const char *name)
4607 xmlAttrPtr prop;
4609 if ((node == NULL) || (name == NULL))
4610 return(NULL);
4611 prop = node->properties;
4612 while (prop != NULL) {
4613 if ((prop->ns == NULL) && xmlStrEqual(prop->name, BAD_CAST name))
4614 return(prop);
4615 prop = prop->next;
4617 return (NULL);
4621 * xmlSchemaGetPropNodeNs:
4622 * @node: the element node
4623 * @uri: the uri
4624 * @name: the name of the attribute
4626 * Seeks an attribute with a local name of @name and
4627 * a namespace URI of @uri.
4629 * Returns the attribute or NULL if not present.
4631 static xmlAttrPtr
4632 xmlSchemaGetPropNodeNs(xmlNodePtr node, const char *uri, const char *name)
4634 xmlAttrPtr prop;
4636 if ((node == NULL) || (name == NULL))
4637 return(NULL);
4638 prop = node->properties;
4639 while (prop != NULL) {
4640 if ((prop->ns != NULL) &&
4641 xmlStrEqual(prop->name, BAD_CAST name) &&
4642 xmlStrEqual(prop->ns->href, BAD_CAST uri))
4643 return(prop);
4644 prop = prop->next;
4646 return (NULL);
4649 static const xmlChar *
4650 xmlSchemaGetNodeContent(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
4652 xmlChar *val;
4653 const xmlChar *ret;
4655 val = xmlNodeGetContent(node);
4656 if (val == NULL)
4657 val = xmlStrdup((xmlChar *)"");
4658 ret = xmlDictLookup(ctxt->dict, val, -1);
4659 xmlFree(val);
4660 return(ret);
4663 static const xmlChar *
4664 xmlSchemaGetNodeContentNoDict(xmlNodePtr node)
4666 return((const xmlChar*) xmlNodeGetContent(node));
4670 * xmlSchemaGetProp:
4671 * @ctxt: the parser context
4672 * @node: the node
4673 * @name: the property name
4675 * Read a attribute value and internalize the string
4677 * Returns the string or NULL if not present.
4679 static const xmlChar *
4680 xmlSchemaGetProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
4681 const char *name)
4683 xmlChar *val;
4684 const xmlChar *ret;
4686 val = xmlGetNoNsProp(node, BAD_CAST name);
4687 if (val == NULL)
4688 return(NULL);
4689 ret = xmlDictLookup(ctxt->dict, val, -1);
4690 xmlFree(val);
4691 return(ret);
4694 /************************************************************************
4696 * Parsing functions *
4698 ************************************************************************/
4700 #define WXS_FIND_GLOBAL_ITEM(slot) \
4701 if (xmlStrEqual(nsName, schema->targetNamespace)) { \
4702 ret = xmlHashLookup(schema->slot, name); \
4703 if (ret != NULL) goto exit; \
4705 if (xmlHashSize(schema->schemasImports) > 1) { \
4706 xmlSchemaImportPtr import; \
4707 if (nsName == NULL) \
4708 import = xmlHashLookup(schema->schemasImports, \
4709 XML_SCHEMAS_NO_NAMESPACE); \
4710 else \
4711 import = xmlHashLookup(schema->schemasImports, nsName); \
4712 if (import == NULL) \
4713 goto exit; \
4714 ret = xmlHashLookup(import->schema->slot, name); \
4718 * xmlSchemaGetElem:
4719 * @schema: the schema context
4720 * @name: the element name
4721 * @ns: the element namespace
4723 * Lookup a global element declaration in the schema.
4725 * Returns the element declaration or NULL if not found.
4727 static xmlSchemaElementPtr
4728 xmlSchemaGetElem(xmlSchemaPtr schema, const xmlChar * name,
4729 const xmlChar * nsName)
4731 xmlSchemaElementPtr ret = NULL;
4733 if ((name == NULL) || (schema == NULL))
4734 return(NULL);
4735 if (schema != NULL) {
4736 WXS_FIND_GLOBAL_ITEM(elemDecl)
4738 exit:
4739 #ifdef DEBUG
4740 if (ret == NULL) {
4741 if (nsName == NULL)
4742 fprintf(stderr, "Unable to lookup element decl. %s", name);
4743 else
4744 fprintf(stderr, "Unable to lookup element decl. %s:%s", name,
4745 nsName);
4747 #endif
4748 return (ret);
4752 * xmlSchemaGetType:
4753 * @schema: the main schema
4754 * @name: the type's name
4755 * nsName: the type's namespace
4757 * Lookup a type in the schemas or the predefined types
4759 * Returns the group definition or NULL if not found.
4761 static xmlSchemaTypePtr
4762 xmlSchemaGetType(xmlSchemaPtr schema, const xmlChar * name,
4763 const xmlChar * nsName)
4765 xmlSchemaTypePtr ret = NULL;
4767 if (name == NULL)
4768 return (NULL);
4769 /* First try the built-in types. */
4770 if ((nsName != NULL) && xmlStrEqual(nsName, xmlSchemaNs)) {
4771 ret = xmlSchemaGetPredefinedType(name, nsName);
4772 if (ret != NULL)
4773 goto exit;
4775 * Note that we try the parsed schemas as well here
4776 * since one might have parsed the S4S, which contain more
4777 * than the built-in types.
4778 * TODO: Can we optimize this?
4781 if (schema != NULL) {
4782 WXS_FIND_GLOBAL_ITEM(typeDecl)
4784 exit:
4786 #ifdef DEBUG
4787 if (ret == NULL) {
4788 if (nsName == NULL)
4789 fprintf(stderr, "Unable to lookup type %s", name);
4790 else
4791 fprintf(stderr, "Unable to lookup type %s:%s", name,
4792 nsName);
4794 #endif
4795 return (ret);
4799 * xmlSchemaGetAttributeDecl:
4800 * @schema: the context of the schema
4801 * @name: the name of the attribute
4802 * @ns: the target namespace of the attribute
4804 * Lookup a an attribute in the schema or imported schemas
4806 * Returns the attribute declaration or NULL if not found.
4808 static xmlSchemaAttributePtr
4809 xmlSchemaGetAttributeDecl(xmlSchemaPtr schema, const xmlChar * name,
4810 const xmlChar * nsName)
4812 xmlSchemaAttributePtr ret = NULL;
4814 if ((name == NULL) || (schema == NULL))
4815 return (NULL);
4816 if (schema != NULL) {
4817 WXS_FIND_GLOBAL_ITEM(attrDecl)
4819 exit:
4820 #ifdef DEBUG
4821 if (ret == NULL) {
4822 if (nsName == NULL)
4823 fprintf(stderr, "Unable to lookup attribute %s", name);
4824 else
4825 fprintf(stderr, "Unable to lookup attribute %s:%s", name,
4826 nsName);
4828 #endif
4829 return (ret);
4833 * xmlSchemaGetAttributeGroup:
4834 * @schema: the context of the schema
4835 * @name: the name of the attribute group
4836 * @ns: the target namespace of the attribute group
4838 * Lookup a an attribute group in the schema or imported schemas
4840 * Returns the attribute group definition or NULL if not found.
4842 static xmlSchemaAttributeGroupPtr
4843 xmlSchemaGetAttributeGroup(xmlSchemaPtr schema, const xmlChar * name,
4844 const xmlChar * nsName)
4846 xmlSchemaAttributeGroupPtr ret = NULL;
4848 if ((name == NULL) || (schema == NULL))
4849 return (NULL);
4850 if (schema != NULL) {
4851 WXS_FIND_GLOBAL_ITEM(attrgrpDecl)
4853 exit:
4854 /* TODO:
4855 if ((ret != NULL) && (ret->redef != NULL)) {
4856 * Return the last redefinition. *
4857 ret = ret->redef;
4860 #ifdef DEBUG
4861 if (ret == NULL) {
4862 if (nsName == NULL)
4863 fprintf(stderr, "Unable to lookup attribute group %s", name);
4864 else
4865 fprintf(stderr, "Unable to lookup attribute group %s:%s", name,
4866 nsName);
4868 #endif
4869 return (ret);
4873 * xmlSchemaGetGroup:
4874 * @schema: the context of the schema
4875 * @name: the name of the group
4876 * @ns: the target namespace of the group
4878 * Lookup a group in the schema or imported schemas
4880 * Returns the group definition or NULL if not found.
4882 static xmlSchemaModelGroupDefPtr
4883 xmlSchemaGetGroup(xmlSchemaPtr schema, const xmlChar * name,
4884 const xmlChar * nsName)
4886 xmlSchemaModelGroupDefPtr ret = NULL;
4888 if ((name == NULL) || (schema == NULL))
4889 return (NULL);
4890 if (schema != NULL) {
4891 WXS_FIND_GLOBAL_ITEM(groupDecl)
4893 exit:
4895 #ifdef DEBUG
4896 if (ret == NULL) {
4897 if (nsName == NULL)
4898 fprintf(stderr, "Unable to lookup group %s", name);
4899 else
4900 fprintf(stderr, "Unable to lookup group %s:%s", name,
4901 nsName);
4903 #endif
4904 return (ret);
4907 static xmlSchemaNotationPtr
4908 xmlSchemaGetNotation(xmlSchemaPtr schema,
4909 const xmlChar *name,
4910 const xmlChar *nsName)
4912 xmlSchemaNotationPtr ret = NULL;
4914 if ((name == NULL) || (schema == NULL))
4915 return (NULL);
4916 if (schema != NULL) {
4917 WXS_FIND_GLOBAL_ITEM(notaDecl)
4919 exit:
4920 return (ret);
4923 static xmlSchemaIDCPtr
4924 xmlSchemaGetIDC(xmlSchemaPtr schema,
4925 const xmlChar *name,
4926 const xmlChar *nsName)
4928 xmlSchemaIDCPtr ret = NULL;
4930 if ((name == NULL) || (schema == NULL))
4931 return (NULL);
4932 if (schema != NULL) {
4933 WXS_FIND_GLOBAL_ITEM(idcDef)
4935 exit:
4936 return (ret);
4940 * xmlSchemaGetNamedComponent:
4941 * @schema: the schema
4942 * @name: the name of the group
4943 * @ns: the target namespace of the group
4945 * Lookup a group in the schema or imported schemas
4947 * Returns the group definition or NULL if not found.
4949 static xmlSchemaBasicItemPtr
4950 xmlSchemaGetNamedComponent(xmlSchemaPtr schema,
4951 xmlSchemaTypeType itemType,
4952 const xmlChar *name,
4953 const xmlChar *targetNs)
4955 switch (itemType) {
4956 case XML_SCHEMA_TYPE_GROUP:
4957 return ((xmlSchemaBasicItemPtr) xmlSchemaGetGroup(schema,
4958 name, targetNs));
4959 case XML_SCHEMA_TYPE_ELEMENT:
4960 return ((xmlSchemaBasicItemPtr) xmlSchemaGetElem(schema,
4961 name, targetNs));
4962 default:
4963 TODO
4964 return (NULL);
4968 /************************************************************************
4970 * Parsing functions *
4972 ************************************************************************/
4974 #define IS_BLANK_NODE(n) \
4975 (((n)->type == XML_TEXT_NODE) && (xmlSchemaIsBlank((n)->content, -1)))
4978 * xmlSchemaIsBlank:
4979 * @str: a string
4980 * @len: the length of the string or -1
4982 * Check if a string is ignorable
4984 * Returns 1 if the string is NULL or made of blanks chars, 0 otherwise
4986 static int
4987 xmlSchemaIsBlank(xmlChar * str, int len)
4989 if (str == NULL)
4990 return (1);
4991 if (len < 0) {
4992 while (*str != 0) {
4993 if (!(IS_BLANK_CH(*str)))
4994 return (0);
4995 str++;
4997 } else while ((*str != 0) && (len != 0)) {
4998 if (!(IS_BLANK_CH(*str)))
4999 return (0);
5000 str++;
5001 len--;
5004 return (1);
5007 #define WXS_COMP_NAME(c, t) ((t) (c))->name
5008 #define WXS_COMP_TNS(c, t) ((t) (c))->targetNamespace
5010 * xmlSchemaFindRedefCompInGraph:
5011 * ATTENTION TODO: This uses pointer comp. for strings.
5013 static xmlSchemaBasicItemPtr
5014 xmlSchemaFindRedefCompInGraph(xmlSchemaBucketPtr bucket,
5015 xmlSchemaTypeType type,
5016 const xmlChar *name,
5017 const xmlChar *nsName)
5019 xmlSchemaBasicItemPtr ret;
5020 int i;
5022 if ((bucket == NULL) || (name == NULL))
5023 return(NULL);
5024 if ((bucket->globals == NULL) ||
5025 (bucket->globals->nbItems == 0))
5026 goto subschemas;
5028 * Search in global components.
5030 for (i = 0; i < bucket->globals->nbItems; i++) {
5031 ret = bucket->globals->items[i];
5032 if (ret->type == type) {
5033 switch (type) {
5034 case XML_SCHEMA_TYPE_COMPLEX:
5035 case XML_SCHEMA_TYPE_SIMPLE:
5036 if ((WXS_COMP_NAME(ret, xmlSchemaTypePtr) == name) &&
5037 (WXS_COMP_TNS(ret, xmlSchemaTypePtr) ==
5038 nsName))
5040 return(ret);
5042 break;
5043 case XML_SCHEMA_TYPE_GROUP:
5044 if ((WXS_COMP_NAME(ret,
5045 xmlSchemaModelGroupDefPtr) == name) &&
5046 (WXS_COMP_TNS(ret,
5047 xmlSchemaModelGroupDefPtr) == nsName))
5049 return(ret);
5051 break;
5052 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
5053 if ((WXS_COMP_NAME(ret,
5054 xmlSchemaAttributeGroupPtr) == name) &&
5055 (WXS_COMP_TNS(ret,
5056 xmlSchemaAttributeGroupPtr) == nsName))
5058 return(ret);
5060 break;
5061 default:
5062 /* Should not be hit. */
5063 return(NULL);
5067 subschemas:
5069 * Process imported/included schemas.
5071 if (bucket->relations != NULL) {
5072 xmlSchemaSchemaRelationPtr rel = bucket->relations;
5075 * TODO: Marking the bucket will not avoid multiple searches
5076 * in the same schema, but avoids at least circularity.
5078 bucket->flags |= XML_SCHEMA_BUCKET_MARKED;
5079 do {
5080 if ((rel->bucket != NULL) &&
5081 ((rel->bucket->flags & XML_SCHEMA_BUCKET_MARKED) == 0)) {
5082 ret = xmlSchemaFindRedefCompInGraph(rel->bucket,
5083 type, name, nsName);
5084 if (ret != NULL)
5085 return(ret);
5087 rel = rel->next;
5088 } while (rel != NULL);
5089 bucket->flags ^= XML_SCHEMA_BUCKET_MARKED;
5091 return(NULL);
5095 * xmlSchemaAddNotation:
5096 * @ctxt: a schema parser context
5097 * @schema: the schema being built
5098 * @name: the item name
5100 * Add an XML schema annotation declaration
5101 * *WARNING* this interface is highly subject to change
5103 * Returns the new struture or NULL in case of error
5105 static xmlSchemaNotationPtr
5106 xmlSchemaAddNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5107 const xmlChar *name, const xmlChar *nsName,
5108 xmlNodePtr node ATTRIBUTE_UNUSED)
5110 xmlSchemaNotationPtr ret = NULL;
5112 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
5113 return (NULL);
5115 ret = (xmlSchemaNotationPtr) xmlMalloc(sizeof(xmlSchemaNotation));
5116 if (ret == NULL) {
5117 xmlSchemaPErrMemory(ctxt, "add annotation", NULL);
5118 return (NULL);
5120 memset(ret, 0, sizeof(xmlSchemaNotation));
5121 ret->type = XML_SCHEMA_TYPE_NOTATION;
5122 ret->name = name;
5123 ret->targetNamespace = nsName;
5124 /* TODO: do we need the node to be set?
5125 * ret->node = node;*/
5126 WXS_ADD_GLOBAL(ctxt, ret);
5127 return (ret);
5131 * xmlSchemaAddAttribute:
5132 * @ctxt: a schema parser context
5133 * @schema: the schema being built
5134 * @name: the item name
5135 * @namespace: the namespace
5137 * Add an XML schema Attrribute declaration
5138 * *WARNING* this interface is highly subject to change
5140 * Returns the new struture or NULL in case of error
5142 static xmlSchemaAttributePtr
5143 xmlSchemaAddAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5144 const xmlChar * name, const xmlChar * nsName,
5145 xmlNodePtr node, int topLevel)
5147 xmlSchemaAttributePtr ret = NULL;
5149 if ((ctxt == NULL) || (schema == NULL))
5150 return (NULL);
5152 ret = (xmlSchemaAttributePtr) xmlMalloc(sizeof(xmlSchemaAttribute));
5153 if (ret == NULL) {
5154 xmlSchemaPErrMemory(ctxt, "allocating attribute", NULL);
5155 return (NULL);
5157 memset(ret, 0, sizeof(xmlSchemaAttribute));
5158 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
5159 ret->node = node;
5160 ret->name = name;
5161 ret->targetNamespace = nsName;
5163 if (topLevel)
5164 WXS_ADD_GLOBAL(ctxt, ret);
5165 else
5166 WXS_ADD_LOCAL(ctxt, ret);
5167 WXS_ADD_PENDING(ctxt, ret);
5168 return (ret);
5172 * xmlSchemaAddAttributeUse:
5173 * @ctxt: a schema parser context
5174 * @schema: the schema being built
5175 * @name: the item name
5176 * @namespace: the namespace
5178 * Add an XML schema Attrribute declaration
5179 * *WARNING* this interface is highly subject to change
5181 * Returns the new struture or NULL in case of error
5183 static xmlSchemaAttributeUsePtr
5184 xmlSchemaAddAttributeUse(xmlSchemaParserCtxtPtr pctxt,
5185 xmlNodePtr node)
5187 xmlSchemaAttributeUsePtr ret = NULL;
5189 if (pctxt == NULL)
5190 return (NULL);
5192 ret = (xmlSchemaAttributeUsePtr) xmlMalloc(sizeof(xmlSchemaAttributeUse));
5193 if (ret == NULL) {
5194 xmlSchemaPErrMemory(pctxt, "allocating attribute", NULL);
5195 return (NULL);
5197 memset(ret, 0, sizeof(xmlSchemaAttributeUse));
5198 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE_USE;
5199 ret->node = node;
5201 WXS_ADD_LOCAL(pctxt, ret);
5202 return (ret);
5206 * xmlSchemaAddRedef:
5208 * Adds a redefinition information. This is used at a later stage to:
5209 * resolve references to the redefined components and to check constraints.
5211 static xmlSchemaRedefPtr
5212 xmlSchemaAddRedef(xmlSchemaParserCtxtPtr pctxt,
5213 xmlSchemaBucketPtr targetBucket,
5214 void *item,
5215 const xmlChar *refName,
5216 const xmlChar *refTargetNs)
5218 xmlSchemaRedefPtr ret;
5220 ret = (xmlSchemaRedefPtr)
5221 xmlMalloc(sizeof(xmlSchemaRedef));
5222 if (ret == NULL) {
5223 xmlSchemaPErrMemory(pctxt,
5224 "allocating redefinition info", NULL);
5225 return (NULL);
5227 memset(ret, 0, sizeof(xmlSchemaRedef));
5228 ret->item = item;
5229 ret->targetBucket = targetBucket;
5230 ret->refName = refName;
5231 ret->refTargetNs = refTargetNs;
5232 if (WXS_CONSTRUCTOR(pctxt)->redefs == NULL)
5233 WXS_CONSTRUCTOR(pctxt)->redefs = ret;
5234 else
5235 WXS_CONSTRUCTOR(pctxt)->lastRedef->next = ret;
5236 WXS_CONSTRUCTOR(pctxt)->lastRedef = ret;
5238 return (ret);
5242 * xmlSchemaAddAttributeGroupDefinition:
5243 * @ctxt: a schema parser context
5244 * @schema: the schema being built
5245 * @name: the item name
5246 * @nsName: the target namespace
5247 * @node: the corresponding node
5249 * Add an XML schema Attrribute Group definition.
5251 * Returns the new struture or NULL in case of error
5253 static xmlSchemaAttributeGroupPtr
5254 xmlSchemaAddAttributeGroupDefinition(xmlSchemaParserCtxtPtr pctxt,
5255 xmlSchemaPtr schema ATTRIBUTE_UNUSED,
5256 const xmlChar *name,
5257 const xmlChar *nsName,
5258 xmlNodePtr node)
5260 xmlSchemaAttributeGroupPtr ret = NULL;
5262 if ((pctxt == NULL) || (name == NULL))
5263 return (NULL);
5265 ret = (xmlSchemaAttributeGroupPtr)
5266 xmlMalloc(sizeof(xmlSchemaAttributeGroup));
5267 if (ret == NULL) {
5268 xmlSchemaPErrMemory(pctxt, "allocating attribute group", NULL);
5269 return (NULL);
5271 memset(ret, 0, sizeof(xmlSchemaAttributeGroup));
5272 ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
5273 ret->name = name;
5274 ret->targetNamespace = nsName;
5275 ret->node = node;
5277 /* TODO: Remove the flag. */
5278 ret->flags |= XML_SCHEMAS_ATTRGROUP_GLOBAL;
5279 if (pctxt->isRedefine) {
5280 pctxt->redef = xmlSchemaAddRedef(pctxt, pctxt->redefined,
5281 ret, name, nsName);
5282 if (pctxt->redef == NULL) {
5283 xmlFree(ret);
5284 return(NULL);
5286 pctxt->redefCounter = 0;
5288 WXS_ADD_GLOBAL(pctxt, ret);
5289 WXS_ADD_PENDING(pctxt, ret);
5290 return (ret);
5294 * xmlSchemaAddElement:
5295 * @ctxt: a schema parser context
5296 * @schema: the schema being built
5297 * @name: the type name
5298 * @namespace: the type namespace
5300 * Add an XML schema Element declaration
5301 * *WARNING* this interface is highly subject to change
5303 * Returns the new struture or NULL in case of error
5305 static xmlSchemaElementPtr
5306 xmlSchemaAddElement(xmlSchemaParserCtxtPtr ctxt,
5307 const xmlChar * name, const xmlChar * nsName,
5308 xmlNodePtr node, int topLevel)
5310 xmlSchemaElementPtr ret = NULL;
5312 if ((ctxt == NULL) || (name == NULL))
5313 return (NULL);
5315 ret = (xmlSchemaElementPtr) xmlMalloc(sizeof(xmlSchemaElement));
5316 if (ret == NULL) {
5317 xmlSchemaPErrMemory(ctxt, "allocating element", NULL);
5318 return (NULL);
5320 memset(ret, 0, sizeof(xmlSchemaElement));
5321 ret->type = XML_SCHEMA_TYPE_ELEMENT;
5322 ret->name = name;
5323 ret->targetNamespace = nsName;
5324 ret->node = node;
5326 if (topLevel)
5327 WXS_ADD_GLOBAL(ctxt, ret);
5328 else
5329 WXS_ADD_LOCAL(ctxt, ret);
5330 WXS_ADD_PENDING(ctxt, ret);
5331 return (ret);
5335 * xmlSchemaAddType:
5336 * @ctxt: a schema parser context
5337 * @schema: the schema being built
5338 * @name: the item name
5339 * @namespace: the namespace
5341 * Add an XML schema item
5342 * *WARNING* this interface is highly subject to change
5344 * Returns the new struture or NULL in case of error
5346 static xmlSchemaTypePtr
5347 xmlSchemaAddType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5348 xmlSchemaTypeType type,
5349 const xmlChar * name, const xmlChar * nsName,
5350 xmlNodePtr node, int topLevel)
5352 xmlSchemaTypePtr ret = NULL;
5354 if ((ctxt == NULL) || (schema == NULL))
5355 return (NULL);
5357 ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
5358 if (ret == NULL) {
5359 xmlSchemaPErrMemory(ctxt, "allocating type", NULL);
5360 return (NULL);
5362 memset(ret, 0, sizeof(xmlSchemaType));
5363 ret->type = type;
5364 ret->name = name;
5365 ret->targetNamespace = nsName;
5366 ret->node = node;
5367 if (topLevel) {
5368 if (ctxt->isRedefine) {
5369 ctxt->redef = xmlSchemaAddRedef(ctxt, ctxt->redefined,
5370 ret, name, nsName);
5371 if (ctxt->redef == NULL) {
5372 xmlFree(ret);
5373 return(NULL);
5375 ctxt->redefCounter = 0;
5377 WXS_ADD_GLOBAL(ctxt, ret);
5378 } else
5379 WXS_ADD_LOCAL(ctxt, ret);
5380 WXS_ADD_PENDING(ctxt, ret);
5381 return (ret);
5384 static xmlSchemaQNameRefPtr
5385 xmlSchemaNewQNameRef(xmlSchemaParserCtxtPtr pctxt,
5386 xmlSchemaTypeType refType,
5387 const xmlChar *refName,
5388 const xmlChar *refNs)
5390 xmlSchemaQNameRefPtr ret;
5392 ret = (xmlSchemaQNameRefPtr)
5393 xmlMalloc(sizeof(xmlSchemaQNameRef));
5394 if (ret == NULL) {
5395 xmlSchemaPErrMemory(pctxt,
5396 "allocating QName reference item", NULL);
5397 return (NULL);
5399 ret->node = NULL;
5400 ret->type = XML_SCHEMA_EXTRA_QNAMEREF;
5401 ret->name = refName;
5402 ret->targetNamespace = refNs;
5403 ret->item = NULL;
5404 ret->itemType = refType;
5406 * Store the reference item in the schema.
5408 WXS_ADD_LOCAL(pctxt, ret);
5409 return (ret);
5412 static xmlSchemaAttributeUseProhibPtr
5413 xmlSchemaAddAttributeUseProhib(xmlSchemaParserCtxtPtr pctxt)
5415 xmlSchemaAttributeUseProhibPtr ret;
5417 ret = (xmlSchemaAttributeUseProhibPtr)
5418 xmlMalloc(sizeof(xmlSchemaAttributeUseProhib));
5419 if (ret == NULL) {
5420 xmlSchemaPErrMemory(pctxt,
5421 "allocating attribute use prohibition", NULL);
5422 return (NULL);
5424 memset(ret, 0, sizeof(xmlSchemaAttributeUseProhib));
5425 ret->type = XML_SCHEMA_EXTRA_ATTR_USE_PROHIB;
5426 WXS_ADD_LOCAL(pctxt, ret);
5427 return (ret);
5432 * xmlSchemaAddModelGroup:
5433 * @ctxt: a schema parser context
5434 * @schema: the schema being built
5435 * @type: the "compositor" type of the model group
5436 * @node: the node in the schema doc
5438 * Adds a schema model group
5439 * *WARNING* this interface is highly subject to change
5441 * Returns the new struture or NULL in case of error
5443 static xmlSchemaModelGroupPtr
5444 xmlSchemaAddModelGroup(xmlSchemaParserCtxtPtr ctxt,
5445 xmlSchemaPtr schema,
5446 xmlSchemaTypeType type,
5447 xmlNodePtr node)
5449 xmlSchemaModelGroupPtr ret = NULL;
5451 if ((ctxt == NULL) || (schema == NULL))
5452 return (NULL);
5454 ret = (xmlSchemaModelGroupPtr)
5455 xmlMalloc(sizeof(xmlSchemaModelGroup));
5456 if (ret == NULL) {
5457 xmlSchemaPErrMemory(ctxt, "allocating model group component",
5458 NULL);
5459 return (NULL);
5461 memset(ret, 0, sizeof(xmlSchemaModelGroup));
5462 ret->type = type;
5463 ret->node = node;
5464 WXS_ADD_LOCAL(ctxt, ret);
5465 if ((type == XML_SCHEMA_TYPE_SEQUENCE) ||
5466 (type == XML_SCHEMA_TYPE_CHOICE))
5467 WXS_ADD_PENDING(ctxt, ret);
5468 return (ret);
5473 * xmlSchemaAddParticle:
5474 * @ctxt: a schema parser context
5475 * @schema: the schema being built
5476 * @node: the corresponding node in the schema doc
5477 * @min: the minOccurs
5478 * @max: the maxOccurs
5480 * Adds an XML schema particle component.
5481 * *WARNING* this interface is highly subject to change
5483 * Returns the new struture or NULL in case of error
5485 static xmlSchemaParticlePtr
5486 xmlSchemaAddParticle(xmlSchemaParserCtxtPtr ctxt,
5487 xmlNodePtr node, int min, int max)
5489 xmlSchemaParticlePtr ret = NULL;
5490 if (ctxt == NULL)
5491 return (NULL);
5493 #ifdef DEBUG
5494 fprintf(stderr, "Adding particle component\n");
5495 #endif
5496 ret = (xmlSchemaParticlePtr)
5497 xmlMalloc(sizeof(xmlSchemaParticle));
5498 if (ret == NULL) {
5499 xmlSchemaPErrMemory(ctxt, "allocating particle component",
5500 NULL);
5501 return (NULL);
5503 ret->type = XML_SCHEMA_TYPE_PARTICLE;
5504 ret->annot = NULL;
5505 ret->node = node;
5506 ret->minOccurs = min;
5507 ret->maxOccurs = max;
5508 ret->next = NULL;
5509 ret->children = NULL;
5511 WXS_ADD_LOCAL(ctxt, ret);
5513 * Note that addition to pending components will be done locally
5514 * to the specific parsing function, since the most particles
5515 * need not to be fixed up (i.e. the reference to be resolved).
5516 * REMOVED: WXS_ADD_PENDING(ctxt, ret);
5518 return (ret);
5522 * xmlSchemaAddModelGroupDefinition:
5523 * @ctxt: a schema validation context
5524 * @schema: the schema being built
5525 * @name: the group name
5527 * Add an XML schema Group definition
5529 * Returns the new struture or NULL in case of error
5531 static xmlSchemaModelGroupDefPtr
5532 xmlSchemaAddModelGroupDefinition(xmlSchemaParserCtxtPtr ctxt,
5533 xmlSchemaPtr schema,
5534 const xmlChar *name,
5535 const xmlChar *nsName,
5536 xmlNodePtr node)
5538 xmlSchemaModelGroupDefPtr ret = NULL;
5540 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
5541 return (NULL);
5543 ret = (xmlSchemaModelGroupDefPtr)
5544 xmlMalloc(sizeof(xmlSchemaModelGroupDef));
5545 if (ret == NULL) {
5546 xmlSchemaPErrMemory(ctxt, "adding group", NULL);
5547 return (NULL);
5549 memset(ret, 0, sizeof(xmlSchemaModelGroupDef));
5550 ret->name = name;
5551 ret->type = XML_SCHEMA_TYPE_GROUP;
5552 ret->node = node;
5553 ret->targetNamespace = nsName;
5555 if (ctxt->isRedefine) {
5556 ctxt->redef = xmlSchemaAddRedef(ctxt, ctxt->redefined,
5557 ret, name, nsName);
5558 if (ctxt->redef == NULL) {
5559 xmlFree(ret);
5560 return(NULL);
5562 ctxt->redefCounter = 0;
5564 WXS_ADD_GLOBAL(ctxt, ret);
5565 WXS_ADD_PENDING(ctxt, ret);
5566 return (ret);
5570 * xmlSchemaNewWildcardNs:
5571 * @ctxt: a schema validation context
5573 * Creates a new wildcard namespace constraint.
5575 * Returns the new struture or NULL in case of error
5577 static xmlSchemaWildcardNsPtr
5578 xmlSchemaNewWildcardNsConstraint(xmlSchemaParserCtxtPtr ctxt)
5580 xmlSchemaWildcardNsPtr ret;
5582 ret = (xmlSchemaWildcardNsPtr)
5583 xmlMalloc(sizeof(xmlSchemaWildcardNs));
5584 if (ret == NULL) {
5585 xmlSchemaPErrMemory(ctxt, "creating wildcard namespace constraint", NULL);
5586 return (NULL);
5588 ret->value = NULL;
5589 ret->next = NULL;
5590 return (ret);
5593 static xmlSchemaIDCPtr
5594 xmlSchemaAddIDC(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5595 const xmlChar *name, const xmlChar *nsName,
5596 int category, xmlNodePtr node)
5598 xmlSchemaIDCPtr ret = NULL;
5600 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
5601 return (NULL);
5603 ret = (xmlSchemaIDCPtr) xmlMalloc(sizeof(xmlSchemaIDC));
5604 if (ret == NULL) {
5605 xmlSchemaPErrMemory(ctxt,
5606 "allocating an identity-constraint definition", NULL);
5607 return (NULL);
5609 memset(ret, 0, sizeof(xmlSchemaIDC));
5610 /* The target namespace of the parent element declaration. */
5611 ret->targetNamespace = nsName;
5612 ret->name = name;
5613 ret->type = category;
5614 ret->node = node;
5616 WXS_ADD_GLOBAL(ctxt, ret);
5618 * Only keyrefs need to be fixup up.
5620 if (category == XML_SCHEMA_TYPE_IDC_KEYREF)
5621 WXS_ADD_PENDING(ctxt, ret);
5622 return (ret);
5626 * xmlSchemaAddWildcard:
5627 * @ctxt: a schema validation context
5628 * @schema: a schema
5630 * Adds a wildcard.
5631 * It corresponds to a xsd:anyAttribute and xsd:any.
5633 * Returns the new struture or NULL in case of error
5635 static xmlSchemaWildcardPtr
5636 xmlSchemaAddWildcard(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5637 xmlSchemaTypeType type, xmlNodePtr node)
5639 xmlSchemaWildcardPtr ret = NULL;
5641 if ((ctxt == NULL) || (schema == NULL))
5642 return (NULL);
5644 ret = (xmlSchemaWildcardPtr) xmlMalloc(sizeof(xmlSchemaWildcard));
5645 if (ret == NULL) {
5646 xmlSchemaPErrMemory(ctxt, "adding wildcard", NULL);
5647 return (NULL);
5649 memset(ret, 0, sizeof(xmlSchemaWildcard));
5650 ret->type = type;
5651 ret->node = node;
5652 WXS_ADD_LOCAL(ctxt, ret);
5653 return (ret);
5656 static void
5657 xmlSchemaSubstGroupFree(xmlSchemaSubstGroupPtr group)
5659 if (group == NULL)
5660 return;
5661 if (group->members != NULL)
5662 xmlSchemaItemListFree(group->members);
5663 xmlFree(group);
5666 static xmlSchemaSubstGroupPtr
5667 xmlSchemaSubstGroupAdd(xmlSchemaParserCtxtPtr pctxt,
5668 xmlSchemaElementPtr head)
5670 xmlSchemaSubstGroupPtr ret;
5672 /* Init subst group hash. */
5673 if (WXS_SUBST_GROUPS(pctxt) == NULL) {
5674 WXS_SUBST_GROUPS(pctxt) = xmlHashCreateDict(10, pctxt->dict);
5675 if (WXS_SUBST_GROUPS(pctxt) == NULL)
5676 return(NULL);
5678 /* Create a new substitution group. */
5679 ret = (xmlSchemaSubstGroupPtr) xmlMalloc(sizeof(xmlSchemaSubstGroup));
5680 if (ret == NULL) {
5681 xmlSchemaPErrMemory(NULL,
5682 "allocating a substitution group container", NULL);
5683 return(NULL);
5685 memset(ret, 0, sizeof(xmlSchemaSubstGroup));
5686 ret->head = head;
5687 /* Create list of members. */
5688 ret->members = xmlSchemaItemListCreate();
5689 if (ret->members == NULL) {
5690 xmlSchemaSubstGroupFree(ret);
5691 return(NULL);
5693 /* Add subst group to hash. */
5694 if (xmlHashAddEntry2(WXS_SUBST_GROUPS(pctxt),
5695 head->name, head->targetNamespace, ret) != 0) {
5696 PERROR_INT("xmlSchemaSubstGroupAdd",
5697 "failed to add a new substitution container");
5698 xmlSchemaSubstGroupFree(ret);
5699 return(NULL);
5701 return(ret);
5704 static xmlSchemaSubstGroupPtr
5705 xmlSchemaSubstGroupGet(xmlSchemaParserCtxtPtr pctxt,
5706 xmlSchemaElementPtr head)
5708 if (WXS_SUBST_GROUPS(pctxt) == NULL)
5709 return(NULL);
5710 return(xmlHashLookup2(WXS_SUBST_GROUPS(pctxt),
5711 head->name, head->targetNamespace));
5716 * xmlSchemaAddElementSubstitutionMember:
5717 * @pctxt: a schema parser context
5718 * @head: the head of the substitution group
5719 * @member: the new member of the substitution group
5721 * Allocate a new annotation structure.
5723 * Returns the newly allocated structure or NULL in case or error
5725 static int
5726 xmlSchemaAddElementSubstitutionMember(xmlSchemaParserCtxtPtr pctxt,
5727 xmlSchemaElementPtr head,
5728 xmlSchemaElementPtr member)
5730 xmlSchemaSubstGroupPtr substGroup = NULL;
5732 if ((pctxt == NULL) || (head == NULL) || (member == NULL))
5733 return (-1);
5735 substGroup = xmlSchemaSubstGroupGet(pctxt, head);
5736 if (substGroup == NULL)
5737 substGroup = xmlSchemaSubstGroupAdd(pctxt, head);
5738 if (substGroup == NULL)
5739 return(-1);
5740 if (xmlSchemaItemListAdd(substGroup->members, member) == -1)
5741 return(-1);
5742 return(0);
5745 /************************************************************************
5747 * Utilities for parsing *
5749 ************************************************************************/
5752 * xmlSchemaPValAttrNodeQNameValue:
5753 * @ctxt: a schema parser context
5754 * @schema: the schema context
5755 * @ownerDes: the designation of the parent element
5756 * @ownerItem: the parent as a schema object
5757 * @value: the QName value
5758 * @local: the resulting local part if found, the attribute value otherwise
5759 * @uri: the resulting namespace URI if found
5761 * Extracts the local name and the URI of a QName value and validates it.
5762 * This one is intended to be used on attribute values that
5763 * should resolve to schema components.
5765 * Returns 0, in case the QName is valid, a positive error code
5766 * if not valid and -1 if an internal error occurs.
5768 static int
5769 xmlSchemaPValAttrNodeQNameValue(xmlSchemaParserCtxtPtr ctxt,
5770 xmlSchemaPtr schema,
5771 xmlSchemaBasicItemPtr ownerItem,
5772 xmlAttrPtr attr,
5773 const xmlChar *value,
5774 const xmlChar **uri,
5775 const xmlChar **local)
5777 const xmlChar *pref;
5778 xmlNsPtr ns;
5779 int len, ret;
5781 *uri = NULL;
5782 *local = NULL;
5783 ret = xmlValidateQName(value, 1);
5784 if (ret > 0) {
5785 xmlSchemaPSimpleTypeErr(ctxt,
5786 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5787 ownerItem, (xmlNodePtr) attr,
5788 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
5789 NULL, value, NULL, NULL, NULL);
5790 *local = value;
5791 return (ctxt->err);
5792 } else if (ret < 0)
5793 return (-1);
5795 if (!strchr((char *) value, ':')) {
5796 ns = xmlSearchNs(attr->doc, attr->parent, NULL);
5797 if (ns)
5798 *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
5799 else if (schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) {
5800 /* TODO: move XML_SCHEMAS_INCLUDING_CONVERT_NS to the
5801 * parser context. */
5803 * This one takes care of included schemas with no
5804 * target namespace.
5806 *uri = ctxt->targetNamespace;
5808 *local = xmlDictLookup(ctxt->dict, value, -1);
5809 return (0);
5812 * At this point xmlSplitQName3 has to return a local name.
5814 *local = xmlSplitQName3(value, &len);
5815 *local = xmlDictLookup(ctxt->dict, *local, -1);
5816 pref = xmlDictLookup(ctxt->dict, value, len);
5817 ns = xmlSearchNs(attr->doc, attr->parent, pref);
5818 if (ns == NULL) {
5819 xmlSchemaPSimpleTypeErr(ctxt,
5820 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5821 ownerItem, (xmlNodePtr) attr,
5822 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), NULL, value,
5823 "The value '%s' of simple type 'xs:QName' has no "
5824 "corresponding namespace declaration in scope", value, NULL);
5825 return (ctxt->err);
5826 } else {
5827 *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
5829 return (0);
5833 * xmlSchemaPValAttrNodeQName:
5834 * @ctxt: a schema parser context
5835 * @schema: the schema context
5836 * @ownerDes: the designation of the owner element
5837 * @ownerItem: the owner as a schema object
5838 * @attr: the attribute node
5839 * @local: the resulting local part if found, the attribute value otherwise
5840 * @uri: the resulting namespace URI if found
5842 * Extracts and validates the QName of an attribute value.
5843 * This one is intended to be used on attribute values that
5844 * should resolve to schema components.
5846 * Returns 0, in case the QName is valid, a positive error code
5847 * if not valid and -1 if an internal error occurs.
5849 static int
5850 xmlSchemaPValAttrNodeQName(xmlSchemaParserCtxtPtr ctxt,
5851 xmlSchemaPtr schema,
5852 xmlSchemaBasicItemPtr ownerItem,
5853 xmlAttrPtr attr,
5854 const xmlChar **uri,
5855 const xmlChar **local)
5857 const xmlChar *value;
5859 value = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5860 return (xmlSchemaPValAttrNodeQNameValue(ctxt, schema,
5861 ownerItem, attr, value, uri, local));
5865 * xmlSchemaPValAttrQName:
5866 * @ctxt: a schema parser context
5867 * @schema: the schema context
5868 * @ownerDes: the designation of the parent element
5869 * @ownerItem: the owner as a schema object
5870 * @ownerElem: the parent node of the attribute
5871 * @name: the name of the attribute
5872 * @local: the resulting local part if found, the attribute value otherwise
5873 * @uri: the resulting namespace URI if found
5875 * Extracts and validates the QName of an attribute value.
5877 * Returns 0, in case the QName is valid, a positive error code
5878 * if not valid and -1 if an internal error occurs.
5880 static int
5881 xmlSchemaPValAttrQName(xmlSchemaParserCtxtPtr ctxt,
5882 xmlSchemaPtr schema,
5883 xmlSchemaBasicItemPtr ownerItem,
5884 xmlNodePtr ownerElem,
5885 const char *name,
5886 const xmlChar **uri,
5887 const xmlChar **local)
5889 xmlAttrPtr attr;
5891 attr = xmlSchemaGetPropNode(ownerElem, name);
5892 if (attr == NULL) {
5893 *local = NULL;
5894 *uri = NULL;
5895 return (0);
5897 return (xmlSchemaPValAttrNodeQName(ctxt, schema,
5898 ownerItem, attr, uri, local));
5902 * xmlSchemaPValAttrID:
5903 * @ctxt: a schema parser context
5904 * @schema: the schema context
5905 * @ownerDes: the designation of the parent element
5906 * @ownerItem: the owner as a schema object
5907 * @ownerElem: the parent node of the attribute
5908 * @name: the name of the attribute
5910 * Extracts and validates the ID of an attribute value.
5912 * Returns 0, in case the ID is valid, a positive error code
5913 * if not valid and -1 if an internal error occurs.
5915 static int
5916 xmlSchemaPValAttrNodeID(xmlSchemaParserCtxtPtr ctxt, xmlAttrPtr attr)
5918 int ret;
5919 const xmlChar *value;
5921 if (attr == NULL)
5922 return(0);
5923 value = xmlSchemaGetNodeContentNoDict((xmlNodePtr) attr);
5924 ret = xmlValidateNCName(value, 1);
5925 if (ret == 0) {
5927 * NOTE: the IDness might have already be declared in the DTD
5929 if (attr->atype != XML_ATTRIBUTE_ID) {
5930 xmlIDPtr res;
5931 xmlChar *strip;
5934 * TODO: Use xmlSchemaStrip here; it's not exported at this
5935 * moment.
5937 strip = xmlSchemaCollapseString(value);
5938 if (strip != NULL) {
5939 xmlFree((xmlChar *) value);
5940 value = strip;
5942 res = xmlAddID(NULL, attr->doc, value, attr);
5943 if (res == NULL) {
5944 ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
5945 xmlSchemaPSimpleTypeErr(ctxt,
5946 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5947 NULL, (xmlNodePtr) attr,
5948 xmlSchemaGetBuiltInType(XML_SCHEMAS_ID),
5949 NULL, NULL, "Duplicate value '%s' of simple "
5950 "type 'xs:ID'", value, NULL);
5951 } else
5952 attr->atype = XML_ATTRIBUTE_ID;
5954 } else if (ret > 0) {
5955 ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
5956 xmlSchemaPSimpleTypeErr(ctxt,
5957 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5958 NULL, (xmlNodePtr) attr,
5959 xmlSchemaGetBuiltInType(XML_SCHEMAS_ID),
5960 NULL, NULL, "The value '%s' of simple type 'xs:ID' is "
5961 "not a valid 'xs:NCName'",
5962 value, NULL);
5964 if (value != NULL)
5965 xmlFree((xmlChar *)value);
5967 return (ret);
5970 static int
5971 xmlSchemaPValAttrID(xmlSchemaParserCtxtPtr ctxt,
5972 xmlNodePtr ownerElem,
5973 const xmlChar *name)
5975 xmlAttrPtr attr;
5977 attr = xmlSchemaGetPropNode(ownerElem, (const char *) name);
5978 if (attr == NULL)
5979 return(0);
5980 return(xmlSchemaPValAttrNodeID(ctxt, attr));
5985 * xmlGetMaxOccurs:
5986 * @ctxt: a schema validation context
5987 * @node: a subtree containing XML Schema informations
5989 * Get the maxOccurs property
5991 * Returns the default if not found, or the value
5993 static int
5994 xmlGetMaxOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
5995 int min, int max, int def, const char *expected)
5997 const xmlChar *val, *cur;
5998 int ret = 0;
5999 xmlAttrPtr attr;
6001 attr = xmlSchemaGetPropNode(node, "maxOccurs");
6002 if (attr == NULL)
6003 return (def);
6004 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6006 if (xmlStrEqual(val, (const xmlChar *) "unbounded")) {
6007 if (max != UNBOUNDED) {
6008 xmlSchemaPSimpleTypeErr(ctxt,
6009 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6010 /* XML_SCHEMAP_INVALID_MINOCCURS, */
6011 NULL, (xmlNodePtr) attr, NULL, expected,
6012 val, NULL, NULL, NULL);
6013 return (def);
6014 } else
6015 return (UNBOUNDED); /* encoding it with -1 might be another option */
6018 cur = val;
6019 while (IS_BLANK_CH(*cur))
6020 cur++;
6021 if (*cur == 0) {
6022 xmlSchemaPSimpleTypeErr(ctxt,
6023 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6024 /* XML_SCHEMAP_INVALID_MINOCCURS, */
6025 NULL, (xmlNodePtr) attr, NULL, expected,
6026 val, NULL, NULL, NULL);
6027 return (def);
6029 while ((*cur >= '0') && (*cur <= '9')) {
6030 ret = ret * 10 + (*cur - '0');
6031 cur++;
6033 while (IS_BLANK_CH(*cur))
6034 cur++;
6036 * TODO: Restrict the maximal value to Integer.
6038 if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
6039 xmlSchemaPSimpleTypeErr(ctxt,
6040 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6041 /* XML_SCHEMAP_INVALID_MINOCCURS, */
6042 NULL, (xmlNodePtr) attr, NULL, expected,
6043 val, NULL, NULL, NULL);
6044 return (def);
6046 return (ret);
6050 * xmlGetMinOccurs:
6051 * @ctxt: a schema validation context
6052 * @node: a subtree containing XML Schema informations
6054 * Get the minOccurs property
6056 * Returns the default if not found, or the value
6058 static int
6059 xmlGetMinOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
6060 int min, int max, int def, const char *expected)
6062 const xmlChar *val, *cur;
6063 int ret = 0;
6064 xmlAttrPtr attr;
6066 attr = xmlSchemaGetPropNode(node, "minOccurs");
6067 if (attr == NULL)
6068 return (def);
6069 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6070 cur = val;
6071 while (IS_BLANK_CH(*cur))
6072 cur++;
6073 if (*cur == 0) {
6074 xmlSchemaPSimpleTypeErr(ctxt,
6075 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6076 /* XML_SCHEMAP_INVALID_MINOCCURS, */
6077 NULL, (xmlNodePtr) attr, NULL, expected,
6078 val, NULL, NULL, NULL);
6079 return (def);
6081 while ((*cur >= '0') && (*cur <= '9')) {
6082 ret = ret * 10 + (*cur - '0');
6083 cur++;
6085 while (IS_BLANK_CH(*cur))
6086 cur++;
6088 * TODO: Restrict the maximal value to Integer.
6090 if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
6091 xmlSchemaPSimpleTypeErr(ctxt,
6092 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6093 /* XML_SCHEMAP_INVALID_MINOCCURS, */
6094 NULL, (xmlNodePtr) attr, NULL, expected,
6095 val, NULL, NULL, NULL);
6096 return (def);
6098 return (ret);
6102 * xmlSchemaPGetBoolNodeValue:
6103 * @ctxt: a schema validation context
6104 * @ownerDes: owner designation
6105 * @ownerItem: the owner as a schema item
6106 * @node: the node holding the value
6108 * Converts a boolean string value into 1 or 0.
6110 * Returns 0 or 1.
6112 static int
6113 xmlSchemaPGetBoolNodeValue(xmlSchemaParserCtxtPtr ctxt,
6114 xmlSchemaBasicItemPtr ownerItem,
6115 xmlNodePtr node)
6117 xmlChar *value = NULL;
6118 int res = 0;
6120 value = xmlNodeGetContent(node);
6122 * 3.2.2.1 Lexical representation
6123 * An instance of a datatype that is defined as �boolean�
6124 * can have the following legal literals {true, false, 1, 0}.
6126 if (xmlStrEqual(BAD_CAST value, BAD_CAST "true"))
6127 res = 1;
6128 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "false"))
6129 res = 0;
6130 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "1"))
6131 res = 1;
6132 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "0"))
6133 res = 0;
6134 else {
6135 xmlSchemaPSimpleTypeErr(ctxt,
6136 XML_SCHEMAP_INVALID_BOOLEAN,
6137 ownerItem, node,
6138 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
6139 NULL, BAD_CAST value,
6140 NULL, NULL, NULL);
6142 if (value != NULL)
6143 xmlFree(value);
6144 return (res);
6148 * xmlGetBooleanProp:
6149 * @ctxt: a schema validation context
6150 * @node: a subtree containing XML Schema informations
6151 * @name: the attribute name
6152 * @def: the default value
6154 * Evaluate if a boolean property is set
6156 * Returns the default if not found, 0 if found to be false,
6157 * 1 if found to be true
6159 static int
6160 xmlGetBooleanProp(xmlSchemaParserCtxtPtr ctxt,
6161 xmlNodePtr node,
6162 const char *name, int def)
6164 const xmlChar *val;
6166 val = xmlSchemaGetProp(ctxt, node, name);
6167 if (val == NULL)
6168 return (def);
6170 * 3.2.2.1 Lexical representation
6171 * An instance of a datatype that is defined as �boolean�
6172 * can have the following legal literals {true, false, 1, 0}.
6174 if (xmlStrEqual(val, BAD_CAST "true"))
6175 def = 1;
6176 else if (xmlStrEqual(val, BAD_CAST "false"))
6177 def = 0;
6178 else if (xmlStrEqual(val, BAD_CAST "1"))
6179 def = 1;
6180 else if (xmlStrEqual(val, BAD_CAST "0"))
6181 def = 0;
6182 else {
6183 xmlSchemaPSimpleTypeErr(ctxt,
6184 XML_SCHEMAP_INVALID_BOOLEAN,
6185 NULL,
6186 (xmlNodePtr) xmlSchemaGetPropNode(node, name),
6187 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
6188 NULL, val, NULL, NULL, NULL);
6190 return (def);
6193 /************************************************************************
6195 * Shema extraction from an Infoset *
6197 ************************************************************************/
6198 static xmlSchemaTypePtr xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr
6199 ctxt, xmlSchemaPtr schema,
6200 xmlNodePtr node,
6201 int topLevel);
6202 static xmlSchemaTypePtr xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr
6203 ctxt,
6204 xmlSchemaPtr schema,
6205 xmlNodePtr node,
6206 int topLevel);
6207 static xmlSchemaTypePtr xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr
6208 ctxt,
6209 xmlSchemaPtr schema,
6210 xmlNodePtr node,
6211 xmlSchemaTypeType parentType);
6212 static xmlSchemaBasicItemPtr
6213 xmlSchemaParseLocalAttribute(xmlSchemaParserCtxtPtr pctxt,
6214 xmlSchemaPtr schema,
6215 xmlNodePtr node,
6216 xmlSchemaItemListPtr uses,
6217 int parentType);
6218 static xmlSchemaTypePtr xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt,
6219 xmlSchemaPtr schema,
6220 xmlNodePtr node);
6221 static xmlSchemaWildcardPtr
6222 xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
6223 xmlSchemaPtr schema, xmlNodePtr node);
6226 * xmlSchemaPValAttrNodeValue:
6228 * @ctxt: a schema parser context
6229 * @ownerDes: the designation of the parent element
6230 * @ownerItem: the schema object owner if existent
6231 * @attr: the schema attribute node being validated
6232 * @value: the value
6233 * @type: the built-in type to be validated against
6235 * Validates a value against the given built-in type.
6236 * This one is intended to be used internally for validation
6237 * of schema attribute values during parsing of the schema.
6239 * Returns 0 if the value is valid, a positive error code
6240 * number otherwise and -1 in case of an internal or API error.
6242 static int
6243 xmlSchemaPValAttrNodeValue(xmlSchemaParserCtxtPtr pctxt,
6244 xmlSchemaBasicItemPtr ownerItem,
6245 xmlAttrPtr attr,
6246 const xmlChar *value,
6247 xmlSchemaTypePtr type)
6250 int ret = 0;
6253 * NOTE: Should we move this to xmlschematypes.c? Hmm, but this
6254 * one is really meant to be used internally, so better not.
6256 if ((pctxt == NULL) || (type == NULL) || (attr == NULL))
6257 return (-1);
6258 if (type->type != XML_SCHEMA_TYPE_BASIC) {
6259 PERROR_INT("xmlSchemaPValAttrNodeValue",
6260 "the given type is not a built-in type");
6261 return (-1);
6263 switch (type->builtInType) {
6264 case XML_SCHEMAS_NCNAME:
6265 case XML_SCHEMAS_QNAME:
6266 case XML_SCHEMAS_ANYURI:
6267 case XML_SCHEMAS_TOKEN:
6268 case XML_SCHEMAS_LANGUAGE:
6269 ret = xmlSchemaValPredefTypeNode(type, value, NULL,
6270 (xmlNodePtr) attr);
6271 break;
6272 default: {
6273 PERROR_INT("xmlSchemaPValAttrNodeValue",
6274 "validation using the given type is not supported while "
6275 "parsing a schema");
6276 return (-1);
6280 * TODO: Should we use the S4S error codes instead?
6282 if (ret < 0) {
6283 PERROR_INT("xmlSchemaPValAttrNodeValue",
6284 "failed to validate a schema attribute value");
6285 return (-1);
6286 } else if (ret > 0) {
6287 if (WXS_IS_LIST(type))
6288 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
6289 else
6290 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
6291 xmlSchemaPSimpleTypeErr(pctxt,
6292 ret, ownerItem, (xmlNodePtr) attr,
6293 type, NULL, value, NULL, NULL, NULL);
6295 return (ret);
6299 * xmlSchemaPValAttrNode:
6301 * @ctxt: a schema parser context
6302 * @ownerDes: the designation of the parent element
6303 * @ownerItem: the schema object owner if existent
6304 * @attr: the schema attribute node being validated
6305 * @type: the built-in type to be validated against
6306 * @value: the resulting value if any
6308 * Extracts and validates a value against the given built-in type.
6309 * This one is intended to be used internally for validation
6310 * of schema attribute values during parsing of the schema.
6312 * Returns 0 if the value is valid, a positive error code
6313 * number otherwise and -1 in case of an internal or API error.
6315 static int
6316 xmlSchemaPValAttrNode(xmlSchemaParserCtxtPtr ctxt,
6317 xmlSchemaBasicItemPtr ownerItem,
6318 xmlAttrPtr attr,
6319 xmlSchemaTypePtr type,
6320 const xmlChar **value)
6322 const xmlChar *val;
6324 if ((ctxt == NULL) || (type == NULL) || (attr == NULL))
6325 return (-1);
6327 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6328 if (value != NULL)
6329 *value = val;
6331 return (xmlSchemaPValAttrNodeValue(ctxt, ownerItem, attr,
6332 val, type));
6336 * xmlSchemaPValAttr:
6338 * @ctxt: a schema parser context
6339 * @node: the element node of the attribute
6340 * @ownerDes: the designation of the parent element
6341 * @ownerItem: the schema object owner if existent
6342 * @ownerElem: the owner element node
6343 * @name: the name of the schema attribute node
6344 * @type: the built-in type to be validated against
6345 * @value: the resulting value if any
6347 * Extracts and validates a value against the given built-in type.
6348 * This one is intended to be used internally for validation
6349 * of schema attribute values during parsing of the schema.
6351 * Returns 0 if the value is valid, a positive error code
6352 * number otherwise and -1 in case of an internal or API error.
6354 static int
6355 xmlSchemaPValAttr(xmlSchemaParserCtxtPtr ctxt,
6356 xmlSchemaBasicItemPtr ownerItem,
6357 xmlNodePtr ownerElem,
6358 const char *name,
6359 xmlSchemaTypePtr type,
6360 const xmlChar **value)
6362 xmlAttrPtr attr;
6364 if ((ctxt == NULL) || (type == NULL)) {
6365 if (value != NULL)
6366 *value = NULL;
6367 return (-1);
6369 if (type->type != XML_SCHEMA_TYPE_BASIC) {
6370 if (value != NULL)
6371 *value = NULL;
6372 xmlSchemaPErr(ctxt, ownerElem,
6373 XML_SCHEMAP_INTERNAL,
6374 "Internal error: xmlSchemaPValAttr, the given "
6375 "type '%s' is not a built-in type.\n",
6376 type->name, NULL);
6377 return (-1);
6379 attr = xmlSchemaGetPropNode(ownerElem, name);
6380 if (attr == NULL) {
6381 if (value != NULL)
6382 *value = NULL;
6383 return (0);
6385 return (xmlSchemaPValAttrNode(ctxt, ownerItem, attr,
6386 type, value));
6389 static int
6390 xmlSchemaCheckReference(xmlSchemaParserCtxtPtr pctxt,
6391 xmlSchemaPtr schema ATTRIBUTE_UNUSED,
6392 xmlNodePtr node,
6393 xmlAttrPtr attr,
6394 const xmlChar *namespaceName)
6396 /* TODO: Pointer comparison instead? */
6397 if (xmlStrEqual(pctxt->targetNamespace, namespaceName))
6398 return (0);
6399 if (xmlStrEqual(xmlSchemaNs, namespaceName))
6400 return (0);
6402 * Check if the referenced namespace was <import>ed.
6404 if (WXS_BUCKET(pctxt)->relations != NULL) {
6405 xmlSchemaSchemaRelationPtr rel;
6407 rel = WXS_BUCKET(pctxt)->relations;
6408 do {
6409 if (WXS_IS_BUCKET_IMPMAIN(rel->type) &&
6410 xmlStrEqual(namespaceName, rel->importNamespace))
6411 return (0);
6412 rel = rel->next;
6413 } while (rel != NULL);
6416 * No matching <import>ed namespace found.
6419 xmlNodePtr n = (attr != NULL) ? (xmlNodePtr) attr : node;
6421 if (namespaceName == NULL)
6422 xmlSchemaCustomErr(ACTXT_CAST pctxt,
6423 XML_SCHEMAP_SRC_RESOLVE, n, NULL,
6424 "References from this schema to components in no "
6425 "namespace are not allowed, since not indicated by an "
6426 "import statement", NULL, NULL);
6427 else
6428 xmlSchemaCustomErr(ACTXT_CAST pctxt,
6429 XML_SCHEMAP_SRC_RESOLVE, n, NULL,
6430 "References from this schema to components in the "
6431 "namespace '%s' are not allowed, since not indicated by an "
6432 "import statement", namespaceName, NULL);
6434 return (XML_SCHEMAP_SRC_RESOLVE);
6438 * xmlSchemaParseLocalAttributes:
6439 * @ctxt: a schema validation context
6440 * @schema: the schema being built
6441 * @node: a subtree containing XML Schema informations
6442 * @type: the hosting type where the attributes will be anchored
6444 * Parses attribute uses and attribute declarations and
6445 * attribute group references.
6447 static int
6448 xmlSchemaParseLocalAttributes(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6449 xmlNodePtr *child, xmlSchemaItemListPtr *list,
6450 int parentType, int *hasRefs)
6452 void *item;
6454 while ((IS_SCHEMA((*child), "attribute")) ||
6455 (IS_SCHEMA((*child), "attributeGroup"))) {
6456 if (IS_SCHEMA((*child), "attribute")) {
6457 item = xmlSchemaParseLocalAttribute(ctxt, schema, *child,
6458 *list, parentType);
6459 } else {
6460 item = xmlSchemaParseAttributeGroupRef(ctxt, schema, *child);
6461 if ((item != NULL) && (hasRefs != NULL))
6462 *hasRefs = 1;
6464 if (item != NULL) {
6465 if (*list == NULL) {
6466 /* TODO: Customize grow factor. */
6467 *list = xmlSchemaItemListCreate();
6468 if (*list == NULL)
6469 return(-1);
6471 if (xmlSchemaItemListAddSize(*list, 2, item) == -1)
6472 return(-1);
6474 *child = (*child)->next;
6476 return (0);
6480 * xmlSchemaParseAnnotation:
6481 * @ctxt: a schema validation context
6482 * @schema: the schema being built
6483 * @node: a subtree containing XML Schema informations
6485 * parse a XML schema Attrribute declaration
6486 * *WARNING* this interface is highly subject to change
6488 * Returns -1 in case of error, 0 if the declaration is improper and
6489 * 1 in case of success.
6491 static xmlSchemaAnnotPtr
6492 xmlSchemaParseAnnotation(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int needed)
6494 xmlSchemaAnnotPtr ret;
6495 xmlNodePtr child = NULL;
6496 xmlAttrPtr attr;
6497 int barked = 0;
6500 * INFO: S4S completed.
6503 * id = ID
6504 * {any attributes with non-schema namespace . . .}>
6505 * Content: (appinfo | documentation)*
6507 if ((ctxt == NULL) || (node == NULL))
6508 return (NULL);
6509 if (needed)
6510 ret = xmlSchemaNewAnnot(ctxt, node);
6511 else
6512 ret = NULL;
6513 attr = node->properties;
6514 while (attr != NULL) {
6515 if (((attr->ns == NULL) &&
6516 (!xmlStrEqual(attr->name, BAD_CAST "id"))) ||
6517 ((attr->ns != NULL) &&
6518 xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
6520 xmlSchemaPIllegalAttrErr(ctxt,
6521 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
6523 attr = attr->next;
6525 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
6527 * And now for the children...
6529 child = node->children;
6530 while (child != NULL) {
6531 if (IS_SCHEMA(child, "appinfo")) {
6532 /* TODO: make available the content of "appinfo". */
6534 * source = anyURI
6535 * {any attributes with non-schema namespace . . .}>
6536 * Content: ({any})*
6538 attr = child->properties;
6539 while (attr != NULL) {
6540 if (((attr->ns == NULL) &&
6541 (!xmlStrEqual(attr->name, BAD_CAST "source"))) ||
6542 ((attr->ns != NULL) &&
6543 xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
6545 xmlSchemaPIllegalAttrErr(ctxt,
6546 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
6548 attr = attr->next;
6550 xmlSchemaPValAttr(ctxt, NULL, child, "source",
6551 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), NULL);
6552 child = child->next;
6553 } else if (IS_SCHEMA(child, "documentation")) {
6554 /* TODO: make available the content of "documentation". */
6556 * source = anyURI
6557 * {any attributes with non-schema namespace . . .}>
6558 * Content: ({any})*
6560 attr = child->properties;
6561 while (attr != NULL) {
6562 if (attr->ns == NULL) {
6563 if (!xmlStrEqual(attr->name, BAD_CAST "source")) {
6564 xmlSchemaPIllegalAttrErr(ctxt,
6565 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
6567 } else {
6568 if (xmlStrEqual(attr->ns->href, xmlSchemaNs) ||
6569 (xmlStrEqual(attr->name, BAD_CAST "lang") &&
6570 (!xmlStrEqual(attr->ns->href, XML_XML_NAMESPACE)))) {
6572 xmlSchemaPIllegalAttrErr(ctxt,
6573 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
6576 attr = attr->next;
6579 * Attribute "xml:lang".
6581 attr = xmlSchemaGetPropNodeNs(child, (const char *) XML_XML_NAMESPACE, "lang");
6582 if (attr != NULL)
6583 xmlSchemaPValAttrNode(ctxt, NULL, attr,
6584 xmlSchemaGetBuiltInType(XML_SCHEMAS_LANGUAGE), NULL);
6585 child = child->next;
6586 } else {
6587 if (!barked)
6588 xmlSchemaPContentErr(ctxt,
6589 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6590 NULL, node, child, NULL, "(appinfo | documentation)*");
6591 barked = 1;
6592 child = child->next;
6596 return (ret);
6600 * xmlSchemaParseFacet:
6601 * @ctxt: a schema validation context
6602 * @schema: the schema being built
6603 * @node: a subtree containing XML Schema informations
6605 * parse a XML schema Facet declaration
6606 * *WARNING* this interface is highly subject to change
6608 * Returns the new type structure or NULL in case of error
6610 static xmlSchemaFacetPtr
6611 xmlSchemaParseFacet(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6612 xmlNodePtr node)
6614 xmlSchemaFacetPtr facet;
6615 xmlNodePtr child = NULL;
6616 const xmlChar *value;
6618 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6619 return (NULL);
6621 facet = xmlSchemaNewFacet();
6622 if (facet == NULL) {
6623 xmlSchemaPErrMemory(ctxt, "allocating facet", node);
6624 return (NULL);
6626 facet->node = node;
6627 value = xmlSchemaGetProp(ctxt, node, "value");
6628 if (value == NULL) {
6629 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_FACET_NO_VALUE,
6630 "Facet %s has no value\n", node->name, NULL);
6631 xmlSchemaFreeFacet(facet);
6632 return (NULL);
6634 if (IS_SCHEMA(node, "minInclusive")) {
6635 facet->type = XML_SCHEMA_FACET_MININCLUSIVE;
6636 } else if (IS_SCHEMA(node, "minExclusive")) {
6637 facet->type = XML_SCHEMA_FACET_MINEXCLUSIVE;
6638 } else if (IS_SCHEMA(node, "maxInclusive")) {
6639 facet->type = XML_SCHEMA_FACET_MAXINCLUSIVE;
6640 } else if (IS_SCHEMA(node, "maxExclusive")) {
6641 facet->type = XML_SCHEMA_FACET_MAXEXCLUSIVE;
6642 } else if (IS_SCHEMA(node, "totalDigits")) {
6643 facet->type = XML_SCHEMA_FACET_TOTALDIGITS;
6644 } else if (IS_SCHEMA(node, "fractionDigits")) {
6645 facet->type = XML_SCHEMA_FACET_FRACTIONDIGITS;
6646 } else if (IS_SCHEMA(node, "pattern")) {
6647 facet->type = XML_SCHEMA_FACET_PATTERN;
6648 } else if (IS_SCHEMA(node, "enumeration")) {
6649 facet->type = XML_SCHEMA_FACET_ENUMERATION;
6650 } else if (IS_SCHEMA(node, "whiteSpace")) {
6651 facet->type = XML_SCHEMA_FACET_WHITESPACE;
6652 } else if (IS_SCHEMA(node, "length")) {
6653 facet->type = XML_SCHEMA_FACET_LENGTH;
6654 } else if (IS_SCHEMA(node, "maxLength")) {
6655 facet->type = XML_SCHEMA_FACET_MAXLENGTH;
6656 } else if (IS_SCHEMA(node, "minLength")) {
6657 facet->type = XML_SCHEMA_FACET_MINLENGTH;
6658 } else {
6659 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_TYPE,
6660 "Unknown facet type %s\n", node->name, NULL);
6661 xmlSchemaFreeFacet(facet);
6662 return (NULL);
6664 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
6665 facet->value = value;
6666 if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
6667 (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
6668 const xmlChar *fixed;
6670 fixed = xmlSchemaGetProp(ctxt, node, "fixed");
6671 if (fixed != NULL) {
6672 if (xmlStrEqual(fixed, BAD_CAST "true"))
6673 facet->fixed = 1;
6676 child = node->children;
6678 if (IS_SCHEMA(child, "annotation")) {
6679 facet->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
6680 child = child->next;
6682 if (child != NULL) {
6683 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_CHILD,
6684 "Facet %s has unexpected child content\n",
6685 node->name, NULL);
6687 return (facet);
6691 * xmlSchemaParseWildcardNs:
6692 * @ctxt: a schema parser context
6693 * @wildc: the wildcard, already created
6694 * @node: a subtree containing XML Schema informations
6696 * Parses the attribute "processContents" and "namespace"
6697 * of a xsd:anyAttribute and xsd:any.
6698 * *WARNING* this interface is highly subject to change
6700 * Returns 0 if everything goes fine, a positive error code
6701 * if something is not valid and -1 if an internal error occurs.
6703 static int
6704 xmlSchemaParseWildcardNs(xmlSchemaParserCtxtPtr ctxt,
6705 xmlSchemaPtr schema ATTRIBUTE_UNUSED,
6706 xmlSchemaWildcardPtr wildc,
6707 xmlNodePtr node)
6709 const xmlChar *pc, *ns, *dictnsItem;
6710 int ret = 0;
6711 xmlChar *nsItem;
6712 xmlSchemaWildcardNsPtr tmp, lastNs = NULL;
6713 xmlAttrPtr attr;
6715 pc = xmlSchemaGetProp(ctxt, node, "processContents");
6716 if ((pc == NULL)
6717 || (xmlStrEqual(pc, (const xmlChar *) "strict"))) {
6718 wildc->processContents = XML_SCHEMAS_ANY_STRICT;
6719 } else if (xmlStrEqual(pc, (const xmlChar *) "skip")) {
6720 wildc->processContents = XML_SCHEMAS_ANY_SKIP;
6721 } else if (xmlStrEqual(pc, (const xmlChar *) "lax")) {
6722 wildc->processContents = XML_SCHEMAS_ANY_LAX;
6723 } else {
6724 xmlSchemaPSimpleTypeErr(ctxt,
6725 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6726 NULL, node,
6727 NULL, "(strict | skip | lax)", pc,
6728 NULL, NULL, NULL);
6729 wildc->processContents = XML_SCHEMAS_ANY_STRICT;
6730 ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
6733 * Build the namespace constraints.
6735 attr = xmlSchemaGetPropNode(node, "namespace");
6736 ns = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6737 if ((attr == NULL) || (xmlStrEqual(ns, BAD_CAST "##any")))
6738 wildc->any = 1;
6739 else if (xmlStrEqual(ns, BAD_CAST "##other")) {
6740 wildc->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
6741 if (wildc->negNsSet == NULL) {
6742 return (-1);
6744 wildc->negNsSet->value = ctxt->targetNamespace;
6745 } else {
6746 const xmlChar *end, *cur;
6748 cur = ns;
6749 do {
6750 while (IS_BLANK_CH(*cur))
6751 cur++;
6752 end = cur;
6753 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
6754 end++;
6755 if (end == cur)
6756 break;
6757 nsItem = xmlStrndup(cur, end - cur);
6758 if ((xmlStrEqual(nsItem, BAD_CAST "##other")) ||
6759 (xmlStrEqual(nsItem, BAD_CAST "##any"))) {
6760 xmlSchemaPSimpleTypeErr(ctxt,
6761 XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER,
6762 NULL, (xmlNodePtr) attr,
6763 NULL,
6764 "((##any | ##other) | List of (xs:anyURI | "
6765 "(##targetNamespace | ##local)))",
6766 nsItem, NULL, NULL, NULL);
6767 ret = XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER;
6768 } else {
6769 if (xmlStrEqual(nsItem, BAD_CAST "##targetNamespace")) {
6770 dictnsItem = ctxt->targetNamespace;
6771 } else if (xmlStrEqual(nsItem, BAD_CAST "##local")) {
6772 dictnsItem = NULL;
6773 } else {
6775 * Validate the item (anyURI).
6777 xmlSchemaPValAttrNodeValue(ctxt, NULL, attr,
6778 nsItem, xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI));
6779 dictnsItem = xmlDictLookup(ctxt->dict, nsItem, -1);
6782 * Avoid dublicate namespaces.
6784 tmp = wildc->nsSet;
6785 while (tmp != NULL) {
6786 if (dictnsItem == tmp->value)
6787 break;
6788 tmp = tmp->next;
6790 if (tmp == NULL) {
6791 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
6792 if (tmp == NULL) {
6793 xmlFree(nsItem);
6794 return (-1);
6796 tmp->value = dictnsItem;
6797 tmp->next = NULL;
6798 if (wildc->nsSet == NULL)
6799 wildc->nsSet = tmp;
6800 else if (lastNs != NULL)
6801 lastNs->next = tmp;
6802 lastNs = tmp;
6806 xmlFree(nsItem);
6807 cur = end;
6808 } while (*cur != 0);
6810 return (ret);
6813 static int
6814 xmlSchemaPCheckParticleCorrect_2(xmlSchemaParserCtxtPtr ctxt,
6815 xmlSchemaParticlePtr item ATTRIBUTE_UNUSED,
6816 xmlNodePtr node,
6817 int minOccurs,
6818 int maxOccurs) {
6820 if ((maxOccurs == 0) && ( minOccurs == 0))
6821 return (0);
6822 if (maxOccurs != UNBOUNDED) {
6824 * TODO: Maybe we should better not create the particle,
6825 * if min/max is invalid, since it could confuse the build of the
6826 * content model.
6829 * 3.9.6 Schema Component Constraint: Particle Correct
6832 if (maxOccurs < 1) {
6834 * 2.2 {max occurs} must be greater than or equal to 1.
6836 xmlSchemaPCustomAttrErr(ctxt,
6837 XML_SCHEMAP_P_PROPS_CORRECT_2_2,
6838 NULL, NULL,
6839 xmlSchemaGetPropNode(node, "maxOccurs"),
6840 "The value must be greater than or equal to 1");
6841 return (XML_SCHEMAP_P_PROPS_CORRECT_2_2);
6842 } else if (minOccurs > maxOccurs) {
6844 * 2.1 {min occurs} must not be greater than {max occurs}.
6846 xmlSchemaPCustomAttrErr(ctxt,
6847 XML_SCHEMAP_P_PROPS_CORRECT_2_1,
6848 NULL, NULL,
6849 xmlSchemaGetPropNode(node, "minOccurs"),
6850 "The value must not be greater than the value of 'maxOccurs'");
6851 return (XML_SCHEMAP_P_PROPS_CORRECT_2_1);
6854 return (0);
6858 * xmlSchemaParseAny:
6859 * @ctxt: a schema validation context
6860 * @schema: the schema being built
6861 * @node: a subtree containing XML Schema informations
6863 * Parsea a XML schema <any> element. A particle and wildcard
6864 * will be created (except if minOccurs==maxOccurs==0, in this case
6865 * nothing will be created).
6866 * *WARNING* this interface is highly subject to change
6868 * Returns the particle or NULL in case of error or if minOccurs==maxOccurs==0
6870 static xmlSchemaParticlePtr
6871 xmlSchemaParseAny(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6872 xmlNodePtr node)
6874 xmlSchemaParticlePtr particle;
6875 xmlNodePtr child = NULL;
6876 xmlSchemaWildcardPtr wild;
6877 int min, max;
6878 xmlAttrPtr attr;
6879 xmlSchemaAnnotPtr annot = NULL;
6881 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6882 return (NULL);
6884 * Check for illegal attributes.
6886 attr = node->properties;
6887 while (attr != NULL) {
6888 if (attr->ns == NULL) {
6889 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
6890 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
6891 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
6892 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
6893 (!xmlStrEqual(attr->name, BAD_CAST "processContents"))) {
6894 xmlSchemaPIllegalAttrErr(ctxt,
6895 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
6897 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
6898 xmlSchemaPIllegalAttrErr(ctxt,
6899 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
6901 attr = attr->next;
6903 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
6905 * minOccurs/maxOccurs.
6907 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
6908 "(xs:nonNegativeInteger | unbounded)");
6909 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1,
6910 "xs:nonNegativeInteger");
6911 xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
6913 * Create & parse the wildcard.
6915 wild = xmlSchemaAddWildcard(ctxt, schema, XML_SCHEMA_TYPE_ANY, node);
6916 if (wild == NULL)
6917 return (NULL);
6918 xmlSchemaParseWildcardNs(ctxt, schema, wild, node);
6920 * And now for the children...
6922 child = node->children;
6923 if (IS_SCHEMA(child, "annotation")) {
6924 annot = xmlSchemaParseAnnotation(ctxt, child, 1);
6925 child = child->next;
6927 if (child != NULL) {
6928 xmlSchemaPContentErr(ctxt,
6929 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6930 NULL, node, child,
6931 NULL, "(annotation?)");
6934 * No component if minOccurs==maxOccurs==0.
6936 if ((min == 0) && (max == 0)) {
6937 /* Don't free the wildcard, since it's already on the list. */
6938 return (NULL);
6941 * Create the particle.
6943 particle = xmlSchemaAddParticle(ctxt, node, min, max);
6944 if (particle == NULL)
6945 return (NULL);
6946 particle->annot = annot;
6947 particle->children = (xmlSchemaTreeItemPtr) wild;
6949 return (particle);
6953 * xmlSchemaParseNotation:
6954 * @ctxt: a schema validation context
6955 * @schema: the schema being built
6956 * @node: a subtree containing XML Schema informations
6958 * parse a XML schema Notation declaration
6960 * Returns the new structure or NULL in case of error
6962 static xmlSchemaNotationPtr
6963 xmlSchemaParseNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6964 xmlNodePtr node)
6966 const xmlChar *name;
6967 xmlSchemaNotationPtr ret;
6968 xmlNodePtr child = NULL;
6970 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6971 return (NULL);
6972 name = xmlSchemaGetProp(ctxt, node, "name");
6973 if (name == NULL) {
6974 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_NOTATION_NO_NAME,
6975 "Notation has no name\n", NULL, NULL);
6976 return (NULL);
6978 ret = xmlSchemaAddNotation(ctxt, schema, name,
6979 ctxt->targetNamespace, node);
6980 if (ret == NULL)
6981 return (NULL);
6982 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
6984 child = node->children;
6985 if (IS_SCHEMA(child, "annotation")) {
6986 ret->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
6987 child = child->next;
6989 if (child != NULL) {
6990 xmlSchemaPContentErr(ctxt,
6991 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6992 NULL, node, child,
6993 NULL, "(annotation?)");
6996 return (ret);
7000 * xmlSchemaParseAnyAttribute:
7001 * @ctxt: a schema validation context
7002 * @schema: the schema being built
7003 * @node: a subtree containing XML Schema informations
7005 * parse a XML schema AnyAttrribute declaration
7006 * *WARNING* this interface is highly subject to change
7008 * Returns a wildcard or NULL.
7010 static xmlSchemaWildcardPtr
7011 xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
7012 xmlSchemaPtr schema, xmlNodePtr node)
7014 xmlSchemaWildcardPtr ret;
7015 xmlNodePtr child = NULL;
7016 xmlAttrPtr attr;
7018 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7019 return (NULL);
7021 ret = xmlSchemaAddWildcard(ctxt, schema, XML_SCHEMA_TYPE_ANY_ATTRIBUTE,
7022 node);
7023 if (ret == NULL) {
7024 return (NULL);
7027 * Check for illegal attributes.
7029 attr = node->properties;
7030 while (attr != NULL) {
7031 if (attr->ns == NULL) {
7032 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7033 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
7034 (!xmlStrEqual(attr->name, BAD_CAST "processContents"))) {
7035 xmlSchemaPIllegalAttrErr(ctxt,
7036 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7038 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7039 xmlSchemaPIllegalAttrErr(ctxt,
7040 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7042 attr = attr->next;
7044 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
7046 * Parse the namespace list.
7048 if (xmlSchemaParseWildcardNs(ctxt, schema, ret, node) != 0)
7049 return (NULL);
7051 * And now for the children...
7053 child = node->children;
7054 if (IS_SCHEMA(child, "annotation")) {
7055 ret->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
7056 child = child->next;
7058 if (child != NULL) {
7059 xmlSchemaPContentErr(ctxt,
7060 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7061 NULL, node, child,
7062 NULL, "(annotation?)");
7065 return (ret);
7070 * xmlSchemaParseAttribute:
7071 * @ctxt: a schema validation context
7072 * @schema: the schema being built
7073 * @node: a subtree containing XML Schema informations
7075 * parse a XML schema Attrribute declaration
7076 * *WARNING* this interface is highly subject to change
7078 * Returns the attribute declaration.
7080 static xmlSchemaBasicItemPtr
7081 xmlSchemaParseLocalAttribute(xmlSchemaParserCtxtPtr pctxt,
7082 xmlSchemaPtr schema,
7083 xmlNodePtr node,
7084 xmlSchemaItemListPtr uses,
7085 int parentType)
7087 const xmlChar *attrValue, *name = NULL, *ns = NULL;
7088 xmlSchemaAttributeUsePtr use = NULL;
7089 xmlNodePtr child = NULL;
7090 xmlAttrPtr attr;
7091 const xmlChar *tmpNs = NULL, *tmpName = NULL, *defValue = NULL;
7092 int isRef = 0, occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
7093 int nberrors, hasForm = 0, defValueType = 0;
7095 #define WXS_ATTR_DEF_VAL_DEFAULT 1
7096 #define WXS_ATTR_DEF_VAL_FIXED 2
7099 * 3.2.3 Constraints on XML Representations of Attribute Declarations
7102 if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
7103 return (NULL);
7104 attr = xmlSchemaGetPropNode(node, "ref");
7105 if (attr != NULL) {
7106 if (xmlSchemaPValAttrNodeQName(pctxt, schema,
7107 NULL, attr, &tmpNs, &tmpName) != 0) {
7108 return (NULL);
7110 if (xmlSchemaCheckReference(pctxt, schema, node, attr, tmpNs) != 0)
7111 return(NULL);
7112 isRef = 1;
7114 nberrors = pctxt->nberrors;
7116 * Check for illegal attributes.
7118 attr = node->properties;
7119 while (attr != NULL) {
7120 if (attr->ns == NULL) {
7121 if (isRef) {
7122 if (xmlStrEqual(attr->name, BAD_CAST "id")) {
7123 xmlSchemaPValAttrNodeID(pctxt, attr);
7124 goto attr_next;
7125 } else if (xmlStrEqual(attr->name, BAD_CAST "ref")) {
7126 goto attr_next;
7128 } else {
7129 if (xmlStrEqual(attr->name, BAD_CAST "name")) {
7130 goto attr_next;
7131 } else if (xmlStrEqual(attr->name, BAD_CAST "id")) {
7132 xmlSchemaPValAttrNodeID(pctxt, attr);
7133 goto attr_next;
7134 } else if (xmlStrEqual(attr->name, BAD_CAST "type")) {
7135 xmlSchemaPValAttrNodeQName(pctxt, schema, NULL,
7136 attr, &tmpNs, &tmpName);
7137 goto attr_next;
7138 } else if (xmlStrEqual(attr->name, BAD_CAST "form")) {
7140 * Evaluate the target namespace
7142 hasForm = 1;
7143 attrValue = xmlSchemaGetNodeContent(pctxt,
7144 (xmlNodePtr) attr);
7145 if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
7146 ns = pctxt->targetNamespace;
7147 } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified"))
7149 xmlSchemaPSimpleTypeErr(pctxt,
7150 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
7151 NULL, (xmlNodePtr) attr,
7152 NULL, "(qualified | unqualified)",
7153 attrValue, NULL, NULL, NULL);
7155 goto attr_next;
7158 if (xmlStrEqual(attr->name, BAD_CAST "use")) {
7160 attrValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
7161 /* TODO: Maybe we need to normalize the value beforehand. */
7162 if (xmlStrEqual(attrValue, BAD_CAST "optional"))
7163 occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
7164 else if (xmlStrEqual(attrValue, BAD_CAST "prohibited"))
7165 occurs = XML_SCHEMAS_ATTR_USE_PROHIBITED;
7166 else if (xmlStrEqual(attrValue, BAD_CAST "required"))
7167 occurs = XML_SCHEMAS_ATTR_USE_REQUIRED;
7168 else {
7169 xmlSchemaPSimpleTypeErr(pctxt,
7170 XML_SCHEMAP_INVALID_ATTR_USE,
7171 NULL, (xmlNodePtr) attr,
7172 NULL, "(optional | prohibited | required)",
7173 attrValue, NULL, NULL, NULL);
7175 goto attr_next;
7176 } else if (xmlStrEqual(attr->name, BAD_CAST "default")) {
7178 * 3.2.3 : 1
7179 * default and fixed must not both be present.
7181 if (defValue) {
7182 xmlSchemaPMutualExclAttrErr(pctxt,
7183 XML_SCHEMAP_SRC_ATTRIBUTE_1,
7184 NULL, attr, "default", "fixed");
7185 } else {
7186 defValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
7187 defValueType = WXS_ATTR_DEF_VAL_DEFAULT;
7189 goto attr_next;
7190 } else if (xmlStrEqual(attr->name, BAD_CAST "fixed")) {
7192 * 3.2.3 : 1
7193 * default and fixed must not both be present.
7195 if (defValue) {
7196 xmlSchemaPMutualExclAttrErr(pctxt,
7197 XML_SCHEMAP_SRC_ATTRIBUTE_1,
7198 NULL, attr, "default", "fixed");
7199 } else {
7200 defValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
7201 defValueType = WXS_ATTR_DEF_VAL_FIXED;
7203 goto attr_next;
7205 } else if (! xmlStrEqual(attr->ns->href, xmlSchemaNs))
7206 goto attr_next;
7208 xmlSchemaPIllegalAttrErr(pctxt,
7209 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7211 attr_next:
7212 attr = attr->next;
7215 * 3.2.3 : 2
7216 * If default and use are both present, use must have
7217 * the actual value optional.
7219 if ((defValueType == WXS_ATTR_DEF_VAL_DEFAULT) &&
7220 (occurs != XML_SCHEMAS_ATTR_USE_OPTIONAL)) {
7221 xmlSchemaPSimpleTypeErr(pctxt,
7222 XML_SCHEMAP_SRC_ATTRIBUTE_2,
7223 NULL, node, NULL,
7224 "(optional | prohibited | required)", NULL,
7225 "The value of the attribute 'use' must be 'optional' "
7226 "if the attribute 'default' is present",
7227 NULL, NULL);
7230 * We want correct attributes.
7232 if (nberrors != pctxt->nberrors)
7233 return(NULL);
7234 if (! isRef) {
7235 xmlSchemaAttributePtr attrDecl;
7237 /* TODO: move XML_SCHEMAS_QUALIF_ATTR to the parser. */
7238 if ((! hasForm) && (schema->flags & XML_SCHEMAS_QUALIF_ATTR))
7239 ns = pctxt->targetNamespace;
7241 * 3.2.6 Schema Component Constraint: xsi: Not Allowed
7242 * TODO: Move this to the component layer.
7244 if (xmlStrEqual(ns, xmlSchemaInstanceNs)) {
7245 xmlSchemaCustomErr(ACTXT_CAST pctxt,
7246 XML_SCHEMAP_NO_XSI,
7247 node, NULL,
7248 "The target namespace must not match '%s'",
7249 xmlSchemaInstanceNs, NULL);
7251 attr = xmlSchemaGetPropNode(node, "name");
7252 if (attr == NULL) {
7253 xmlSchemaPMissingAttrErr(pctxt, XML_SCHEMAP_S4S_ATTR_MISSING,
7254 NULL, node, "name", NULL);
7255 return (NULL);
7257 if (xmlSchemaPValAttrNode(pctxt, NULL, attr,
7258 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
7259 return (NULL);
7262 * 3.2.6 Schema Component Constraint: xmlns Not Allowed
7263 * TODO: Move this to the component layer.
7265 if (xmlStrEqual(name, BAD_CAST "xmlns")) {
7266 xmlSchemaPSimpleTypeErr(pctxt,
7267 XML_SCHEMAP_NO_XMLNS,
7268 NULL, (xmlNodePtr) attr,
7269 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), NULL, NULL,
7270 "The value of the attribute must not match 'xmlns'",
7271 NULL, NULL);
7272 return (NULL);
7274 if (occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED)
7275 goto check_children;
7277 * Create the attribute use component.
7279 use = xmlSchemaAddAttributeUse(pctxt, node);
7280 if (use == NULL)
7281 return(NULL);
7282 use->occurs = occurs;
7284 * Create the attribute declaration.
7286 attrDecl = xmlSchemaAddAttribute(pctxt, schema, name, ns, node, 0);
7287 if (attrDecl == NULL)
7288 return (NULL);
7289 if (tmpName != NULL) {
7290 attrDecl->typeName = tmpName;
7291 attrDecl->typeNs = tmpNs;
7293 use->attrDecl = attrDecl;
7295 * Value constraint.
7297 if (defValue != NULL) {
7298 attrDecl->defValue = defValue;
7299 if (defValueType == WXS_ATTR_DEF_VAL_FIXED)
7300 attrDecl->flags |= XML_SCHEMAS_ATTR_FIXED;
7302 } else if (occurs != XML_SCHEMAS_ATTR_USE_PROHIBITED) {
7303 xmlSchemaQNameRefPtr ref;
7306 * Create the attribute use component.
7308 use = xmlSchemaAddAttributeUse(pctxt, node);
7309 if (use == NULL)
7310 return(NULL);
7312 * We need to resolve the reference at later stage.
7314 WXS_ADD_PENDING(pctxt, use);
7315 use->occurs = occurs;
7317 * Create a QName reference to the attribute declaration.
7319 ref = xmlSchemaNewQNameRef(pctxt, XML_SCHEMA_TYPE_ATTRIBUTE,
7320 tmpName, tmpNs);
7321 if (ref == NULL)
7322 return(NULL);
7324 * Assign the reference. This will be substituted for the
7325 * referenced attribute declaration when the QName is resolved.
7327 use->attrDecl = WXS_ATTR_CAST ref;
7329 * Value constraint.
7331 if (defValue != NULL)
7332 use->defValue = defValue;
7333 if (defValueType == WXS_ATTR_DEF_VAL_FIXED)
7334 use->flags |= XML_SCHEMA_ATTR_USE_FIXED;
7337 check_children:
7339 * And now for the children...
7341 child = node->children;
7342 if (occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) {
7343 xmlSchemaAttributeUseProhibPtr prohib;
7345 if (IS_SCHEMA(child, "annotation")) {
7346 xmlSchemaParseAnnotation(pctxt, child, 0);
7347 child = child->next;
7349 if (child != NULL) {
7350 xmlSchemaPContentErr(pctxt,
7351 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7352 NULL, node, child, NULL,
7353 "(annotation?)");
7356 * Check for pointlessness of attribute prohibitions.
7358 if (parentType == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
7359 xmlSchemaCustomWarning(ACTXT_CAST pctxt,
7360 XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
7361 node, NULL,
7362 "Skipping attribute use prohibition, since it is "
7363 "pointless inside an <attributeGroup>",
7364 NULL, NULL, NULL);
7365 return(NULL);
7366 } else if (parentType == XML_SCHEMA_TYPE_EXTENSION) {
7367 xmlSchemaCustomWarning(ACTXT_CAST pctxt,
7368 XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
7369 node, NULL,
7370 "Skipping attribute use prohibition, since it is "
7371 "pointless when extending a type",
7372 NULL, NULL, NULL);
7373 return(NULL);
7375 if (! isRef) {
7376 tmpName = name;
7377 tmpNs = ns;
7380 * Check for duplicate attribute prohibitions.
7382 if (uses) {
7383 int i;
7385 for (i = 0; i < uses->nbItems; i++) {
7386 use = uses->items[i];
7387 if ((use->type == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB) &&
7388 (tmpName == (WXS_ATTR_PROHIB_CAST use)->name) &&
7389 (tmpNs == (WXS_ATTR_PROHIB_CAST use)->targetNamespace))
7391 xmlChar *str = NULL;
7393 xmlSchemaCustomWarning(ACTXT_CAST pctxt,
7394 XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
7395 node, NULL,
7396 "Skipping duplicate attribute use prohibition '%s'",
7397 xmlSchemaFormatQName(&str, tmpNs, tmpName),
7398 NULL, NULL);
7399 FREE_AND_NULL(str)
7400 return(NULL);
7405 * Create the attribute prohibition helper component.
7407 prohib = xmlSchemaAddAttributeUseProhib(pctxt);
7408 if (prohib == NULL)
7409 return(NULL);
7410 prohib->node = node;
7411 prohib->name = tmpName;
7412 prohib->targetNamespace = tmpNs;
7413 if (isRef) {
7415 * We need at least to resolve to the attribute declaration.
7417 WXS_ADD_PENDING(pctxt, prohib);
7419 return(WXS_BASIC_CAST prohib);
7420 } else {
7421 if (IS_SCHEMA(child, "annotation")) {
7423 * TODO: Should this go into the attr decl?
7425 use->annot = xmlSchemaParseAnnotation(pctxt, child, 1);
7426 child = child->next;
7428 if (isRef) {
7429 if (child != NULL) {
7430 if (IS_SCHEMA(child, "simpleType"))
7432 * 3.2.3 : 3.2
7433 * If ref is present, then all of <simpleType>,
7434 * form and type must be absent.
7436 xmlSchemaPContentErr(pctxt,
7437 XML_SCHEMAP_SRC_ATTRIBUTE_3_2,
7438 NULL, node, child, NULL,
7439 "(annotation?)");
7440 else
7441 xmlSchemaPContentErr(pctxt,
7442 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7443 NULL, node, child, NULL,
7444 "(annotation?)");
7446 } else {
7447 if (IS_SCHEMA(child, "simpleType")) {
7448 if (WXS_ATTRUSE_DECL(use)->typeName != NULL) {
7450 * 3.2.3 : 4
7451 * type and <simpleType> must not both be present.
7453 xmlSchemaPContentErr(pctxt, XML_SCHEMAP_SRC_ATTRIBUTE_4,
7454 NULL, node, child,
7455 "The attribute 'type' and the <simpleType> child "
7456 "are mutually exclusive", NULL);
7457 } else
7458 WXS_ATTRUSE_TYPEDEF(use) =
7459 xmlSchemaParseSimpleType(pctxt, schema, child, 0);
7460 child = child->next;
7462 if (child != NULL)
7463 xmlSchemaPContentErr(pctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7464 NULL, node, child, NULL,
7465 "(annotation?, simpleType?)");
7468 return (WXS_BASIC_CAST use);
7472 static xmlSchemaAttributePtr
7473 xmlSchemaParseGlobalAttribute(xmlSchemaParserCtxtPtr pctxt,
7474 xmlSchemaPtr schema,
7475 xmlNodePtr node)
7477 const xmlChar *attrValue;
7478 xmlSchemaAttributePtr ret;
7479 xmlNodePtr child = NULL;
7480 xmlAttrPtr attr;
7483 * Note that the w3c spec assumes the schema to be validated with schema
7484 * for schemas beforehand.
7486 * 3.2.3 Constraints on XML Representations of Attribute Declarations
7488 if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
7489 return (NULL);
7491 * 3.2.3 : 3.1
7492 * One of ref or name must be present, but not both
7494 attr = xmlSchemaGetPropNode(node, "name");
7495 if (attr == NULL) {
7496 xmlSchemaPMissingAttrErr(pctxt, XML_SCHEMAP_S4S_ATTR_MISSING,
7497 NULL, node, "name", NULL);
7498 return (NULL);
7500 if (xmlSchemaPValAttrNode(pctxt, NULL, attr,
7501 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &attrValue) != 0) {
7502 return (NULL);
7505 * 3.2.6 Schema Component Constraint: xmlns Not Allowed
7506 * TODO: Move this to the component layer.
7508 if (xmlStrEqual(attrValue, BAD_CAST "xmlns")) {
7509 xmlSchemaPSimpleTypeErr(pctxt,
7510 XML_SCHEMAP_NO_XMLNS,
7511 NULL, (xmlNodePtr) attr,
7512 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), NULL, NULL,
7513 "The value of the attribute must not match 'xmlns'",
7514 NULL, NULL);
7515 return (NULL);
7518 * 3.2.6 Schema Component Constraint: xsi: Not Allowed
7519 * TODO: Move this to the component layer.
7520 * Or better leave it here and add it to the component layer
7521 * if we have a schema construction API.
7523 if (xmlStrEqual(pctxt->targetNamespace, xmlSchemaInstanceNs)) {
7524 xmlSchemaCustomErr(ACTXT_CAST pctxt,
7525 XML_SCHEMAP_NO_XSI, node, NULL,
7526 "The target namespace must not match '%s'",
7527 xmlSchemaInstanceNs, NULL);
7530 ret = xmlSchemaAddAttribute(pctxt, schema, attrValue,
7531 pctxt->targetNamespace, node, 1);
7532 if (ret == NULL)
7533 return (NULL);
7534 ret->flags |= XML_SCHEMAS_ATTR_GLOBAL;
7537 * Check for illegal attributes.
7539 attr = node->properties;
7540 while (attr != NULL) {
7541 if (attr->ns == NULL) {
7542 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7543 (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
7544 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
7545 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
7546 (!xmlStrEqual(attr->name, BAD_CAST "type")))
7548 xmlSchemaPIllegalAttrErr(pctxt,
7549 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7551 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7552 xmlSchemaPIllegalAttrErr(pctxt,
7553 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7555 attr = attr->next;
7557 xmlSchemaPValAttrQName(pctxt, schema, NULL,
7558 node, "type", &ret->typeNs, &ret->typeName);
7560 xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
7562 * Attribute "fixed".
7564 ret->defValue = xmlSchemaGetProp(pctxt, node, "fixed");
7565 if (ret->defValue != NULL)
7566 ret->flags |= XML_SCHEMAS_ATTR_FIXED;
7568 * Attribute "default".
7570 attr = xmlSchemaGetPropNode(node, "default");
7571 if (attr != NULL) {
7573 * 3.2.3 : 1
7574 * default and fixed must not both be present.
7576 if (ret->flags & XML_SCHEMAS_ATTR_FIXED) {
7577 xmlSchemaPMutualExclAttrErr(pctxt, XML_SCHEMAP_SRC_ATTRIBUTE_1,
7578 WXS_BASIC_CAST ret, attr, "default", "fixed");
7579 } else
7580 ret->defValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
7583 * And now for the children...
7585 child = node->children;
7586 if (IS_SCHEMA(child, "annotation")) {
7587 ret->annot = xmlSchemaParseAnnotation(pctxt, child, 1);
7588 child = child->next;
7590 if (IS_SCHEMA(child, "simpleType")) {
7591 if (ret->typeName != NULL) {
7593 * 3.2.3 : 4
7594 * type and <simpleType> must not both be present.
7596 xmlSchemaPContentErr(pctxt, XML_SCHEMAP_SRC_ATTRIBUTE_4,
7597 NULL, node, child,
7598 "The attribute 'type' and the <simpleType> child "
7599 "are mutually exclusive", NULL);
7600 } else
7601 ret->subtypes = xmlSchemaParseSimpleType(pctxt, schema, child, 0);
7602 child = child->next;
7604 if (child != NULL)
7605 xmlSchemaPContentErr(pctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7606 NULL, node, child, NULL,
7607 "(annotation?, simpleType?)");
7609 return (ret);
7613 * xmlSchemaParseAttributeGroupRef:
7614 * @ctxt: a schema validation context
7615 * @schema: the schema being built
7616 * @node: a subtree containing XML Schema informations
7618 * Parse an attribute group definition reference.
7619 * Note that a reference to an attribute group does not
7620 * correspond to any component at all.
7621 * *WARNING* this interface is highly subject to change
7623 * Returns the attribute group or NULL in case of error.
7625 static xmlSchemaQNameRefPtr
7626 xmlSchemaParseAttributeGroupRef(xmlSchemaParserCtxtPtr pctxt,
7627 xmlSchemaPtr schema,
7628 xmlNodePtr node)
7630 xmlSchemaQNameRefPtr ret;
7631 xmlNodePtr child = NULL;
7632 xmlAttrPtr attr;
7633 const xmlChar *refNs = NULL, *ref = NULL;
7635 if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
7636 return (NULL);
7638 attr = xmlSchemaGetPropNode(node, "ref");
7639 if (attr == NULL) {
7640 xmlSchemaPMissingAttrErr(pctxt,
7641 XML_SCHEMAP_S4S_ATTR_MISSING,
7642 NULL, node, "ref", NULL);
7643 return (NULL);
7645 xmlSchemaPValAttrNodeQName(pctxt, schema,
7646 NULL, attr, &refNs, &ref);
7647 if (xmlSchemaCheckReference(pctxt, schema, node, attr, refNs) != 0)
7648 return(NULL);
7651 * Check for illegal attributes.
7653 attr = node->properties;
7654 while (attr != NULL) {
7655 if (attr->ns == NULL) {
7656 if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
7657 (!xmlStrEqual(attr->name, BAD_CAST "id")))
7659 xmlSchemaPIllegalAttrErr(pctxt,
7660 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7662 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7663 xmlSchemaPIllegalAttrErr(pctxt,
7664 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7666 attr = attr->next;
7668 /* Attribute ID */
7669 xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
7672 * And now for the children...
7674 child = node->children;
7675 if (IS_SCHEMA(child, "annotation")) {
7677 * TODO: We do not have a place to store the annotation, do we?
7679 xmlSchemaParseAnnotation(pctxt, child, 0);
7680 child = child->next;
7682 if (child != NULL) {
7683 xmlSchemaPContentErr(pctxt,
7684 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7685 NULL, node, child, NULL,
7686 "(annotation?)");
7690 * Handle attribute group redefinitions.
7692 if (pctxt->isRedefine && pctxt->redef &&
7693 (pctxt->redef->item->type ==
7694 XML_SCHEMA_TYPE_ATTRIBUTEGROUP) &&
7695 (ref == pctxt->redef->refName) &&
7696 (refNs == pctxt->redef->refTargetNs))
7699 * SPEC src-redefine:
7700 * (7.1) "If it has an <attributeGroup> among its contents
7701 * the �actual value� of whose ref [attribute] is the same
7702 * as the �actual value� of its own name attribute plus
7703 * target namespace, then it must have exactly one such group."
7705 if (pctxt->redefCounter != 0) {
7706 xmlChar *str = NULL;
7708 xmlSchemaCustomErr(ACTXT_CAST pctxt,
7709 XML_SCHEMAP_SRC_REDEFINE, node, NULL,
7710 "The redefining attribute group definition "
7711 "'%s' must not contain more than one "
7712 "reference to the redefined definition",
7713 xmlSchemaFormatQName(&str, refNs, ref), NULL);
7714 FREE_AND_NULL(str);
7715 return(NULL);
7717 pctxt->redefCounter++;
7719 * URGENT TODO: How to ensure that the reference will not be
7720 * handled by the normal component resolution mechanism?
7722 ret = xmlSchemaNewQNameRef(pctxt,
7723 XML_SCHEMA_TYPE_ATTRIBUTEGROUP, ref, refNs);
7724 if (ret == NULL)
7725 return(NULL);
7726 ret->node = node;
7727 pctxt->redef->reference = WXS_BASIC_CAST ret;
7728 } else {
7730 * Create a QName-reference helper component. We will substitute this
7731 * component for the attribute uses of the referenced attribute group
7732 * definition.
7734 ret = xmlSchemaNewQNameRef(pctxt,
7735 XML_SCHEMA_TYPE_ATTRIBUTEGROUP, ref, refNs);
7736 if (ret == NULL)
7737 return(NULL);
7738 ret->node = node;
7739 /* Add to pending items, to be able to resolve the reference. */
7740 WXS_ADD_PENDING(pctxt, ret);
7742 return (ret);
7746 * xmlSchemaParseAttributeGroupDefinition:
7747 * @pctxt: a schema validation context
7748 * @schema: the schema being built
7749 * @node: a subtree containing XML Schema informations
7751 * parse a XML schema Attribute Group declaration
7752 * *WARNING* this interface is highly subject to change
7754 * Returns the attribute group definition or NULL in case of error.
7756 static xmlSchemaAttributeGroupPtr
7757 xmlSchemaParseAttributeGroupDefinition(xmlSchemaParserCtxtPtr pctxt,
7758 xmlSchemaPtr schema,
7759 xmlNodePtr node)
7761 const xmlChar *name;
7762 xmlSchemaAttributeGroupPtr ret;
7763 xmlNodePtr child = NULL;
7764 xmlAttrPtr attr;
7765 int hasRefs = 0;
7767 if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
7768 return (NULL);
7770 attr = xmlSchemaGetPropNode(node, "name");
7771 if (attr == NULL) {
7772 xmlSchemaPMissingAttrErr(pctxt,
7773 XML_SCHEMAP_S4S_ATTR_MISSING,
7774 NULL, node, "name", NULL);
7775 return (NULL);
7778 * The name is crucial, exit if invalid.
7780 if (xmlSchemaPValAttrNode(pctxt,
7781 NULL, attr,
7782 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
7783 return (NULL);
7785 ret = xmlSchemaAddAttributeGroupDefinition(pctxt, schema,
7786 name, pctxt->targetNamespace, node);
7787 if (ret == NULL)
7788 return (NULL);
7790 * Check for illegal attributes.
7792 attr = node->properties;
7793 while (attr != NULL) {
7794 if (attr->ns == NULL) {
7795 if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
7796 (!xmlStrEqual(attr->name, BAD_CAST "id")))
7798 xmlSchemaPIllegalAttrErr(pctxt,
7799 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7801 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7802 xmlSchemaPIllegalAttrErr(pctxt,
7803 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7805 attr = attr->next;
7807 /* Attribute ID */
7808 xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
7810 * And now for the children...
7812 child = node->children;
7813 if (IS_SCHEMA(child, "annotation")) {
7814 ret->annot = xmlSchemaParseAnnotation(pctxt, child, 1);
7815 child = child->next;
7818 * Parse contained attribute decls/refs.
7820 if (xmlSchemaParseLocalAttributes(pctxt, schema, &child,
7821 (xmlSchemaItemListPtr *) &(ret->attrUses),
7822 XML_SCHEMA_TYPE_ATTRIBUTEGROUP, &hasRefs) == -1)
7823 return(NULL);
7824 if (hasRefs)
7825 ret->flags |= XML_SCHEMAS_ATTRGROUP_HAS_REFS;
7827 * Parse the attribute wildcard.
7829 if (IS_SCHEMA(child, "anyAttribute")) {
7830 ret->attributeWildcard = xmlSchemaParseAnyAttribute(pctxt,
7831 schema, child);
7832 child = child->next;
7834 if (child != NULL) {
7835 xmlSchemaPContentErr(pctxt,
7836 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7837 NULL, node, child, NULL,
7838 "(annotation?, ((attribute | attributeGroup)*, anyAttribute?))");
7840 return (ret);
7844 * xmlSchemaPValAttrFormDefault:
7845 * @value: the value
7846 * @flags: the flags to be modified
7847 * @flagQualified: the specific flag for "qualified"
7849 * Returns 0 if the value is valid, 1 otherwise.
7851 static int
7852 xmlSchemaPValAttrFormDefault(const xmlChar *value,
7853 int *flags,
7854 int flagQualified)
7856 if (xmlStrEqual(value, BAD_CAST "qualified")) {
7857 if ((*flags & flagQualified) == 0)
7858 *flags |= flagQualified;
7859 } else if (!xmlStrEqual(value, BAD_CAST "unqualified"))
7860 return (1);
7862 return (0);
7866 * xmlSchemaPValAttrBlockFinal:
7867 * @value: the value
7868 * @flags: the flags to be modified
7869 * @flagAll: the specific flag for "#all"
7870 * @flagExtension: the specific flag for "extension"
7871 * @flagRestriction: the specific flag for "restriction"
7872 * @flagSubstitution: the specific flag for "substitution"
7873 * @flagList: the specific flag for "list"
7874 * @flagUnion: the specific flag for "union"
7876 * Validates the value of the attribute "final" and "block". The value
7877 * is converted into the specified flag values and returned in @flags.
7879 * Returns 0 if the value is valid, 1 otherwise.
7882 static int
7883 xmlSchemaPValAttrBlockFinal(const xmlChar *value,
7884 int *flags,
7885 int flagAll,
7886 int flagExtension,
7887 int flagRestriction,
7888 int flagSubstitution,
7889 int flagList,
7890 int flagUnion)
7892 int ret = 0;
7895 * TODO: This does not check for dublicate entries.
7897 if ((flags == NULL) || (value == NULL))
7898 return (-1);
7899 if (value[0] == 0)
7900 return (0);
7901 if (xmlStrEqual(value, BAD_CAST "#all")) {
7902 if (flagAll != -1)
7903 *flags |= flagAll;
7904 else {
7905 if (flagExtension != -1)
7906 *flags |= flagExtension;
7907 if (flagRestriction != -1)
7908 *flags |= flagRestriction;
7909 if (flagSubstitution != -1)
7910 *flags |= flagSubstitution;
7911 if (flagList != -1)
7912 *flags |= flagList;
7913 if (flagUnion != -1)
7914 *flags |= flagUnion;
7916 } else {
7917 const xmlChar *end, *cur = value;
7918 xmlChar *item;
7920 do {
7921 while (IS_BLANK_CH(*cur))
7922 cur++;
7923 end = cur;
7924 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
7925 end++;
7926 if (end == cur)
7927 break;
7928 item = xmlStrndup(cur, end - cur);
7929 if (xmlStrEqual(item, BAD_CAST "extension")) {
7930 if (flagExtension != -1) {
7931 if ((*flags & flagExtension) == 0)
7932 *flags |= flagExtension;
7933 } else
7934 ret = 1;
7935 } else if (xmlStrEqual(item, BAD_CAST "restriction")) {
7936 if (flagRestriction != -1) {
7937 if ((*flags & flagRestriction) == 0)
7938 *flags |= flagRestriction;
7939 } else
7940 ret = 1;
7941 } else if (xmlStrEqual(item, BAD_CAST "substitution")) {
7942 if (flagSubstitution != -1) {
7943 if ((*flags & flagSubstitution) == 0)
7944 *flags |= flagSubstitution;
7945 } else
7946 ret = 1;
7947 } else if (xmlStrEqual(item, BAD_CAST "list")) {
7948 if (flagList != -1) {
7949 if ((*flags & flagList) == 0)
7950 *flags |= flagList;
7951 } else
7952 ret = 1;
7953 } else if (xmlStrEqual(item, BAD_CAST "union")) {
7954 if (flagUnion != -1) {
7955 if ((*flags & flagUnion) == 0)
7956 *flags |= flagUnion;
7957 } else
7958 ret = 1;
7959 } else
7960 ret = 1;
7961 if (item != NULL)
7962 xmlFree(item);
7963 cur = end;
7964 } while ((ret == 0) && (*cur != 0));
7967 return (ret);
7970 static int
7971 xmlSchemaCheckCSelectorXPath(xmlSchemaParserCtxtPtr ctxt,
7972 xmlSchemaIDCPtr idc,
7973 xmlSchemaIDCSelectPtr selector,
7974 xmlAttrPtr attr,
7975 int isField)
7977 xmlNodePtr node;
7980 * c-selector-xpath:
7981 * Schema Component Constraint: Selector Value OK
7983 * TODO: 1 The {selector} must be a valid XPath expression, as defined
7984 * in [XPath].
7986 if (selector == NULL) {
7987 xmlSchemaPErr(ctxt, idc->node,
7988 XML_SCHEMAP_INTERNAL,
7989 "Internal error: xmlSchemaCheckCSelectorXPath, "
7990 "the selector is not specified.\n", NULL, NULL);
7991 return (-1);
7993 if (attr == NULL)
7994 node = idc->node;
7995 else
7996 node = (xmlNodePtr) attr;
7997 if (selector->xpath == NULL) {
7998 xmlSchemaPCustomErr(ctxt,
7999 /* TODO: Adjust error code. */
8000 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8001 NULL, node,
8002 "The XPath expression of the selector is not valid", NULL);
8003 return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE);
8004 } else {
8005 const xmlChar **nsArray = NULL;
8006 xmlNsPtr *nsList = NULL;
8008 * Compile the XPath expression.
8011 * TODO: We need the array of in-scope namespaces for compilation.
8012 * TODO: Call xmlPatterncompile with different options for selector/
8013 * field.
8015 if (attr == NULL)
8016 nsList = NULL;
8017 else
8018 nsList = xmlGetNsList(attr->doc, attr->parent);
8020 * Build an array of prefixes and namespaces.
8022 if (nsList != NULL) {
8023 int i, count = 0;
8025 for (i = 0; nsList[i] != NULL; i++)
8026 count++;
8028 nsArray = (const xmlChar **) xmlMalloc(
8029 (count * 2 + 1) * sizeof(const xmlChar *));
8030 if (nsArray == NULL) {
8031 xmlSchemaPErrMemory(ctxt, "allocating a namespace array",
8032 NULL);
8033 xmlFree(nsList);
8034 return (-1);
8036 for (i = 0; i < count; i++) {
8037 nsArray[2 * i] = nsList[i]->href;
8038 nsArray[2 * i + 1] = nsList[i]->prefix;
8040 nsArray[count * 2] = NULL;
8041 xmlFree(nsList);
8044 * TODO: Differentiate between "selector" and "field".
8046 if (isField)
8047 selector->xpathComp = (void *) xmlPatterncompile(selector->xpath,
8048 NULL, XML_PATTERN_XSFIELD, nsArray);
8049 else
8050 selector->xpathComp = (void *) xmlPatterncompile(selector->xpath,
8051 NULL, XML_PATTERN_XSSEL, nsArray);
8052 if (nsArray != NULL)
8053 xmlFree((xmlChar **) nsArray);
8055 if (selector->xpathComp == NULL) {
8056 xmlSchemaPCustomErr(ctxt,
8057 /* TODO: Adjust error code? */
8058 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8059 NULL, node,
8060 "The XPath expression '%s' could not be "
8061 "compiled", selector->xpath);
8062 return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE);
8065 return (0);
8068 #define ADD_ANNOTATION(annot) \
8069 xmlSchemaAnnotPtr cur = item->annot; \
8070 if (item->annot == NULL) { \
8071 item->annot = annot; \
8072 return (annot); \
8074 cur = item->annot; \
8075 if (cur->next != NULL) { \
8076 cur = cur->next; \
8078 cur->next = annot;
8081 * xmlSchemaAssignAnnotation:
8082 * @item: the schema component
8083 * @annot: the annotation
8085 * Adds the annotation to the given schema component.
8087 * Returns the given annotaion.
8089 static xmlSchemaAnnotPtr
8090 xmlSchemaAddAnnotation(xmlSchemaAnnotItemPtr annItem,
8091 xmlSchemaAnnotPtr annot)
8093 if ((annItem == NULL) || (annot == NULL))
8094 return (NULL);
8095 switch (annItem->type) {
8096 case XML_SCHEMA_TYPE_ELEMENT: {
8097 xmlSchemaElementPtr item = (xmlSchemaElementPtr) annItem;
8098 ADD_ANNOTATION(annot)
8100 break;
8101 case XML_SCHEMA_TYPE_ATTRIBUTE: {
8102 xmlSchemaAttributePtr item = (xmlSchemaAttributePtr) annItem;
8103 ADD_ANNOTATION(annot)
8105 break;
8106 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
8107 case XML_SCHEMA_TYPE_ANY: {
8108 xmlSchemaWildcardPtr item = (xmlSchemaWildcardPtr) annItem;
8109 ADD_ANNOTATION(annot)
8111 break;
8112 case XML_SCHEMA_TYPE_PARTICLE:
8113 case XML_SCHEMA_TYPE_IDC_KEY:
8114 case XML_SCHEMA_TYPE_IDC_KEYREF:
8115 case XML_SCHEMA_TYPE_IDC_UNIQUE: {
8116 xmlSchemaAnnotItemPtr item = (xmlSchemaAnnotItemPtr) annItem;
8117 ADD_ANNOTATION(annot)
8119 break;
8120 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP: {
8121 xmlSchemaAttributeGroupPtr item =
8122 (xmlSchemaAttributeGroupPtr) annItem;
8123 ADD_ANNOTATION(annot)
8125 break;
8126 case XML_SCHEMA_TYPE_NOTATION: {
8127 xmlSchemaNotationPtr item = (xmlSchemaNotationPtr) annItem;
8128 ADD_ANNOTATION(annot)
8130 break;
8131 case XML_SCHEMA_FACET_MININCLUSIVE:
8132 case XML_SCHEMA_FACET_MINEXCLUSIVE:
8133 case XML_SCHEMA_FACET_MAXINCLUSIVE:
8134 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
8135 case XML_SCHEMA_FACET_TOTALDIGITS:
8136 case XML_SCHEMA_FACET_FRACTIONDIGITS:
8137 case XML_SCHEMA_FACET_PATTERN:
8138 case XML_SCHEMA_FACET_ENUMERATION:
8139 case XML_SCHEMA_FACET_WHITESPACE:
8140 case XML_SCHEMA_FACET_LENGTH:
8141 case XML_SCHEMA_FACET_MAXLENGTH:
8142 case XML_SCHEMA_FACET_MINLENGTH: {
8143 xmlSchemaFacetPtr item = (xmlSchemaFacetPtr) annItem;
8144 ADD_ANNOTATION(annot)
8146 break;
8147 case XML_SCHEMA_TYPE_SIMPLE:
8148 case XML_SCHEMA_TYPE_COMPLEX: {
8149 xmlSchemaTypePtr item = (xmlSchemaTypePtr) annItem;
8150 ADD_ANNOTATION(annot)
8152 break;
8153 case XML_SCHEMA_TYPE_GROUP: {
8154 xmlSchemaModelGroupDefPtr item = (xmlSchemaModelGroupDefPtr) annItem;
8155 ADD_ANNOTATION(annot)
8157 break;
8158 case XML_SCHEMA_TYPE_SEQUENCE:
8159 case XML_SCHEMA_TYPE_CHOICE:
8160 case XML_SCHEMA_TYPE_ALL: {
8161 xmlSchemaModelGroupPtr item = (xmlSchemaModelGroupPtr) annItem;
8162 ADD_ANNOTATION(annot)
8164 break;
8165 default:
8166 xmlSchemaPCustomErr(NULL,
8167 XML_SCHEMAP_INTERNAL,
8168 NULL, NULL,
8169 "Internal error: xmlSchemaAddAnnotation, "
8170 "The item is not a annotated schema component", NULL);
8171 break;
8173 return (annot);
8177 * xmlSchemaParseIDCSelectorAndField:
8178 * @ctxt: a schema validation context
8179 * @schema: the schema being built
8180 * @node: a subtree containing XML Schema informations
8182 * Parses a XML Schema identity-contraint definition's
8183 * <selector> and <field> elements.
8185 * Returns the parsed identity-constraint definition.
8187 static xmlSchemaIDCSelectPtr
8188 xmlSchemaParseIDCSelectorAndField(xmlSchemaParserCtxtPtr ctxt,
8189 xmlSchemaIDCPtr idc,
8190 xmlNodePtr node,
8191 int isField)
8193 xmlSchemaIDCSelectPtr item;
8194 xmlNodePtr child = NULL;
8195 xmlAttrPtr attr;
8198 * Check for illegal attributes.
8200 attr = node->properties;
8201 while (attr != NULL) {
8202 if (attr->ns == NULL) {
8203 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8204 (!xmlStrEqual(attr->name, BAD_CAST "xpath"))) {
8205 xmlSchemaPIllegalAttrErr(ctxt,
8206 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8208 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8209 xmlSchemaPIllegalAttrErr(ctxt,
8210 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8212 attr = attr->next;
8215 * Create the item.
8217 item = (xmlSchemaIDCSelectPtr) xmlMalloc(sizeof(xmlSchemaIDCSelect));
8218 if (item == NULL) {
8219 xmlSchemaPErrMemory(ctxt,
8220 "allocating a 'selector' of an identity-constraint definition",
8221 NULL);
8222 return (NULL);
8224 memset(item, 0, sizeof(xmlSchemaIDCSelect));
8226 * Attribute "xpath" (mandatory).
8228 attr = xmlSchemaGetPropNode(node, "xpath");
8229 if (attr == NULL) {
8230 xmlSchemaPMissingAttrErr(ctxt,
8231 XML_SCHEMAP_S4S_ATTR_MISSING,
8232 NULL, node,
8233 "name", NULL);
8234 } else {
8235 item->xpath = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8237 * URGENT TODO: "field"s have an other syntax than "selector"s.
8240 if (xmlSchemaCheckCSelectorXPath(ctxt, idc, item, attr,
8241 isField) == -1) {
8242 xmlSchemaPErr(ctxt,
8243 (xmlNodePtr) attr,
8244 XML_SCHEMAP_INTERNAL,
8245 "Internal error: xmlSchemaParseIDCSelectorAndField, "
8246 "validating the XPath expression of a IDC selector.\n",
8247 NULL, NULL);
8251 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
8253 * And now for the children...
8255 child = node->children;
8256 if (IS_SCHEMA(child, "annotation")) {
8258 * Add the annotation to the parent IDC.
8260 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) idc,
8261 xmlSchemaParseAnnotation(ctxt, child, 1));
8262 child = child->next;
8264 if (child != NULL) {
8265 xmlSchemaPContentErr(ctxt,
8266 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8267 NULL, node, child,
8268 NULL, "(annotation?)");
8271 return (item);
8275 * xmlSchemaParseIDC:
8276 * @ctxt: a schema validation context
8277 * @schema: the schema being built
8278 * @node: a subtree containing XML Schema informations
8280 * Parses a XML Schema identity-contraint definition.
8282 * Returns the parsed identity-constraint definition.
8284 static xmlSchemaIDCPtr
8285 xmlSchemaParseIDC(xmlSchemaParserCtxtPtr ctxt,
8286 xmlSchemaPtr schema,
8287 xmlNodePtr node,
8288 xmlSchemaTypeType idcCategory,
8289 const xmlChar *targetNamespace)
8291 xmlSchemaIDCPtr item = NULL;
8292 xmlNodePtr child = NULL;
8293 xmlAttrPtr attr;
8294 const xmlChar *name = NULL;
8295 xmlSchemaIDCSelectPtr field = NULL, lastField = NULL;
8298 * Check for illegal attributes.
8300 attr = node->properties;
8301 while (attr != NULL) {
8302 if (attr->ns == NULL) {
8303 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8304 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
8305 ((idcCategory != XML_SCHEMA_TYPE_IDC_KEYREF) ||
8306 (!xmlStrEqual(attr->name, BAD_CAST "refer")))) {
8307 xmlSchemaPIllegalAttrErr(ctxt,
8308 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8310 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8311 xmlSchemaPIllegalAttrErr(ctxt,
8312 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8314 attr = attr->next;
8317 * Attribute "name" (mandatory).
8319 attr = xmlSchemaGetPropNode(node, "name");
8320 if (attr == NULL) {
8321 xmlSchemaPMissingAttrErr(ctxt,
8322 XML_SCHEMAP_S4S_ATTR_MISSING,
8323 NULL, node,
8324 "name", NULL);
8325 return (NULL);
8326 } else if (xmlSchemaPValAttrNode(ctxt,
8327 NULL, attr,
8328 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
8329 return (NULL);
8331 /* Create the component. */
8332 item = xmlSchemaAddIDC(ctxt, schema, name, targetNamespace,
8333 idcCategory, node);
8334 if (item == NULL)
8335 return(NULL);
8337 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
8338 if (idcCategory == XML_SCHEMA_TYPE_IDC_KEYREF) {
8340 * Attribute "refer" (mandatory).
8342 attr = xmlSchemaGetPropNode(node, "refer");
8343 if (attr == NULL) {
8344 xmlSchemaPMissingAttrErr(ctxt,
8345 XML_SCHEMAP_S4S_ATTR_MISSING,
8346 NULL, node,
8347 "refer", NULL);
8348 } else {
8350 * Create a reference item.
8352 item->ref = xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_IDC_KEY,
8353 NULL, NULL);
8354 if (item->ref == NULL)
8355 return (NULL);
8356 xmlSchemaPValAttrNodeQName(ctxt, schema,
8357 NULL, attr,
8358 &(item->ref->targetNamespace),
8359 &(item->ref->name));
8360 xmlSchemaCheckReference(ctxt, schema, node, attr,
8361 item->ref->targetNamespace);
8365 * And now for the children...
8367 child = node->children;
8368 if (IS_SCHEMA(child, "annotation")) {
8369 item->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
8370 child = child->next;
8372 if (child == NULL) {
8373 xmlSchemaPContentErr(ctxt,
8374 XML_SCHEMAP_S4S_ELEM_MISSING,
8375 NULL, node, child,
8376 "A child element is missing",
8377 "(annotation?, (selector, field+))");
8380 * Child element <selector>.
8382 if (IS_SCHEMA(child, "selector")) {
8383 item->selector = xmlSchemaParseIDCSelectorAndField(ctxt,
8384 item, child, 0);
8385 child = child->next;
8387 * Child elements <field>.
8389 if (IS_SCHEMA(child, "field")) {
8390 do {
8391 field = xmlSchemaParseIDCSelectorAndField(ctxt,
8392 item, child, 1);
8393 if (field != NULL) {
8394 field->index = item->nbFields;
8395 item->nbFields++;
8396 if (lastField != NULL)
8397 lastField->next = field;
8398 else
8399 item->fields = field;
8400 lastField = field;
8402 child = child->next;
8403 } while (IS_SCHEMA(child, "field"));
8404 } else {
8405 xmlSchemaPContentErr(ctxt,
8406 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8407 NULL, node, child,
8408 NULL, "(annotation?, (selector, field+))");
8411 if (child != NULL) {
8412 xmlSchemaPContentErr(ctxt,
8413 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8414 NULL, node, child,
8415 NULL, "(annotation?, (selector, field+))");
8418 return (item);
8422 * xmlSchemaParseElement:
8423 * @ctxt: a schema validation context
8424 * @schema: the schema being built
8425 * @node: a subtree containing XML Schema informations
8426 * @topLevel: indicates if this is global declaration
8428 * Parses a XML schema element declaration.
8429 * *WARNING* this interface is highly subject to change
8431 * Returns the element declaration or a particle; NULL in case
8432 * of an error or if the particle has minOccurs==maxOccurs==0.
8434 static xmlSchemaBasicItemPtr
8435 xmlSchemaParseElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
8436 xmlNodePtr node, int *isElemRef, int topLevel)
8438 xmlSchemaElementPtr decl = NULL;
8439 xmlSchemaParticlePtr particle = NULL;
8440 xmlSchemaAnnotPtr annot = NULL;
8441 xmlNodePtr child = NULL;
8442 xmlAttrPtr attr, nameAttr;
8443 int min, max, isRef = 0;
8444 xmlChar *des = NULL;
8446 /* 3.3.3 Constraints on XML Representations of Element Declarations */
8447 /* TODO: Complete implementation of 3.3.6 */
8449 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8450 return (NULL);
8452 if (isElemRef != NULL)
8453 *isElemRef = 0;
8455 * If we get a "ref" attribute on a local <element> we will assume it's
8456 * a reference - even if there's a "name" attribute; this seems to be more
8457 * robust.
8459 nameAttr = xmlSchemaGetPropNode(node, "name");
8460 attr = xmlSchemaGetPropNode(node, "ref");
8461 if ((topLevel) || (attr == NULL)) {
8462 if (nameAttr == NULL) {
8463 xmlSchemaPMissingAttrErr(ctxt,
8464 XML_SCHEMAP_S4S_ATTR_MISSING,
8465 NULL, node, "name", NULL);
8466 return (NULL);
8468 } else
8469 isRef = 1;
8471 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
8472 child = node->children;
8473 if (IS_SCHEMA(child, "annotation")) {
8474 annot = xmlSchemaParseAnnotation(ctxt, child, 1);
8475 child = child->next;
8478 * Skip particle part if a global declaration.
8480 if (topLevel)
8481 goto declaration_part;
8483 * The particle part ==================================================
8485 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
8486 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1, "(xs:nonNegativeInteger | unbounded)");
8487 xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
8488 particle = xmlSchemaAddParticle(ctxt, node, min, max);
8489 if (particle == NULL)
8490 goto return_null;
8492 /* ret->flags |= XML_SCHEMAS_ELEM_REF; */
8494 if (isRef) {
8495 const xmlChar *refNs = NULL, *ref = NULL;
8496 xmlSchemaQNameRefPtr refer = NULL;
8498 * The reference part =============================================
8500 if (isElemRef != NULL)
8501 *isElemRef = 1;
8503 xmlSchemaPValAttrNodeQName(ctxt, schema,
8504 NULL, attr, &refNs, &ref);
8505 xmlSchemaCheckReference(ctxt, schema, node, attr, refNs);
8507 * SPEC (3.3.3 : 2.1) "One of ref or name must be present, but not both"
8509 if (nameAttr != NULL) {
8510 xmlSchemaPMutualExclAttrErr(ctxt,
8511 XML_SCHEMAP_SRC_ELEMENT_2_1, NULL, nameAttr, "ref", "name");
8514 * Check for illegal attributes.
8516 attr = node->properties;
8517 while (attr != NULL) {
8518 if (attr->ns == NULL) {
8519 if (xmlStrEqual(attr->name, BAD_CAST "ref") ||
8520 xmlStrEqual(attr->name, BAD_CAST "name") ||
8521 xmlStrEqual(attr->name, BAD_CAST "id") ||
8522 xmlStrEqual(attr->name, BAD_CAST "maxOccurs") ||
8523 xmlStrEqual(attr->name, BAD_CAST "minOccurs"))
8525 attr = attr->next;
8526 continue;
8527 } else {
8528 /* SPEC (3.3.3 : 2.2) */
8529 xmlSchemaPCustomAttrErr(ctxt,
8530 XML_SCHEMAP_SRC_ELEMENT_2_2,
8531 NULL, NULL, attr,
8532 "Only the attributes 'minOccurs', 'maxOccurs' and "
8533 "'id' are allowed in addition to 'ref'");
8534 break;
8536 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8537 xmlSchemaPIllegalAttrErr(ctxt,
8538 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8540 attr = attr->next;
8543 * No children except <annotation> expected.
8545 if (child != NULL) {
8546 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8547 NULL, node, child, NULL, "(annotation?)");
8549 if ((min == 0) && (max == 0))
8550 goto return_null;
8552 * Create the reference item and attach it to the particle.
8554 refer = xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_ELEMENT,
8555 ref, refNs);
8556 if (refer == NULL)
8557 goto return_null;
8558 particle->children = (xmlSchemaTreeItemPtr) refer;
8559 particle->annot = annot;
8561 * Add the particle to pending components, since the reference
8562 * need to be resolved.
8564 WXS_ADD_PENDING(ctxt, particle);
8565 return ((xmlSchemaBasicItemPtr) particle);
8568 * The declaration part ===============================================
8570 declaration_part:
8572 const xmlChar *ns = NULL, *fixed, *name, *attrValue;
8573 xmlSchemaIDCPtr curIDC = NULL, lastIDC = NULL;
8575 if (xmlSchemaPValAttrNode(ctxt, NULL, nameAttr,
8576 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0)
8577 goto return_null;
8579 * Evaluate the target namespace.
8581 if (topLevel) {
8582 ns = ctxt->targetNamespace;
8583 } else {
8584 attr = xmlSchemaGetPropNode(node, "form");
8585 if (attr != NULL) {
8586 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8587 if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
8588 ns = ctxt->targetNamespace;
8589 } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) {
8590 xmlSchemaPSimpleTypeErr(ctxt,
8591 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8592 NULL, (xmlNodePtr) attr,
8593 NULL, "(qualified | unqualified)",
8594 attrValue, NULL, NULL, NULL);
8596 } else if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
8597 ns = ctxt->targetNamespace;
8599 decl = xmlSchemaAddElement(ctxt, name, ns, node, topLevel);
8600 if (decl == NULL) {
8601 goto return_null;
8604 * Check for illegal attributes.
8606 attr = node->properties;
8607 while (attr != NULL) {
8608 if (attr->ns == NULL) {
8609 if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
8610 (!xmlStrEqual(attr->name, BAD_CAST "type")) &&
8611 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8612 (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
8613 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
8614 (!xmlStrEqual(attr->name, BAD_CAST "block")) &&
8615 (!xmlStrEqual(attr->name, BAD_CAST "nillable")))
8617 if (topLevel == 0) {
8618 if ((!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
8619 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
8620 (!xmlStrEqual(attr->name, BAD_CAST "form")))
8622 xmlSchemaPIllegalAttrErr(ctxt,
8623 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8625 } else if ((!xmlStrEqual(attr->name, BAD_CAST "final")) &&
8626 (!xmlStrEqual(attr->name, BAD_CAST "abstract")) &&
8627 (!xmlStrEqual(attr->name, BAD_CAST "substitutionGroup"))) {
8629 xmlSchemaPIllegalAttrErr(ctxt,
8630 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8633 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8635 xmlSchemaPIllegalAttrErr(ctxt,
8636 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8638 attr = attr->next;
8641 * Extract/validate attributes.
8643 if (topLevel) {
8645 * Process top attributes of global element declarations here.
8647 decl->flags |= XML_SCHEMAS_ELEM_GLOBAL;
8648 decl->flags |= XML_SCHEMAS_ELEM_TOPLEVEL;
8649 xmlSchemaPValAttrQName(ctxt, schema,
8650 NULL, node, "substitutionGroup",
8651 &(decl->substGroupNs), &(decl->substGroup));
8652 if (xmlGetBooleanProp(ctxt, node, "abstract", 0))
8653 decl->flags |= XML_SCHEMAS_ELEM_ABSTRACT;
8655 * Attribute "final".
8657 attr = xmlSchemaGetPropNode(node, "final");
8658 if (attr == NULL) {
8659 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
8660 decl->flags |= XML_SCHEMAS_ELEM_FINAL_EXTENSION;
8661 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
8662 decl->flags |= XML_SCHEMAS_ELEM_FINAL_RESTRICTION;
8663 } else {
8664 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8665 if (xmlSchemaPValAttrBlockFinal(attrValue, &(decl->flags),
8667 XML_SCHEMAS_ELEM_FINAL_EXTENSION,
8668 XML_SCHEMAS_ELEM_FINAL_RESTRICTION, -1, -1, -1) != 0) {
8669 xmlSchemaPSimpleTypeErr(ctxt,
8670 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8671 NULL, (xmlNodePtr) attr,
8672 NULL, "(#all | List of (extension | restriction))",
8673 attrValue, NULL, NULL, NULL);
8678 * Attribute "block".
8680 attr = xmlSchemaGetPropNode(node, "block");
8681 if (attr == NULL) {
8683 * Apply default "block" values.
8685 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
8686 decl->flags |= XML_SCHEMAS_ELEM_BLOCK_RESTRICTION;
8687 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
8688 decl->flags |= XML_SCHEMAS_ELEM_BLOCK_EXTENSION;
8689 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
8690 decl->flags |= XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION;
8691 } else {
8692 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8693 if (xmlSchemaPValAttrBlockFinal(attrValue, &(decl->flags),
8695 XML_SCHEMAS_ELEM_BLOCK_EXTENSION,
8696 XML_SCHEMAS_ELEM_BLOCK_RESTRICTION,
8697 XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION, -1, -1) != 0) {
8698 xmlSchemaPSimpleTypeErr(ctxt,
8699 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8700 NULL, (xmlNodePtr) attr,
8701 NULL, "(#all | List of (extension | "
8702 "restriction | substitution))", attrValue,
8703 NULL, NULL, NULL);
8706 if (xmlGetBooleanProp(ctxt, node, "nillable", 0))
8707 decl->flags |= XML_SCHEMAS_ELEM_NILLABLE;
8709 attr = xmlSchemaGetPropNode(node, "type");
8710 if (attr != NULL) {
8711 xmlSchemaPValAttrNodeQName(ctxt, schema,
8712 NULL, attr,
8713 &(decl->namedTypeNs), &(decl->namedType));
8714 xmlSchemaCheckReference(ctxt, schema, node,
8715 attr, decl->namedTypeNs);
8717 decl->value = xmlSchemaGetProp(ctxt, node, "default");
8718 attr = xmlSchemaGetPropNode(node, "fixed");
8719 if (attr != NULL) {
8720 fixed = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8721 if (decl->value != NULL) {
8723 * 3.3.3 : 1
8724 * default and fixed must not both be present.
8726 xmlSchemaPMutualExclAttrErr(ctxt,
8727 XML_SCHEMAP_SRC_ELEMENT_1,
8728 NULL, attr, "default", "fixed");
8729 } else {
8730 decl->flags |= XML_SCHEMAS_ELEM_FIXED;
8731 decl->value = fixed;
8735 * And now for the children...
8737 if (IS_SCHEMA(child, "complexType")) {
8739 * 3.3.3 : 3
8740 * "type" and either <simpleType> or <complexType> are mutually
8741 * exclusive
8743 if (decl->namedType != NULL) {
8744 xmlSchemaPContentErr(ctxt,
8745 XML_SCHEMAP_SRC_ELEMENT_3,
8746 NULL, node, child,
8747 "The attribute 'type' and the <complexType> child are "
8748 "mutually exclusive", NULL);
8749 } else
8750 WXS_ELEM_TYPEDEF(decl) = xmlSchemaParseComplexType(ctxt, schema, child, 0);
8751 child = child->next;
8752 } else if (IS_SCHEMA(child, "simpleType")) {
8754 * 3.3.3 : 3
8755 * "type" and either <simpleType> or <complexType> are
8756 * mutually exclusive
8758 if (decl->namedType != NULL) {
8759 xmlSchemaPContentErr(ctxt,
8760 XML_SCHEMAP_SRC_ELEMENT_3,
8761 NULL, node, child,
8762 "The attribute 'type' and the <simpleType> child are "
8763 "mutually exclusive", NULL);
8764 } else
8765 WXS_ELEM_TYPEDEF(decl) = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
8766 child = child->next;
8768 while ((IS_SCHEMA(child, "unique")) ||
8769 (IS_SCHEMA(child, "key")) || (IS_SCHEMA(child, "keyref"))) {
8770 if (IS_SCHEMA(child, "unique")) {
8771 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
8772 XML_SCHEMA_TYPE_IDC_UNIQUE, decl->targetNamespace);
8773 } else if (IS_SCHEMA(child, "key")) {
8774 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
8775 XML_SCHEMA_TYPE_IDC_KEY, decl->targetNamespace);
8776 } else if (IS_SCHEMA(child, "keyref")) {
8777 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
8778 XML_SCHEMA_TYPE_IDC_KEYREF, decl->targetNamespace);
8780 if (lastIDC != NULL)
8781 lastIDC->next = curIDC;
8782 else
8783 decl->idcs = (void *) curIDC;
8784 lastIDC = curIDC;
8785 child = child->next;
8787 if (child != NULL) {
8788 xmlSchemaPContentErr(ctxt,
8789 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8790 NULL, node, child,
8791 NULL, "(annotation?, ((simpleType | complexType)?, "
8792 "(unique | key | keyref)*))");
8794 decl->annot = annot;
8797 * NOTE: Element Declaration Representation OK 4. will be checked at a
8798 * different layer.
8800 FREE_AND_NULL(des)
8801 if (topLevel)
8802 return ((xmlSchemaBasicItemPtr) decl);
8803 else {
8804 particle->children = (xmlSchemaTreeItemPtr) decl;
8805 return ((xmlSchemaBasicItemPtr) particle);
8808 return_null:
8809 FREE_AND_NULL(des);
8810 if (annot != NULL) {
8811 if (particle != NULL)
8812 particle->annot = NULL;
8813 if (decl != NULL)
8814 decl->annot = NULL;
8815 xmlSchemaFreeAnnot(annot);
8817 return (NULL);
8821 * xmlSchemaParseUnion:
8822 * @ctxt: a schema validation context
8823 * @schema: the schema being built
8824 * @node: a subtree containing XML Schema informations
8826 * parse a XML schema Union definition
8827 * *WARNING* this interface is highly subject to change
8829 * Returns -1 in case of internal error, 0 in case of success and a positive
8830 * error code otherwise.
8832 static int
8833 xmlSchemaParseUnion(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
8834 xmlNodePtr node)
8836 xmlSchemaTypePtr type;
8837 xmlNodePtr child = NULL;
8838 xmlAttrPtr attr;
8839 const xmlChar *cur = NULL;
8841 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8842 return (-1);
8843 /* Not a component, don't create it. */
8844 type = ctxt->ctxtType;
8846 * Mark the simple type as being of variety "union".
8848 type->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
8850 * SPEC (Base type) (2) "If the <list> or <union> alternative is chosen,
8851 * then the �simple ur-type definition�."
8853 type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
8855 * Check for illegal attributes.
8857 attr = node->properties;
8858 while (attr != NULL) {
8859 if (attr->ns == NULL) {
8860 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8861 (!xmlStrEqual(attr->name, BAD_CAST "memberTypes"))) {
8862 xmlSchemaPIllegalAttrErr(ctxt,
8863 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8865 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8866 xmlSchemaPIllegalAttrErr(ctxt,
8867 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8869 attr = attr->next;
8871 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
8873 * Attribute "memberTypes". This is a list of QNames.
8874 * TODO: Check the value to contain anything.
8876 attr = xmlSchemaGetPropNode(node, "memberTypes");
8877 if (attr != NULL) {
8878 const xmlChar *end;
8879 xmlChar *tmp;
8880 const xmlChar *localName, *nsName;
8881 xmlSchemaTypeLinkPtr link, lastLink = NULL;
8882 xmlSchemaQNameRefPtr ref;
8884 cur = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8885 type->base = cur;
8886 do {
8887 while (IS_BLANK_CH(*cur))
8888 cur++;
8889 end = cur;
8890 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
8891 end++;
8892 if (end == cur)
8893 break;
8894 tmp = xmlStrndup(cur, end - cur);
8895 if (xmlSchemaPValAttrNodeQNameValue(ctxt, schema,
8896 NULL, attr, BAD_CAST tmp, &nsName, &localName) == 0) {
8898 * Create the member type link.
8900 link = (xmlSchemaTypeLinkPtr)
8901 xmlMalloc(sizeof(xmlSchemaTypeLink));
8902 if (link == NULL) {
8903 xmlSchemaPErrMemory(ctxt, "xmlSchemaParseUnion, "
8904 "allocating a type link", NULL);
8905 return (-1);
8907 link->type = NULL;
8908 link->next = NULL;
8909 if (lastLink == NULL)
8910 type->memberTypes = link;
8911 else
8912 lastLink->next = link;
8913 lastLink = link;
8915 * Create a reference item.
8917 ref = xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_SIMPLE,
8918 localName, nsName);
8919 if (ref == NULL) {
8920 FREE_AND_NULL(tmp)
8921 return (-1);
8924 * Assign the reference to the link, it will be resolved
8925 * later during fixup of the union simple type.
8927 link->type = (xmlSchemaTypePtr) ref;
8929 FREE_AND_NULL(tmp)
8930 cur = end;
8931 } while (*cur != 0);
8935 * And now for the children...
8937 child = node->children;
8938 if (IS_SCHEMA(child, "annotation")) {
8940 * Add the annotation to the simple type ancestor.
8942 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
8943 xmlSchemaParseAnnotation(ctxt, child, 1));
8944 child = child->next;
8946 if (IS_SCHEMA(child, "simpleType")) {
8947 xmlSchemaTypePtr subtype, last = NULL;
8950 * Anchor the member types in the "subtypes" field of the
8951 * simple type.
8953 while (IS_SCHEMA(child, "simpleType")) {
8954 subtype = (xmlSchemaTypePtr)
8955 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
8956 if (subtype != NULL) {
8957 if (last == NULL) {
8958 type->subtypes = subtype;
8959 last = subtype;
8960 } else {
8961 last->next = subtype;
8962 last = subtype;
8964 last->next = NULL;
8966 child = child->next;
8969 if (child != NULL) {
8970 xmlSchemaPContentErr(ctxt,
8971 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8972 NULL, node, child, NULL, "(annotation?, simpleType*)");
8974 if ((attr == NULL) && (type->subtypes == NULL)) {
8976 * src-union-memberTypes-or-simpleTypes
8977 * Either the memberTypes [attribute] of the <union> element must
8978 * be non-empty or there must be at least one simpleType [child].
8980 xmlSchemaPCustomErr(ctxt,
8981 XML_SCHEMAP_SRC_UNION_MEMBERTYPES_OR_SIMPLETYPES,
8982 NULL, node,
8983 "Either the attribute 'memberTypes' or "
8984 "at least one <simpleType> child must be present", NULL);
8986 return (0);
8990 * xmlSchemaParseList:
8991 * @ctxt: a schema validation context
8992 * @schema: the schema being built
8993 * @node: a subtree containing XML Schema informations
8995 * parse a XML schema List definition
8996 * *WARNING* this interface is highly subject to change
8998 * Returns -1 in case of error, 0 if the declaration is improper and
8999 * 1 in case of success.
9001 static xmlSchemaTypePtr
9002 xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
9003 xmlNodePtr node)
9005 xmlSchemaTypePtr type;
9006 xmlNodePtr child = NULL;
9007 xmlAttrPtr attr;
9009 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9010 return (NULL);
9011 /* Not a component, don't create it. */
9012 type = ctxt->ctxtType;
9014 * Mark the type as being of variety "list".
9016 type->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
9018 * SPEC (Base type) (2) "If the <list> or <union> alternative is chosen,
9019 * then the �simple ur-type definition�."
9021 type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
9023 * Check for illegal attributes.
9025 attr = node->properties;
9026 while (attr != NULL) {
9027 if (attr->ns == NULL) {
9028 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9029 (!xmlStrEqual(attr->name, BAD_CAST "itemType"))) {
9030 xmlSchemaPIllegalAttrErr(ctxt,
9031 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9033 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9034 xmlSchemaPIllegalAttrErr(ctxt,
9035 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9037 attr = attr->next;
9040 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
9043 * Attribute "itemType". NOTE that we will use the "ref" and "refNs"
9044 * fields for holding the reference to the itemType.
9046 * REVAMP TODO: Use the "base" and "baseNs" fields, since we will remove
9047 * the "ref" fields.
9049 xmlSchemaPValAttrQName(ctxt, schema, NULL,
9050 node, "itemType", &(type->baseNs), &(type->base));
9052 * And now for the children...
9054 child = node->children;
9055 if (IS_SCHEMA(child, "annotation")) {
9056 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
9057 xmlSchemaParseAnnotation(ctxt, child, 1));
9058 child = child->next;
9060 if (IS_SCHEMA(child, "simpleType")) {
9062 * src-list-itemType-or-simpleType
9063 * Either the itemType [attribute] or the <simpleType> [child] of
9064 * the <list> element must be present, but not both.
9066 if (type->base != NULL) {
9067 xmlSchemaPCustomErr(ctxt,
9068 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
9069 NULL, node,
9070 "The attribute 'itemType' and the <simpleType> child "
9071 "are mutually exclusive", NULL);
9072 } else {
9073 type->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
9075 child = child->next;
9076 } else if (type->base == NULL) {
9077 xmlSchemaPCustomErr(ctxt,
9078 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
9079 NULL, node,
9080 "Either the attribute 'itemType' or the <simpleType> child "
9081 "must be present", NULL);
9083 if (child != NULL) {
9084 xmlSchemaPContentErr(ctxt,
9085 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9086 NULL, node, child, NULL, "(annotation?, simpleType?)");
9088 if ((type->base == NULL) &&
9089 (type->subtypes == NULL) &&
9090 (xmlSchemaGetPropNode(node, "itemType") == NULL)) {
9091 xmlSchemaPCustomErr(ctxt,
9092 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
9093 NULL, node,
9094 "Either the attribute 'itemType' or the <simpleType> child "
9095 "must be present", NULL);
9097 return (NULL);
9101 * xmlSchemaParseSimpleType:
9102 * @ctxt: a schema validation context
9103 * @schema: the schema being built
9104 * @node: a subtree containing XML Schema informations
9106 * parse a XML schema Simple Type definition
9107 * *WARNING* this interface is highly subject to change
9109 * Returns -1 in case of error, 0 if the declaration is improper and
9110 * 1 in case of success.
9112 static xmlSchemaTypePtr
9113 xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
9114 xmlNodePtr node, int topLevel)
9116 xmlSchemaTypePtr type, oldCtxtType;
9117 xmlNodePtr child = NULL;
9118 const xmlChar *attrValue = NULL;
9119 xmlAttrPtr attr;
9120 int hasRestriction = 0;
9122 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9123 return (NULL);
9125 if (topLevel) {
9126 attr = xmlSchemaGetPropNode(node, "name");
9127 if (attr == NULL) {
9128 xmlSchemaPMissingAttrErr(ctxt,
9129 XML_SCHEMAP_S4S_ATTR_MISSING,
9130 NULL, node,
9131 "name", NULL);
9132 return (NULL);
9133 } else {
9134 if (xmlSchemaPValAttrNode(ctxt,
9135 NULL, attr,
9136 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &attrValue) != 0)
9137 return (NULL);
9139 * Skip built-in types.
9141 if (ctxt->isS4S) {
9142 xmlSchemaTypePtr biType;
9144 if (ctxt->isRedefine) {
9146 * REDEFINE: Disallow redefinition of built-in-types.
9147 * TODO: It seems that the spec does not say anything
9148 * about this case.
9150 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_SRC_REDEFINE,
9151 NULL, node,
9152 "Redefinition of built-in simple types is not "
9153 "supported", NULL);
9154 return(NULL);
9156 biType = xmlSchemaGetPredefinedType(attrValue, xmlSchemaNs);
9157 if (biType != NULL)
9158 return (biType);
9163 * TargetNamespace:
9164 * SPEC "The �actual value� of the targetNamespace [attribute]
9165 * of the <schema> ancestor element information item if present,
9166 * otherwise �absent�.
9168 if (topLevel == 0) {
9169 #ifdef ENABLE_NAMED_LOCALS
9170 char buf[40];
9171 #endif
9173 * Parse as local simple type definition.
9175 #ifdef ENABLE_NAMED_LOCALS
9176 snprintf(buf, 39, "#ST%d", ctxt->counter++ + 1);
9177 type = xmlSchemaAddType(ctxt, schema,
9178 XML_SCHEMA_TYPE_SIMPLE,
9179 xmlDictLookup(ctxt->dict, (const xmlChar *)buf, -1),
9180 ctxt->targetNamespace, node, 0);
9181 #else
9182 type = xmlSchemaAddType(ctxt, schema,
9183 XML_SCHEMA_TYPE_SIMPLE,
9184 NULL, ctxt->targetNamespace, node, 0);
9185 #endif
9186 if (type == NULL)
9187 return (NULL);
9188 type->type = XML_SCHEMA_TYPE_SIMPLE;
9189 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
9191 * Check for illegal attributes.
9193 attr = node->properties;
9194 while (attr != NULL) {
9195 if (attr->ns == NULL) {
9196 if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
9197 xmlSchemaPIllegalAttrErr(ctxt,
9198 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9200 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9201 xmlSchemaPIllegalAttrErr(ctxt,
9202 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9204 attr = attr->next;
9206 } else {
9208 * Parse as global simple type definition.
9210 * Note that attrValue is the value of the attribute "name" here.
9212 type = xmlSchemaAddType(ctxt, schema, XML_SCHEMA_TYPE_SIMPLE,
9213 attrValue, ctxt->targetNamespace, node, 1);
9214 if (type == NULL)
9215 return (NULL);
9216 type->type = XML_SCHEMA_TYPE_SIMPLE;
9217 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
9218 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
9220 * Check for illegal attributes.
9222 attr = node->properties;
9223 while (attr != NULL) {
9224 if (attr->ns == NULL) {
9225 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9226 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
9227 (!xmlStrEqual(attr->name, BAD_CAST "final"))) {
9228 xmlSchemaPIllegalAttrErr(ctxt,
9229 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9231 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9232 xmlSchemaPIllegalAttrErr(ctxt,
9233 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9235 attr = attr->next;
9238 * Attribute "final".
9240 attr = xmlSchemaGetPropNode(node, "final");
9241 if (attr == NULL) {
9242 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
9243 type->flags |= XML_SCHEMAS_TYPE_FINAL_RESTRICTION;
9244 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST)
9245 type->flags |= XML_SCHEMAS_TYPE_FINAL_LIST;
9246 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION)
9247 type->flags |= XML_SCHEMAS_TYPE_FINAL_UNION;
9248 } else {
9249 attrValue = xmlSchemaGetProp(ctxt, node, "final");
9250 if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
9251 -1, -1, XML_SCHEMAS_TYPE_FINAL_RESTRICTION, -1,
9252 XML_SCHEMAS_TYPE_FINAL_LIST,
9253 XML_SCHEMAS_TYPE_FINAL_UNION) != 0) {
9255 xmlSchemaPSimpleTypeErr(ctxt,
9256 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
9257 WXS_BASIC_CAST type, (xmlNodePtr) attr,
9258 NULL, "(#all | List of (list | union | restriction)",
9259 attrValue, NULL, NULL, NULL);
9263 type->targetNamespace = ctxt->targetNamespace;
9264 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
9266 * And now for the children...
9268 oldCtxtType = ctxt->ctxtType;
9270 ctxt->ctxtType = type;
9272 child = node->children;
9273 if (IS_SCHEMA(child, "annotation")) {
9274 type->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
9275 child = child->next;
9277 if (child == NULL) {
9278 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_MISSING,
9279 NULL, node, child, NULL,
9280 "(annotation?, (restriction | list | union))");
9281 } else if (IS_SCHEMA(child, "restriction")) {
9282 xmlSchemaParseRestriction(ctxt, schema, child,
9283 XML_SCHEMA_TYPE_SIMPLE);
9284 hasRestriction = 1;
9285 child = child->next;
9286 } else if (IS_SCHEMA(child, "list")) {
9287 xmlSchemaParseList(ctxt, schema, child);
9288 child = child->next;
9289 } else if (IS_SCHEMA(child, "union")) {
9290 xmlSchemaParseUnion(ctxt, schema, child);
9291 child = child->next;
9293 if (child != NULL) {
9294 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9295 NULL, node, child, NULL,
9296 "(annotation?, (restriction | list | union))");
9299 * REDEFINE: SPEC src-redefine (5)
9300 * "Within the [children], each <simpleType> must have a
9301 * <restriction> among its [children] ... the �actual value� of whose
9302 * base [attribute] must be the same as the �actual value� of its own
9303 * name attribute plus target namespace;"
9305 if (topLevel && ctxt->isRedefine && (! hasRestriction)) {
9306 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_SRC_REDEFINE,
9307 NULL, node, "This is a redefinition, thus the "
9308 "<simpleType> must have a <restriction> child", NULL);
9311 ctxt->ctxtType = oldCtxtType;
9312 return (type);
9316 * xmlSchemaParseModelGroupDefRef:
9317 * @ctxt: the parser context
9318 * @schema: the schema being built
9319 * @node: the node
9321 * Parses a reference to a model group definition.
9323 * We will return a particle component with a qname-component or
9324 * NULL in case of an error.
9326 static xmlSchemaTreeItemPtr
9327 xmlSchemaParseModelGroupDefRef(xmlSchemaParserCtxtPtr ctxt,
9328 xmlSchemaPtr schema,
9329 xmlNodePtr node)
9331 xmlSchemaParticlePtr item;
9332 xmlNodePtr child = NULL;
9333 xmlAttrPtr attr;
9334 const xmlChar *ref = NULL, *refNs = NULL;
9335 int min, max;
9337 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9338 return (NULL);
9340 attr = xmlSchemaGetPropNode(node, "ref");
9341 if (attr == NULL) {
9342 xmlSchemaPMissingAttrErr(ctxt,
9343 XML_SCHEMAP_S4S_ATTR_MISSING,
9344 NULL, node, "ref", NULL);
9345 return (NULL);
9346 } else if (xmlSchemaPValAttrNodeQName(ctxt, schema, NULL,
9347 attr, &refNs, &ref) != 0) {
9348 return (NULL);
9350 xmlSchemaCheckReference(ctxt, schema, node, attr, refNs);
9351 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
9352 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
9353 "(xs:nonNegativeInteger | unbounded)");
9355 * Check for illegal attributes.
9357 attr = node->properties;
9358 while (attr != NULL) {
9359 if (attr->ns == NULL) {
9360 if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
9361 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9362 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
9363 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs"))) {
9364 xmlSchemaPIllegalAttrErr(ctxt,
9365 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9367 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9368 xmlSchemaPIllegalAttrErr(ctxt,
9369 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9371 attr = attr->next;
9373 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
9374 item = xmlSchemaAddParticle(ctxt, node, min, max);
9375 if (item == NULL)
9376 return (NULL);
9378 * Create a qname-reference and set as the term; it will be substituted
9379 * for the model group after the reference has been resolved.
9381 item->children = (xmlSchemaTreeItemPtr)
9382 xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_GROUP, ref, refNs);
9383 xmlSchemaPCheckParticleCorrect_2(ctxt, item, node, min, max);
9385 * And now for the children...
9387 child = node->children;
9388 /* TODO: Is annotation even allowed for a model group reference? */
9389 if (IS_SCHEMA(child, "annotation")) {
9391 * TODO: What to do exactly with the annotation?
9393 item->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
9394 child = child->next;
9396 if (child != NULL) {
9397 xmlSchemaPContentErr(ctxt,
9398 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9399 NULL, node, child, NULL,
9400 "(annotation?)");
9403 * Corresponds to no component at all if minOccurs==maxOccurs==0.
9405 if ((min == 0) && (max == 0))
9406 return (NULL);
9408 return ((xmlSchemaTreeItemPtr) item);
9412 * xmlSchemaParseModelGroupDefinition:
9413 * @ctxt: a schema validation context
9414 * @schema: the schema being built
9415 * @node: a subtree containing XML Schema informations
9417 * Parses a XML schema model group definition.
9419 * Note that the contraint src-redefine (6.2) can't be applied until
9420 * references have been resolved. So we will do this at the
9421 * component fixup level.
9423 * *WARNING* this interface is highly subject to change
9425 * Returns -1 in case of error, 0 if the declaration is improper and
9426 * 1 in case of success.
9428 static xmlSchemaModelGroupDefPtr
9429 xmlSchemaParseModelGroupDefinition(xmlSchemaParserCtxtPtr ctxt,
9430 xmlSchemaPtr schema,
9431 xmlNodePtr node)
9433 xmlSchemaModelGroupDefPtr item;
9434 xmlNodePtr child = NULL;
9435 xmlAttrPtr attr;
9436 const xmlChar *name;
9438 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9439 return (NULL);
9441 attr = xmlSchemaGetPropNode(node, "name");
9442 if (attr == NULL) {
9443 xmlSchemaPMissingAttrErr(ctxt,
9444 XML_SCHEMAP_S4S_ATTR_MISSING,
9445 NULL, node,
9446 "name", NULL);
9447 return (NULL);
9448 } else if (xmlSchemaPValAttrNode(ctxt, NULL, attr,
9449 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
9450 return (NULL);
9452 item = xmlSchemaAddModelGroupDefinition(ctxt, schema, name,
9453 ctxt->targetNamespace, node);
9454 if (item == NULL)
9455 return (NULL);
9457 * Check for illegal attributes.
9459 attr = node->properties;
9460 while (attr != NULL) {
9461 if (attr->ns == NULL) {
9462 if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
9463 (!xmlStrEqual(attr->name, BAD_CAST "id"))) {
9464 xmlSchemaPIllegalAttrErr(ctxt,
9465 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9467 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9468 xmlSchemaPIllegalAttrErr(ctxt,
9469 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9471 attr = attr->next;
9473 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
9475 * And now for the children...
9477 child = node->children;
9478 if (IS_SCHEMA(child, "annotation")) {
9479 item->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
9480 child = child->next;
9482 if (IS_SCHEMA(child, "all")) {
9483 item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
9484 XML_SCHEMA_TYPE_ALL, 0);
9485 child = child->next;
9486 } else if (IS_SCHEMA(child, "choice")) {
9487 item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
9488 XML_SCHEMA_TYPE_CHOICE, 0);
9489 child = child->next;
9490 } else if (IS_SCHEMA(child, "sequence")) {
9491 item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
9492 XML_SCHEMA_TYPE_SEQUENCE, 0);
9493 child = child->next;
9498 if (child != NULL) {
9499 xmlSchemaPContentErr(ctxt,
9500 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9501 NULL, node, child, NULL,
9502 "(annotation?, (all | choice | sequence)?)");
9504 return (item);
9508 * xmlSchemaCleanupDoc:
9509 * @ctxt: a schema validation context
9510 * @node: the root of the document.
9512 * removes unwanted nodes in a schemas document tree
9514 static void
9515 xmlSchemaCleanupDoc(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr root)
9517 xmlNodePtr delete, cur;
9519 if ((ctxt == NULL) || (root == NULL)) return;
9522 * Remove all the blank text nodes
9524 delete = NULL;
9525 cur = root;
9526 while (cur != NULL) {
9527 if (delete != NULL) {
9528 xmlUnlinkNode(delete);
9529 xmlFreeNode(delete);
9530 delete = NULL;
9532 if (cur->type == XML_TEXT_NODE) {
9533 if (IS_BLANK_NODE(cur)) {
9534 if (xmlNodeGetSpacePreserve(cur) != 1) {
9535 delete = cur;
9538 } else if ((cur->type != XML_ELEMENT_NODE) &&
9539 (cur->type != XML_CDATA_SECTION_NODE)) {
9540 delete = cur;
9541 goto skip_children;
9545 * Skip to next node
9547 if (cur->children != NULL) {
9548 if ((cur->children->type != XML_ENTITY_DECL) &&
9549 (cur->children->type != XML_ENTITY_REF_NODE) &&
9550 (cur->children->type != XML_ENTITY_NODE)) {
9551 cur = cur->children;
9552 continue;
9555 skip_children:
9556 if (cur->next != NULL) {
9557 cur = cur->next;
9558 continue;
9561 do {
9562 cur = cur->parent;
9563 if (cur == NULL)
9564 break;
9565 if (cur == root) {
9566 cur = NULL;
9567 break;
9569 if (cur->next != NULL) {
9570 cur = cur->next;
9571 break;
9573 } while (cur != NULL);
9575 if (delete != NULL) {
9576 xmlUnlinkNode(delete);
9577 xmlFreeNode(delete);
9578 delete = NULL;
9583 static void
9584 xmlSchemaClearSchemaDefaults(xmlSchemaPtr schema)
9586 if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
9587 schema->flags ^= XML_SCHEMAS_QUALIF_ELEM;
9589 if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
9590 schema->flags ^= XML_SCHEMAS_QUALIF_ATTR;
9592 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
9593 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_EXTENSION;
9594 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
9595 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION;
9596 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST)
9597 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_LIST;
9598 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION)
9599 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_UNION;
9601 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
9602 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION;
9603 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
9604 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION;
9605 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
9606 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION;
9609 static int
9610 xmlSchemaParseSchemaElement(xmlSchemaParserCtxtPtr ctxt,
9611 xmlSchemaPtr schema,
9612 xmlNodePtr node)
9614 xmlAttrPtr attr;
9615 const xmlChar *val;
9616 int res = 0, oldErrs = ctxt->nberrors;
9619 * Those flags should be moved to the parser context flags,
9620 * since they are not visible at the component level. I.e.
9621 * they are used if processing schema *documents* only.
9623 res = xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
9624 HFAILURE;
9627 * Since the version is of type xs:token, we won't bother to
9628 * check it.
9630 /* REMOVED:
9631 attr = xmlSchemaGetPropNode(node, "version");
9632 if (attr != NULL) {
9633 res = xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
9634 xmlSchemaGetBuiltInType(XML_SCHEMAS_TOKEN), &val);
9635 HFAILURE;
9638 attr = xmlSchemaGetPropNode(node, "targetNamespace");
9639 if (attr != NULL) {
9640 res = xmlSchemaPValAttrNode(ctxt, NULL, attr,
9641 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), NULL);
9642 HFAILURE;
9643 if (res != 0) {
9644 ctxt->stop = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
9645 goto exit;
9648 attr = xmlSchemaGetPropNode(node, "elementFormDefault");
9649 if (attr != NULL) {
9650 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
9651 res = xmlSchemaPValAttrFormDefault(val, &schema->flags,
9652 XML_SCHEMAS_QUALIF_ELEM);
9653 HFAILURE;
9654 if (res != 0) {
9655 xmlSchemaPSimpleTypeErr(ctxt,
9656 XML_SCHEMAP_ELEMFORMDEFAULT_VALUE,
9657 NULL, (xmlNodePtr) attr, NULL,
9658 "(qualified | unqualified)", val, NULL, NULL, NULL);
9661 attr = xmlSchemaGetPropNode(node, "attributeFormDefault");
9662 if (attr != NULL) {
9663 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
9664 res = xmlSchemaPValAttrFormDefault(val, &schema->flags,
9665 XML_SCHEMAS_QUALIF_ATTR);
9666 HFAILURE;
9667 if (res != 0) {
9668 xmlSchemaPSimpleTypeErr(ctxt,
9669 XML_SCHEMAP_ATTRFORMDEFAULT_VALUE,
9670 NULL, (xmlNodePtr) attr, NULL,
9671 "(qualified | unqualified)", val, NULL, NULL, NULL);
9674 attr = xmlSchemaGetPropNode(node, "finalDefault");
9675 if (attr != NULL) {
9676 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
9677 res = xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
9678 XML_SCHEMAS_FINAL_DEFAULT_EXTENSION,
9679 XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION,
9681 XML_SCHEMAS_FINAL_DEFAULT_LIST,
9682 XML_SCHEMAS_FINAL_DEFAULT_UNION);
9683 HFAILURE;
9684 if (res != 0) {
9685 xmlSchemaPSimpleTypeErr(ctxt,
9686 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
9687 NULL, (xmlNodePtr) attr, NULL,
9688 "(#all | List of (extension | restriction | list | union))",
9689 val, NULL, NULL, NULL);
9692 attr = xmlSchemaGetPropNode(node, "blockDefault");
9693 if (attr != NULL) {
9694 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
9695 res = xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
9696 XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION,
9697 XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION,
9698 XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION, -1, -1);
9699 HFAILURE;
9700 if (res != 0) {
9701 xmlSchemaPSimpleTypeErr(ctxt,
9702 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
9703 NULL, (xmlNodePtr) attr, NULL,
9704 "(#all | List of (extension | restriction | substitution))",
9705 val, NULL, NULL, NULL);
9709 exit:
9710 if (oldErrs != ctxt->nberrors)
9711 res = ctxt->err;
9712 return(res);
9713 exit_failure:
9714 return(-1);
9718 * xmlSchemaParseSchemaTopLevel:
9719 * @ctxt: a schema validation context
9720 * @schema: the schemas
9721 * @nodes: the list of top level nodes
9723 * Returns the internal XML Schema structure built from the resource or
9724 * NULL in case of error
9726 static int
9727 xmlSchemaParseSchemaTopLevel(xmlSchemaParserCtxtPtr ctxt,
9728 xmlSchemaPtr schema, xmlNodePtr nodes)
9730 xmlNodePtr child;
9731 xmlSchemaAnnotPtr annot;
9732 int res = 0, oldErrs, tmpOldErrs;
9734 if ((ctxt == NULL) || (schema == NULL) || (nodes == NULL))
9735 return(-1);
9737 oldErrs = ctxt->nberrors;
9738 child = nodes;
9739 while ((IS_SCHEMA(child, "include")) ||
9740 (IS_SCHEMA(child, "import")) ||
9741 (IS_SCHEMA(child, "redefine")) ||
9742 (IS_SCHEMA(child, "annotation"))) {
9743 if (IS_SCHEMA(child, "annotation")) {
9744 annot = xmlSchemaParseAnnotation(ctxt, child, 1);
9745 if (schema->annot == NULL)
9746 schema->annot = annot;
9747 else
9748 xmlSchemaFreeAnnot(annot);
9749 } else if (IS_SCHEMA(child, "import")) {
9750 tmpOldErrs = ctxt->nberrors;
9751 res = xmlSchemaParseImport(ctxt, schema, child);
9752 HFAILURE;
9753 HSTOP(ctxt);
9754 if (tmpOldErrs != ctxt->nberrors)
9755 goto exit;
9756 } else if (IS_SCHEMA(child, "include")) {
9757 tmpOldErrs = ctxt->nberrors;
9758 res = xmlSchemaParseInclude(ctxt, schema, child);
9759 HFAILURE;
9760 HSTOP(ctxt);
9761 if (tmpOldErrs != ctxt->nberrors)
9762 goto exit;
9763 } else if (IS_SCHEMA(child, "redefine")) {
9764 tmpOldErrs = ctxt->nberrors;
9765 res = xmlSchemaParseRedefine(ctxt, schema, child);
9766 HFAILURE;
9767 HSTOP(ctxt);
9768 if (tmpOldErrs != ctxt->nberrors)
9769 goto exit;
9771 child = child->next;
9774 * URGENT TODO: Change the functions to return int results.
9775 * We need especially to catch internal errors.
9777 while (child != NULL) {
9778 if (IS_SCHEMA(child, "complexType")) {
9779 xmlSchemaParseComplexType(ctxt, schema, child, 1);
9780 child = child->next;
9781 } else if (IS_SCHEMA(child, "simpleType")) {
9782 xmlSchemaParseSimpleType(ctxt, schema, child, 1);
9783 child = child->next;
9784 } else if (IS_SCHEMA(child, "element")) {
9785 xmlSchemaParseElement(ctxt, schema, child, NULL, 1);
9786 child = child->next;
9787 } else if (IS_SCHEMA(child, "attribute")) {
9788 xmlSchemaParseGlobalAttribute(ctxt, schema, child);
9789 child = child->next;
9790 } else if (IS_SCHEMA(child, "attributeGroup")) {
9791 xmlSchemaParseAttributeGroupDefinition(ctxt, schema, child);
9792 child = child->next;
9793 } else if (IS_SCHEMA(child, "group")) {
9794 xmlSchemaParseModelGroupDefinition(ctxt, schema, child);
9795 child = child->next;
9796 } else if (IS_SCHEMA(child, "notation")) {
9797 xmlSchemaParseNotation(ctxt, schema, child);
9798 child = child->next;
9799 } else {
9800 xmlSchemaPContentErr(ctxt,
9801 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9802 NULL, child->parent, child,
9803 NULL, "((include | import | redefine | annotation)*, "
9804 "(((simpleType | complexType | group | attributeGroup) "
9805 "| element | attribute | notation), annotation*)*)");
9806 child = child->next;
9808 while (IS_SCHEMA(child, "annotation")) {
9810 * TODO: We should add all annotations.
9812 annot = xmlSchemaParseAnnotation(ctxt, child, 1);
9813 if (schema->annot == NULL)
9814 schema->annot = annot;
9815 else
9816 xmlSchemaFreeAnnot(annot);
9817 child = child->next;
9820 exit:
9821 ctxt->ctxtType = NULL;
9822 if (oldErrs != ctxt->nberrors)
9823 res = ctxt->err;
9824 return(res);
9825 exit_failure:
9826 return(-1);
9829 static xmlSchemaSchemaRelationPtr
9830 xmlSchemaSchemaRelationCreate(void)
9832 xmlSchemaSchemaRelationPtr ret;
9834 ret = (xmlSchemaSchemaRelationPtr)
9835 xmlMalloc(sizeof(xmlSchemaSchemaRelation));
9836 if (ret == NULL) {
9837 xmlSchemaPErrMemory(NULL, "allocating schema relation", NULL);
9838 return(NULL);
9840 memset(ret, 0, sizeof(xmlSchemaSchemaRelation));
9841 return(ret);
9844 #if 0
9845 static void
9846 xmlSchemaSchemaRelationFree(xmlSchemaSchemaRelationPtr rel)
9848 xmlFree(rel);
9850 #endif
9852 static void
9853 xmlSchemaRedefListFree(xmlSchemaRedefPtr redef)
9855 xmlSchemaRedefPtr prev;
9857 while (redef != NULL) {
9858 prev = redef;
9859 redef = redef->next;
9860 xmlFree(prev);
9864 static void
9865 xmlSchemaConstructionCtxtFree(xmlSchemaConstructionCtxtPtr con)
9868 * After the construction context has been freed, there will be
9869 * no schema graph available any more. Only the schema buckets
9870 * will stay alive, which are put into the "schemasImports" and
9871 * "includes" slots of the xmlSchema.
9873 if (con->buckets != NULL)
9874 xmlSchemaItemListFree(con->buckets);
9875 if (con->pending != NULL)
9876 xmlSchemaItemListFree(con->pending);
9877 if (con->substGroups != NULL)
9878 xmlHashFree(con->substGroups,
9879 (xmlHashDeallocator) xmlSchemaSubstGroupFree);
9880 if (con->redefs != NULL)
9881 xmlSchemaRedefListFree(con->redefs);
9882 if (con->dict != NULL)
9883 xmlDictFree(con->dict);
9884 xmlFree(con);
9887 static xmlSchemaConstructionCtxtPtr
9888 xmlSchemaConstructionCtxtCreate(xmlDictPtr dict)
9890 xmlSchemaConstructionCtxtPtr ret;
9892 ret = (xmlSchemaConstructionCtxtPtr)
9893 xmlMalloc(sizeof(xmlSchemaConstructionCtxt));
9894 if (ret == NULL) {
9895 xmlSchemaPErrMemory(NULL,
9896 "allocating schema construction context", NULL);
9897 return (NULL);
9899 memset(ret, 0, sizeof(xmlSchemaConstructionCtxt));
9901 ret->buckets = xmlSchemaItemListCreate();
9902 if (ret->buckets == NULL) {
9903 xmlSchemaPErrMemory(NULL,
9904 "allocating list of schema buckets", NULL);
9905 xmlFree(ret);
9906 return (NULL);
9908 ret->pending = xmlSchemaItemListCreate();
9909 if (ret->pending == NULL) {
9910 xmlSchemaPErrMemory(NULL,
9911 "allocating list of pending global components", NULL);
9912 xmlSchemaConstructionCtxtFree(ret);
9913 return (NULL);
9915 ret->dict = dict;
9916 xmlDictReference(dict);
9917 return(ret);
9920 static xmlSchemaParserCtxtPtr
9921 xmlSchemaParserCtxtCreate(void)
9923 xmlSchemaParserCtxtPtr ret;
9925 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
9926 if (ret == NULL) {
9927 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
9928 NULL);
9929 return (NULL);
9931 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
9932 ret->type = XML_SCHEMA_CTXT_PARSER;
9933 ret->attrProhibs = xmlSchemaItemListCreate();
9934 if (ret->attrProhibs == NULL) {
9935 xmlFree(ret);
9936 return(NULL);
9938 return(ret);
9942 * xmlSchemaNewParserCtxtUseDict:
9943 * @URL: the location of the schema
9944 * @dict: the dictionary to be used
9946 * Create an XML Schemas parse context for that file/resource expected
9947 * to contain an XML Schemas file.
9949 * Returns the parser context or NULL in case of error
9951 static xmlSchemaParserCtxtPtr
9952 xmlSchemaNewParserCtxtUseDict(const char *URL, xmlDictPtr dict)
9954 xmlSchemaParserCtxtPtr ret;
9956 ret = xmlSchemaParserCtxtCreate();
9957 if (ret == NULL)
9958 return (NULL);
9959 ret->dict = dict;
9960 xmlDictReference(dict);
9961 if (URL != NULL)
9962 ret->URL = xmlDictLookup(dict, (const xmlChar *) URL, -1);
9963 return (ret);
9966 static int
9967 xmlSchemaCreatePCtxtOnVCtxt(xmlSchemaValidCtxtPtr vctxt)
9969 if (vctxt->pctxt == NULL) {
9970 if (vctxt->schema != NULL)
9971 vctxt->pctxt =
9972 xmlSchemaNewParserCtxtUseDict("*", vctxt->schema->dict);
9973 else
9974 vctxt->pctxt = xmlSchemaNewParserCtxt("*");
9975 if (vctxt->pctxt == NULL) {
9976 VERROR_INT("xmlSchemaCreatePCtxtOnVCtxt",
9977 "failed to create a temp. parser context");
9978 return (-1);
9980 /* TODO: Pass user data. */
9981 xmlSchemaSetParserErrors(vctxt->pctxt, vctxt->error,
9982 vctxt->warning, vctxt->errCtxt);
9983 xmlSchemaSetParserStructuredErrors(vctxt->pctxt, vctxt->serror,
9984 vctxt->errCtxt);
9986 return (0);
9990 * xmlSchemaGetSchemaBucket:
9991 * @pctxt: the schema parser context
9992 * @schemaLocation: the URI of the schema document
9994 * Returns a schema bucket if it was already parsed.
9996 * Returns a schema bucket if it was already parsed from
9997 * @schemaLocation, NULL otherwise.
9999 static xmlSchemaBucketPtr
10000 xmlSchemaGetSchemaBucket(xmlSchemaParserCtxtPtr pctxt,
10001 const xmlChar *schemaLocation)
10003 xmlSchemaBucketPtr cur;
10004 xmlSchemaItemListPtr list;
10006 list = pctxt->constructor->buckets;
10007 if (list->nbItems == 0)
10008 return(NULL);
10009 else {
10010 int i;
10011 for (i = 0; i < list->nbItems; i++) {
10012 cur = (xmlSchemaBucketPtr) list->items[i];
10013 /* Pointer comparison! */
10014 if (cur->schemaLocation == schemaLocation)
10015 return(cur);
10018 return(NULL);
10021 static xmlSchemaBucketPtr
10022 xmlSchemaGetChameleonSchemaBucket(xmlSchemaParserCtxtPtr pctxt,
10023 const xmlChar *schemaLocation,
10024 const xmlChar *targetNamespace)
10026 xmlSchemaBucketPtr cur;
10027 xmlSchemaItemListPtr list;
10029 list = pctxt->constructor->buckets;
10030 if (list->nbItems == 0)
10031 return(NULL);
10032 else {
10033 int i;
10034 for (i = 0; i < list->nbItems; i++) {
10035 cur = (xmlSchemaBucketPtr) list->items[i];
10036 /* Pointer comparison! */
10037 if ((cur->origTargetNamespace == NULL) &&
10038 (cur->schemaLocation == schemaLocation) &&
10039 (cur->targetNamespace == targetNamespace))
10040 return(cur);
10043 return(NULL);
10047 #define IS_BAD_SCHEMA_DOC(b) \
10048 (((b)->doc == NULL) && ((b)->schemaLocation != NULL))
10050 static xmlSchemaBucketPtr
10051 xmlSchemaGetSchemaBucketByTNS(xmlSchemaParserCtxtPtr pctxt,
10052 const xmlChar *targetNamespace,
10053 int imported)
10055 xmlSchemaBucketPtr cur;
10056 xmlSchemaItemListPtr list;
10058 list = pctxt->constructor->buckets;
10059 if (list->nbItems == 0)
10060 return(NULL);
10061 else {
10062 int i;
10063 for (i = 0; i < list->nbItems; i++) {
10064 cur = (xmlSchemaBucketPtr) list->items[i];
10065 if ((! IS_BAD_SCHEMA_DOC(cur)) &&
10066 (cur->origTargetNamespace == targetNamespace) &&
10067 ((imported && cur->imported) ||
10068 ((!imported) && (!cur->imported))))
10069 return(cur);
10072 return(NULL);
10075 static int
10076 xmlSchemaParseNewDocWithContext(xmlSchemaParserCtxtPtr pctxt,
10077 xmlSchemaPtr schema,
10078 xmlSchemaBucketPtr bucket)
10080 int oldFlags;
10081 xmlDocPtr oldDoc;
10082 xmlNodePtr node;
10083 int ret, oldErrs;
10084 xmlSchemaBucketPtr oldbucket = pctxt->constructor->bucket;
10087 * Save old values; reset the *main* schema.
10088 * URGENT TODO: This is not good; move the per-document information
10089 * to the parser. Get rid of passing the main schema to the
10090 * parsing functions.
10092 oldFlags = schema->flags;
10093 oldDoc = schema->doc;
10094 if (schema->flags != 0)
10095 xmlSchemaClearSchemaDefaults(schema);
10096 schema->doc = bucket->doc;
10097 pctxt->schema = schema;
10099 * Keep the current target namespace on the parser *not* on the
10100 * main schema.
10102 pctxt->targetNamespace = bucket->targetNamespace;
10103 WXS_CONSTRUCTOR(pctxt)->bucket = bucket;
10105 if ((bucket->targetNamespace != NULL) &&
10106 xmlStrEqual(bucket->targetNamespace, xmlSchemaNs)) {
10108 * We are parsing the schema for schemas!
10110 pctxt->isS4S = 1;
10112 /* Mark it as parsed, even if parsing fails. */
10113 bucket->parsed++;
10114 /* Compile the schema doc. */
10115 node = xmlDocGetRootElement(bucket->doc);
10116 ret = xmlSchemaParseSchemaElement(pctxt, schema, node);
10117 if (ret != 0)
10118 goto exit;
10119 /* An empty schema; just get out. */
10120 if (node->children == NULL)
10121 goto exit;
10122 oldErrs = pctxt->nberrors;
10123 ret = xmlSchemaParseSchemaTopLevel(pctxt, schema, node->children);
10124 if (ret != 0)
10125 goto exit;
10127 * TODO: Not nice, but I'm not 100% sure we will get always an error
10128 * as a result of the obove functions; so better rely on pctxt->err
10129 * as well.
10131 if ((ret == 0) && (oldErrs != pctxt->nberrors)) {
10132 ret = pctxt->err;
10133 goto exit;
10136 exit:
10137 WXS_CONSTRUCTOR(pctxt)->bucket = oldbucket;
10138 /* Restore schema values. */
10139 schema->doc = oldDoc;
10140 schema->flags = oldFlags;
10141 return(ret);
10144 static int
10145 xmlSchemaParseNewDoc(xmlSchemaParserCtxtPtr pctxt,
10146 xmlSchemaPtr schema,
10147 xmlSchemaBucketPtr bucket)
10149 xmlSchemaParserCtxtPtr newpctxt;
10150 int res = 0;
10152 if (bucket == NULL)
10153 return(0);
10154 if (bucket->parsed) {
10155 PERROR_INT("xmlSchemaParseNewDoc",
10156 "reparsing a schema doc");
10157 return(-1);
10159 if (bucket->doc == NULL) {
10160 PERROR_INT("xmlSchemaParseNewDoc",
10161 "parsing a schema doc, but there's no doc");
10162 return(-1);
10164 if (pctxt->constructor == NULL) {
10165 PERROR_INT("xmlSchemaParseNewDoc",
10166 "no constructor");
10167 return(-1);
10169 /* Create and init the temporary parser context. */
10170 newpctxt = xmlSchemaNewParserCtxtUseDict(
10171 (const char *) bucket->schemaLocation, pctxt->dict);
10172 if (newpctxt == NULL)
10173 return(-1);
10174 newpctxt->constructor = pctxt->constructor;
10176 * TODO: Can we avoid that the parser knows about the main schema?
10177 * It would be better if he knows about the current schema bucket
10178 * only.
10180 newpctxt->schema = schema;
10181 xmlSchemaSetParserErrors(newpctxt, pctxt->error, pctxt->warning,
10182 pctxt->errCtxt);
10183 xmlSchemaSetParserStructuredErrors(newpctxt, pctxt->serror,
10184 pctxt->errCtxt);
10185 newpctxt->counter = pctxt->counter;
10188 res = xmlSchemaParseNewDocWithContext(newpctxt, schema, bucket);
10190 /* Channel back errors and cleanup the temporary parser context. */
10191 if (res != 0)
10192 pctxt->err = res;
10193 pctxt->nberrors += newpctxt->nberrors;
10194 pctxt->counter = newpctxt->counter;
10195 newpctxt->constructor = NULL;
10196 /* Free the parser context. */
10197 xmlSchemaFreeParserCtxt(newpctxt);
10198 return(res);
10201 static void
10202 xmlSchemaSchemaRelationAddChild(xmlSchemaBucketPtr bucket,
10203 xmlSchemaSchemaRelationPtr rel)
10205 xmlSchemaSchemaRelationPtr cur = bucket->relations;
10207 if (cur == NULL) {
10208 bucket->relations = rel;
10209 return;
10211 while (cur->next != NULL)
10212 cur = cur->next;
10213 cur->next = rel;
10217 static const xmlChar *
10218 xmlSchemaBuildAbsoluteURI(xmlDictPtr dict, const xmlChar* location,
10219 xmlNodePtr ctxtNode)
10222 * Build an absolue location URI.
10224 if (location != NULL) {
10225 if (ctxtNode == NULL)
10226 return(location);
10227 else {
10228 xmlChar *base, *URI;
10229 const xmlChar *ret = NULL;
10231 base = xmlNodeGetBase(ctxtNode->doc, ctxtNode);
10232 if (base == NULL) {
10233 URI = xmlBuildURI(location, ctxtNode->doc->URL);
10234 } else {
10235 URI = xmlBuildURI(location, base);
10236 xmlFree(base);
10238 if (URI != NULL) {
10239 ret = xmlDictLookup(dict, URI, -1);
10240 xmlFree(URI);
10241 return(ret);
10245 return(NULL);
10251 * xmlSchemaAddSchemaDoc:
10252 * @pctxt: a schema validation context
10253 * @schema: the schema being built
10254 * @node: a subtree containing XML Schema informations
10256 * Parse an included (and to-be-redefined) XML schema document.
10258 * Returns 0 on success, a positive error code on errors and
10259 * -1 in case of an internal or API error.
10262 static int
10263 xmlSchemaAddSchemaDoc(xmlSchemaParserCtxtPtr pctxt,
10264 int type, /* import or include or redefine */
10265 const xmlChar *schemaLocation,
10266 xmlDocPtr schemaDoc,
10267 const char *schemaBuffer,
10268 int schemaBufferLen,
10269 xmlNodePtr invokingNode,
10270 const xmlChar *sourceTargetNamespace,
10271 const xmlChar *importNamespace,
10272 xmlSchemaBucketPtr *bucket)
10274 const xmlChar *targetNamespace = NULL;
10275 xmlSchemaSchemaRelationPtr relation = NULL;
10276 xmlDocPtr doc = NULL;
10277 int res = 0, err = 0, located = 0, preserveDoc = 0;
10278 xmlSchemaBucketPtr bkt = NULL;
10280 if (bucket != NULL)
10281 *bucket = NULL;
10283 switch (type) {
10284 case XML_SCHEMA_SCHEMA_IMPORT:
10285 case XML_SCHEMA_SCHEMA_MAIN:
10286 err = XML_SCHEMAP_SRC_IMPORT;
10287 break;
10288 case XML_SCHEMA_SCHEMA_INCLUDE:
10289 err = XML_SCHEMAP_SRC_INCLUDE;
10290 break;
10291 case XML_SCHEMA_SCHEMA_REDEFINE:
10292 err = XML_SCHEMAP_SRC_REDEFINE;
10293 break;
10297 /* Special handling for the main schema:
10298 * skip the location and relation logic and just parse the doc.
10299 * We need just a bucket to be returned in this case.
10301 if ((type == XML_SCHEMA_SCHEMA_MAIN) || (! WXS_HAS_BUCKETS(pctxt)))
10302 goto doc_load;
10304 /* Note that we expect the location to be an absulute URI. */
10305 if (schemaLocation != NULL) {
10306 bkt = xmlSchemaGetSchemaBucket(pctxt, schemaLocation);
10307 if ((bkt != NULL) &&
10308 (pctxt->constructor->bucket == bkt)) {
10309 /* Report self-imports/inclusions/redefinitions. */
10311 xmlSchemaCustomErr(ACTXT_CAST pctxt, err,
10312 invokingNode, NULL,
10313 "The schema must not import/include/redefine itself",
10314 NULL, NULL);
10315 goto exit;
10319 * Create a relation for the graph of schemas.
10321 relation = xmlSchemaSchemaRelationCreate();
10322 if (relation == NULL)
10323 return(-1);
10324 xmlSchemaSchemaRelationAddChild(pctxt->constructor->bucket,
10325 relation);
10326 relation->type = type;
10329 * Save the namespace import information.
10331 if (WXS_IS_BUCKET_IMPMAIN(type)) {
10332 relation->importNamespace = importNamespace;
10333 if (schemaLocation == NULL) {
10335 * No location; this is just an import of the namespace.
10336 * Note that we don't assign a bucket to the relation
10337 * in this case.
10339 goto exit;
10341 targetNamespace = importNamespace;
10344 /* Did we already fetch the doc? */
10345 if (bkt != NULL) {
10346 if ((WXS_IS_BUCKET_IMPMAIN(type)) && (! bkt->imported)) {
10348 * We included/redefined and then try to import a schema,
10349 * but the new location provided for import was different.
10351 if (schemaLocation == NULL)
10352 schemaLocation = BAD_CAST "in_memory_buffer";
10353 if (!xmlStrEqual(schemaLocation,
10354 bkt->schemaLocation)) {
10355 xmlSchemaCustomErr(ACTXT_CAST pctxt, err,
10356 invokingNode, NULL,
10357 "The schema document '%s' cannot be imported, since "
10358 "it was already included or redefined",
10359 schemaLocation, NULL);
10360 goto exit;
10362 } else if ((! WXS_IS_BUCKET_IMPMAIN(type)) && (bkt->imported)) {
10364 * We imported and then try to include/redefine a schema,
10365 * but the new location provided for the include/redefine
10366 * was different.
10368 if (schemaLocation == NULL)
10369 schemaLocation = BAD_CAST "in_memory_buffer";
10370 if (!xmlStrEqual(schemaLocation,
10371 bkt->schemaLocation)) {
10372 xmlSchemaCustomErr(ACTXT_CAST pctxt, err,
10373 invokingNode, NULL,
10374 "The schema document '%s' cannot be included or "
10375 "redefined, since it was already imported",
10376 schemaLocation, NULL);
10377 goto exit;
10382 if (WXS_IS_BUCKET_IMPMAIN(type)) {
10384 * Given that the schemaLocation [attribute] is only a hint, it is open
10385 * to applications to ignore all but the first <import> for a given
10386 * namespace, regardless of the �actual value� of schemaLocation, but
10387 * such a strategy risks missing useful information when new
10388 * schemaLocations are offered.
10390 * We will use the first <import> that comes with a location.
10391 * Further <import>s *with* a location, will result in an error.
10392 * TODO: Better would be to just report a warning here, but
10393 * we'll try it this way until someone complains.
10395 * Schema Document Location Strategy:
10396 * 3 Based on the namespace name, identify an existing schema document,
10397 * either as a resource which is an XML document or a <schema> element
10398 * information item, in some local schema repository;
10399 * 5 Attempt to resolve the namespace name to locate such a resource.
10401 * NOTE: (3) and (5) are not supported.
10403 if (bkt != NULL) {
10404 relation->bucket = bkt;
10405 goto exit;
10407 bkt = xmlSchemaGetSchemaBucketByTNS(pctxt,
10408 importNamespace, 1);
10410 if (bkt != NULL) {
10411 relation->bucket = bkt;
10412 if (bkt->schemaLocation == NULL) {
10413 /* First given location of the schema; load the doc. */
10414 bkt->schemaLocation = schemaLocation;
10415 } else {
10416 if (!xmlStrEqual(schemaLocation,
10417 bkt->schemaLocation)) {
10419 * Additional location given; just skip it.
10420 * URGENT TODO: We should report a warning here.
10421 * res = XML_SCHEMAP_SRC_IMPORT;
10423 if (schemaLocation == NULL)
10424 schemaLocation = BAD_CAST "in_memory_buffer";
10426 xmlSchemaCustomWarning(ACTXT_CAST pctxt,
10427 XML_SCHEMAP_WARN_SKIP_SCHEMA,
10428 invokingNode, NULL,
10429 "Skipping import of schema located at '%s' for the "
10430 "namespace '%s', since this namespace was already "
10431 "imported with the schema located at '%s'",
10432 schemaLocation, importNamespace, bkt->schemaLocation);
10434 goto exit;
10438 * No bucket + first location: load the doc and create a
10439 * bucket.
10441 } else {
10442 /* <include> and <redefine> */
10443 if (bkt != NULL) {
10445 if ((bkt->origTargetNamespace == NULL) &&
10446 (bkt->targetNamespace != sourceTargetNamespace)) {
10447 xmlSchemaBucketPtr chamel;
10450 * Chameleon include/redefine: skip loading only if it was
10451 * aleady build for the targetNamespace of the including
10452 * schema.
10455 * URGENT TODO: If the schema is a chameleon-include then copy
10456 * the components into the including schema and modify the
10457 * targetNamespace of those components, do nothing otherwise.
10458 * NOTE: This is currently worked-around by compiling the
10459 * chameleon for every destinct including targetNamespace; thus
10460 * not performant at the moment.
10461 * TODO: Check when the namespace in wildcards for chameleons
10462 * needs to be converted: before we built wildcard intersections
10463 * or after.
10464 * Answer: after!
10466 chamel = xmlSchemaGetChameleonSchemaBucket(pctxt,
10467 schemaLocation, sourceTargetNamespace);
10468 if (chamel != NULL) {
10469 /* A fitting chameleon was already parsed; NOP. */
10470 relation->bucket = chamel;
10471 goto exit;
10474 * We need to parse the chameleon again for a different
10475 * targetNamespace.
10476 * CHAMELEON TODO: Optimize this by only parsing the
10477 * chameleon once, and then copying the components to
10478 * the new targetNamespace.
10480 bkt = NULL;
10481 } else {
10482 relation->bucket = bkt;
10483 goto exit;
10487 if ((bkt != NULL) && (bkt->doc != NULL)) {
10488 PERROR_INT("xmlSchemaAddSchemaDoc",
10489 "trying to load a schema doc, but a doc is already "
10490 "assigned to the schema bucket");
10491 goto exit_failure;
10494 doc_load:
10496 * Load the document.
10498 if (schemaDoc != NULL) {
10499 doc = schemaDoc;
10500 /* Don' free this one, since it was provided by the caller. */
10501 preserveDoc = 1;
10502 /* TODO: Does the context or the doc hold the location? */
10503 if (schemaDoc->URL != NULL)
10504 schemaLocation = xmlDictLookup(pctxt->dict,
10505 schemaDoc->URL, -1);
10506 else
10507 schemaLocation = BAD_CAST "in_memory_buffer";
10508 } else if ((schemaLocation != NULL) || (schemaBuffer != NULL)) {
10509 xmlParserCtxtPtr parserCtxt;
10511 parserCtxt = xmlNewParserCtxt();
10512 if (parserCtxt == NULL) {
10513 xmlSchemaPErrMemory(NULL, "xmlSchemaGetDoc, "
10514 "allocating a parser context", NULL);
10515 goto exit_failure;
10517 if ((pctxt->dict != NULL) && (parserCtxt->dict != NULL)) {
10519 * TODO: Do we have to burden the schema parser dict with all
10520 * the content of the schema doc?
10522 xmlDictFree(parserCtxt->dict);
10523 parserCtxt->dict = pctxt->dict;
10524 xmlDictReference(parserCtxt->dict);
10526 if (schemaLocation != NULL) {
10527 /* Parse from file. */
10528 doc = xmlCtxtReadFile(parserCtxt, (const char *) schemaLocation,
10529 NULL, SCHEMAS_PARSE_OPTIONS);
10530 } else if (schemaBuffer != NULL) {
10531 /* Parse from memory buffer. */
10532 doc = xmlCtxtReadMemory(parserCtxt, schemaBuffer, schemaBufferLen,
10533 NULL, NULL, SCHEMAS_PARSE_OPTIONS);
10534 schemaLocation = BAD_CAST "in_memory_buffer";
10535 if (doc != NULL)
10536 doc->URL = xmlStrdup(schemaLocation);
10539 * For <import>:
10540 * 2.1 The referent is (a fragment of) a resource which is an
10541 * XML document (see clause 1.1), which in turn corresponds to
10542 * a <schema> element information item in a well-formed information
10543 * set, which in turn corresponds to a valid schema.
10544 * TODO: (2.1) fragments of XML documents are not supported.
10546 * 2.2 The referent is a <schema> element information item in
10547 * a well-formed information set, which in turn corresponds
10548 * to a valid schema.
10549 * TODO: (2.2) is not supported.
10551 if (doc == NULL) {
10552 xmlErrorPtr lerr;
10553 lerr = xmlGetLastError();
10555 * Check if this a parser error, or if the document could
10556 * just not be located.
10557 * TODO: Try to find specific error codes to react only on
10558 * localisation failures.
10560 if ((lerr == NULL) || (lerr->domain != XML_FROM_IO)) {
10562 * We assume a parser error here.
10564 located = 1;
10565 /* TODO: Error code ?? */
10566 res = XML_SCHEMAP_SRC_IMPORT_2_1;
10567 xmlSchemaCustomErr(ACTXT_CAST pctxt, res,
10568 invokingNode, NULL,
10569 "Failed to parse the XML resource '%s'",
10570 schemaLocation, NULL);
10573 xmlFreeParserCtxt(parserCtxt);
10574 if ((doc == NULL) && located)
10575 goto exit_error;
10576 } else {
10577 xmlSchemaPErr(pctxt, NULL,
10578 XML_SCHEMAP_NOTHING_TO_PARSE,
10579 "No information for parsing was provided with the "
10580 "given schema parser context.\n",
10581 NULL, NULL);
10582 goto exit_failure;
10585 * Preprocess the document.
10587 if (doc != NULL) {
10588 xmlNodePtr docElem = NULL;
10590 located = 1;
10591 docElem = xmlDocGetRootElement(doc);
10592 if (docElem == NULL) {
10593 xmlSchemaCustomErr(ACTXT_CAST pctxt, XML_SCHEMAP_NOROOT,
10594 invokingNode, NULL,
10595 "The document '%s' has no document element",
10596 schemaLocation, NULL);
10597 goto exit_error;
10600 * Remove all the blank text nodes.
10602 xmlSchemaCleanupDoc(pctxt, docElem);
10604 * Check the schema's top level element.
10606 if (!IS_SCHEMA(docElem, "schema")) {
10607 xmlSchemaCustomErr(ACTXT_CAST pctxt, XML_SCHEMAP_NOT_SCHEMA,
10608 invokingNode, NULL,
10609 "The XML document '%s' is not a schema document",
10610 schemaLocation, NULL);
10611 goto exit_error;
10614 * Note that we don't apply a type check for the
10615 * targetNamespace value here.
10617 targetNamespace = xmlSchemaGetProp(pctxt, docElem,
10618 "targetNamespace");
10621 /* after_doc_loading: */
10622 if ((bkt == NULL) && located) {
10623 /* Only create a bucket if the schema was located. */
10624 bkt = xmlSchemaBucketCreate(pctxt, type,
10625 targetNamespace);
10626 if (bkt == NULL)
10627 goto exit_failure;
10629 if (bkt != NULL) {
10630 bkt->schemaLocation = schemaLocation;
10631 bkt->located = located;
10632 if (doc != NULL) {
10633 bkt->doc = doc;
10634 bkt->targetNamespace = targetNamespace;
10635 bkt->origTargetNamespace = targetNamespace;
10636 if (preserveDoc)
10637 bkt->preserveDoc = 1;
10639 if (WXS_IS_BUCKET_IMPMAIN(type))
10640 bkt->imported++;
10642 * Add it to the graph of schemas.
10644 if (relation != NULL)
10645 relation->bucket = bkt;
10648 exit:
10650 * Return the bucket explicitely; this is needed for the
10651 * main schema.
10653 if (bucket != NULL)
10654 *bucket = bkt;
10655 return (0);
10657 exit_error:
10658 if ((doc != NULL) && (! preserveDoc)) {
10659 xmlFreeDoc(doc);
10660 if (bkt != NULL)
10661 bkt->doc = NULL;
10663 return(pctxt->err);
10665 exit_failure:
10666 if ((doc != NULL) && (! preserveDoc)) {
10667 xmlFreeDoc(doc);
10668 if (bkt != NULL)
10669 bkt->doc = NULL;
10671 return (-1);
10675 * xmlSchemaParseImport:
10676 * @ctxt: a schema validation context
10677 * @schema: the schema being built
10678 * @node: a subtree containing XML Schema informations
10680 * parse a XML schema Import definition
10681 * *WARNING* this interface is highly subject to change
10683 * Returns 0 in case of success, a positive error code if
10684 * not valid and -1 in case of an internal error.
10686 static int
10687 xmlSchemaParseImport(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema,
10688 xmlNodePtr node)
10690 xmlNodePtr child;
10691 const xmlChar *namespaceName = NULL, *schemaLocation = NULL;
10692 const xmlChar *thisTargetNamespace;
10693 xmlAttrPtr attr;
10694 int ret = 0;
10695 xmlSchemaBucketPtr bucket = NULL;
10697 if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
10698 return (-1);
10701 * Check for illegal attributes.
10703 attr = node->properties;
10704 while (attr != NULL) {
10705 if (attr->ns == NULL) {
10706 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
10707 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
10708 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
10709 xmlSchemaPIllegalAttrErr(pctxt,
10710 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
10712 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
10713 xmlSchemaPIllegalAttrErr(pctxt,
10714 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
10716 attr = attr->next;
10719 * Extract and validate attributes.
10721 if (xmlSchemaPValAttr(pctxt, NULL, node,
10722 "namespace", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
10723 &namespaceName) != 0) {
10724 xmlSchemaPSimpleTypeErr(pctxt,
10725 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
10726 NULL, node,
10727 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
10728 NULL, namespaceName, NULL, NULL, NULL);
10729 return (pctxt->err);
10732 if (xmlSchemaPValAttr(pctxt, NULL, node,
10733 "schemaLocation", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
10734 &schemaLocation) != 0) {
10735 xmlSchemaPSimpleTypeErr(pctxt,
10736 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
10737 NULL, node,
10738 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
10739 NULL, namespaceName, NULL, NULL, NULL);
10740 return (pctxt->err);
10743 * And now for the children...
10745 child = node->children;
10746 if (IS_SCHEMA(child, "annotation")) {
10748 * the annotation here is simply discarded ...
10749 * TODO: really?
10751 child = child->next;
10753 if (child != NULL) {
10754 xmlSchemaPContentErr(pctxt,
10755 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
10756 NULL, node, child, NULL,
10757 "(annotation?)");
10760 * Apply additional constraints.
10762 * Note that it is important to use the original @targetNamespace
10763 * (or none at all), to rule out imports of schemas _with_ a
10764 * @targetNamespace if the importing schema is a chameleon schema
10765 * (with no @targetNamespace).
10767 thisTargetNamespace = WXS_BUCKET(pctxt)->origTargetNamespace;
10768 if (namespaceName != NULL) {
10770 * 1.1 If the namespace [attribute] is present, then its �actual value�
10771 * must not match the �actual value� of the enclosing <schema>'s
10772 * targetNamespace [attribute].
10774 if (xmlStrEqual(thisTargetNamespace, namespaceName)) {
10775 xmlSchemaPCustomErr(pctxt,
10776 XML_SCHEMAP_SRC_IMPORT_1_1,
10777 NULL, node,
10778 "The value of the attribute 'namespace' must not match "
10779 "the target namespace '%s' of the importing schema",
10780 thisTargetNamespace);
10781 return (pctxt->err);
10783 } else {
10785 * 1.2 If the namespace [attribute] is not present, then the enclosing
10786 * <schema> must have a targetNamespace [attribute].
10788 if (thisTargetNamespace == NULL) {
10789 xmlSchemaPCustomErr(pctxt,
10790 XML_SCHEMAP_SRC_IMPORT_1_2,
10791 NULL, node,
10792 "The attribute 'namespace' must be existent if "
10793 "the importing schema has no target namespace",
10794 NULL);
10795 return (pctxt->err);
10799 * Locate and acquire the schema document.
10801 if (schemaLocation != NULL)
10802 schemaLocation = xmlSchemaBuildAbsoluteURI(pctxt->dict,
10803 schemaLocation, node);
10804 ret = xmlSchemaAddSchemaDoc(pctxt, XML_SCHEMA_SCHEMA_IMPORT,
10805 schemaLocation, NULL, NULL, 0, node, thisTargetNamespace,
10806 namespaceName, &bucket);
10808 if (ret != 0)
10809 return(ret);
10812 * For <import>: "It is *not* an error for the application
10813 * schema reference strategy to fail."
10814 * So just don't parse if no schema document was found.
10815 * Note that we will get no bucket if the schema could not be
10816 * located or if there was no schemaLocation.
10818 if ((bucket == NULL) && (schemaLocation != NULL)) {
10819 xmlSchemaCustomWarning(ACTXT_CAST pctxt,
10820 XML_SCHEMAP_WARN_UNLOCATED_SCHEMA,
10821 node, NULL,
10822 "Failed to locate a schema at location '%s'. "
10823 "Skipping the import", schemaLocation, NULL, NULL);
10826 if ((bucket != NULL) && CAN_PARSE_SCHEMA(bucket)) {
10827 ret = xmlSchemaParseNewDoc(pctxt, schema, bucket);
10830 return (ret);
10833 static int
10834 xmlSchemaParseIncludeOrRedefineAttrs(xmlSchemaParserCtxtPtr pctxt,
10835 xmlSchemaPtr schema,
10836 xmlNodePtr node,
10837 xmlChar **schemaLocation,
10838 int type)
10840 xmlAttrPtr attr;
10842 if ((pctxt == NULL) || (schema == NULL) || (node == NULL) ||
10843 (schemaLocation == NULL))
10844 return (-1);
10846 *schemaLocation = NULL;
10848 * Check for illegal attributes.
10849 * Applies for both <include> and <redefine>.
10851 attr = node->properties;
10852 while (attr != NULL) {
10853 if (attr->ns == NULL) {
10854 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
10855 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
10856 xmlSchemaPIllegalAttrErr(pctxt,
10857 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
10859 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
10860 xmlSchemaPIllegalAttrErr(pctxt,
10861 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
10863 attr = attr->next;
10865 xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
10867 * Preliminary step, extract the URI-Reference and make an URI
10868 * from the base.
10871 * Attribute "schemaLocation" is mandatory.
10873 attr = xmlSchemaGetPropNode(node, "schemaLocation");
10874 if (attr != NULL) {
10875 xmlChar *base = NULL;
10876 xmlChar *uri = NULL;
10878 if (xmlSchemaPValAttrNode(pctxt, NULL, attr,
10879 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
10880 (const xmlChar **) schemaLocation) != 0)
10881 goto exit_error;
10882 base = xmlNodeGetBase(node->doc, node);
10883 if (base == NULL) {
10884 uri = xmlBuildURI(*schemaLocation, node->doc->URL);
10885 } else {
10886 uri = xmlBuildURI(*schemaLocation, base);
10887 xmlFree(base);
10889 if (uri == NULL) {
10890 PERROR_INT("xmlSchemaParseIncludeOrRedefine",
10891 "could not build an URI from the schemaLocation")
10892 goto exit_failure;
10894 (*schemaLocation) = (xmlChar *) xmlDictLookup(pctxt->dict, uri, -1);
10895 xmlFree(uri);
10896 } else {
10897 xmlSchemaPMissingAttrErr(pctxt,
10898 XML_SCHEMAP_S4S_ATTR_MISSING,
10899 NULL, node, "schemaLocation", NULL);
10900 goto exit_error;
10903 * Report self-inclusion and self-redefinition.
10905 if (xmlStrEqual(*schemaLocation, pctxt->URL)) {
10906 if (type == XML_SCHEMA_SCHEMA_REDEFINE) {
10907 xmlSchemaPCustomErr(pctxt,
10908 XML_SCHEMAP_SRC_REDEFINE,
10909 NULL, node,
10910 "The schema document '%s' cannot redefine itself.",
10911 *schemaLocation);
10912 } else {
10913 xmlSchemaPCustomErr(pctxt,
10914 XML_SCHEMAP_SRC_INCLUDE,
10915 NULL, node,
10916 "The schema document '%s' cannot include itself.",
10917 *schemaLocation);
10919 goto exit_error;
10922 return(0);
10923 exit_error:
10924 return(pctxt->err);
10925 exit_failure:
10926 return(-1);
10929 static int
10930 xmlSchemaParseIncludeOrRedefine(xmlSchemaParserCtxtPtr pctxt,
10931 xmlSchemaPtr schema,
10932 xmlNodePtr node,
10933 int type)
10935 xmlNodePtr child = NULL;
10936 const xmlChar *schemaLocation = NULL;
10937 int res = 0; /* hasRedefinitions = 0 */
10938 int isChameleon = 0, wasChameleon = 0;
10939 xmlSchemaBucketPtr bucket = NULL;
10941 if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
10942 return (-1);
10945 * Parse attributes. Note that the returned schemaLocation will
10946 * be already converted to an absolute URI.
10948 res = xmlSchemaParseIncludeOrRedefineAttrs(pctxt, schema,
10949 node, (xmlChar **) (&schemaLocation), type);
10950 if (res != 0)
10951 return(res);
10953 * Load and add the schema document.
10955 res = xmlSchemaAddSchemaDoc(pctxt, type, schemaLocation, NULL,
10956 NULL, 0, node, pctxt->targetNamespace, NULL, &bucket);
10957 if (res != 0)
10958 return(res);
10960 * If we get no schema bucket back, then this means that the schema
10961 * document could not be located or was broken XML or was not
10962 * a schema document.
10964 if ((bucket == NULL) || (bucket->doc == NULL)) {
10965 if (type == XML_SCHEMA_SCHEMA_INCLUDE) {
10967 * WARNING for <include>:
10968 * We will raise an error if the schema cannot be located
10969 * for inclusions, since the that was the feedback from the
10970 * schema people. I.e. the following spec piece will *not* be
10971 * satisfied:
10972 * SPEC src-include: "It is not an error for the �actual value� of the
10973 * schemaLocation [attribute] to fail to resolve it all, in which
10974 * case no corresponding inclusion is performed.
10975 * So do we need a warning report here?"
10977 res = XML_SCHEMAP_SRC_INCLUDE;
10978 xmlSchemaCustomErr(ACTXT_CAST pctxt, res,
10979 node, NULL,
10980 "Failed to load the document '%s' for inclusion",
10981 schemaLocation, NULL);
10982 } else {
10984 * NOTE: This was changed to raise an error even if no redefinitions
10985 * are specified.
10987 * SPEC src-redefine (1)
10988 * "If there are any element information items among the [children]
10989 * other than <annotation> then the �actual value� of the
10990 * schemaLocation [attribute] must successfully resolve."
10991 * TODO: Ask the WG if a the location has always to resolve
10992 * here as well!
10994 res = XML_SCHEMAP_SRC_REDEFINE;
10995 xmlSchemaCustomErr(ACTXT_CAST pctxt, res,
10996 node, NULL,
10997 "Failed to load the document '%s' for redefinition",
10998 schemaLocation, NULL);
11000 } else {
11002 * Check targetNamespace sanity before parsing the new schema.
11003 * TODO: Note that we won't check further content if the
11004 * targetNamespace was bad.
11006 if (bucket->origTargetNamespace != NULL) {
11008 * SPEC src-include (2.1)
11009 * "SII has a targetNamespace [attribute], and its �actual
11010 * value� is identical to the �actual value� of the targetNamespace
11011 * [attribute] of SII� (which must have such an [attribute])."
11013 if (pctxt->targetNamespace == NULL) {
11014 xmlSchemaCustomErr(ACTXT_CAST pctxt,
11015 XML_SCHEMAP_SRC_INCLUDE,
11016 node, NULL,
11017 "The target namespace of the included/redefined schema "
11018 "'%s' has to be absent, since the including/redefining "
11019 "schema has no target namespace",
11020 schemaLocation, NULL);
11021 goto exit_error;
11022 } else if (!xmlStrEqual(bucket->origTargetNamespace,
11023 pctxt->targetNamespace)) {
11024 /* TODO: Change error function. */
11025 xmlSchemaPCustomErrExt(pctxt,
11026 XML_SCHEMAP_SRC_INCLUDE,
11027 NULL, node,
11028 "The target namespace '%s' of the included/redefined "
11029 "schema '%s' differs from '%s' of the "
11030 "including/redefining schema",
11031 bucket->origTargetNamespace, schemaLocation,
11032 pctxt->targetNamespace);
11033 goto exit_error;
11035 } else if (pctxt->targetNamespace != NULL) {
11037 * Chameleons: the original target namespace will
11038 * differ from the resulting namespace.
11040 isChameleon = 1;
11041 if (bucket->parsed &&
11042 bucket->origTargetNamespace != NULL) {
11043 xmlSchemaCustomErr(ACTXT_CAST pctxt,
11044 XML_SCHEMAP_SRC_INCLUDE,
11045 node, NULL,
11046 "The target namespace of the included/redefined schema "
11047 "'%s' has to be absent or the same as the "
11048 "including/redefining schema's target namespace",
11049 schemaLocation, NULL);
11050 goto exit_error;
11052 bucket->targetNamespace = pctxt->targetNamespace;
11056 * Parse the schema.
11058 if (bucket && (!bucket->parsed) && (bucket->doc != NULL)) {
11059 if (isChameleon) {
11060 /* TODO: Get rid of this flag on the schema itself. */
11061 if ((schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) == 0) {
11062 schema->flags |= XML_SCHEMAS_INCLUDING_CONVERT_NS;
11063 } else
11064 wasChameleon = 1;
11066 xmlSchemaParseNewDoc(pctxt, schema, bucket);
11067 /* Restore chameleon flag. */
11068 if (isChameleon && (!wasChameleon))
11069 schema->flags ^= XML_SCHEMAS_INCLUDING_CONVERT_NS;
11072 * And now for the children...
11074 child = node->children;
11075 if (type == XML_SCHEMA_SCHEMA_REDEFINE) {
11077 * Parse (simpleType | complexType | group | attributeGroup))*
11079 pctxt->redefined = bucket;
11081 * How to proceed if the redefined schema was not located?
11083 pctxt->isRedefine = 1;
11084 while (IS_SCHEMA(child, "annotation") ||
11085 IS_SCHEMA(child, "simpleType") ||
11086 IS_SCHEMA(child, "complexType") ||
11087 IS_SCHEMA(child, "group") ||
11088 IS_SCHEMA(child, "attributeGroup")) {
11089 if (IS_SCHEMA(child, "annotation")) {
11091 * TODO: discard or not?
11093 } else if (IS_SCHEMA(child, "simpleType")) {
11094 xmlSchemaParseSimpleType(pctxt, schema, child, 1);
11095 } else if (IS_SCHEMA(child, "complexType")) {
11096 xmlSchemaParseComplexType(pctxt, schema, child, 1);
11097 /* hasRedefinitions = 1; */
11098 } else if (IS_SCHEMA(child, "group")) {
11099 /* hasRedefinitions = 1; */
11100 xmlSchemaParseModelGroupDefinition(pctxt,
11101 schema, child);
11102 } else if (IS_SCHEMA(child, "attributeGroup")) {
11103 /* hasRedefinitions = 1; */
11104 xmlSchemaParseAttributeGroupDefinition(pctxt, schema,
11105 child);
11107 child = child->next;
11109 pctxt->redefined = NULL;
11110 pctxt->isRedefine = 0;
11111 } else {
11112 if (IS_SCHEMA(child, "annotation")) {
11114 * TODO: discard or not?
11116 child = child->next;
11119 if (child != NULL) {
11120 res = XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED;
11121 if (type == XML_SCHEMA_SCHEMA_REDEFINE) {
11122 xmlSchemaPContentErr(pctxt, res,
11123 NULL, node, child, NULL,
11124 "(annotation | (simpleType | complexType | group | attributeGroup))*");
11125 } else {
11126 xmlSchemaPContentErr(pctxt, res,
11127 NULL, node, child, NULL,
11128 "(annotation?)");
11131 return(res);
11133 exit_error:
11134 return(pctxt->err);
11137 static int
11138 xmlSchemaParseRedefine(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema,
11139 xmlNodePtr node)
11141 int res;
11142 #ifndef ENABLE_REDEFINE
11143 TODO
11144 return(0);
11145 #endif
11146 res = xmlSchemaParseIncludeOrRedefine(pctxt, schema, node,
11147 XML_SCHEMA_SCHEMA_REDEFINE);
11148 if (res != 0)
11149 return(res);
11150 return(0);
11153 static int
11154 xmlSchemaParseInclude(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema,
11155 xmlNodePtr node)
11157 int res;
11159 res = xmlSchemaParseIncludeOrRedefine(pctxt, schema, node,
11160 XML_SCHEMA_SCHEMA_INCLUDE);
11161 if (res != 0)
11162 return(res);
11163 return(0);
11167 * xmlSchemaParseModelGroup:
11168 * @ctxt: a schema validation context
11169 * @schema: the schema being built
11170 * @node: a subtree containing XML Schema informations
11171 * @type: the "compositor" type
11172 * @particleNeeded: if a a model group with a particle
11174 * parse a XML schema Sequence definition.
11175 * Applies parts of:
11176 * Schema Representation Constraint:
11177 * Redefinition Constraints and Semantics (src-redefine)
11178 * (6.1), (6.1.1), (6.1.2)
11180 * Schema Component Constraint:
11181 * All Group Limited (cos-all-limited) (2)
11182 * TODO: Actually this should go to component-level checks,
11183 * but is done here due to performance. Move it to an other layer
11184 * is schema construction via an API is implemented.
11186 * *WARNING* this interface is highly subject to change
11188 * Returns -1 in case of error, 0 if the declaration is improper and
11189 * 1 in case of success.
11191 static xmlSchemaTreeItemPtr
11192 xmlSchemaParseModelGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
11193 xmlNodePtr node, xmlSchemaTypeType type,
11194 int withParticle)
11196 xmlSchemaModelGroupPtr item;
11197 xmlSchemaParticlePtr particle = NULL;
11198 xmlNodePtr child = NULL;
11199 xmlAttrPtr attr;
11200 int min = 1, max = 1, isElemRef, hasRefs = 0;
11202 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
11203 return (NULL);
11205 * Create a model group with the given compositor.
11207 item = xmlSchemaAddModelGroup(ctxt, schema, type, node);
11208 if (item == NULL)
11209 return (NULL);
11211 if (withParticle) {
11212 if (type == XML_SCHEMA_TYPE_ALL) {
11213 min = xmlGetMinOccurs(ctxt, node, 0, 1, 1, "(0 | 1)");
11214 max = xmlGetMaxOccurs(ctxt, node, 1, 1, 1, "1");
11215 } else {
11216 /* choice + sequence */
11217 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
11218 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
11219 "(xs:nonNegativeInteger | unbounded)");
11221 xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
11223 * Create a particle
11225 particle = xmlSchemaAddParticle(ctxt, node, min, max);
11226 if (particle == NULL)
11227 return (NULL);
11228 particle->children = (xmlSchemaTreeItemPtr) item;
11230 * Check for illegal attributes.
11232 attr = node->properties;
11233 while (attr != NULL) {
11234 if (attr->ns == NULL) {
11235 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
11236 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
11237 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs"))) {
11238 xmlSchemaPIllegalAttrErr(ctxt,
11239 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11241 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
11242 xmlSchemaPIllegalAttrErr(ctxt,
11243 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11245 attr = attr->next;
11247 } else {
11249 * Check for illegal attributes.
11251 attr = node->properties;
11252 while (attr != NULL) {
11253 if (attr->ns == NULL) {
11254 if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
11255 xmlSchemaPIllegalAttrErr(ctxt,
11256 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11258 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
11259 xmlSchemaPIllegalAttrErr(ctxt,
11260 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11262 attr = attr->next;
11267 * Extract and validate attributes.
11269 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
11271 * And now for the children...
11273 child = node->children;
11274 if (IS_SCHEMA(child, "annotation")) {
11275 item->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
11276 child = child->next;
11278 if (type == XML_SCHEMA_TYPE_ALL) {
11279 xmlSchemaParticlePtr part, last = NULL;
11281 while (IS_SCHEMA(child, "element")) {
11282 part = (xmlSchemaParticlePtr) xmlSchemaParseElement(ctxt,
11283 schema, child, &isElemRef, 0);
11285 * SPEC cos-all-limited (2)
11286 * "The {max occurs} of all the particles in the {particles}
11287 * of the ('all') group must be 0 or 1.
11289 if (part != NULL) {
11290 if (isElemRef)
11291 hasRefs++;
11292 if (part->minOccurs > 1) {
11293 xmlSchemaPCustomErr(ctxt,
11294 XML_SCHEMAP_COS_ALL_LIMITED,
11295 NULL, child,
11296 "Invalid value for minOccurs (must be 0 or 1)",
11297 NULL);
11298 /* Reset to 1. */
11299 part->minOccurs = 1;
11301 if (part->maxOccurs > 1) {
11302 xmlSchemaPCustomErr(ctxt,
11303 XML_SCHEMAP_COS_ALL_LIMITED,
11304 NULL, child,
11305 "Invalid value for maxOccurs (must be 0 or 1)",
11306 NULL);
11307 /* Reset to 1. */
11308 part->maxOccurs = 1;
11310 if (last == NULL)
11311 item->children = (xmlSchemaTreeItemPtr) part;
11312 else
11313 last->next = (xmlSchemaTreeItemPtr) part;
11314 last = part;
11316 child = child->next;
11318 if (child != NULL) {
11319 xmlSchemaPContentErr(ctxt,
11320 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11321 NULL, node, child, NULL,
11322 "(annotation?, (annotation?, element*)");
11324 } else {
11325 /* choice + sequence */
11326 xmlSchemaTreeItemPtr part = NULL, last = NULL;
11328 while ((IS_SCHEMA(child, "element")) ||
11329 (IS_SCHEMA(child, "group")) ||
11330 (IS_SCHEMA(child, "any")) ||
11331 (IS_SCHEMA(child, "choice")) ||
11332 (IS_SCHEMA(child, "sequence"))) {
11334 if (IS_SCHEMA(child, "element")) {
11335 part = (xmlSchemaTreeItemPtr)
11336 xmlSchemaParseElement(ctxt, schema, child, &isElemRef, 0);
11337 if (part && isElemRef)
11338 hasRefs++;
11339 } else if (IS_SCHEMA(child, "group")) {
11340 part =
11341 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
11342 if (part != NULL)
11343 hasRefs++;
11345 * Handle redefinitions.
11347 if (ctxt->isRedefine && ctxt->redef &&
11348 (ctxt->redef->item->type == XML_SCHEMA_TYPE_GROUP) &&
11349 part && part->children)
11351 if ((xmlSchemaGetQNameRefName(part->children) ==
11352 ctxt->redef->refName) &&
11353 (xmlSchemaGetQNameRefTargetNs(part->children) ==
11354 ctxt->redef->refTargetNs))
11357 * SPEC src-redefine:
11358 * (6.1) "If it has a <group> among its contents at
11359 * some level the �actual value� of whose ref
11360 * [attribute] is the same as the �actual value� of
11361 * its own name attribute plus target namespace, then
11362 * all of the following must be true:"
11363 * (6.1.1) "It must have exactly one such group."
11365 if (ctxt->redefCounter != 0) {
11366 xmlChar *str = NULL;
11368 xmlSchemaCustomErr(ACTXT_CAST ctxt,
11369 XML_SCHEMAP_SRC_REDEFINE, child, NULL,
11370 "The redefining model group definition "
11371 "'%s' must not contain more than one "
11372 "reference to the redefined definition",
11373 xmlSchemaFormatQName(&str,
11374 ctxt->redef->refTargetNs,
11375 ctxt->redef->refName),
11376 NULL);
11377 FREE_AND_NULL(str)
11378 part = NULL;
11379 } else if (((WXS_PARTICLE(part))->minOccurs != 1) ||
11380 ((WXS_PARTICLE(part))->maxOccurs != 1))
11382 xmlChar *str = NULL;
11384 * SPEC src-redefine:
11385 * (6.1.2) "The �actual value� of both that
11386 * group's minOccurs and maxOccurs [attribute]
11387 * must be 1 (or �absent�).
11389 xmlSchemaCustomErr(ACTXT_CAST ctxt,
11390 XML_SCHEMAP_SRC_REDEFINE, child, NULL,
11391 "The redefining model group definition "
11392 "'%s' must not contain a reference to the "
11393 "redefined definition with a "
11394 "maxOccurs/minOccurs other than 1",
11395 xmlSchemaFormatQName(&str,
11396 ctxt->redef->refTargetNs,
11397 ctxt->redef->refName),
11398 NULL);
11399 FREE_AND_NULL(str)
11400 part = NULL;
11402 ctxt->redef->reference = WXS_BASIC_CAST part;
11403 ctxt->redefCounter++;
11406 } else if (IS_SCHEMA(child, "any")) {
11407 part = (xmlSchemaTreeItemPtr)
11408 xmlSchemaParseAny(ctxt, schema, child);
11409 } else if (IS_SCHEMA(child, "choice")) {
11410 part = xmlSchemaParseModelGroup(ctxt, schema, child,
11411 XML_SCHEMA_TYPE_CHOICE, 1);
11412 } else if (IS_SCHEMA(child, "sequence")) {
11413 part = xmlSchemaParseModelGroup(ctxt, schema, child,
11414 XML_SCHEMA_TYPE_SEQUENCE, 1);
11416 if (part != NULL) {
11417 if (last == NULL)
11418 item->children = part;
11419 else
11420 last->next = part;
11421 last = part;
11423 child = child->next;
11425 if (child != NULL) {
11426 xmlSchemaPContentErr(ctxt,
11427 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11428 NULL, node, child, NULL,
11429 "(annotation?, (element | group | choice | sequence | any)*)");
11432 if ((max == 0) && (min == 0))
11433 return (NULL);
11434 if (hasRefs) {
11436 * We need to resolve references.
11438 WXS_ADD_PENDING(ctxt, item);
11440 if (withParticle)
11441 return ((xmlSchemaTreeItemPtr) particle);
11442 else
11443 return ((xmlSchemaTreeItemPtr) item);
11447 * xmlSchemaParseRestriction:
11448 * @ctxt: a schema validation context
11449 * @schema: the schema being built
11450 * @node: a subtree containing XML Schema informations
11452 * parse a XML schema Restriction definition
11453 * *WARNING* this interface is highly subject to change
11455 * Returns the type definition or NULL in case of error
11457 static xmlSchemaTypePtr
11458 xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
11459 xmlNodePtr node, xmlSchemaTypeType parentType)
11461 xmlSchemaTypePtr type;
11462 xmlNodePtr child = NULL;
11463 xmlAttrPtr attr;
11465 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
11466 return (NULL);
11467 /* Not a component, don't create it. */
11468 type = ctxt->ctxtType;
11469 type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
11472 * Check for illegal attributes.
11474 attr = node->properties;
11475 while (attr != NULL) {
11476 if (attr->ns == NULL) {
11477 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
11478 (!xmlStrEqual(attr->name, BAD_CAST "base"))) {
11479 xmlSchemaPIllegalAttrErr(ctxt,
11480 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11482 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
11483 xmlSchemaPIllegalAttrErr(ctxt,
11484 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11486 attr = attr->next;
11489 * Extract and validate attributes.
11491 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
11493 * Attribute
11496 * Extract the base type. The "base" attribute is mandatory if inside
11497 * a complex type or if redefining.
11499 * SPEC (1.2) "...otherwise (<restriction> has no <simpleType> "
11500 * among its [children]), the simple type definition which is
11501 * the {content type} of the type definition �resolved� to by
11502 * the �actual value� of the base [attribute]"
11504 if (xmlSchemaPValAttrQName(ctxt, schema, NULL, node, "base",
11505 &(type->baseNs), &(type->base)) == 0)
11507 if ((type->base == NULL) && (type->type == XML_SCHEMA_TYPE_COMPLEX)) {
11508 xmlSchemaPMissingAttrErr(ctxt,
11509 XML_SCHEMAP_S4S_ATTR_MISSING,
11510 NULL, node, "base", NULL);
11511 } else if ((ctxt->isRedefine) &&
11512 (type->flags & XML_SCHEMAS_TYPE_GLOBAL))
11514 if (type->base == NULL) {
11515 xmlSchemaPMissingAttrErr(ctxt,
11516 XML_SCHEMAP_S4S_ATTR_MISSING,
11517 NULL, node, "base", NULL);
11518 } else if ((! xmlStrEqual(type->base, type->name)) ||
11519 (! xmlStrEqual(type->baseNs, type->targetNamespace)))
11521 xmlChar *str1 = NULL, *str2 = NULL;
11523 * REDEFINE: SPEC src-redefine (5)
11524 * "Within the [children], each <simpleType> must have a
11525 * <restriction> among its [children] ... the �actual value� of
11526 * whose base [attribute] must be the same as the �actual value�
11527 * of its own name attribute plus target namespace;"
11529 xmlSchemaPCustomErrExt(ctxt, XML_SCHEMAP_SRC_REDEFINE,
11530 NULL, node, "This is a redefinition, but the QName "
11531 "value '%s' of the 'base' attribute does not match the "
11532 "type's designation '%s'",
11533 xmlSchemaFormatQName(&str1, type->baseNs, type->base),
11534 xmlSchemaFormatQName(&str2, type->targetNamespace,
11535 type->name), NULL);
11536 FREE_AND_NULL(str1);
11537 FREE_AND_NULL(str2);
11538 /* Avoid confusion and erase the values. */
11539 type->base = NULL;
11540 type->baseNs = NULL;
11545 * And now for the children...
11547 child = node->children;
11548 if (IS_SCHEMA(child, "annotation")) {
11550 * Add the annotation to the simple type ancestor.
11552 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
11553 xmlSchemaParseAnnotation(ctxt, child, 1));
11554 child = child->next;
11556 if (parentType == XML_SCHEMA_TYPE_SIMPLE) {
11558 * Corresponds to <simpleType><restriction><simpleType>.
11560 if (IS_SCHEMA(child, "simpleType")) {
11561 if (type->base != NULL) {
11563 * src-restriction-base-or-simpleType
11564 * Either the base [attribute] or the simpleType [child] of the
11565 * <restriction> element must be present, but not both.
11567 xmlSchemaPContentErr(ctxt,
11568 XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
11569 NULL, node, child,
11570 "The attribute 'base' and the <simpleType> child are "
11571 "mutually exclusive", NULL);
11572 } else {
11573 type->baseType = (xmlSchemaTypePtr)
11574 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
11576 child = child->next;
11577 } else if (type->base == NULL) {
11578 xmlSchemaPContentErr(ctxt,
11579 XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
11580 NULL, node, child,
11581 "Either the attribute 'base' or a <simpleType> child "
11582 "must be present", NULL);
11584 } else if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11586 * Corresponds to <complexType><complexContent><restriction>...
11587 * followed by:
11589 * Model groups <all>, <choice> and <sequence>.
11591 if (IS_SCHEMA(child, "all")) {
11592 type->subtypes = (xmlSchemaTypePtr)
11593 xmlSchemaParseModelGroup(ctxt, schema, child,
11594 XML_SCHEMA_TYPE_ALL, 1);
11595 child = child->next;
11596 } else if (IS_SCHEMA(child, "choice")) {
11597 type->subtypes = (xmlSchemaTypePtr)
11598 xmlSchemaParseModelGroup(ctxt,
11599 schema, child, XML_SCHEMA_TYPE_CHOICE, 1);
11600 child = child->next;
11601 } else if (IS_SCHEMA(child, "sequence")) {
11602 type->subtypes = (xmlSchemaTypePtr)
11603 xmlSchemaParseModelGroup(ctxt, schema, child,
11604 XML_SCHEMA_TYPE_SEQUENCE, 1);
11605 child = child->next;
11607 * Model group reference <group>.
11609 } else if (IS_SCHEMA(child, "group")) {
11610 type->subtypes = (xmlSchemaTypePtr)
11611 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
11613 * Note that the reference will be resolved in
11614 * xmlSchemaResolveTypeReferences();
11616 child = child->next;
11618 } else if (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
11620 * Corresponds to <complexType><simpleContent><restriction>...
11622 * "1.1 the simple type definition corresponding to the <simpleType>
11623 * among the [children] of <restriction> if there is one;"
11625 if (IS_SCHEMA(child, "simpleType")) {
11627 * We will store the to-be-restricted simple type in
11628 * type->contentTypeDef *temporarily*.
11630 type->contentTypeDef = (xmlSchemaTypePtr)
11631 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
11632 if ( type->contentTypeDef == NULL)
11633 return (NULL);
11634 child = child->next;
11638 if ((parentType == XML_SCHEMA_TYPE_SIMPLE) ||
11639 (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT)) {
11640 xmlSchemaFacetPtr facet, lastfacet = NULL;
11642 * Corresponds to <complexType><simpleContent><restriction>...
11643 * <simpleType><restriction>...
11647 * Add the facets to the simple type ancestor.
11650 * TODO: Datatypes: 4.1.3 Constraints on XML Representation of
11651 * Simple Type Definition Schema Representation Constraint:
11652 * *Single Facet Value*
11654 while ((IS_SCHEMA(child, "minInclusive")) ||
11655 (IS_SCHEMA(child, "minExclusive")) ||
11656 (IS_SCHEMA(child, "maxInclusive")) ||
11657 (IS_SCHEMA(child, "maxExclusive")) ||
11658 (IS_SCHEMA(child, "totalDigits")) ||
11659 (IS_SCHEMA(child, "fractionDigits")) ||
11660 (IS_SCHEMA(child, "pattern")) ||
11661 (IS_SCHEMA(child, "enumeration")) ||
11662 (IS_SCHEMA(child, "whiteSpace")) ||
11663 (IS_SCHEMA(child, "length")) ||
11664 (IS_SCHEMA(child, "maxLength")) ||
11665 (IS_SCHEMA(child, "minLength"))) {
11666 facet = xmlSchemaParseFacet(ctxt, schema, child);
11667 if (facet != NULL) {
11668 if (lastfacet == NULL)
11669 type->facets = facet;
11670 else
11671 lastfacet->next = facet;
11672 lastfacet = facet;
11673 lastfacet->next = NULL;
11675 child = child->next;
11678 * Create links for derivation and validation.
11680 if (type->facets != NULL) {
11681 xmlSchemaFacetLinkPtr facetLink, lastFacetLink = NULL;
11683 facet = type->facets;
11684 do {
11685 facetLink = (xmlSchemaFacetLinkPtr)
11686 xmlMalloc(sizeof(xmlSchemaFacetLink));
11687 if (facetLink == NULL) {
11688 xmlSchemaPErrMemory(ctxt, "allocating a facet link", NULL);
11689 xmlFree(facetLink);
11690 return (NULL);
11692 facetLink->facet = facet;
11693 facetLink->next = NULL;
11694 if (lastFacetLink == NULL)
11695 type->facetSet = facetLink;
11696 else
11697 lastFacetLink->next = facetLink;
11698 lastFacetLink = facetLink;
11699 facet = facet->next;
11700 } while (facet != NULL);
11703 if (type->type == XML_SCHEMA_TYPE_COMPLEX) {
11705 * Attribute uses/declarations.
11707 if (xmlSchemaParseLocalAttributes(ctxt, schema, &child,
11708 (xmlSchemaItemListPtr *) &(type->attrUses),
11709 XML_SCHEMA_TYPE_RESTRICTION, NULL) == -1)
11710 return(NULL);
11712 * Attribute wildcard.
11714 if (IS_SCHEMA(child, "anyAttribute")) {
11715 type->attributeWildcard =
11716 xmlSchemaParseAnyAttribute(ctxt, schema, child);
11717 child = child->next;
11720 if (child != NULL) {
11721 if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11722 xmlSchemaPContentErr(ctxt,
11723 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11724 NULL, node, child, NULL,
11725 "annotation?, (group | all | choice | sequence)?, "
11726 "((attribute | attributeGroup)*, anyAttribute?))");
11727 } else if (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
11728 xmlSchemaPContentErr(ctxt,
11729 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11730 NULL, node, child, NULL,
11731 "(annotation?, (simpleType?, (minExclusive | minInclusive | "
11732 "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
11733 "length | minLength | maxLength | enumeration | whiteSpace | "
11734 "pattern)*)?, ((attribute | attributeGroup)*, anyAttribute?))");
11735 } else {
11736 /* Simple type */
11737 xmlSchemaPContentErr(ctxt,
11738 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11739 NULL, node, child, NULL,
11740 "(annotation?, (simpleType?, (minExclusive | minInclusive | "
11741 "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
11742 "length | minLength | maxLength | enumeration | whiteSpace | "
11743 "pattern)*))");
11746 return (NULL);
11750 * xmlSchemaParseExtension:
11751 * @ctxt: a schema validation context
11752 * @schema: the schema being built
11753 * @node: a subtree containing XML Schema informations
11755 * Parses an <extension>, which is found inside a
11756 * <simpleContent> or <complexContent>.
11757 * *WARNING* this interface is highly subject to change.
11759 * TODO: Returns the type definition or NULL in case of error
11761 static xmlSchemaTypePtr
11762 xmlSchemaParseExtension(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
11763 xmlNodePtr node, xmlSchemaTypeType parentType)
11765 xmlSchemaTypePtr type;
11766 xmlNodePtr child = NULL;
11767 xmlAttrPtr attr;
11769 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
11770 return (NULL);
11771 /* Not a component, don't create it. */
11772 type = ctxt->ctxtType;
11773 type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION;
11776 * Check for illegal attributes.
11778 attr = node->properties;
11779 while (attr != NULL) {
11780 if (attr->ns == NULL) {
11781 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
11782 (!xmlStrEqual(attr->name, BAD_CAST "base"))) {
11783 xmlSchemaPIllegalAttrErr(ctxt,
11784 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11786 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
11787 xmlSchemaPIllegalAttrErr(ctxt,
11788 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11790 attr = attr->next;
11793 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
11796 * Attribute "base" - mandatory.
11798 if ((xmlSchemaPValAttrQName(ctxt, schema, NULL, node,
11799 "base", &(type->baseNs), &(type->base)) == 0) &&
11800 (type->base == NULL)) {
11801 xmlSchemaPMissingAttrErr(ctxt,
11802 XML_SCHEMAP_S4S_ATTR_MISSING,
11803 NULL, node, "base", NULL);
11806 * And now for the children...
11808 child = node->children;
11809 if (IS_SCHEMA(child, "annotation")) {
11811 * Add the annotation to the type ancestor.
11813 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
11814 xmlSchemaParseAnnotation(ctxt, child, 1));
11815 child = child->next;
11817 if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11819 * Corresponds to <complexType><complexContent><extension>... and:
11821 * Model groups <all>, <choice>, <sequence> and <group>.
11823 if (IS_SCHEMA(child, "all")) {
11824 type->subtypes = (xmlSchemaTypePtr)
11825 xmlSchemaParseModelGroup(ctxt, schema,
11826 child, XML_SCHEMA_TYPE_ALL, 1);
11827 child = child->next;
11828 } else if (IS_SCHEMA(child, "choice")) {
11829 type->subtypes = (xmlSchemaTypePtr)
11830 xmlSchemaParseModelGroup(ctxt, schema,
11831 child, XML_SCHEMA_TYPE_CHOICE, 1);
11832 child = child->next;
11833 } else if (IS_SCHEMA(child, "sequence")) {
11834 type->subtypes = (xmlSchemaTypePtr)
11835 xmlSchemaParseModelGroup(ctxt, schema,
11836 child, XML_SCHEMA_TYPE_SEQUENCE, 1);
11837 child = child->next;
11838 } else if (IS_SCHEMA(child, "group")) {
11839 type->subtypes = (xmlSchemaTypePtr)
11840 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
11842 * Note that the reference will be resolved in
11843 * xmlSchemaResolveTypeReferences();
11845 child = child->next;
11848 if (child != NULL) {
11850 * Attribute uses/declarations.
11852 if (xmlSchemaParseLocalAttributes(ctxt, schema, &child,
11853 (xmlSchemaItemListPtr *) &(type->attrUses),
11854 XML_SCHEMA_TYPE_EXTENSION, NULL) == -1)
11855 return(NULL);
11857 * Attribute wildcard.
11859 if (IS_SCHEMA(child, "anyAttribute")) {
11860 ctxt->ctxtType->attributeWildcard =
11861 xmlSchemaParseAnyAttribute(ctxt, schema, child);
11862 child = child->next;
11865 if (child != NULL) {
11866 if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11867 /* Complex content extension. */
11868 xmlSchemaPContentErr(ctxt,
11869 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11870 NULL, node, child, NULL,
11871 "(annotation?, ((group | all | choice | sequence)?, "
11872 "((attribute | attributeGroup)*, anyAttribute?)))");
11873 } else {
11874 /* Simple content extension. */
11875 xmlSchemaPContentErr(ctxt,
11876 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11877 NULL, node, child, NULL,
11878 "(annotation?, ((attribute | attributeGroup)*, "
11879 "anyAttribute?))");
11882 return (NULL);
11886 * xmlSchemaParseSimpleContent:
11887 * @ctxt: a schema validation context
11888 * @schema: the schema being built
11889 * @node: a subtree containing XML Schema informations
11891 * parse a XML schema SimpleContent definition
11892 * *WARNING* this interface is highly subject to change
11894 * Returns the type definition or NULL in case of error
11896 static int
11897 xmlSchemaParseSimpleContent(xmlSchemaParserCtxtPtr ctxt,
11898 xmlSchemaPtr schema, xmlNodePtr node,
11899 int *hasRestrictionOrExtension)
11901 xmlSchemaTypePtr type;
11902 xmlNodePtr child = NULL;
11903 xmlAttrPtr attr;
11905 if ((ctxt == NULL) || (schema == NULL) || (node == NULL) ||
11906 (hasRestrictionOrExtension == NULL))
11907 return (-1);
11908 *hasRestrictionOrExtension = 0;
11909 /* Not a component, don't create it. */
11910 type = ctxt->ctxtType;
11911 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
11913 * Check for illegal attributes.
11915 attr = node->properties;
11916 while (attr != NULL) {
11917 if (attr->ns == NULL) {
11918 if ((!xmlStrEqual(attr->name, BAD_CAST "id"))) {
11919 xmlSchemaPIllegalAttrErr(ctxt,
11920 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11922 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
11923 xmlSchemaPIllegalAttrErr(ctxt,
11924 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11926 attr = attr->next;
11929 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
11932 * And now for the children...
11934 child = node->children;
11935 if (IS_SCHEMA(child, "annotation")) {
11937 * Add the annotation to the complex type ancestor.
11939 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
11940 xmlSchemaParseAnnotation(ctxt, child, 1));
11941 child = child->next;
11943 if (child == NULL) {
11944 xmlSchemaPContentErr(ctxt,
11945 XML_SCHEMAP_S4S_ELEM_MISSING,
11946 NULL, node, NULL, NULL,
11947 "(annotation?, (restriction | extension))");
11949 if (child == NULL) {
11950 xmlSchemaPContentErr(ctxt,
11951 XML_SCHEMAP_S4S_ELEM_MISSING,
11952 NULL, node, NULL, NULL,
11953 "(annotation?, (restriction | extension))");
11955 if (IS_SCHEMA(child, "restriction")) {
11956 xmlSchemaParseRestriction(ctxt, schema, child,
11957 XML_SCHEMA_TYPE_SIMPLE_CONTENT);
11958 (*hasRestrictionOrExtension) = 1;
11959 child = child->next;
11960 } else if (IS_SCHEMA(child, "extension")) {
11961 xmlSchemaParseExtension(ctxt, schema, child,
11962 XML_SCHEMA_TYPE_SIMPLE_CONTENT);
11963 (*hasRestrictionOrExtension) = 1;
11964 child = child->next;
11966 if (child != NULL) {
11967 xmlSchemaPContentErr(ctxt,
11968 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11969 NULL, node, child, NULL,
11970 "(annotation?, (restriction | extension))");
11972 return (0);
11976 * xmlSchemaParseComplexContent:
11977 * @ctxt: a schema validation context
11978 * @schema: the schema being built
11979 * @node: a subtree containing XML Schema informations
11981 * parse a XML schema ComplexContent definition
11982 * *WARNING* this interface is highly subject to change
11984 * Returns the type definition or NULL in case of error
11986 static int
11987 xmlSchemaParseComplexContent(xmlSchemaParserCtxtPtr ctxt,
11988 xmlSchemaPtr schema, xmlNodePtr node,
11989 int *hasRestrictionOrExtension)
11991 xmlSchemaTypePtr type;
11992 xmlNodePtr child = NULL;
11993 xmlAttrPtr attr;
11995 if ((ctxt == NULL) || (schema == NULL) || (node == NULL) ||
11996 (hasRestrictionOrExtension == NULL))
11997 return (-1);
11998 *hasRestrictionOrExtension = 0;
11999 /* Not a component, don't create it. */
12000 type = ctxt->ctxtType;
12002 * Check for illegal attributes.
12004 attr = node->properties;
12005 while (attr != NULL) {
12006 if (attr->ns == NULL) {
12007 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
12008 (!xmlStrEqual(attr->name, BAD_CAST "mixed")))
12010 xmlSchemaPIllegalAttrErr(ctxt,
12011 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
12013 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
12014 xmlSchemaPIllegalAttrErr(ctxt,
12015 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
12017 attr = attr->next;
12020 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
12023 * Set the 'mixed' on the complex type ancestor.
12025 if (xmlGetBooleanProp(ctxt, node, "mixed", 0)) {
12026 if ((type->flags & XML_SCHEMAS_TYPE_MIXED) == 0)
12027 type->flags |= XML_SCHEMAS_TYPE_MIXED;
12029 child = node->children;
12030 if (IS_SCHEMA(child, "annotation")) {
12032 * Add the annotation to the complex type ancestor.
12034 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
12035 xmlSchemaParseAnnotation(ctxt, child, 1));
12036 child = child->next;
12038 if (child == NULL) {
12039 xmlSchemaPContentErr(ctxt,
12040 XML_SCHEMAP_S4S_ELEM_MISSING,
12041 NULL, node, NULL,
12042 NULL, "(annotation?, (restriction | extension))");
12044 if (child == NULL) {
12045 xmlSchemaPContentErr(ctxt,
12046 XML_SCHEMAP_S4S_ELEM_MISSING,
12047 NULL, node, NULL,
12048 NULL, "(annotation?, (restriction | extension))");
12050 if (IS_SCHEMA(child, "restriction")) {
12051 xmlSchemaParseRestriction(ctxt, schema, child,
12052 XML_SCHEMA_TYPE_COMPLEX_CONTENT);
12053 (*hasRestrictionOrExtension) = 1;
12054 child = child->next;
12055 } else if (IS_SCHEMA(child, "extension")) {
12056 xmlSchemaParseExtension(ctxt, schema, child,
12057 XML_SCHEMA_TYPE_COMPLEX_CONTENT);
12058 (*hasRestrictionOrExtension) = 1;
12059 child = child->next;
12061 if (child != NULL) {
12062 xmlSchemaPContentErr(ctxt,
12063 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
12064 NULL, node, child,
12065 NULL, "(annotation?, (restriction | extension))");
12067 return (0);
12071 * xmlSchemaParseComplexType:
12072 * @ctxt: a schema validation context
12073 * @schema: the schema being built
12074 * @node: a subtree containing XML Schema informations
12076 * parse a XML schema Complex Type definition
12077 * *WARNING* this interface is highly subject to change
12079 * Returns the type definition or NULL in case of error
12081 static xmlSchemaTypePtr
12082 xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
12083 xmlNodePtr node, int topLevel)
12085 xmlSchemaTypePtr type, ctxtType;
12086 xmlNodePtr child = NULL;
12087 const xmlChar *name = NULL;
12088 xmlAttrPtr attr;
12089 const xmlChar *attrValue;
12090 #ifdef ENABLE_NAMED_LOCALS
12091 char buf[40];
12092 #endif
12093 int final = 0, block = 0, hasRestrictionOrExtension = 0;
12096 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
12097 return (NULL);
12099 ctxtType = ctxt->ctxtType;
12101 if (topLevel) {
12102 attr = xmlSchemaGetPropNode(node, "name");
12103 if (attr == NULL) {
12104 xmlSchemaPMissingAttrErr(ctxt,
12105 XML_SCHEMAP_S4S_ATTR_MISSING, NULL, node, "name", NULL);
12106 return (NULL);
12107 } else if (xmlSchemaPValAttrNode(ctxt, NULL, attr,
12108 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
12109 return (NULL);
12113 if (topLevel == 0) {
12115 * Parse as local complex type definition.
12117 #ifdef ENABLE_NAMED_LOCALS
12118 snprintf(buf, 39, "#CT%d", ctxt->counter++ + 1);
12119 type = xmlSchemaAddType(ctxt, schema,
12120 XML_SCHEMA_TYPE_COMPLEX,
12121 xmlDictLookup(ctxt->dict, (const xmlChar *)buf, -1),
12122 ctxt->targetNamespace, node, 0);
12123 #else
12124 type = xmlSchemaAddType(ctxt, schema,
12125 XML_SCHEMA_TYPE_COMPLEX,
12126 NULL, ctxt->targetNamespace, node, 0);
12127 #endif
12128 if (type == NULL)
12129 return (NULL);
12130 name = type->name;
12131 type->node = node;
12132 type->type = XML_SCHEMA_TYPE_COMPLEX;
12134 * TODO: We need the target namespace.
12136 } else {
12138 * Parse as global complex type definition.
12140 type = xmlSchemaAddType(ctxt, schema,
12141 XML_SCHEMA_TYPE_COMPLEX,
12142 name, ctxt->targetNamespace, node, 1);
12143 if (type == NULL)
12144 return (NULL);
12145 type->node = node;
12146 type->type = XML_SCHEMA_TYPE_COMPLEX;
12147 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
12149 type->targetNamespace = ctxt->targetNamespace;
12151 * Handle attributes.
12153 attr = node->properties;
12154 while (attr != NULL) {
12155 if (attr->ns == NULL) {
12156 if (xmlStrEqual(attr->name, BAD_CAST "id")) {
12158 * Attribute "id".
12160 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
12161 } else if (xmlStrEqual(attr->name, BAD_CAST "mixed")) {
12163 * Attribute "mixed".
12165 if (xmlSchemaPGetBoolNodeValue(ctxt,
12166 NULL, (xmlNodePtr) attr))
12167 type->flags |= XML_SCHEMAS_TYPE_MIXED;
12168 } else if (topLevel) {
12170 * Attributes of global complex type definitions.
12172 if (xmlStrEqual(attr->name, BAD_CAST "name")) {
12173 /* Pass. */
12174 } else if (xmlStrEqual(attr->name, BAD_CAST "abstract")) {
12176 * Attribute "abstract".
12178 if (xmlSchemaPGetBoolNodeValue(ctxt,
12179 NULL, (xmlNodePtr) attr))
12180 type->flags |= XML_SCHEMAS_TYPE_ABSTRACT;
12181 } else if (xmlStrEqual(attr->name, BAD_CAST "final")) {
12183 * Attribute "final".
12185 attrValue = xmlSchemaGetNodeContent(ctxt,
12186 (xmlNodePtr) attr);
12187 if (xmlSchemaPValAttrBlockFinal(attrValue,
12188 &(type->flags),
12190 XML_SCHEMAS_TYPE_FINAL_EXTENSION,
12191 XML_SCHEMAS_TYPE_FINAL_RESTRICTION,
12192 -1, -1, -1) != 0)
12194 xmlSchemaPSimpleTypeErr(ctxt,
12195 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
12196 NULL, (xmlNodePtr) attr, NULL,
12197 "(#all | List of (extension | restriction))",
12198 attrValue, NULL, NULL, NULL);
12199 } else
12200 final = 1;
12201 } else if (xmlStrEqual(attr->name, BAD_CAST "block")) {
12203 * Attribute "block".
12205 attrValue = xmlSchemaGetNodeContent(ctxt,
12206 (xmlNodePtr) attr);
12207 if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
12209 XML_SCHEMAS_TYPE_BLOCK_EXTENSION,
12210 XML_SCHEMAS_TYPE_BLOCK_RESTRICTION,
12211 -1, -1, -1) != 0) {
12212 xmlSchemaPSimpleTypeErr(ctxt,
12213 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
12214 NULL, (xmlNodePtr) attr, NULL,
12215 "(#all | List of (extension | restriction)) ",
12216 attrValue, NULL, NULL, NULL);
12217 } else
12218 block = 1;
12219 } else {
12220 xmlSchemaPIllegalAttrErr(ctxt,
12221 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
12223 } else {
12224 xmlSchemaPIllegalAttrErr(ctxt,
12225 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
12227 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
12228 xmlSchemaPIllegalAttrErr(ctxt,
12229 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
12231 attr = attr->next;
12233 if (! block) {
12235 * Apply default "block" values.
12237 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
12238 type->flags |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
12239 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
12240 type->flags |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
12242 if (! final) {
12244 * Apply default "block" values.
12246 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
12247 type->flags |= XML_SCHEMAS_TYPE_FINAL_RESTRICTION;
12248 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
12249 type->flags |= XML_SCHEMAS_TYPE_FINAL_EXTENSION;
12252 * And now for the children...
12254 child = node->children;
12255 if (IS_SCHEMA(child, "annotation")) {
12256 type->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
12257 child = child->next;
12259 ctxt->ctxtType = type;
12260 if (IS_SCHEMA(child, "simpleContent")) {
12262 * <complexType><simpleContent>...
12263 * 3.4.3 : 2.2
12264 * Specifying mixed='true' when the <simpleContent>
12265 * alternative is chosen has no effect
12267 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
12268 type->flags ^= XML_SCHEMAS_TYPE_MIXED;
12269 xmlSchemaParseSimpleContent(ctxt, schema, child,
12270 &hasRestrictionOrExtension);
12271 child = child->next;
12272 } else if (IS_SCHEMA(child, "complexContent")) {
12274 * <complexType><complexContent>...
12276 type->contentType = XML_SCHEMA_CONTENT_EMPTY;
12277 xmlSchemaParseComplexContent(ctxt, schema, child,
12278 &hasRestrictionOrExtension);
12279 child = child->next;
12280 } else {
12282 * E.g <complexType><sequence>... or <complexType><attribute>... etc.
12284 * SPEC
12285 * "...the third alternative (neither <simpleContent> nor
12286 * <complexContent>) is chosen. This case is understood as shorthand
12287 * for complex content restricting the �ur-type definition�, and the
12288 * details of the mappings should be modified as necessary.
12290 type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
12291 type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
12293 * Parse model groups.
12295 if (IS_SCHEMA(child, "all")) {
12296 type->subtypes = (xmlSchemaTypePtr)
12297 xmlSchemaParseModelGroup(ctxt, schema, child,
12298 XML_SCHEMA_TYPE_ALL, 1);
12299 child = child->next;
12300 } else if (IS_SCHEMA(child, "choice")) {
12301 type->subtypes = (xmlSchemaTypePtr)
12302 xmlSchemaParseModelGroup(ctxt, schema, child,
12303 XML_SCHEMA_TYPE_CHOICE, 1);
12304 child = child->next;
12305 } else if (IS_SCHEMA(child, "sequence")) {
12306 type->subtypes = (xmlSchemaTypePtr)
12307 xmlSchemaParseModelGroup(ctxt, schema, child,
12308 XML_SCHEMA_TYPE_SEQUENCE, 1);
12309 child = child->next;
12310 } else if (IS_SCHEMA(child, "group")) {
12311 type->subtypes = (xmlSchemaTypePtr)
12312 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
12314 * Note that the reference will be resolved in
12315 * xmlSchemaResolveTypeReferences();
12317 child = child->next;
12320 * Parse attribute decls/refs.
12322 if (xmlSchemaParseLocalAttributes(ctxt, schema, &child,
12323 (xmlSchemaItemListPtr *) &(type->attrUses),
12324 XML_SCHEMA_TYPE_RESTRICTION, NULL) == -1)
12325 return(NULL);
12327 * Parse attribute wildcard.
12329 if (IS_SCHEMA(child, "anyAttribute")) {
12330 type->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
12331 child = child->next;
12334 if (child != NULL) {
12335 xmlSchemaPContentErr(ctxt,
12336 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
12337 NULL, node, child,
12338 NULL, "(annotation?, (simpleContent | complexContent | "
12339 "((group | all | choice | sequence)?, ((attribute | "
12340 "attributeGroup)*, anyAttribute?))))");
12343 * REDEFINE: SPEC src-redefine (5)
12345 if (topLevel && ctxt->isRedefine && (! hasRestrictionOrExtension)) {
12346 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_SRC_REDEFINE,
12347 NULL, node, "This is a redefinition, thus the "
12348 "<complexType> must have a <restriction> or <extension> "
12349 "grand-child", NULL);
12351 ctxt->ctxtType = ctxtType;
12352 return (type);
12355 /************************************************************************
12357 * Validating using Schemas *
12359 ************************************************************************/
12361 /************************************************************************
12363 * Reading/Writing Schemas *
12365 ************************************************************************/
12367 #if 0 /* Will be enabled if it is clear what options are needed. */
12369 * xmlSchemaParserCtxtSetOptions:
12370 * @ctxt: a schema parser context
12371 * @options: a combination of xmlSchemaParserOption
12373 * Sets the options to be used during the parse.
12375 * Returns 0 in case of success, -1 in case of an
12376 * API error.
12378 static int
12379 xmlSchemaParserCtxtSetOptions(xmlSchemaParserCtxtPtr ctxt,
12380 int options)
12383 int i;
12385 if (ctxt == NULL)
12386 return (-1);
12388 * WARNING: Change the start value if adding to the
12389 * xmlSchemaParseOption.
12391 for (i = 1; i < (int) sizeof(int) * 8; i++) {
12392 if (options & 1<<i) {
12393 return (-1);
12396 ctxt->options = options;
12397 return (0);
12401 * xmlSchemaValidCtxtGetOptions:
12402 * @ctxt: a schema parser context
12404 * Returns the option combination of the parser context.
12406 static int
12407 xmlSchemaParserCtxtGetOptions(xmlSchemaParserCtxtPtr ctxt)
12410 if (ctxt == NULL)
12411 return (-1);
12412 else
12413 return (ctxt->options);
12415 #endif
12418 * xmlSchemaNewParserCtxt:
12419 * @URL: the location of the schema
12421 * Create an XML Schemas parse context for that file/resource expected
12422 * to contain an XML Schemas file.
12424 * Returns the parser context or NULL in case of error
12426 xmlSchemaParserCtxtPtr
12427 xmlSchemaNewParserCtxt(const char *URL)
12429 xmlSchemaParserCtxtPtr ret;
12431 if (URL == NULL)
12432 return (NULL);
12434 ret = xmlSchemaParserCtxtCreate();
12435 if (ret == NULL)
12436 return(NULL);
12437 ret->dict = xmlDictCreate();
12438 ret->URL = xmlDictLookup(ret->dict, (const xmlChar *) URL, -1);
12439 return (ret);
12443 * xmlSchemaNewMemParserCtxt:
12444 * @buffer: a pointer to a char array containing the schemas
12445 * @size: the size of the array
12447 * Create an XML Schemas parse context for that memory buffer expected
12448 * to contain an XML Schemas file.
12450 * Returns the parser context or NULL in case of error
12452 xmlSchemaParserCtxtPtr
12453 xmlSchemaNewMemParserCtxt(const char *buffer, int size)
12455 xmlSchemaParserCtxtPtr ret;
12457 if ((buffer == NULL) || (size <= 0))
12458 return (NULL);
12459 ret = xmlSchemaParserCtxtCreate();
12460 if (ret == NULL)
12461 return(NULL);
12462 ret->buffer = buffer;
12463 ret->size = size;
12464 ret->dict = xmlDictCreate();
12465 return (ret);
12469 * xmlSchemaNewDocParserCtxt:
12470 * @doc: a preparsed document tree
12472 * Create an XML Schemas parse context for that document.
12473 * NB. The document may be modified during the parsing process.
12475 * Returns the parser context or NULL in case of error
12477 xmlSchemaParserCtxtPtr
12478 xmlSchemaNewDocParserCtxt(xmlDocPtr doc)
12480 xmlSchemaParserCtxtPtr ret;
12482 if (doc == NULL)
12483 return (NULL);
12484 ret = xmlSchemaParserCtxtCreate();
12485 if (ret == NULL)
12486 return(NULL);
12487 ret->doc = doc;
12488 ret->dict = xmlDictCreate();
12489 /* The application has responsibility for the document */
12490 ret->preserve = 1;
12492 return (ret);
12496 * xmlSchemaFreeParserCtxt:
12497 * @ctxt: the schema parser context
12499 * Free the resources associated to the schema parser context
12501 void
12502 xmlSchemaFreeParserCtxt(xmlSchemaParserCtxtPtr ctxt)
12504 if (ctxt == NULL)
12505 return;
12506 if (ctxt->doc != NULL && !ctxt->preserve)
12507 xmlFreeDoc(ctxt->doc);
12508 if (ctxt->vctxt != NULL) {
12509 xmlSchemaFreeValidCtxt(ctxt->vctxt);
12511 if (ctxt->ownsConstructor && (ctxt->constructor != NULL)) {
12512 xmlSchemaConstructionCtxtFree(ctxt->constructor);
12513 ctxt->constructor = NULL;
12514 ctxt->ownsConstructor = 0;
12516 if (ctxt->attrProhibs != NULL)
12517 xmlSchemaItemListFree(ctxt->attrProhibs);
12518 xmlDictFree(ctxt->dict);
12519 xmlFree(ctxt);
12522 /************************************************************************
12524 * Building the content models *
12526 ************************************************************************/
12529 * xmlSchemaBuildContentModelForSubstGroup:
12531 * Returns 1 if nillable, 0 otherwise
12533 static int
12534 xmlSchemaBuildContentModelForSubstGroup(xmlSchemaParserCtxtPtr pctxt,
12535 xmlSchemaParticlePtr particle, int counter, xmlAutomataStatePtr end)
12537 xmlAutomataStatePtr start, tmp;
12538 xmlSchemaElementPtr elemDecl, member;
12539 xmlSchemaSubstGroupPtr substGroup;
12540 int i;
12541 int ret = 0;
12543 elemDecl = (xmlSchemaElementPtr) particle->children;
12545 * Wrap the substitution group with a CHOICE.
12547 start = pctxt->state;
12548 if (end == NULL)
12549 end = xmlAutomataNewState(pctxt->am);
12550 substGroup = xmlSchemaSubstGroupGet(pctxt, elemDecl);
12551 if (substGroup == NULL) {
12552 xmlSchemaPErr(pctxt, WXS_ITEM_NODE(particle),
12553 XML_SCHEMAP_INTERNAL,
12554 "Internal error: xmlSchemaBuildContentModelForSubstGroup, "
12555 "declaration is marked having a subst. group but none "
12556 "available.\n", elemDecl->name, NULL);
12557 return(0);
12559 if (counter >= 0) {
12561 * NOTE that we put the declaration in, even if it's abstract.
12562 * However, an error will be raised during *validation* if an element
12563 * information item shall be validated against an abstract element
12564 * declaration.
12566 tmp = xmlAutomataNewCountedTrans(pctxt->am, start, NULL, counter);
12567 xmlAutomataNewTransition2(pctxt->am, tmp, end,
12568 elemDecl->name, elemDecl->targetNamespace, elemDecl);
12570 * Add subst. group members.
12572 for (i = 0; i < substGroup->members->nbItems; i++) {
12573 member = (xmlSchemaElementPtr) substGroup->members->items[i];
12574 xmlAutomataNewTransition2(pctxt->am, tmp, end,
12575 member->name, member->targetNamespace, member);
12577 } else if (particle->maxOccurs == 1) {
12579 * NOTE that we put the declaration in, even if it's abstract,
12581 xmlAutomataNewEpsilon(pctxt->am,
12582 xmlAutomataNewTransition2(pctxt->am,
12583 start, NULL,
12584 elemDecl->name, elemDecl->targetNamespace, elemDecl), end);
12586 * Add subst. group members.
12588 for (i = 0; i < substGroup->members->nbItems; i++) {
12589 member = (xmlSchemaElementPtr) substGroup->members->items[i];
12591 * NOTE: This fixes bug #341150. xmlAutomataNewOnceTrans2()
12592 * was incorrectly used instead of xmlAutomataNewTransition2()
12593 * (seems like a copy&paste bug from the XML_SCHEMA_TYPE_ALL
12594 * section in xmlSchemaBuildAContentModel() ).
12595 * TODO: Check if xmlAutomataNewOnceTrans2() was instead
12596 * intended for the above "counter" section originally. I.e.,
12597 * check xs:all with subst-groups.
12599 * tmp = xmlAutomataNewOnceTrans2(pctxt->am, start, NULL,
12600 * member->name, member->targetNamespace,
12601 * 1, 1, member);
12603 tmp = xmlAutomataNewTransition2(pctxt->am, start, NULL,
12604 member->name, member->targetNamespace, member);
12605 xmlAutomataNewEpsilon(pctxt->am, tmp, end);
12607 } else {
12608 xmlAutomataStatePtr hop;
12609 int maxOccurs = particle->maxOccurs == UNBOUNDED ?
12610 UNBOUNDED : particle->maxOccurs - 1;
12611 int minOccurs = particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
12613 counter =
12614 xmlAutomataNewCounter(pctxt->am, minOccurs,
12615 maxOccurs);
12616 hop = xmlAutomataNewState(pctxt->am);
12618 xmlAutomataNewEpsilon(pctxt->am,
12619 xmlAutomataNewTransition2(pctxt->am,
12620 start, NULL,
12621 elemDecl->name, elemDecl->targetNamespace, elemDecl),
12622 hop);
12624 * Add subst. group members.
12626 for (i = 0; i < substGroup->members->nbItems; i++) {
12627 member = (xmlSchemaElementPtr) substGroup->members->items[i];
12628 xmlAutomataNewEpsilon(pctxt->am,
12629 xmlAutomataNewTransition2(pctxt->am,
12630 start, NULL,
12631 member->name, member->targetNamespace, member),
12632 hop);
12634 xmlAutomataNewCountedTrans(pctxt->am, hop, start, counter);
12635 xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
12637 if (particle->minOccurs == 0) {
12638 xmlAutomataNewEpsilon(pctxt->am, start, end);
12639 ret = 1;
12641 pctxt->state = end;
12642 return(ret);
12646 * xmlSchemaBuildContentModelForElement:
12648 * Returns 1 if nillable, 0 otherwise
12650 static int
12651 xmlSchemaBuildContentModelForElement(xmlSchemaParserCtxtPtr ctxt,
12652 xmlSchemaParticlePtr particle)
12654 int ret = 0;
12656 if (((xmlSchemaElementPtr) particle->children)->flags &
12657 XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) {
12659 * Substitution groups.
12661 ret = xmlSchemaBuildContentModelForSubstGroup(ctxt, particle, -1, NULL);
12662 } else {
12663 xmlSchemaElementPtr elemDecl;
12664 xmlAutomataStatePtr start;
12666 elemDecl = (xmlSchemaElementPtr) particle->children;
12668 if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT)
12669 return(0);
12670 if (particle->maxOccurs == 1) {
12671 start = ctxt->state;
12672 ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
12673 elemDecl->name, elemDecl->targetNamespace, elemDecl);
12674 } else if ((particle->maxOccurs >= UNBOUNDED) &&
12675 (particle->minOccurs < 2)) {
12676 /* Special case. */
12677 start = ctxt->state;
12678 ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
12679 elemDecl->name, elemDecl->targetNamespace, elemDecl);
12680 ctxt->state = xmlAutomataNewTransition2(ctxt->am, ctxt->state, ctxt->state,
12681 elemDecl->name, elemDecl->targetNamespace, elemDecl);
12682 } else {
12683 int counter;
12684 int maxOccurs = particle->maxOccurs == UNBOUNDED ?
12685 UNBOUNDED : particle->maxOccurs - 1;
12686 int minOccurs = particle->minOccurs < 1 ?
12687 0 : particle->minOccurs - 1;
12689 start = xmlAutomataNewEpsilon(ctxt->am, ctxt->state, NULL);
12690 counter = xmlAutomataNewCounter(ctxt->am, minOccurs, maxOccurs);
12691 ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
12692 elemDecl->name, elemDecl->targetNamespace, elemDecl);
12693 xmlAutomataNewCountedTrans(ctxt->am, ctxt->state, start, counter);
12694 ctxt->state = xmlAutomataNewCounterTrans(ctxt->am, ctxt->state,
12695 NULL, counter);
12697 if (particle->minOccurs == 0) {
12698 xmlAutomataNewEpsilon(ctxt->am, start, ctxt->state);
12699 ret = 1;
12702 return(ret);
12706 * xmlSchemaBuildAContentModel:
12707 * @ctxt: the schema parser context
12708 * @particle: the particle component
12709 * @name: the complex type's name whose content is being built
12711 * Create the automaton for the {content type} of a complex type.
12713 * Returns 1 if the content is nillable, 0 otherwise
12715 static int
12716 xmlSchemaBuildAContentModel(xmlSchemaParserCtxtPtr pctxt,
12717 xmlSchemaParticlePtr particle)
12719 int ret = 0, tmp2;
12721 if (particle == NULL) {
12722 PERROR_INT("xmlSchemaBuildAContentModel", "particle is NULL");
12723 return(1);
12725 if (particle->children == NULL) {
12727 * Just return in this case. A missing "term" of the particle
12728 * might arise due to an invalid "term" component.
12730 return(1);
12733 switch (particle->children->type) {
12734 case XML_SCHEMA_TYPE_ANY: {
12735 xmlAutomataStatePtr start, end;
12736 xmlSchemaWildcardPtr wild;
12737 xmlSchemaWildcardNsPtr ns;
12739 wild = (xmlSchemaWildcardPtr) particle->children;
12741 start = pctxt->state;
12742 end = xmlAutomataNewState(pctxt->am);
12744 if (particle->maxOccurs == 1) {
12745 if (wild->any == 1) {
12747 * We need to add both transitions:
12749 * 1. the {"*", "*"} for elements in a namespace.
12751 pctxt->state =
12752 xmlAutomataNewTransition2(pctxt->am,
12753 start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
12754 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
12756 * 2. the {"*"} for elements in no namespace.
12758 pctxt->state =
12759 xmlAutomataNewTransition2(pctxt->am,
12760 start, NULL, BAD_CAST "*", NULL, wild);
12761 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
12763 } else if (wild->nsSet != NULL) {
12764 ns = wild->nsSet;
12765 do {
12766 pctxt->state = start;
12767 pctxt->state = xmlAutomataNewTransition2(pctxt->am,
12768 pctxt->state, NULL, BAD_CAST "*", ns->value, wild);
12769 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
12770 ns = ns->next;
12771 } while (ns != NULL);
12773 } else if (wild->negNsSet != NULL) {
12774 pctxt->state = xmlAutomataNewNegTrans(pctxt->am,
12775 start, end, BAD_CAST "*", wild->negNsSet->value,
12776 wild);
12778 } else {
12779 int counter;
12780 xmlAutomataStatePtr hop;
12781 int maxOccurs =
12782 particle->maxOccurs == UNBOUNDED ? UNBOUNDED :
12783 particle->maxOccurs - 1;
12784 int minOccurs =
12785 particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
12787 counter = xmlAutomataNewCounter(pctxt->am, minOccurs, maxOccurs);
12788 hop = xmlAutomataNewState(pctxt->am);
12789 if (wild->any == 1) {
12790 pctxt->state =
12791 xmlAutomataNewTransition2(pctxt->am,
12792 start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
12793 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
12794 pctxt->state =
12795 xmlAutomataNewTransition2(pctxt->am,
12796 start, NULL, BAD_CAST "*", NULL, wild);
12797 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
12798 } else if (wild->nsSet != NULL) {
12799 ns = wild->nsSet;
12800 do {
12801 pctxt->state =
12802 xmlAutomataNewTransition2(pctxt->am,
12803 start, NULL, BAD_CAST "*", ns->value, wild);
12804 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
12805 ns = ns->next;
12806 } while (ns != NULL);
12808 } else if (wild->negNsSet != NULL) {
12809 pctxt->state = xmlAutomataNewNegTrans(pctxt->am,
12810 start, hop, BAD_CAST "*", wild->negNsSet->value,
12811 wild);
12813 xmlAutomataNewCountedTrans(pctxt->am, hop, start, counter);
12814 xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
12816 if (particle->minOccurs == 0) {
12817 xmlAutomataNewEpsilon(pctxt->am, start, end);
12818 ret = 1;
12820 pctxt->state = end;
12821 break;
12823 case XML_SCHEMA_TYPE_ELEMENT:
12824 ret = xmlSchemaBuildContentModelForElement(pctxt, particle);
12825 break;
12826 case XML_SCHEMA_TYPE_SEQUENCE:{
12827 xmlSchemaTreeItemPtr sub;
12829 ret = 1;
12831 * If max and min occurances are default (1) then
12832 * simply iterate over the particles of the <sequence>.
12834 if ((particle->minOccurs == 1) && (particle->maxOccurs == 1)) {
12835 sub = particle->children->children;
12837 while (sub != NULL) {
12838 tmp2 = xmlSchemaBuildAContentModel(pctxt,
12839 (xmlSchemaParticlePtr) sub);
12840 if (tmp2 != 1) ret = 0;
12841 sub = sub->next;
12843 } else {
12844 xmlAutomataStatePtr oldstate = pctxt->state;
12846 if (particle->maxOccurs >= UNBOUNDED) {
12847 if (particle->minOccurs > 1) {
12848 xmlAutomataStatePtr tmp;
12849 int counter;
12851 pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
12852 oldstate, NULL);
12853 oldstate = pctxt->state;
12855 counter = xmlAutomataNewCounter(pctxt->am,
12856 particle->minOccurs - 1, UNBOUNDED);
12858 sub = particle->children->children;
12859 while (sub != NULL) {
12860 tmp2 = xmlSchemaBuildAContentModel(pctxt,
12861 (xmlSchemaParticlePtr) sub);
12862 if (tmp2 != 1) ret = 0;
12863 sub = sub->next;
12865 tmp = pctxt->state;
12866 xmlAutomataNewCountedTrans(pctxt->am, tmp,
12867 oldstate, counter);
12868 pctxt->state =
12869 xmlAutomataNewCounterTrans(pctxt->am, tmp,
12870 NULL, counter);
12871 if (ret == 1)
12872 xmlAutomataNewEpsilon(pctxt->am,
12873 oldstate, pctxt->state);
12875 } else {
12876 pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
12877 oldstate, NULL);
12878 oldstate = pctxt->state;
12880 sub = particle->children->children;
12881 while (sub != NULL) {
12882 tmp2 = xmlSchemaBuildAContentModel(pctxt,
12883 (xmlSchemaParticlePtr) sub);
12884 if (tmp2 != 1) ret = 0;
12885 sub = sub->next;
12887 xmlAutomataNewEpsilon(pctxt->am, pctxt->state,
12888 oldstate);
12890 * epsilon needed to block previous trans from
12891 * being allowed to enter back from another
12892 * construct
12894 pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
12895 pctxt->state, NULL);
12896 if (particle->minOccurs == 0) {
12897 xmlAutomataNewEpsilon(pctxt->am,
12898 oldstate, pctxt->state);
12899 ret = 1;
12902 } else if ((particle->maxOccurs > 1)
12903 || (particle->minOccurs > 1)) {
12904 xmlAutomataStatePtr tmp;
12905 int counter;
12907 pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
12908 oldstate, NULL);
12909 oldstate = pctxt->state;
12911 counter = xmlAutomataNewCounter(pctxt->am,
12912 particle->minOccurs - 1,
12913 particle->maxOccurs - 1);
12915 sub = particle->children->children;
12916 while (sub != NULL) {
12917 tmp2 = xmlSchemaBuildAContentModel(pctxt,
12918 (xmlSchemaParticlePtr) sub);
12919 if (tmp2 != 1) ret = 0;
12920 sub = sub->next;
12922 tmp = pctxt->state;
12923 xmlAutomataNewCountedTrans(pctxt->am,
12924 tmp, oldstate, counter);
12925 pctxt->state =
12926 xmlAutomataNewCounterTrans(pctxt->am, tmp, NULL,
12927 counter);
12928 if ((particle->minOccurs == 0) || (ret == 1)) {
12929 xmlAutomataNewEpsilon(pctxt->am,
12930 oldstate, pctxt->state);
12931 ret = 1;
12933 } else {
12934 sub = particle->children->children;
12935 while (sub != NULL) {
12936 tmp2 = xmlSchemaBuildAContentModel(pctxt,
12937 (xmlSchemaParticlePtr) sub);
12938 if (tmp2 != 1) ret = 0;
12939 sub = sub->next;
12941 if (particle->minOccurs == 0) {
12942 xmlAutomataNewEpsilon(pctxt->am, oldstate,
12943 pctxt->state);
12944 ret = 1;
12948 break;
12950 case XML_SCHEMA_TYPE_CHOICE:{
12951 xmlSchemaTreeItemPtr sub;
12952 xmlAutomataStatePtr start, end;
12954 ret = 0;
12955 start = pctxt->state;
12956 end = xmlAutomataNewState(pctxt->am);
12959 * iterate over the subtypes and remerge the end with an
12960 * epsilon transition
12962 if (particle->maxOccurs == 1) {
12963 sub = particle->children->children;
12964 while (sub != NULL) {
12965 pctxt->state = start;
12966 tmp2 = xmlSchemaBuildAContentModel(pctxt,
12967 (xmlSchemaParticlePtr) sub);
12968 if (tmp2 == 1) ret = 1;
12969 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
12970 sub = sub->next;
12972 } else {
12973 int counter;
12974 xmlAutomataStatePtr hop, base;
12975 int maxOccurs = particle->maxOccurs == UNBOUNDED ?
12976 UNBOUNDED : particle->maxOccurs - 1;
12977 int minOccurs =
12978 particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
12981 * use a counter to keep track of the number of transtions
12982 * which went through the choice.
12984 counter =
12985 xmlAutomataNewCounter(pctxt->am, minOccurs, maxOccurs);
12986 hop = xmlAutomataNewState(pctxt->am);
12987 base = xmlAutomataNewState(pctxt->am);
12989 sub = particle->children->children;
12990 while (sub != NULL) {
12991 pctxt->state = base;
12992 tmp2 = xmlSchemaBuildAContentModel(pctxt,
12993 (xmlSchemaParticlePtr) sub);
12994 if (tmp2 == 1) ret = 1;
12995 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
12996 sub = sub->next;
12998 xmlAutomataNewEpsilon(pctxt->am, start, base);
12999 xmlAutomataNewCountedTrans(pctxt->am, hop, base, counter);
13000 xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
13001 if (ret == 1)
13002 xmlAutomataNewEpsilon(pctxt->am, base, end);
13004 if (particle->minOccurs == 0) {
13005 xmlAutomataNewEpsilon(pctxt->am, start, end);
13006 ret = 1;
13008 pctxt->state = end;
13009 break;
13011 case XML_SCHEMA_TYPE_ALL:{
13012 xmlAutomataStatePtr start, tmp;
13013 xmlSchemaParticlePtr sub;
13014 xmlSchemaElementPtr elemDecl;
13016 ret = 1;
13018 sub = (xmlSchemaParticlePtr) particle->children->children;
13019 if (sub == NULL)
13020 break;
13022 ret = 0;
13024 start = pctxt->state;
13025 tmp = xmlAutomataNewState(pctxt->am);
13026 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, tmp);
13027 pctxt->state = tmp;
13028 while (sub != NULL) {
13029 pctxt->state = tmp;
13031 elemDecl = (xmlSchemaElementPtr) sub->children;
13032 if (elemDecl == NULL) {
13033 PERROR_INT("xmlSchemaBuildAContentModel",
13034 "<element> particle has no term");
13035 return(ret);
13038 * NOTE: The {max occurs} of all the particles in the
13039 * {particles} of the group must be 0 or 1; this is
13040 * already ensured during the parse of the content of
13041 * <all>.
13043 if (elemDecl->flags & XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) {
13044 int counter;
13047 * This is an abstract group, we need to share
13048 * the same counter for all the element transitions
13049 * derived from the group
13051 counter = xmlAutomataNewCounter(pctxt->am,
13052 sub->minOccurs, sub->maxOccurs);
13053 xmlSchemaBuildContentModelForSubstGroup(pctxt,
13054 sub, counter, pctxt->state);
13055 } else {
13056 if ((sub->minOccurs == 1) &&
13057 (sub->maxOccurs == 1)) {
13058 xmlAutomataNewOnceTrans2(pctxt->am, pctxt->state,
13059 pctxt->state,
13060 elemDecl->name,
13061 elemDecl->targetNamespace,
13062 1, 1, elemDecl);
13063 } else if ((sub->minOccurs == 0) &&
13064 (sub->maxOccurs == 1)) {
13066 xmlAutomataNewCountTrans2(pctxt->am, pctxt->state,
13067 pctxt->state,
13068 elemDecl->name,
13069 elemDecl->targetNamespace,
13072 elemDecl);
13075 sub = (xmlSchemaParticlePtr) sub->next;
13077 pctxt->state =
13078 xmlAutomataNewAllTrans(pctxt->am, pctxt->state, NULL, 0);
13079 if (particle->minOccurs == 0) {
13080 xmlAutomataNewEpsilon(pctxt->am, start, pctxt->state);
13081 ret = 1;
13083 break;
13085 case XML_SCHEMA_TYPE_GROUP:
13087 * If we hit a model group definition, then this means that
13088 * it was empty, thus was not substituted for the containing
13089 * model group. Just do nothing in this case.
13090 * TODO: But the group should be substituted and not occur at
13091 * all in the content model at this point. Fix this.
13093 ret = 1;
13094 break;
13095 default:
13096 xmlSchemaInternalErr2(ACTXT_CAST pctxt,
13097 "xmlSchemaBuildAContentModel",
13098 "found unexpected term of type '%s' in content model",
13099 WXS_ITEM_TYPE_NAME(particle->children), NULL);
13100 return(ret);
13102 return(ret);
13106 * xmlSchemaBuildContentModel:
13107 * @ctxt: the schema parser context
13108 * @type: the complex type definition
13109 * @name: the element name
13111 * Builds the content model of the complex type.
13113 static void
13114 xmlSchemaBuildContentModel(xmlSchemaTypePtr type,
13115 xmlSchemaParserCtxtPtr ctxt)
13117 if ((type->type != XML_SCHEMA_TYPE_COMPLEX) ||
13118 (type->contModel != NULL) ||
13119 ((type->contentType != XML_SCHEMA_CONTENT_ELEMENTS) &&
13120 (type->contentType != XML_SCHEMA_CONTENT_MIXED)))
13121 return;
13123 #ifdef DEBUG_CONTENT
13124 xmlGenericError(xmlGenericErrorContext,
13125 "Building content model for %s\n", name);
13126 #endif
13127 ctxt->am = NULL;
13128 ctxt->am = xmlNewAutomata();
13129 if (ctxt->am == NULL) {
13130 xmlGenericError(xmlGenericErrorContext,
13131 "Cannot create automata for complex type %s\n", type->name);
13132 return;
13134 ctxt->state = xmlAutomataGetInitState(ctxt->am);
13136 * Build the automaton.
13138 xmlSchemaBuildAContentModel(ctxt, WXS_TYPE_PARTICLE(type));
13139 xmlAutomataSetFinalState(ctxt->am, ctxt->state);
13140 type->contModel = xmlAutomataCompile(ctxt->am);
13141 if (type->contModel == NULL) {
13142 xmlSchemaPCustomErr(ctxt,
13143 XML_SCHEMAP_INTERNAL,
13144 WXS_BASIC_CAST type, type->node,
13145 "Failed to compile the content model", NULL);
13146 } else if (xmlRegexpIsDeterminist(type->contModel) != 1) {
13147 xmlSchemaPCustomErr(ctxt,
13148 XML_SCHEMAP_NOT_DETERMINISTIC,
13149 /* XML_SCHEMAS_ERR_NOTDETERMINIST, */
13150 WXS_BASIC_CAST type, type->node,
13151 "The content model is not determinist", NULL);
13152 } else {
13153 #ifdef DEBUG_CONTENT_REGEXP
13154 xmlGenericError(xmlGenericErrorContext,
13155 "Content model of %s:\n", type->name);
13156 xmlRegexpPrint(stderr, type->contModel);
13157 #endif
13159 ctxt->state = NULL;
13160 xmlFreeAutomata(ctxt->am);
13161 ctxt->am = NULL;
13165 * xmlSchemaResolveElementReferences:
13166 * @elem: the schema element context
13167 * @ctxt: the schema parser context
13169 * Resolves the references of an element declaration
13170 * or particle, which has an element declaration as it's
13171 * term.
13173 static void
13174 xmlSchemaResolveElementReferences(xmlSchemaElementPtr elemDecl,
13175 xmlSchemaParserCtxtPtr ctxt)
13177 if ((ctxt == NULL) || (elemDecl == NULL) ||
13178 ((elemDecl != NULL) &&
13179 (elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_RESOLVED)))
13180 return;
13181 elemDecl->flags |= XML_SCHEMAS_ELEM_INTERNAL_RESOLVED;
13183 if ((elemDecl->subtypes == NULL) && (elemDecl->namedType != NULL)) {
13184 xmlSchemaTypePtr type;
13186 /* (type definition) ... otherwise the type definition �resolved�
13187 * to by the �actual value� of the type [attribute] ...
13189 type = xmlSchemaGetType(ctxt->schema, elemDecl->namedType,
13190 elemDecl->namedTypeNs);
13191 if (type == NULL) {
13192 xmlSchemaPResCompAttrErr(ctxt,
13193 XML_SCHEMAP_SRC_RESOLVE,
13194 WXS_BASIC_CAST elemDecl, elemDecl->node,
13195 "type", elemDecl->namedType, elemDecl->namedTypeNs,
13196 XML_SCHEMA_TYPE_BASIC, "type definition");
13197 } else
13198 elemDecl->subtypes = type;
13200 if (elemDecl->substGroup != NULL) {
13201 xmlSchemaElementPtr substHead;
13204 * FIXME TODO: Do we need a new field in _xmlSchemaElement for
13205 * substitutionGroup?
13207 substHead = xmlSchemaGetElem(ctxt->schema, elemDecl->substGroup,
13208 elemDecl->substGroupNs);
13209 if (substHead == NULL) {
13210 xmlSchemaPResCompAttrErr(ctxt,
13211 XML_SCHEMAP_SRC_RESOLVE,
13212 WXS_BASIC_CAST elemDecl, NULL,
13213 "substitutionGroup", elemDecl->substGroup,
13214 elemDecl->substGroupNs, XML_SCHEMA_TYPE_ELEMENT, NULL);
13215 } else {
13216 xmlSchemaResolveElementReferences(substHead, ctxt);
13218 * Set the "substitution group affiliation".
13219 * NOTE that now we use the "refDecl" field for this.
13221 WXS_SUBST_HEAD(elemDecl) = substHead;
13223 * The type definitions is set to:
13224 * SPEC "...the {type definition} of the element
13225 * declaration �resolved� to by the �actual value�
13226 * of the substitutionGroup [attribute], if present"
13228 if (elemDecl->subtypes == NULL)
13229 elemDecl->subtypes = substHead->subtypes;
13233 * SPEC "The definition of anyType serves as the default type definition
13234 * for element declarations whose XML representation does not specify one."
13236 if ((elemDecl->subtypes == NULL) &&
13237 (elemDecl->namedType == NULL) &&
13238 (elemDecl->substGroup == NULL))
13239 elemDecl->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
13243 * xmlSchemaResolveUnionMemberTypes:
13244 * @ctxt: the schema parser context
13245 * @type: the schema simple type definition
13247 * Checks and builds the "member type definitions" property of the union
13248 * simple type. This handles part (1), part (2) is done in
13249 * xmlSchemaFinishMemberTypeDefinitionsProperty()
13251 * Returns -1 in case of an internal error, 0 otherwise.
13253 static int
13254 xmlSchemaResolveUnionMemberTypes(xmlSchemaParserCtxtPtr ctxt,
13255 xmlSchemaTypePtr type)
13258 xmlSchemaTypeLinkPtr link, lastLink, newLink;
13259 xmlSchemaTypePtr memberType;
13262 * SPEC (1) "If the <union> alternative is chosen, then [Definition:]
13263 * define the explicit members as the type definitions �resolved�
13264 * to by the items in the �actual value� of the memberTypes [attribute],
13265 * if any, followed by the type definitions corresponding to the
13266 * <simpleType>s among the [children] of <union>, if any."
13269 * Resolve references.
13271 link = type->memberTypes;
13272 lastLink = NULL;
13273 while (link != NULL) {
13274 const xmlChar *name, *nsName;
13276 name = ((xmlSchemaQNameRefPtr) link->type)->name;
13277 nsName = ((xmlSchemaQNameRefPtr) link->type)->targetNamespace;
13279 memberType = xmlSchemaGetType(ctxt->schema, name, nsName);
13280 if ((memberType == NULL) || (! WXS_IS_SIMPLE(memberType))) {
13281 xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
13282 WXS_BASIC_CAST type, type->node, "memberTypes",
13283 name, nsName, XML_SCHEMA_TYPE_SIMPLE, NULL);
13285 * Remove the member type link.
13287 if (lastLink == NULL)
13288 type->memberTypes = link->next;
13289 else
13290 lastLink->next = link->next;
13291 newLink = link;
13292 link = link->next;
13293 xmlFree(newLink);
13294 } else {
13295 link->type = memberType;
13296 lastLink = link;
13297 link = link->next;
13301 * Add local simple types,
13303 memberType = type->subtypes;
13304 while (memberType != NULL) {
13305 link = (xmlSchemaTypeLinkPtr) xmlMalloc(sizeof(xmlSchemaTypeLink));
13306 if (link == NULL) {
13307 xmlSchemaPErrMemory(ctxt, "allocating a type link", NULL);
13308 return (-1);
13310 link->type = memberType;
13311 link->next = NULL;
13312 if (lastLink == NULL)
13313 type->memberTypes = link;
13314 else
13315 lastLink->next = link;
13316 lastLink = link;
13317 memberType = memberType->next;
13319 return (0);
13323 * xmlSchemaIsDerivedFromBuiltInType:
13324 * @ctxt: the schema parser context
13325 * @type: the type definition
13326 * @valType: the value type
13329 * Returns 1 if the type has the given value type, or
13330 * is derived from such a type.
13332 static int
13333 xmlSchemaIsDerivedFromBuiltInType(xmlSchemaTypePtr type, int valType)
13335 if (type == NULL)
13336 return (0);
13337 if (WXS_IS_COMPLEX(type))
13338 return (0);
13339 if (type->type == XML_SCHEMA_TYPE_BASIC) {
13340 if (type->builtInType == valType)
13341 return(1);
13342 if ((type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) ||
13343 (type->builtInType == XML_SCHEMAS_ANYTYPE))
13344 return (0);
13345 return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
13347 return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
13350 #if 0
13352 * xmlSchemaIsDerivedFromBuiltInType:
13353 * @ctxt: the schema parser context
13354 * @type: the type definition
13355 * @valType: the value type
13358 * Returns 1 if the type has the given value type, or
13359 * is derived from such a type.
13361 static int
13362 xmlSchemaIsUserDerivedFromBuiltInType(xmlSchemaTypePtr type, int valType)
13364 if (type == NULL)
13365 return (0);
13366 if (WXS_IS_COMPLEX(type))
13367 return (0);
13368 if (type->type == XML_SCHEMA_TYPE_BASIC) {
13369 if (type->builtInType == valType)
13370 return(1);
13371 return (0);
13372 } else
13373 return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
13375 return (0);
13378 static xmlSchemaTypePtr
13379 xmlSchemaQueryBuiltInType(xmlSchemaTypePtr type)
13381 if (type == NULL)
13382 return (NULL);
13383 if (WXS_IS_COMPLEX(type))
13384 return (NULL);
13385 if (type->type == XML_SCHEMA_TYPE_BASIC)
13386 return(type);
13387 return(xmlSchemaQueryBuiltInType(type->subtypes));
13389 #endif
13392 * xmlSchemaGetPrimitiveType:
13393 * @type: the simpleType definition
13395 * Returns the primitive type of the given type or
13396 * NULL in case of error.
13398 static xmlSchemaTypePtr
13399 xmlSchemaGetPrimitiveType(xmlSchemaTypePtr type)
13402 while (type != NULL) {
13404 * Note that anySimpleType is actually not a primitive type
13405 * but we need that here.
13407 if ((type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) ||
13408 (type->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE))
13409 return (type);
13410 type = type->baseType;
13413 return (NULL);
13416 #if 0
13418 * xmlSchemaGetBuiltInTypeAncestor:
13419 * @type: the simpleType definition
13421 * Returns the primitive type of the given type or
13422 * NULL in case of error.
13424 static xmlSchemaTypePtr
13425 xmlSchemaGetBuiltInTypeAncestor(xmlSchemaTypePtr type)
13427 if (WXS_IS_LIST(type) || WXS_IS_UNION(type))
13428 return (0);
13429 while (type != NULL) {
13430 if (type->type == XML_SCHEMA_TYPE_BASIC)
13431 return (type);
13432 type = type->baseType;
13435 return (NULL);
13437 #endif
13440 * xmlSchemaCloneWildcardNsConstraints:
13441 * @ctxt: the schema parser context
13442 * @dest: the destination wildcard
13443 * @source: the source wildcard
13445 * Clones the namespace constraints of source
13446 * and assignes them to dest.
13447 * Returns -1 on internal error, 0 otherwise.
13449 static int
13450 xmlSchemaCloneWildcardNsConstraints(xmlSchemaParserCtxtPtr ctxt,
13451 xmlSchemaWildcardPtr dest,
13452 xmlSchemaWildcardPtr source)
13454 xmlSchemaWildcardNsPtr cur, tmp, last;
13456 if ((source == NULL) || (dest == NULL))
13457 return(-1);
13458 dest->any = source->any;
13459 cur = source->nsSet;
13460 last = NULL;
13461 while (cur != NULL) {
13462 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
13463 if (tmp == NULL)
13464 return(-1);
13465 tmp->value = cur->value;
13466 if (last == NULL)
13467 dest->nsSet = tmp;
13468 else
13469 last->next = tmp;
13470 last = tmp;
13471 cur = cur->next;
13473 if (dest->negNsSet != NULL)
13474 xmlSchemaFreeWildcardNsSet(dest->negNsSet);
13475 if (source->negNsSet != NULL) {
13476 dest->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13477 if (dest->negNsSet == NULL)
13478 return(-1);
13479 dest->negNsSet->value = source->negNsSet->value;
13480 } else
13481 dest->negNsSet = NULL;
13482 return(0);
13486 * xmlSchemaUnionWildcards:
13487 * @ctxt: the schema parser context
13488 * @completeWild: the first wildcard
13489 * @curWild: the second wildcard
13491 * Unions the namespace constraints of the given wildcards.
13492 * @completeWild will hold the resulting union.
13493 * Returns a positive error code on failure, -1 in case of an
13494 * internal error, 0 otherwise.
13496 static int
13497 xmlSchemaUnionWildcards(xmlSchemaParserCtxtPtr ctxt,
13498 xmlSchemaWildcardPtr completeWild,
13499 xmlSchemaWildcardPtr curWild)
13501 xmlSchemaWildcardNsPtr cur, curB, tmp;
13504 * 1 If O1 and O2 are the same value, then that value must be the
13505 * value.
13507 if ((completeWild->any == curWild->any) &&
13508 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
13509 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
13511 if ((completeWild->negNsSet == NULL) ||
13512 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
13514 if (completeWild->nsSet != NULL) {
13515 int found = 0;
13518 * Check equality of sets.
13520 cur = completeWild->nsSet;
13521 while (cur != NULL) {
13522 found = 0;
13523 curB = curWild->nsSet;
13524 while (curB != NULL) {
13525 if (cur->value == curB->value) {
13526 found = 1;
13527 break;
13529 curB = curB->next;
13531 if (!found)
13532 break;
13533 cur = cur->next;
13535 if (found)
13536 return(0);
13537 } else
13538 return(0);
13542 * 2 If either O1 or O2 is any, then any must be the value
13544 if (completeWild->any != curWild->any) {
13545 if (completeWild->any == 0) {
13546 completeWild->any = 1;
13547 if (completeWild->nsSet != NULL) {
13548 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13549 completeWild->nsSet = NULL;
13551 if (completeWild->negNsSet != NULL) {
13552 xmlFree(completeWild->negNsSet);
13553 completeWild->negNsSet = NULL;
13556 return (0);
13559 * 3 If both O1 and O2 are sets of (namespace names or �absent�),
13560 * then the union of those sets must be the value.
13562 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
13563 int found;
13564 xmlSchemaWildcardNsPtr start;
13566 cur = curWild->nsSet;
13567 start = completeWild->nsSet;
13568 while (cur != NULL) {
13569 found = 0;
13570 curB = start;
13571 while (curB != NULL) {
13572 if (cur->value == curB->value) {
13573 found = 1;
13574 break;
13576 curB = curB->next;
13578 if (!found) {
13579 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
13580 if (tmp == NULL)
13581 return (-1);
13582 tmp->value = cur->value;
13583 tmp->next = completeWild->nsSet;
13584 completeWild->nsSet = tmp;
13586 cur = cur->next;
13589 return(0);
13592 * 4 If the two are negations of different values (namespace names
13593 * or �absent�), then a pair of not and �absent� must be the value.
13595 if ((completeWild->negNsSet != NULL) &&
13596 (curWild->negNsSet != NULL) &&
13597 (completeWild->negNsSet->value != curWild->negNsSet->value)) {
13598 completeWild->negNsSet->value = NULL;
13600 return(0);
13603 * 5.
13605 if (((completeWild->negNsSet != NULL) &&
13606 (completeWild->negNsSet->value != NULL) &&
13607 (curWild->nsSet != NULL)) ||
13608 ((curWild->negNsSet != NULL) &&
13609 (curWild->negNsSet->value != NULL) &&
13610 (completeWild->nsSet != NULL))) {
13612 int nsFound, absentFound = 0;
13614 if (completeWild->nsSet != NULL) {
13615 cur = completeWild->nsSet;
13616 curB = curWild->negNsSet;
13617 } else {
13618 cur = curWild->nsSet;
13619 curB = completeWild->negNsSet;
13621 nsFound = 0;
13622 while (cur != NULL) {
13623 if (cur->value == NULL)
13624 absentFound = 1;
13625 else if (cur->value == curB->value)
13626 nsFound = 1;
13627 if (nsFound && absentFound)
13628 break;
13629 cur = cur->next;
13632 if (nsFound && absentFound) {
13634 * 5.1 If the set S includes both the negated namespace
13635 * name and �absent�, then any must be the value.
13637 completeWild->any = 1;
13638 if (completeWild->nsSet != NULL) {
13639 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13640 completeWild->nsSet = NULL;
13642 if (completeWild->negNsSet != NULL) {
13643 xmlFree(completeWild->negNsSet);
13644 completeWild->negNsSet = NULL;
13646 } else if (nsFound && (!absentFound)) {
13648 * 5.2 If the set S includes the negated namespace name
13649 * but not �absent�, then a pair of not and �absent� must
13650 * be the value.
13652 if (completeWild->nsSet != NULL) {
13653 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13654 completeWild->nsSet = NULL;
13656 if (completeWild->negNsSet == NULL) {
13657 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13658 if (completeWild->negNsSet == NULL)
13659 return (-1);
13661 completeWild->negNsSet->value = NULL;
13662 } else if ((!nsFound) && absentFound) {
13664 * 5.3 If the set S includes �absent� but not the negated
13665 * namespace name, then the union is not expressible.
13667 xmlSchemaPErr(ctxt, completeWild->node,
13668 XML_SCHEMAP_UNION_NOT_EXPRESSIBLE,
13669 "The union of the wilcard is not expressible.\n",
13670 NULL, NULL);
13671 return(XML_SCHEMAP_UNION_NOT_EXPRESSIBLE);
13672 } else if ((!nsFound) && (!absentFound)) {
13674 * 5.4 If the set S does not include either the negated namespace
13675 * name or �absent�, then whichever of O1 or O2 is a pair of not
13676 * and a namespace name must be the value.
13678 if (completeWild->negNsSet == NULL) {
13679 if (completeWild->nsSet != NULL) {
13680 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13681 completeWild->nsSet = NULL;
13683 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13684 if (completeWild->negNsSet == NULL)
13685 return (-1);
13686 completeWild->negNsSet->value = curWild->negNsSet->value;
13689 return (0);
13692 * 6.
13694 if (((completeWild->negNsSet != NULL) &&
13695 (completeWild->negNsSet->value == NULL) &&
13696 (curWild->nsSet != NULL)) ||
13697 ((curWild->negNsSet != NULL) &&
13698 (curWild->negNsSet->value == NULL) &&
13699 (completeWild->nsSet != NULL))) {
13701 if (completeWild->nsSet != NULL) {
13702 cur = completeWild->nsSet;
13703 } else {
13704 cur = curWild->nsSet;
13706 while (cur != NULL) {
13707 if (cur->value == NULL) {
13709 * 6.1 If the set S includes �absent�, then any must be the
13710 * value.
13712 completeWild->any = 1;
13713 if (completeWild->nsSet != NULL) {
13714 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13715 completeWild->nsSet = NULL;
13717 if (completeWild->negNsSet != NULL) {
13718 xmlFree(completeWild->negNsSet);
13719 completeWild->negNsSet = NULL;
13721 return (0);
13723 cur = cur->next;
13725 if (completeWild->negNsSet == NULL) {
13727 * 6.2 If the set S does not include �absent�, then a pair of not
13728 * and �absent� must be the value.
13730 if (completeWild->nsSet != NULL) {
13731 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13732 completeWild->nsSet = NULL;
13734 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13735 if (completeWild->negNsSet == NULL)
13736 return (-1);
13737 completeWild->negNsSet->value = NULL;
13739 return (0);
13741 return (0);
13746 * xmlSchemaIntersectWildcards:
13747 * @ctxt: the schema parser context
13748 * @completeWild: the first wildcard
13749 * @curWild: the second wildcard
13751 * Intersects the namespace constraints of the given wildcards.
13752 * @completeWild will hold the resulting intersection.
13753 * Returns a positive error code on failure, -1 in case of an
13754 * internal error, 0 otherwise.
13756 static int
13757 xmlSchemaIntersectWildcards(xmlSchemaParserCtxtPtr ctxt,
13758 xmlSchemaWildcardPtr completeWild,
13759 xmlSchemaWildcardPtr curWild)
13761 xmlSchemaWildcardNsPtr cur, curB, prev, tmp;
13764 * 1 If O1 and O2 are the same value, then that value must be the
13765 * value.
13767 if ((completeWild->any == curWild->any) &&
13768 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
13769 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
13771 if ((completeWild->negNsSet == NULL) ||
13772 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
13774 if (completeWild->nsSet != NULL) {
13775 int found = 0;
13778 * Check equality of sets.
13780 cur = completeWild->nsSet;
13781 while (cur != NULL) {
13782 found = 0;
13783 curB = curWild->nsSet;
13784 while (curB != NULL) {
13785 if (cur->value == curB->value) {
13786 found = 1;
13787 break;
13789 curB = curB->next;
13791 if (!found)
13792 break;
13793 cur = cur->next;
13795 if (found)
13796 return(0);
13797 } else
13798 return(0);
13802 * 2 If either O1 or O2 is any, then the other must be the value.
13804 if ((completeWild->any != curWild->any) && (completeWild->any)) {
13805 if (xmlSchemaCloneWildcardNsConstraints(ctxt, completeWild, curWild) == -1)
13806 return(-1);
13807 return(0);
13810 * 3 If either O1 or O2 is a pair of not and a value (a namespace
13811 * name or �absent�) and the other is a set of (namespace names or
13812 * �absent�), then that set, minus the negated value if it was in
13813 * the set, minus �absent� if it was in the set, must be the value.
13815 if (((completeWild->negNsSet != NULL) && (curWild->nsSet != NULL)) ||
13816 ((curWild->negNsSet != NULL) && (completeWild->nsSet != NULL))) {
13817 const xmlChar *neg;
13819 if (completeWild->nsSet == NULL) {
13820 neg = completeWild->negNsSet->value;
13821 if (xmlSchemaCloneWildcardNsConstraints(ctxt, completeWild, curWild) == -1)
13822 return(-1);
13823 } else
13824 neg = curWild->negNsSet->value;
13826 * Remove absent and negated.
13828 prev = NULL;
13829 cur = completeWild->nsSet;
13830 while (cur != NULL) {
13831 if (cur->value == NULL) {
13832 if (prev == NULL)
13833 completeWild->nsSet = cur->next;
13834 else
13835 prev->next = cur->next;
13836 xmlFree(cur);
13837 break;
13839 prev = cur;
13840 cur = cur->next;
13842 if (neg != NULL) {
13843 prev = NULL;
13844 cur = completeWild->nsSet;
13845 while (cur != NULL) {
13846 if (cur->value == neg) {
13847 if (prev == NULL)
13848 completeWild->nsSet = cur->next;
13849 else
13850 prev->next = cur->next;
13851 xmlFree(cur);
13852 break;
13854 prev = cur;
13855 cur = cur->next;
13859 return(0);
13862 * 4 If both O1 and O2 are sets of (namespace names or �absent�),
13863 * then the intersection of those sets must be the value.
13865 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
13866 int found;
13868 cur = completeWild->nsSet;
13869 prev = NULL;
13870 while (cur != NULL) {
13871 found = 0;
13872 curB = curWild->nsSet;
13873 while (curB != NULL) {
13874 if (cur->value == curB->value) {
13875 found = 1;
13876 break;
13878 curB = curB->next;
13880 if (!found) {
13881 if (prev == NULL)
13882 completeWild->nsSet = cur->next;
13883 else
13884 prev->next = cur->next;
13885 tmp = cur->next;
13886 xmlFree(cur);
13887 cur = tmp;
13888 continue;
13890 prev = cur;
13891 cur = cur->next;
13894 return(0);
13896 /* 5 If the two are negations of different namespace names,
13897 * then the intersection is not expressible
13899 if ((completeWild->negNsSet != NULL) &&
13900 (curWild->negNsSet != NULL) &&
13901 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
13902 (completeWild->negNsSet->value != NULL) &&
13903 (curWild->negNsSet->value != NULL)) {
13905 xmlSchemaPErr(ctxt, completeWild->node, XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE,
13906 "The intersection of the wilcard is not expressible.\n",
13907 NULL, NULL);
13908 return(XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE);
13911 * 6 If the one is a negation of a namespace name and the other
13912 * is a negation of �absent�, then the one which is the negation
13913 * of a namespace name must be the value.
13915 if ((completeWild->negNsSet != NULL) && (curWild->negNsSet != NULL) &&
13916 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
13917 (completeWild->negNsSet->value == NULL)) {
13918 completeWild->negNsSet->value = curWild->negNsSet->value;
13920 return(0);
13924 * xmlSchemaIsWildcardNsConstraintSubset:
13925 * @ctxt: the schema parser context
13926 * @sub: the first wildcard
13927 * @super: the second wildcard
13929 * Schema Component Constraint: Wildcard Subset (cos-ns-subset)
13931 * Returns 0 if the namespace constraint of @sub is an intensional
13932 * subset of @super, 1 otherwise.
13934 static int
13935 xmlSchemaCheckCOSNSSubset(xmlSchemaWildcardPtr sub,
13936 xmlSchemaWildcardPtr super)
13939 * 1 super must be any.
13941 if (super->any)
13942 return (0);
13944 * 2.1 sub must be a pair of not and a namespace name or �absent�.
13945 * 2.2 super must be a pair of not and the same value.
13947 if ((sub->negNsSet != NULL) &&
13948 (super->negNsSet != NULL) &&
13949 (sub->negNsSet->value == super->negNsSet->value))
13950 return (0);
13952 * 3.1 sub must be a set whose members are either namespace names or �absent�.
13954 if (sub->nsSet != NULL) {
13956 * 3.2.1 super must be the same set or a superset thereof.
13958 if (super->nsSet != NULL) {
13959 xmlSchemaWildcardNsPtr cur, curB;
13960 int found = 0;
13962 cur = sub->nsSet;
13963 while (cur != NULL) {
13964 found = 0;
13965 curB = super->nsSet;
13966 while (curB != NULL) {
13967 if (cur->value == curB->value) {
13968 found = 1;
13969 break;
13971 curB = curB->next;
13973 if (!found)
13974 return (1);
13975 cur = cur->next;
13977 if (found)
13978 return (0);
13979 } else if (super->negNsSet != NULL) {
13980 xmlSchemaWildcardNsPtr cur;
13982 * 3.2.2 super must be a pair of not and a namespace name or
13983 * �absent� and that value must not be in sub's set.
13985 cur = sub->nsSet;
13986 while (cur != NULL) {
13987 if (cur->value == super->negNsSet->value)
13988 return (1);
13989 cur = cur->next;
13991 return (0);
13994 return (1);
13997 static int
13998 xmlSchemaGetEffectiveValueConstraint(xmlSchemaAttributeUsePtr attruse,
13999 int *fixed,
14000 const xmlChar **value,
14001 xmlSchemaValPtr *val)
14003 *fixed = 0;
14004 *value = NULL;
14005 if (val != 0)
14006 *val = NULL;
14008 if (attruse->defValue != NULL) {
14009 *value = attruse->defValue;
14010 if (val != NULL)
14011 *val = attruse->defVal;
14012 if (attruse->flags & XML_SCHEMA_ATTR_USE_FIXED)
14013 *fixed = 1;
14014 return(1);
14015 } else if ((attruse->attrDecl != NULL) &&
14016 (attruse->attrDecl->defValue != NULL)) {
14017 *value = attruse->attrDecl->defValue;
14018 if (val != NULL)
14019 *val = attruse->attrDecl->defVal;
14020 if (attruse->attrDecl->flags & XML_SCHEMAS_ATTR_FIXED)
14021 *fixed = 1;
14022 return(1);
14024 return(0);
14027 * xmlSchemaCheckCVCWildcardNamespace:
14028 * @wild: the wildcard
14029 * @ns: the namespace
14031 * Validation Rule: Wildcard allows Namespace Name
14032 * (cvc-wildcard-namespace)
14034 * Returns 0 if the given namespace matches the wildcard,
14035 * 1 otherwise and -1 on API errors.
14037 static int
14038 xmlSchemaCheckCVCWildcardNamespace(xmlSchemaWildcardPtr wild,
14039 const xmlChar* ns)
14041 if (wild == NULL)
14042 return(-1);
14044 if (wild->any)
14045 return(0);
14046 else if (wild->nsSet != NULL) {
14047 xmlSchemaWildcardNsPtr cur;
14049 cur = wild->nsSet;
14050 while (cur != NULL) {
14051 if (xmlStrEqual(cur->value, ns))
14052 return(0);
14053 cur = cur->next;
14055 } else if ((wild->negNsSet != NULL) && (ns != NULL) &&
14056 (!xmlStrEqual(wild->negNsSet->value, ns)))
14057 return(0);
14059 return(1);
14062 #define XML_SCHEMA_ACTION_DERIVE 0
14063 #define XML_SCHEMA_ACTION_REDEFINE 1
14065 #define WXS_ACTION_STR(a) \
14066 ((a) == XML_SCHEMA_ACTION_DERIVE) ? (const xmlChar *) "base" : (const xmlChar *) "redefined"
14069 * Schema Component Constraint:
14070 * Derivation Valid (Restriction, Complex)
14071 * derivation-ok-restriction (2) - (4)
14073 * ATTENTION:
14074 * In XML Schema 1.1 this will be:
14075 * Validation Rule:
14076 * Checking complex type subsumption (practicalSubsumption) (1, 2 and 3)
14079 static int
14080 xmlSchemaCheckDerivationOKRestriction2to4(xmlSchemaParserCtxtPtr pctxt,
14081 int action,
14082 xmlSchemaBasicItemPtr item,
14083 xmlSchemaBasicItemPtr baseItem,
14084 xmlSchemaItemListPtr uses,
14085 xmlSchemaItemListPtr baseUses,
14086 xmlSchemaWildcardPtr wild,
14087 xmlSchemaWildcardPtr baseWild)
14089 xmlSchemaAttributeUsePtr cur = NULL, bcur;
14090 int i, j, found; /* err = 0; */
14091 const xmlChar *bEffValue;
14092 int effFixed;
14094 if (uses != NULL) {
14095 for (i = 0; i < uses->nbItems; i++) {
14096 cur = uses->items[i];
14097 found = 0;
14098 if (baseUses == NULL)
14099 goto not_found;
14100 for (j = 0; j < baseUses->nbItems; j++) {
14101 bcur = baseUses->items[j];
14102 if ((WXS_ATTRUSE_DECL_NAME(cur) ==
14103 WXS_ATTRUSE_DECL_NAME(bcur)) &&
14104 (WXS_ATTRUSE_DECL_TNS(cur) ==
14105 WXS_ATTRUSE_DECL_TNS(bcur)))
14108 * (2.1) "If there is an attribute use in the {attribute
14109 * uses} of the {base type definition} (call this B) whose
14110 * {attribute declaration} has the same {name} and {target
14111 * namespace}, then all of the following must be true:"
14113 found = 1;
14115 if ((cur->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
14116 (bcur->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED))
14118 xmlChar *str = NULL;
14120 * (2.1.1) "one of the following must be true:"
14121 * (2.1.1.1) "B's {required} is false."
14122 * (2.1.1.2) "R's {required} is true."
14124 xmlSchemaPAttrUseErr4(pctxt,
14125 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_1,
14126 WXS_ITEM_NODE(item), item, cur,
14127 "The 'optional' attribute use is inconsistent "
14128 "with the corresponding 'required' attribute use of "
14129 "the %s %s",
14130 WXS_ACTION_STR(action),
14131 xmlSchemaGetComponentDesignation(&str, baseItem),
14132 NULL, NULL);
14133 FREE_AND_NULL(str);
14134 /* err = pctxt->err; */
14135 } else if (xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST pctxt,
14136 WXS_ATTRUSE_TYPEDEF(cur),
14137 WXS_ATTRUSE_TYPEDEF(bcur), 0) != 0)
14139 xmlChar *strA = NULL, *strB = NULL, *strC = NULL;
14142 * SPEC (2.1.2) "R's {attribute declaration}'s
14143 * {type definition} must be validly derived from
14144 * B's {type definition} given the empty set as
14145 * defined in Type Derivation OK (Simple) (�3.14.6)."
14147 xmlSchemaPAttrUseErr4(pctxt,
14148 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_2,
14149 WXS_ITEM_NODE(item), item, cur,
14150 "The attribute declaration's %s "
14151 "is not validly derived from "
14152 "the corresponding %s of the "
14153 "attribute declaration in the %s %s",
14154 xmlSchemaGetComponentDesignation(&strA,
14155 WXS_ATTRUSE_TYPEDEF(cur)),
14156 xmlSchemaGetComponentDesignation(&strB,
14157 WXS_ATTRUSE_TYPEDEF(bcur)),
14158 WXS_ACTION_STR(action),
14159 xmlSchemaGetComponentDesignation(&strC, baseItem));
14160 /* xmlSchemaGetComponentDesignation(&str, baseItem), */
14161 FREE_AND_NULL(strA);
14162 FREE_AND_NULL(strB);
14163 FREE_AND_NULL(strC);
14164 /* err = pctxt->err; */
14165 } else {
14167 * 2.1.3 [Definition:] Let the effective value
14168 * constraint of an attribute use be its {value
14169 * constraint}, if present, otherwise its {attribute
14170 * declaration}'s {value constraint} .
14172 xmlSchemaGetEffectiveValueConstraint(bcur,
14173 &effFixed, &bEffValue, NULL);
14175 * 2.1.3 ... one of the following must be true
14177 * 2.1.3.1 B's �effective value constraint� is
14178 * �absent� or default.
14180 if ((bEffValue != NULL) &&
14181 (effFixed == 1)) {
14182 const xmlChar *rEffValue = NULL;
14184 xmlSchemaGetEffectiveValueConstraint(bcur,
14185 &effFixed, &rEffValue, NULL);
14187 * 2.1.3.2 R's �effective value constraint� is
14188 * fixed with the same string as B's.
14189 * MAYBE TODO: Compare the computed values.
14190 * Hmm, it says "same string" so
14191 * string-equality might really be sufficient.
14193 if ((effFixed == 0) ||
14194 (! WXS_ARE_DEFAULT_STR_EQUAL(rEffValue, bEffValue)))
14196 xmlChar *str = NULL;
14198 xmlSchemaPAttrUseErr4(pctxt,
14199 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_3,
14200 WXS_ITEM_NODE(item), item, cur,
14201 "The effective value constraint of the "
14202 "attribute use is inconsistent with "
14203 "its correspondent in the %s %s",
14204 WXS_ACTION_STR(action),
14205 xmlSchemaGetComponentDesignation(&str,
14206 baseItem),
14207 NULL, NULL);
14208 FREE_AND_NULL(str);
14209 /* err = pctxt->err; */
14213 break;
14216 not_found:
14217 if (!found) {
14219 * (2.2) "otherwise the {base type definition} must have an
14220 * {attribute wildcard} and the {target namespace} of the
14221 * R's {attribute declaration} must be �valid� with respect
14222 * to that wildcard, as defined in Wildcard allows Namespace
14223 * Name (�3.10.4)."
14225 if ((baseWild == NULL) ||
14226 (xmlSchemaCheckCVCWildcardNamespace(baseWild,
14227 (WXS_ATTRUSE_DECL(cur))->targetNamespace) != 0))
14229 xmlChar *str = NULL;
14231 xmlSchemaPAttrUseErr4(pctxt,
14232 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_2,
14233 WXS_ITEM_NODE(item), item, cur,
14234 "Neither a matching attribute use, "
14235 "nor a matching wildcard exists in the %s %s",
14236 WXS_ACTION_STR(action),
14237 xmlSchemaGetComponentDesignation(&str, baseItem),
14238 NULL, NULL);
14239 FREE_AND_NULL(str);
14240 /* err = pctxt->err; */
14246 * SPEC derivation-ok-restriction (3):
14247 * (3) "For each attribute use in the {attribute uses} of the {base type
14248 * definition} whose {required} is true, there must be an attribute
14249 * use with an {attribute declaration} with the same {name} and
14250 * {target namespace} as its {attribute declaration} in the {attribute
14251 * uses} of the complex type definition itself whose {required} is true.
14253 if (baseUses != NULL) {
14254 for (j = 0; j < baseUses->nbItems; j++) {
14255 bcur = baseUses->items[j];
14256 if (bcur->occurs != XML_SCHEMAS_ATTR_USE_REQUIRED)
14257 continue;
14258 found = 0;
14259 if (uses != NULL) {
14260 for (i = 0; i < uses->nbItems; i++) {
14261 cur = uses->items[i];
14262 if ((WXS_ATTRUSE_DECL_NAME(cur) ==
14263 WXS_ATTRUSE_DECL_NAME(bcur)) &&
14264 (WXS_ATTRUSE_DECL_TNS(cur) ==
14265 WXS_ATTRUSE_DECL_TNS(bcur))) {
14266 found = 1;
14267 break;
14271 if (!found) {
14272 xmlChar *strA = NULL, *strB = NULL;
14274 xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14275 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_3,
14276 NULL, item,
14277 "A matching attribute use for the "
14278 "'required' %s of the %s %s is missing",
14279 xmlSchemaGetComponentDesignation(&strA, bcur),
14280 WXS_ACTION_STR(action),
14281 xmlSchemaGetComponentDesignation(&strB, baseItem),
14282 NULL);
14283 FREE_AND_NULL(strA);
14284 FREE_AND_NULL(strB);
14289 * derivation-ok-restriction (4)
14291 if (wild != NULL) {
14293 * (4) "If there is an {attribute wildcard}, all of the
14294 * following must be true:"
14296 if (baseWild == NULL) {
14297 xmlChar *str = NULL;
14300 * (4.1) "The {base type definition} must also have one."
14302 xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14303 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_1,
14304 NULL, item,
14305 "The %s has an attribute wildcard, "
14306 "but the %s %s '%s' does not have one",
14307 WXS_ITEM_TYPE_NAME(item),
14308 WXS_ACTION_STR(action),
14309 WXS_ITEM_TYPE_NAME(baseItem),
14310 xmlSchemaGetComponentQName(&str, baseItem));
14311 FREE_AND_NULL(str);
14312 return(pctxt->err);
14313 } else if ((baseWild->any == 0) &&
14314 xmlSchemaCheckCOSNSSubset(wild, baseWild))
14316 xmlChar *str = NULL;
14318 * (4.2) "The complex type definition's {attribute wildcard}'s
14319 * {namespace constraint} must be a subset of the {base type
14320 * definition}'s {attribute wildcard}'s {namespace constraint},
14321 * as defined by Wildcard Subset (�3.10.6)."
14323 xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14324 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_2,
14325 NULL, item,
14326 "The attribute wildcard is not a valid "
14327 "subset of the wildcard in the %s %s '%s'",
14328 WXS_ACTION_STR(action),
14329 WXS_ITEM_TYPE_NAME(baseItem),
14330 xmlSchemaGetComponentQName(&str, baseItem),
14331 NULL);
14332 FREE_AND_NULL(str);
14333 return(pctxt->err);
14335 /* 4.3 Unless the {base type definition} is the �ur-type
14336 * definition�, the complex type definition's {attribute
14337 * wildcard}'s {process contents} must be identical to or
14338 * stronger than the {base type definition}'s {attribute
14339 * wildcard}'s {process contents}, where strict is stronger
14340 * than lax is stronger than skip.
14342 if ((! WXS_IS_ANYTYPE(baseItem)) &&
14343 (wild->processContents < baseWild->processContents)) {
14344 xmlChar *str = NULL;
14345 xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14346 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_3,
14347 NULL, baseItem,
14348 "The {process contents} of the attribute wildcard is "
14349 "weaker than the one in the %s %s '%s'",
14350 WXS_ACTION_STR(action),
14351 WXS_ITEM_TYPE_NAME(baseItem),
14352 xmlSchemaGetComponentQName(&str, baseItem),
14353 NULL);
14354 FREE_AND_NULL(str)
14355 return(pctxt->err);
14358 return(0);
14362 static int
14363 xmlSchemaExpandAttributeGroupRefs(xmlSchemaParserCtxtPtr pctxt,
14364 xmlSchemaBasicItemPtr item,
14365 xmlSchemaWildcardPtr *completeWild,
14366 xmlSchemaItemListPtr list,
14367 xmlSchemaItemListPtr prohibs);
14369 * xmlSchemaFixupTypeAttributeUses:
14370 * @ctxt: the schema parser context
14371 * @type: the complex type definition
14374 * Builds the wildcard and the attribute uses on the given complex type.
14375 * Returns -1 if an internal error occurs, 0 otherwise.
14377 * ATTENTION TODO: Experimantally this uses pointer comparisons for
14378 * strings, so recheck this if we start to hardcode some schemata, since
14379 * they might not be in the same dict.
14380 * NOTE: It is allowed to "extend" the xs:anyType type.
14382 static int
14383 xmlSchemaFixupTypeAttributeUses(xmlSchemaParserCtxtPtr pctxt,
14384 xmlSchemaTypePtr type)
14386 xmlSchemaTypePtr baseType = NULL;
14387 xmlSchemaAttributeUsePtr use;
14388 xmlSchemaItemListPtr uses, baseUses, prohibs = NULL;
14390 if (type->baseType == NULL) {
14391 PERROR_INT("xmlSchemaFixupTypeAttributeUses",
14392 "no base type");
14393 return (-1);
14395 baseType = type->baseType;
14396 if (WXS_IS_TYPE_NOT_FIXED(baseType))
14397 if (xmlSchemaTypeFixup(baseType, ACTXT_CAST pctxt) == -1)
14398 return(-1);
14400 uses = type->attrUses;
14401 baseUses = baseType->attrUses;
14403 * Expand attribute group references. And build the 'complete'
14404 * wildcard, i.e. intersect multiple wildcards.
14405 * Move attribute prohibitions into a separate list.
14407 if (uses != NULL) {
14408 if (WXS_IS_RESTRICTION(type)) {
14410 * This one will transfer all attr. prohibitions
14411 * into pctxt->attrProhibs.
14413 if (xmlSchemaExpandAttributeGroupRefs(pctxt,
14414 WXS_BASIC_CAST type, &(type->attributeWildcard), uses,
14415 pctxt->attrProhibs) == -1)
14417 PERROR_INT("xmlSchemaFixupTypeAttributeUses",
14418 "failed to expand attributes");
14420 if (pctxt->attrProhibs->nbItems != 0)
14421 prohibs = pctxt->attrProhibs;
14422 } else {
14423 if (xmlSchemaExpandAttributeGroupRefs(pctxt,
14424 WXS_BASIC_CAST type, &(type->attributeWildcard), uses,
14425 NULL) == -1)
14427 PERROR_INT("xmlSchemaFixupTypeAttributeUses",
14428 "failed to expand attributes");
14433 * Inherit the attribute uses of the base type.
14435 if (baseUses != NULL) {
14436 int i, j;
14437 xmlSchemaAttributeUseProhibPtr pro;
14439 if (WXS_IS_RESTRICTION(type)) {
14440 int usesCount;
14441 xmlSchemaAttributeUsePtr tmp;
14443 if (uses != NULL)
14444 usesCount = uses->nbItems;
14445 else
14446 usesCount = 0;
14448 /* Restriction. */
14449 for (i = 0; i < baseUses->nbItems; i++) {
14450 use = baseUses->items[i];
14451 if (prohibs) {
14453 * Filter out prohibited uses.
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))
14461 goto inherit_next;
14465 if (usesCount) {
14467 * Filter out existing uses.
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)))
14476 goto inherit_next;
14480 if (uses == NULL) {
14481 type->attrUses = xmlSchemaItemListCreate();
14482 if (type->attrUses == NULL)
14483 goto exit_failure;
14484 uses = type->attrUses;
14486 xmlSchemaItemListAddSize(uses, 2, use);
14487 inherit_next: {}
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;
14499 xmlSchemaItemListAddSize(uses, baseUses->nbItems, use);
14504 * Shrink attr. uses.
14506 if (uses) {
14507 if (uses->nbItems == 0) {
14508 xmlSchemaItemListFree(uses);
14509 type->attrUses = NULL;
14512 * TODO: We could shrink the size of the array
14513 * to fit the actual number of items.
14517 * Compute the complete wildcard.
14519 if (WXS_IS_EXTENSION(type)) {
14520 if (baseType->attributeWildcard != NULL) {
14522 * (3.2.2.1) "If the �base wildcard� is non-�absent�, then
14523 * the appropriate case among the following:"
14525 if (type->attributeWildcard != NULL) {
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)."
14536 if (xmlSchemaUnionWildcards(pctxt, type->attributeWildcard,
14537 baseType->attributeWildcard) == -1)
14538 goto exit_failure;
14539 } else {
14541 * (3.2.2.1.1) "If the �complete wildcard� is �absent�,
14542 * then the �base wildcard�."
14544 type->attributeWildcard = baseType->attributeWildcard;
14546 } else {
14548 * (3.2.2.2) "otherwise (the �base wildcard� is �absent�) the
14549 * �complete wildcard"
14550 * NOOP
14553 } else {
14555 * SPEC {attribute wildcard}
14556 * (3.1) "If the <restriction> alternative is chosen, then the
14557 * �complete wildcard�;"
14558 * NOOP
14562 return (0);
14564 exit_failure:
14565 return(-1);
14569 * xmlSchemaTypeFinalContains:
14570 * @schema: the schema
14571 * @type: the type definition
14572 * @final: the final
14574 * Evaluates if a type definition contains the given "final".
14575 * This does take "finalDefault" into account as well.
14577 * Returns 1 if the type does containt the given "final",
14578 * 0 otherwise.
14580 static int
14581 xmlSchemaTypeFinalContains(xmlSchemaTypePtr type, int final)
14583 if (type == NULL)
14584 return (0);
14585 if (type->flags & final)
14586 return (1);
14587 else
14588 return (0);
14592 * xmlSchemaGetUnionSimpleTypeMemberTypes:
14593 * @type: the Union Simple Type
14595 * Returns a list of member types of @type if existing,
14596 * returns NULL otherwise.
14598 static xmlSchemaTypeLinkPtr
14599 xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type)
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;
14607 return (NULL);
14611 * xmlSchemaGetParticleTotalRangeMin:
14612 * @particle: the particle
14614 * Schema Component Constraint: Effective Total Range
14615 * (all and sequence) + (choice)
14617 * Returns the minimun Effective Total Range.
14619 static int
14620 xmlSchemaGetParticleTotalRangeMin(xmlSchemaParticlePtr particle)
14622 if ((particle->children == NULL) ||
14623 (particle->minOccurs == 0))
14624 return (0);
14625 if (particle->children->type == XML_SCHEMA_TYPE_CHOICE) {
14626 int min = -1, cur;
14627 xmlSchemaParticlePtr part =
14628 (xmlSchemaParticlePtr) particle->children->children;
14630 if (part == NULL)
14631 return (0);
14632 while (part != NULL) {
14633 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14634 (part->children->type == XML_SCHEMA_TYPE_ANY))
14635 cur = part->minOccurs;
14636 else
14637 cur = xmlSchemaGetParticleTotalRangeMin(part);
14638 if (cur == 0)
14639 return (0);
14640 if ((min > cur) || (min == -1))
14641 min = cur;
14642 part = (xmlSchemaParticlePtr) part->next;
14644 return (particle->minOccurs * min);
14645 } else {
14646 /* <all> and <sequence> */
14647 int sum = 0;
14648 xmlSchemaParticlePtr part =
14649 (xmlSchemaParticlePtr) particle->children->children;
14651 if (part == NULL)
14652 return (0);
14653 do {
14654 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14655 (part->children->type == XML_SCHEMA_TYPE_ANY))
14656 sum += part->minOccurs;
14657 else
14658 sum += xmlSchemaGetParticleTotalRangeMin(part);
14659 part = (xmlSchemaParticlePtr) part->next;
14660 } while (part != NULL);
14661 return (particle->minOccurs * sum);
14665 #if 0
14667 * xmlSchemaGetParticleTotalRangeMax:
14668 * @particle: the particle
14670 * Schema Component Constraint: Effective Total Range
14671 * (all and sequence) + (choice)
14673 * Returns the maximum Effective Total Range.
14675 static int
14676 xmlSchemaGetParticleTotalRangeMax(xmlSchemaParticlePtr particle)
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;
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;
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;
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;
14721 /* TODO: Handle overflows? */
14722 return (particle->maxOccurs * sum);
14725 #endif
14728 * xmlSchemaIsParticleEmptiable:
14729 * @particle: the particle
14731 * Schema Component Constraint: Particle Emptiable
14732 * Checks whether the given particle is emptiable.
14734 * Returns 1 if emptiable, 0 otherwise.
14736 static int
14737 xmlSchemaIsParticleEmptiable(xmlSchemaParticlePtr particle)
14740 * SPEC (1) "Its {min occurs} is 0."
14742 if ((particle == NULL) || (particle->minOccurs == 0) ||
14743 (particle->children == NULL))
14744 return (1);
14746 * SPEC (2) "Its {term} is a group and the minimum part of the
14747 * effective total range of that group, [...] is 0."
14749 if (WXS_IS_MODEL_GROUP(particle->children)) {
14750 if (xmlSchemaGetParticleTotalRangeMin(particle) == 0)
14751 return (1);
14753 return (0);
14757 * xmlSchemaCheckCOSSTDerivedOK:
14758 * @actxt: a context
14759 * @type: the derived simple type definition
14760 * @baseType: the base type definition
14761 * @subset: the subset of ('restriction', ect.)
14763 * Schema Component Constraint:
14764 * Type Derivation OK (Simple) (cos-st-derived-OK)
14766 * Checks wheter @type can be validly
14767 * derived from @baseType.
14769 * Returns 0 on success, an positive error code otherwise.
14771 static int
14772 xmlSchemaCheckCOSSTDerivedOK(xmlSchemaAbstractCtxtPtr actxt,
14773 xmlSchemaTypePtr type,
14774 xmlSchemaTypePtr baseType,
14775 int subset)
14778 * 1 They are the same type definition.
14779 * TODO: The identy check might have to be more complex than this.
14781 if (type == baseType)
14782 return (0);
14784 * 2.1 restriction is not in the subset, or in the {final}
14785 * of its own {base type definition};
14787 * NOTE that this will be used also via "xsi:type".
14789 * TODO: Revise this, it looks strange. How can the "type"
14790 * not be fixed or *in* fixing?
14792 if (WXS_IS_TYPE_NOT_FIXED(type))
14793 if (xmlSchemaTypeFixup(type, actxt) == -1)
14794 return(-1);
14795 if (WXS_IS_TYPE_NOT_FIXED(baseType))
14796 if (xmlSchemaTypeFixup(baseType, actxt) == -1)
14797 return(-1);
14798 if ((subset & SUBSET_RESTRICTION) ||
14799 (xmlSchemaTypeFinalContains(type->baseType,
14800 XML_SCHEMAS_TYPE_FINAL_RESTRICTION))) {
14801 return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_1);
14803 /* 2.2 */
14804 if (type->baseType == baseType) {
14806 * 2.2.1 D's �base type definition� is B.
14808 return (0);
14811 * 2.2.2 D's �base type definition� is not the �ur-type definition�
14812 * and is validly derived from B given the subset, as defined by this
14813 * constraint.
14815 if ((! WXS_IS_ANYTYPE(type->baseType)) &&
14816 (xmlSchemaCheckCOSSTDerivedOK(actxt, type->baseType,
14817 baseType, subset) == 0)) {
14818 return (0);
14821 * 2.2.3 D's {variety} is list or union and B is the �simple ur-type
14822 * definition�.
14824 if (WXS_IS_ANY_SIMPLE_TYPE(baseType) &&
14825 (WXS_IS_LIST(type) || WXS_IS_UNION(type))) {
14826 return (0);
14829 * 2.2.4 B's {variety} is union and D is validly derived from a type
14830 * definition in B's {member type definitions} given the subset, as
14831 * defined by this constraint.
14833 * NOTE: This seems not to involve built-in types, since there is no
14834 * built-in Union Simple Type.
14836 if (WXS_IS_UNION(baseType)) {
14837 xmlSchemaTypeLinkPtr cur;
14839 cur = baseType->memberTypes;
14840 while (cur != NULL) {
14841 if (WXS_IS_TYPE_NOT_FIXED(cur->type))
14842 if (xmlSchemaTypeFixup(cur->type, actxt) == -1)
14843 return(-1);
14844 if (xmlSchemaCheckCOSSTDerivedOK(actxt,
14845 type, cur->type, subset) == 0)
14848 * It just has to be validly derived from at least one
14849 * member-type.
14851 return (0);
14853 cur = cur->next;
14856 return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_2);
14860 * xmlSchemaCheckTypeDefCircularInternal:
14861 * @pctxt: the schema parser context
14862 * @ctxtType: the type definition
14863 * @ancestor: an ancestor of @ctxtType
14865 * Checks st-props-correct (2) + ct-props-correct (3).
14866 * Circular type definitions are not allowed.
14868 * Returns XML_SCHEMAP_ST_PROPS_CORRECT_2 if the given type is
14869 * circular, 0 otherwise.
14871 static int
14872 xmlSchemaCheckTypeDefCircularInternal(xmlSchemaParserCtxtPtr pctxt,
14873 xmlSchemaTypePtr ctxtType,
14874 xmlSchemaTypePtr ancestor)
14876 int ret;
14878 if ((ancestor == NULL) || (ancestor->type == XML_SCHEMA_TYPE_BASIC))
14879 return (0);
14881 if (ctxtType == ancestor) {
14882 xmlSchemaPCustomErr(pctxt,
14883 XML_SCHEMAP_ST_PROPS_CORRECT_2,
14884 WXS_BASIC_CAST ctxtType, WXS_ITEM_NODE(ctxtType),
14885 "The definition is circular", NULL);
14886 return (XML_SCHEMAP_ST_PROPS_CORRECT_2);
14888 if (ancestor->flags & XML_SCHEMAS_TYPE_MARKED) {
14890 * Avoid inifinite recursion on circular types not yet checked.
14892 return (0);
14894 ancestor->flags |= XML_SCHEMAS_TYPE_MARKED;
14895 ret = xmlSchemaCheckTypeDefCircularInternal(pctxt, ctxtType,
14896 ancestor->baseType);
14897 ancestor->flags ^= XML_SCHEMAS_TYPE_MARKED;
14898 return (ret);
14902 * xmlSchemaCheckTypeDefCircular:
14903 * @item: the complex/simple type definition
14904 * @ctxt: the parser context
14905 * @name: the name
14907 * Checks for circular type definitions.
14909 static void
14910 xmlSchemaCheckTypeDefCircular(xmlSchemaTypePtr item,
14911 xmlSchemaParserCtxtPtr ctxt)
14913 if ((item == NULL) ||
14914 (item->type == XML_SCHEMA_TYPE_BASIC) ||
14915 (item->baseType == NULL))
14916 return;
14917 xmlSchemaCheckTypeDefCircularInternal(ctxt, item,
14918 item->baseType);
14922 * Simple Type Definition Representation OK (src-simple-type) 4
14924 * "4 Circular union type definition is disallowed. That is, if the
14925 * <union> alternative is chosen, there must not be any entries in the
14926 * memberTypes [attribute] at any depth which resolve to the component
14927 * corresponding to the <simpleType>."
14929 * Note that this should work on the *representation* of a component,
14930 * thus assumes any union types in the member types not being yet
14931 * substituted. At this stage we need the variety of the types
14932 * to be already computed.
14934 static int
14935 xmlSchemaCheckUnionTypeDefCircularRecur(xmlSchemaParserCtxtPtr pctxt,
14936 xmlSchemaTypePtr ctxType,
14937 xmlSchemaTypeLinkPtr members)
14939 xmlSchemaTypeLinkPtr member;
14940 xmlSchemaTypePtr memberType;
14942 member = members;
14943 while (member != NULL) {
14944 memberType = member->type;
14945 while ((memberType != NULL) &&
14946 (memberType->type != XML_SCHEMA_TYPE_BASIC)) {
14947 if (memberType == ctxType) {
14948 xmlSchemaPCustomErr(pctxt,
14949 XML_SCHEMAP_SRC_SIMPLE_TYPE_4,
14950 WXS_BASIC_CAST ctxType, NULL,
14951 "The union type definition is circular", NULL);
14952 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_4);
14954 if ((WXS_IS_UNION(memberType)) &&
14955 ((memberType->flags & XML_SCHEMAS_TYPE_MARKED) == 0))
14957 int res;
14958 memberType->flags |= XML_SCHEMAS_TYPE_MARKED;
14959 res = xmlSchemaCheckUnionTypeDefCircularRecur(pctxt,
14960 ctxType,
14961 xmlSchemaGetUnionSimpleTypeMemberTypes(memberType));
14962 memberType->flags ^= XML_SCHEMAS_TYPE_MARKED;
14963 if (res != 0)
14964 return(res);
14966 memberType = memberType->baseType;
14968 member = member->next;
14970 return(0);
14973 static int
14974 xmlSchemaCheckUnionTypeDefCircular(xmlSchemaParserCtxtPtr pctxt,
14975 xmlSchemaTypePtr type)
14977 if (! WXS_IS_UNION(type))
14978 return(0);
14979 return(xmlSchemaCheckUnionTypeDefCircularRecur(pctxt, type,
14980 type->memberTypes));
14984 * xmlSchemaResolveTypeReferences:
14985 * @item: the complex/simple type definition
14986 * @ctxt: the parser context
14987 * @name: the name
14989 * Resolvese type definition references
14991 static void
14992 xmlSchemaResolveTypeReferences(xmlSchemaTypePtr typeDef,
14993 xmlSchemaParserCtxtPtr ctxt)
14995 if (typeDef == NULL)
14996 return;
14999 * Resolve the base type.
15001 if (typeDef->baseType == NULL) {
15002 typeDef->baseType = xmlSchemaGetType(ctxt->schema,
15003 typeDef->base, typeDef->baseNs);
15004 if (typeDef->baseType == NULL) {
15005 xmlSchemaPResCompAttrErr(ctxt,
15006 XML_SCHEMAP_SRC_RESOLVE,
15007 WXS_BASIC_CAST typeDef, typeDef->node,
15008 "base", typeDef->base, typeDef->baseNs,
15009 XML_SCHEMA_TYPE_SIMPLE, NULL);
15010 return;
15013 if (WXS_IS_SIMPLE(typeDef)) {
15014 if (WXS_IS_UNION(typeDef)) {
15016 * Resolve the memberTypes.
15018 xmlSchemaResolveUnionMemberTypes(ctxt, typeDef);
15019 return;
15020 } else if (WXS_IS_LIST(typeDef)) {
15022 * Resolve the itemType.
15024 if ((typeDef->subtypes == NULL) && (typeDef->base != NULL)) {
15026 typeDef->subtypes = xmlSchemaGetType(ctxt->schema,
15027 typeDef->base, typeDef->baseNs);
15029 if ((typeDef->subtypes == NULL) ||
15030 (! WXS_IS_SIMPLE(typeDef->subtypes)))
15032 typeDef->subtypes = NULL;
15033 xmlSchemaPResCompAttrErr(ctxt,
15034 XML_SCHEMAP_SRC_RESOLVE,
15035 WXS_BASIC_CAST typeDef, typeDef->node,
15036 "itemType", typeDef->base, typeDef->baseNs,
15037 XML_SCHEMA_TYPE_SIMPLE, NULL);
15040 return;
15044 * The ball of letters below means, that if we have a particle
15045 * which has a QName-helper component as its {term}, we want
15046 * to resolve it...
15048 else if ((WXS_TYPE_CONTENTTYPE(typeDef) != NULL) &&
15049 ((WXS_TYPE_CONTENTTYPE(typeDef))->type ==
15050 XML_SCHEMA_TYPE_PARTICLE) &&
15051 (WXS_TYPE_PARTICLE_TERM(typeDef) != NULL) &&
15052 ((WXS_TYPE_PARTICLE_TERM(typeDef))->type ==
15053 XML_SCHEMA_EXTRA_QNAMEREF))
15055 xmlSchemaQNameRefPtr ref =
15056 WXS_QNAME_CAST WXS_TYPE_PARTICLE_TERM(typeDef);
15057 xmlSchemaModelGroupDefPtr groupDef;
15060 * URGENT TODO: Test this.
15062 WXS_TYPE_PARTICLE_TERM(typeDef) = NULL;
15064 * Resolve the MG definition reference.
15066 groupDef =
15067 WXS_MODEL_GROUPDEF_CAST xmlSchemaGetNamedComponent(ctxt->schema,
15068 ref->itemType, ref->name, ref->targetNamespace);
15069 if (groupDef == NULL) {
15070 xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
15071 NULL, WXS_ITEM_NODE(WXS_TYPE_PARTICLE(typeDef)),
15072 "ref", ref->name, ref->targetNamespace, ref->itemType,
15073 NULL);
15074 /* Remove the particle. */
15075 WXS_TYPE_CONTENTTYPE(typeDef) = NULL;
15076 } else if (WXS_MODELGROUPDEF_MODEL(groupDef) == NULL)
15077 /* Remove the particle. */
15078 WXS_TYPE_CONTENTTYPE(typeDef) = NULL;
15079 else {
15081 * Assign the MG definition's {model group} to the
15082 * particle's {term}.
15084 WXS_TYPE_PARTICLE_TERM(typeDef) = WXS_MODELGROUPDEF_MODEL(groupDef);
15086 if (WXS_MODELGROUPDEF_MODEL(groupDef)->type == XML_SCHEMA_TYPE_ALL) {
15088 * SPEC cos-all-limited (1.2)
15089 * "1.2 the {term} property of a particle with
15090 * {max occurs}=1 which is part of a pair which constitutes
15091 * the {content type} of a complex type definition."
15093 if ((WXS_TYPE_PARTICLE(typeDef))->maxOccurs != 1) {
15094 xmlSchemaCustomErr(ACTXT_CAST ctxt,
15095 /* TODO: error code */
15096 XML_SCHEMAP_COS_ALL_LIMITED,
15097 WXS_ITEM_NODE(WXS_TYPE_PARTICLE(typeDef)), NULL,
15098 "The particle's {max occurs} must be 1, since the "
15099 "reference resolves to an 'all' model group",
15100 NULL, NULL);
15110 * xmlSchemaCheckSTPropsCorrect:
15111 * @ctxt: the schema parser context
15112 * @type: the simple type definition
15114 * Checks st-props-correct.
15116 * Returns 0 if the properties are correct,
15117 * if not, a positive error code and -1 on internal
15118 * errors.
15120 static int
15121 xmlSchemaCheckSTPropsCorrect(xmlSchemaParserCtxtPtr ctxt,
15122 xmlSchemaTypePtr type)
15124 xmlSchemaTypePtr baseType = type->baseType;
15125 xmlChar *str = NULL;
15127 /* STATE: error funcs converted. */
15129 * Schema Component Constraint: Simple Type Definition Properties Correct
15131 * NOTE: This is somehow redundant, since we actually built a simple type
15132 * to have all the needed information; this acts as an self test.
15134 /* Base type: If the datatype has been �derived� by �restriction�
15135 * then the Simple Type Definition component from which it is �derived�,
15136 * otherwise the Simple Type Definition for anySimpleType (�4.1.6).
15138 if (baseType == NULL) {
15140 * TODO: Think about: "modulo the impact of Missing
15141 * Sub-components (�5.3)."
15143 xmlSchemaPCustomErr(ctxt,
15144 XML_SCHEMAP_ST_PROPS_CORRECT_1,
15145 WXS_BASIC_CAST type, NULL,
15146 "No base type existent", NULL);
15147 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
15150 if (! WXS_IS_SIMPLE(baseType)) {
15151 xmlSchemaPCustomErr(ctxt,
15152 XML_SCHEMAP_ST_PROPS_CORRECT_1,
15153 WXS_BASIC_CAST type, NULL,
15154 "The base type '%s' is not a simple type",
15155 xmlSchemaGetComponentQName(&str, baseType));
15156 FREE_AND_NULL(str)
15157 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
15159 if ( (WXS_IS_LIST(type) || WXS_IS_UNION(type)) &&
15160 (WXS_IS_RESTRICTION(type) == 0) &&
15161 (! WXS_IS_ANY_SIMPLE_TYPE(baseType))) {
15162 xmlSchemaPCustomErr(ctxt,
15163 XML_SCHEMAP_ST_PROPS_CORRECT_1,
15164 WXS_BASIC_CAST type, NULL,
15165 "A type, derived by list or union, must have "
15166 "the simple ur-type definition as base type, not '%s'",
15167 xmlSchemaGetComponentQName(&str, baseType));
15168 FREE_AND_NULL(str)
15169 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
15172 * Variety: One of {atomic, list, union}.
15174 if ((! WXS_IS_ATOMIC(type)) && (! WXS_IS_UNION(type)) &&
15175 (! WXS_IS_LIST(type))) {
15176 xmlSchemaPCustomErr(ctxt,
15177 XML_SCHEMAP_ST_PROPS_CORRECT_1,
15178 WXS_BASIC_CAST type, NULL,
15179 "The variety is absent", NULL);
15180 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
15182 /* TODO: Finish this. Hmm, is this finished? */
15185 * 3 The {final} of the {base type definition} must not contain restriction.
15187 if (xmlSchemaTypeFinalContains(baseType,
15188 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
15189 xmlSchemaPCustomErr(ctxt,
15190 XML_SCHEMAP_ST_PROPS_CORRECT_3,
15191 WXS_BASIC_CAST type, NULL,
15192 "The 'final' of its base type '%s' must not contain "
15193 "'restriction'",
15194 xmlSchemaGetComponentQName(&str, baseType));
15195 FREE_AND_NULL(str)
15196 return (XML_SCHEMAP_ST_PROPS_CORRECT_3);
15200 * 2 All simple type definitions must be derived ultimately from the �simple
15201 * ur-type definition (so� circular definitions are disallowed). That is, it
15202 * must be possible to reach a built-in primitive datatype or the �simple
15203 * ur-type definition� by repeatedly following the {base type definition}.
15205 * NOTE: this is done in xmlSchemaCheckTypeDefCircular().
15207 return (0);
15211 * xmlSchemaCheckCOSSTRestricts:
15212 * @ctxt: the schema parser context
15213 * @type: the simple type definition
15215 * Schema Component Constraint:
15216 * Derivation Valid (Restriction, Simple) (cos-st-restricts)
15218 * Checks if the given @type (simpleType) is derived validly by restriction.
15219 * STATUS:
15221 * Returns -1 on internal errors, 0 if the type is validly derived,
15222 * a positive error code otherwise.
15224 static int
15225 xmlSchemaCheckCOSSTRestricts(xmlSchemaParserCtxtPtr pctxt,
15226 xmlSchemaTypePtr type)
15228 xmlChar *str = NULL;
15230 if (type->type != XML_SCHEMA_TYPE_SIMPLE) {
15231 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15232 "given type is not a user-derived simpleType");
15233 return (-1);
15236 if (WXS_IS_ATOMIC(type)) {
15237 xmlSchemaTypePtr primitive;
15239 * 1.1 The {base type definition} must be an atomic simple
15240 * type definition or a built-in primitive datatype.
15242 if (! WXS_IS_ATOMIC(type->baseType)) {
15243 xmlSchemaPCustomErr(pctxt,
15244 XML_SCHEMAP_COS_ST_RESTRICTS_1_1,
15245 WXS_BASIC_CAST type, NULL,
15246 "The base type '%s' is not an atomic simple type",
15247 xmlSchemaGetComponentQName(&str, type->baseType));
15248 FREE_AND_NULL(str)
15249 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_1);
15251 /* 1.2 The {final} of the {base type definition} must not contain
15252 * restriction.
15254 /* OPTIMIZE TODO : This is already done in xmlSchemaCheckStPropsCorrect */
15255 if (xmlSchemaTypeFinalContains(type->baseType,
15256 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
15257 xmlSchemaPCustomErr(pctxt,
15258 XML_SCHEMAP_COS_ST_RESTRICTS_1_2,
15259 WXS_BASIC_CAST type, NULL,
15260 "The final of its base type '%s' must not contain 'restriction'",
15261 xmlSchemaGetComponentQName(&str, type->baseType));
15262 FREE_AND_NULL(str)
15263 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_2);
15267 * 1.3.1 DF must be an allowed constraining facet for the {primitive
15268 * type definition}, as specified in the appropriate subsection of 3.2
15269 * Primitive datatypes.
15271 if (type->facets != NULL) {
15272 xmlSchemaFacetPtr facet;
15273 int ok = 1;
15275 primitive = xmlSchemaGetPrimitiveType(type);
15276 if (primitive == NULL) {
15277 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15278 "failed to get primitive type");
15279 return (-1);
15281 facet = type->facets;
15282 do {
15283 if (xmlSchemaIsBuiltInTypeFacet(primitive, facet->type) == 0) {
15284 ok = 0;
15285 xmlSchemaPIllegalFacetAtomicErr(pctxt,
15286 XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1,
15287 type, primitive, facet);
15289 facet = facet->next;
15290 } while (facet != NULL);
15291 if (ok == 0)
15292 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1);
15295 * SPEC (1.3.2) "If there is a facet of the same kind in the {facets}
15296 * of the {base type definition} (call this BF),then the DF's {value}
15297 * must be a valid restriction of BF's {value} as defined in
15298 * [XML Schemas: Datatypes]."
15300 * NOTE (1.3.2) Facet derivation constraints are currently handled in
15301 * xmlSchemaDeriveAndValidateFacets()
15303 } else if (WXS_IS_LIST(type)) {
15304 xmlSchemaTypePtr itemType = NULL;
15306 itemType = type->subtypes;
15307 if ((itemType == NULL) || (! WXS_IS_SIMPLE(itemType))) {
15308 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15309 "failed to evaluate the item type");
15310 return (-1);
15312 if (WXS_IS_TYPE_NOT_FIXED(itemType))
15313 xmlSchemaTypeFixup(itemType, ACTXT_CAST pctxt);
15315 * 2.1 The {item type definition} must have a {variety} of atomic or
15316 * union (in which case all the {member type definitions}
15317 * must be atomic).
15319 if ((! WXS_IS_ATOMIC(itemType)) &&
15320 (! WXS_IS_UNION(itemType))) {
15321 xmlSchemaPCustomErr(pctxt,
15322 XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
15323 WXS_BASIC_CAST type, NULL,
15324 "The item type '%s' does not have a variety of atomic or union",
15325 xmlSchemaGetComponentQName(&str, itemType));
15326 FREE_AND_NULL(str)
15327 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
15328 } else if (WXS_IS_UNION(itemType)) {
15329 xmlSchemaTypeLinkPtr member;
15331 member = itemType->memberTypes;
15332 while (member != NULL) {
15333 if (! WXS_IS_ATOMIC(member->type)) {
15334 xmlSchemaPCustomErr(pctxt,
15335 XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
15336 WXS_BASIC_CAST type, NULL,
15337 "The item type is a union type, but the "
15338 "member type '%s' of this item type is not atomic",
15339 xmlSchemaGetComponentQName(&str, member->type));
15340 FREE_AND_NULL(str)
15341 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
15343 member = member->next;
15347 if (WXS_IS_ANY_SIMPLE_TYPE(type->baseType)) {
15348 xmlSchemaFacetPtr facet;
15350 * This is the case if we have: <simpleType><list ..
15353 * 2.3.1
15354 * 2.3.1.1 The {final} of the {item type definition} must not
15355 * contain list.
15357 if (xmlSchemaTypeFinalContains(itemType,
15358 XML_SCHEMAS_TYPE_FINAL_LIST)) {
15359 xmlSchemaPCustomErr(pctxt,
15360 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1,
15361 WXS_BASIC_CAST type, NULL,
15362 "The final of its item type '%s' must not contain 'list'",
15363 xmlSchemaGetComponentQName(&str, itemType));
15364 FREE_AND_NULL(str)
15365 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1);
15368 * 2.3.1.2 The {facets} must only contain the whiteSpace
15369 * facet component.
15370 * OPTIMIZE TODO: the S4S already disallows any facet
15371 * to be specified.
15373 if (type->facets != NULL) {
15374 facet = type->facets;
15375 do {
15376 if (facet->type != XML_SCHEMA_FACET_WHITESPACE) {
15377 xmlSchemaPIllegalFacetListUnionErr(pctxt,
15378 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2,
15379 type, facet);
15380 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2);
15382 facet = facet->next;
15383 } while (facet != NULL);
15386 * MAYBE TODO: (Hmm, not really) Datatypes states:
15387 * A �list� datatype can be �derived� from an �atomic� datatype
15388 * whose �lexical space� allows space (such as string or anyURI)or
15389 * a �union� datatype any of whose {member type definitions}'s
15390 * �lexical space� allows space.
15392 } else {
15394 * This is the case if we have: <simpleType><restriction ...
15395 * I.e. the variety of "list" is inherited.
15398 * 2.3.2
15399 * 2.3.2.1 The {base type definition} must have a {variety} of list.
15401 if (! WXS_IS_LIST(type->baseType)) {
15402 xmlSchemaPCustomErr(pctxt,
15403 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1,
15404 WXS_BASIC_CAST type, NULL,
15405 "The base type '%s' must be a list type",
15406 xmlSchemaGetComponentQName(&str, type->baseType));
15407 FREE_AND_NULL(str)
15408 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1);
15411 * 2.3.2.2 The {final} of the {base type definition} must not
15412 * contain restriction.
15414 if (xmlSchemaTypeFinalContains(type->baseType,
15415 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
15416 xmlSchemaPCustomErr(pctxt,
15417 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2,
15418 WXS_BASIC_CAST type, NULL,
15419 "The 'final' of the base type '%s' must not contain 'restriction'",
15420 xmlSchemaGetComponentQName(&str, type->baseType));
15421 FREE_AND_NULL(str)
15422 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2);
15425 * 2.3.2.3 The {item type definition} must be validly derived
15426 * from the {base type definition}'s {item type definition} given
15427 * the empty set, as defined in Type Derivation OK (Simple) (�3.14.6).
15430 xmlSchemaTypePtr baseItemType;
15432 baseItemType = type->baseType->subtypes;
15433 if ((baseItemType == NULL) || (! WXS_IS_SIMPLE(baseItemType))) {
15434 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15435 "failed to eval the item type of a base type");
15436 return (-1);
15438 if ((itemType != baseItemType) &&
15439 (xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST pctxt, itemType,
15440 baseItemType, 0) != 0)) {
15441 xmlChar *strBIT = NULL, *strBT = NULL;
15442 xmlSchemaPCustomErrExt(pctxt,
15443 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3,
15444 WXS_BASIC_CAST type, NULL,
15445 "The item type '%s' is not validly derived from "
15446 "the item type '%s' of the base type '%s'",
15447 xmlSchemaGetComponentQName(&str, itemType),
15448 xmlSchemaGetComponentQName(&strBIT, baseItemType),
15449 xmlSchemaGetComponentQName(&strBT, type->baseType));
15451 FREE_AND_NULL(str)
15452 FREE_AND_NULL(strBIT)
15453 FREE_AND_NULL(strBT)
15454 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3);
15458 if (type->facets != NULL) {
15459 xmlSchemaFacetPtr facet;
15460 int ok = 1;
15462 * 2.3.2.4 Only length, minLength, maxLength, whiteSpace, pattern
15463 * and enumeration facet components are allowed among the {facets}.
15465 facet = type->facets;
15466 do {
15467 switch (facet->type) {
15468 case XML_SCHEMA_FACET_LENGTH:
15469 case XML_SCHEMA_FACET_MINLENGTH:
15470 case XML_SCHEMA_FACET_MAXLENGTH:
15471 case XML_SCHEMA_FACET_WHITESPACE:
15473 * TODO: 2.5.1.2 List datatypes
15474 * The value of �whiteSpace� is fixed to the value collapse.
15476 case XML_SCHEMA_FACET_PATTERN:
15477 case XML_SCHEMA_FACET_ENUMERATION:
15478 break;
15479 default: {
15480 xmlSchemaPIllegalFacetListUnionErr(pctxt,
15481 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4,
15482 type, facet);
15484 * We could return, but it's nicer to report all
15485 * invalid facets.
15487 ok = 0;
15490 facet = facet->next;
15491 } while (facet != NULL);
15492 if (ok == 0)
15493 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4);
15495 * SPEC (2.3.2.5) (same as 1.3.2)
15497 * NOTE (2.3.2.5) This is currently done in
15498 * xmlSchemaDeriveAndValidateFacets()
15502 } else if (WXS_IS_UNION(type)) {
15504 * 3.1 The {member type definitions} must all have {variety} of
15505 * atomic or list.
15507 xmlSchemaTypeLinkPtr member;
15509 member = type->memberTypes;
15510 while (member != NULL) {
15511 if (WXS_IS_TYPE_NOT_FIXED(member->type))
15512 xmlSchemaTypeFixup(member->type, ACTXT_CAST pctxt);
15514 if ((! WXS_IS_ATOMIC(member->type)) &&
15515 (! WXS_IS_LIST(member->type))) {
15516 xmlSchemaPCustomErr(pctxt,
15517 XML_SCHEMAP_COS_ST_RESTRICTS_3_1,
15518 WXS_BASIC_CAST type, NULL,
15519 "The member type '%s' is neither an atomic, nor a list type",
15520 xmlSchemaGetComponentQName(&str, member->type));
15521 FREE_AND_NULL(str)
15522 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_1);
15524 member = member->next;
15527 * 3.3.1 If the {base type definition} is the �simple ur-type
15528 * definition�
15530 if (type->baseType->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) {
15532 * 3.3.1.1 All of the {member type definitions} must have a
15533 * {final} which does not contain union.
15535 member = type->memberTypes;
15536 while (member != NULL) {
15537 if (xmlSchemaTypeFinalContains(member->type,
15538 XML_SCHEMAS_TYPE_FINAL_UNION)) {
15539 xmlSchemaPCustomErr(pctxt,
15540 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1,
15541 WXS_BASIC_CAST type, NULL,
15542 "The 'final' of member type '%s' contains 'union'",
15543 xmlSchemaGetComponentQName(&str, member->type));
15544 FREE_AND_NULL(str)
15545 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1);
15547 member = member->next;
15550 * 3.3.1.2 The {facets} must be empty.
15552 if (type->facetSet != NULL) {
15553 xmlSchemaPCustomErr(pctxt,
15554 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2,
15555 WXS_BASIC_CAST type, NULL,
15556 "No facets allowed", NULL);
15557 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2);
15559 } else {
15561 * 3.3.2.1 The {base type definition} must have a {variety} of union.
15562 * I.e. the variety of "list" is inherited.
15564 if (! WXS_IS_UNION(type->baseType)) {
15565 xmlSchemaPCustomErr(pctxt,
15566 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1,
15567 WXS_BASIC_CAST type, NULL,
15568 "The base type '%s' is not a union type",
15569 xmlSchemaGetComponentQName(&str, type->baseType));
15570 FREE_AND_NULL(str)
15571 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1);
15574 * 3.3.2.2 The {final} of the {base type definition} must not contain restriction.
15576 if (xmlSchemaTypeFinalContains(type->baseType,
15577 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
15578 xmlSchemaPCustomErr(pctxt,
15579 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2,
15580 WXS_BASIC_CAST type, NULL,
15581 "The 'final' of its base type '%s' must not contain 'restriction'",
15582 xmlSchemaGetComponentQName(&str, type->baseType));
15583 FREE_AND_NULL(str)
15584 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2);
15587 * 3.3.2.3 The {member type definitions}, in order, must be validly
15588 * derived from the corresponding type definitions in the {base
15589 * type definition}'s {member type definitions} given the empty set,
15590 * as defined in Type Derivation OK (Simple) (�3.14.6).
15593 xmlSchemaTypeLinkPtr baseMember;
15596 * OPTIMIZE: if the type is restricting, it has no local defined
15597 * member types and inherits the member types of the base type;
15598 * thus a check for equality can be skipped.
15601 * Even worse: I cannot see a scenario where a restricting
15602 * union simple type can have other member types as the member
15603 * types of it's base type. This check seems not necessary with
15604 * respect to the derivation process in libxml2.
15605 * But necessary if constructing types with an API.
15607 if (type->memberTypes != NULL) {
15608 member = type->memberTypes;
15609 baseMember = xmlSchemaGetUnionSimpleTypeMemberTypes(type->baseType);
15610 if ((member == NULL) && (baseMember != NULL)) {
15611 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15612 "different number of member types in base");
15614 while (member != NULL) {
15615 if (baseMember == NULL) {
15616 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15617 "different number of member types in base");
15618 } else if ((member->type != baseMember->type) &&
15619 (xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST pctxt,
15620 member->type, baseMember->type, 0) != 0)) {
15621 xmlChar *strBMT = NULL, *strBT = NULL;
15623 xmlSchemaPCustomErrExt(pctxt,
15624 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3,
15625 WXS_BASIC_CAST type, NULL,
15626 "The member type %s is not validly "
15627 "derived from its corresponding member "
15628 "type %s of the base type %s",
15629 xmlSchemaGetComponentQName(&str, member->type),
15630 xmlSchemaGetComponentQName(&strBMT, baseMember->type),
15631 xmlSchemaGetComponentQName(&strBT, type->baseType));
15632 FREE_AND_NULL(str)
15633 FREE_AND_NULL(strBMT)
15634 FREE_AND_NULL(strBT)
15635 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3);
15637 member = member->next;
15638 if (baseMember != NULL)
15639 baseMember = baseMember->next;
15644 * 3.3.2.4 Only pattern and enumeration facet components are
15645 * allowed among the {facets}.
15647 if (type->facets != NULL) {
15648 xmlSchemaFacetPtr facet;
15649 int ok = 1;
15651 facet = type->facets;
15652 do {
15653 if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
15654 (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
15655 xmlSchemaPIllegalFacetListUnionErr(pctxt,
15656 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4,
15657 type, facet);
15658 ok = 0;
15660 facet = facet->next;
15661 } while (facet != NULL);
15662 if (ok == 0)
15663 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4);
15667 * SPEC (3.3.2.5) (same as 1.3.2)
15669 * NOTE (3.3.2.5) This is currently done in
15670 * xmlSchemaDeriveAndValidateFacets()
15675 return (0);
15679 * xmlSchemaCheckSRCSimpleType:
15680 * @ctxt: the schema parser context
15681 * @type: the simple type definition
15683 * Checks crc-simple-type constraints.
15685 * Returns 0 if the constraints are satisfied,
15686 * if not a positive error code and -1 on internal
15687 * errors.
15689 #if 0
15690 static int
15691 xmlSchemaCheckSRCSimpleType(xmlSchemaParserCtxtPtr ctxt,
15692 xmlSchemaTypePtr type)
15695 * src-simple-type.1 The corresponding simple type definition, if any,
15696 * must satisfy the conditions set out in Constraints on Simple Type
15697 * Definition Schema Components (�3.14.6).
15699 if (WXS_IS_RESTRICTION(type)) {
15701 * src-simple-type.2 "If the <restriction> alternative is chosen,
15702 * either it must have a base [attribute] or a <simpleType> among its
15703 * [children], but not both."
15704 * NOTE: This is checked in the parse function of <restriction>.
15709 } else if (WXS_IS_LIST(type)) {
15710 /* src-simple-type.3 "If the <list> alternative is chosen, either it must have
15711 * an itemType [attribute] or a <simpleType> among its [children],
15712 * but not both."
15714 * NOTE: This is checked in the parse function of <list>.
15716 } else if (WXS_IS_UNION(type)) {
15718 * src-simple-type.4 is checked in xmlSchemaCheckUnionTypeDefCircular().
15721 return (0);
15723 #endif
15725 static int
15726 xmlSchemaCreateVCtxtOnPCtxt(xmlSchemaParserCtxtPtr ctxt)
15728 if (ctxt->vctxt == NULL) {
15729 ctxt->vctxt = xmlSchemaNewValidCtxt(NULL);
15730 if (ctxt->vctxt == NULL) {
15731 xmlSchemaPErr(ctxt, NULL,
15732 XML_SCHEMAP_INTERNAL,
15733 "Internal error: xmlSchemaCreateVCtxtOnPCtxt, "
15734 "failed to create a temp. validation context.\n",
15735 NULL, NULL);
15736 return (-1);
15738 /* TODO: Pass user data. */
15739 xmlSchemaSetValidErrors(ctxt->vctxt,
15740 ctxt->error, ctxt->warning, ctxt->errCtxt);
15741 xmlSchemaSetValidStructuredErrors(ctxt->vctxt,
15742 ctxt->serror, ctxt->errCtxt);
15744 return (0);
15747 static int
15748 xmlSchemaVCheckCVCSimpleType(xmlSchemaAbstractCtxtPtr actxt,
15749 xmlNodePtr node,
15750 xmlSchemaTypePtr type,
15751 const xmlChar *value,
15752 xmlSchemaValPtr *retVal,
15753 int fireErrors,
15754 int normalize,
15755 int isNormalized);
15758 * xmlSchemaParseCheckCOSValidDefault:
15759 * @pctxt: the schema parser context
15760 * @type: the simple type definition
15761 * @value: the default value
15762 * @node: an optional node (the holder of the value)
15764 * Schema Component Constraint: Element Default Valid (Immediate)
15765 * (cos-valid-default)
15766 * This will be used by the parser only. For the validator there's
15767 * an other version.
15769 * Returns 0 if the constraints are satisfied,
15770 * if not, a positive error code and -1 on internal
15771 * errors.
15773 static int
15774 xmlSchemaParseCheckCOSValidDefault(xmlSchemaParserCtxtPtr pctxt,
15775 xmlNodePtr node,
15776 xmlSchemaTypePtr type,
15777 const xmlChar *value,
15778 xmlSchemaValPtr *val)
15780 int ret = 0;
15783 * cos-valid-default:
15784 * Schema Component Constraint: Element Default Valid (Immediate)
15785 * For a string to be a valid default with respect to a type
15786 * definition the appropriate case among the following must be true:
15788 if WXS_IS_COMPLEX(type) {
15790 * Complex type.
15792 * SPEC (2.1) "its {content type} must be a simple type definition
15793 * or mixed."
15794 * SPEC (2.2.2) "If the {content type} is mixed, then the {content
15795 * type}'s particle must be �emptiable� as defined by
15796 * Particle Emptiable (�3.9.6)."
15798 if ((! WXS_HAS_SIMPLE_CONTENT(type)) &&
15799 ((! WXS_HAS_MIXED_CONTENT(type)) || (! WXS_EMPTIABLE(type)))) {
15800 /* NOTE that this covers (2.2.2) as well. */
15801 xmlSchemaPCustomErr(pctxt,
15802 XML_SCHEMAP_COS_VALID_DEFAULT_2_1,
15803 WXS_BASIC_CAST type, type->node,
15804 "For a string to be a valid default, the type definition "
15805 "must be a simple type or a complex type with mixed content "
15806 "and a particle emptiable", NULL);
15807 return(XML_SCHEMAP_COS_VALID_DEFAULT_2_1);
15811 * 1 If the type definition is a simple type definition, then the string
15812 * must be �valid� with respect to that definition as defined by String
15813 * Valid (�3.14.4).
15815 * AND
15817 * 2.2.1 If the {content type} is a simple type definition, then the
15818 * string must be �valid� with respect to that simple type definition
15819 * as defined by String Valid (�3.14.4).
15821 if (WXS_IS_SIMPLE(type))
15822 ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST pctxt, node,
15823 type, value, val, 1, 1, 0);
15824 else if (WXS_HAS_SIMPLE_CONTENT(type))
15825 ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST pctxt, node,
15826 type->contentTypeDef, value, val, 1, 1, 0);
15827 else
15828 return (ret);
15830 if (ret < 0) {
15831 PERROR_INT("xmlSchemaParseCheckCOSValidDefault",
15832 "calling xmlSchemaVCheckCVCSimpleType()");
15835 return (ret);
15839 * xmlSchemaCheckCTPropsCorrect:
15840 * @ctxt: the schema parser context
15841 * @type: the complex type definition
15843 *.(4.6) Constraints on Complex Type Definition Schema Components
15844 * Schema Component Constraint:
15845 * Complex Type Definition Properties Correct (ct-props-correct)
15846 * STATUS: (seems) complete
15848 * Returns 0 if the constraints are satisfied, a positive
15849 * error code if not and -1 if an internal error occured.
15851 static int
15852 xmlSchemaCheckCTPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
15853 xmlSchemaTypePtr type)
15856 * TODO: Correct the error code; XML_SCHEMAP_SRC_CT_1 is used temporarily.
15858 * SPEC (1) "The values of the properties of a complex type definition must
15859 * be as described in the property tableau in The Complex Type Definition
15860 * Schema Component (�3.4.1), modulo the impact of Missing
15861 * Sub-components (�5.3)."
15863 if ((type->baseType != NULL) &&
15864 (WXS_IS_SIMPLE(type->baseType)) &&
15865 (WXS_IS_EXTENSION(type) == 0)) {
15867 * SPEC (2) "If the {base type definition} is a simple type definition,
15868 * the {derivation method} must be extension."
15870 xmlSchemaCustomErr(ACTXT_CAST pctxt,
15871 XML_SCHEMAP_SRC_CT_1,
15872 NULL, WXS_BASIC_CAST type,
15873 "If the base type is a simple type, the derivation method must be "
15874 "'extension'", NULL, NULL);
15875 return (XML_SCHEMAP_SRC_CT_1);
15878 * SPEC (3) "Circular definitions are disallowed, except for the �ur-type
15879 * definition�. That is, it must be possible to reach the �ur-type
15880 * definition by repeatedly following the {base type definition}."
15882 * NOTE (3) is done in xmlSchemaCheckTypeDefCircular().
15885 * NOTE that (4) and (5) need the following:
15886 * - attribute uses need to be already inherited (apply attr. prohibitions)
15887 * - attribute group references need to be expanded already
15888 * - simple types need to be typefixed already
15890 if (type->attrUses &&
15891 (((xmlSchemaItemListPtr) type->attrUses)->nbItems > 1))
15893 xmlSchemaItemListPtr uses = (xmlSchemaItemListPtr) type->attrUses;
15894 xmlSchemaAttributeUsePtr use, tmp;
15895 int i, j, hasId = 0;
15897 for (i = uses->nbItems -1; i >= 0; i--) {
15898 use = uses->items[i];
15901 * SPEC ct-props-correct
15902 * (4) "Two distinct attribute declarations in the
15903 * {attribute uses} must not have identical {name}s and
15904 * {target namespace}s."
15906 if (i > 0) {
15907 for (j = i -1; j >= 0; j--) {
15908 tmp = uses->items[j];
15909 if ((WXS_ATTRUSE_DECL_NAME(use) ==
15910 WXS_ATTRUSE_DECL_NAME(tmp)) &&
15911 (WXS_ATTRUSE_DECL_TNS(use) ==
15912 WXS_ATTRUSE_DECL_TNS(tmp)))
15914 xmlChar *str = NULL;
15916 xmlSchemaCustomErr(ACTXT_CAST pctxt,
15917 XML_SCHEMAP_AG_PROPS_CORRECT,
15918 NULL, WXS_BASIC_CAST type,
15919 "Duplicate %s",
15920 xmlSchemaGetComponentDesignation(&str, use),
15921 NULL);
15922 FREE_AND_NULL(str);
15924 * Remove the duplicate.
15926 if (xmlSchemaItemListRemove(uses, i) == -1)
15927 goto exit_failure;
15928 goto next_use;
15933 * SPEC ct-props-correct
15934 * (5) "Two distinct attribute declarations in the
15935 * {attribute uses} must not have {type definition}s which
15936 * are or are derived from ID."
15938 if (WXS_ATTRUSE_TYPEDEF(use) != NULL) {
15939 if (xmlSchemaIsDerivedFromBuiltInType(
15940 WXS_ATTRUSE_TYPEDEF(use), XML_SCHEMAS_ID))
15942 if (hasId) {
15943 xmlChar *str = NULL;
15945 xmlSchemaCustomErr(ACTXT_CAST pctxt,
15946 XML_SCHEMAP_AG_PROPS_CORRECT,
15947 NULL, WXS_BASIC_CAST type,
15948 "There must not exist more than one attribute "
15949 "declaration of type 'xs:ID' "
15950 "(or derived from 'xs:ID'). The %s violates this "
15951 "constraint",
15952 xmlSchemaGetComponentDesignation(&str, use),
15953 NULL);
15954 FREE_AND_NULL(str);
15955 if (xmlSchemaItemListRemove(uses, i) == -1)
15956 goto exit_failure;
15959 hasId = 1;
15962 next_use: {}
15965 return (0);
15966 exit_failure:
15967 return(-1);
15970 static int
15971 xmlSchemaAreEqualTypes(xmlSchemaTypePtr typeA,
15972 xmlSchemaTypePtr typeB)
15975 * TODO: This should implement component-identity
15976 * in the future.
15978 if ((typeA == NULL) || (typeB == NULL))
15979 return (0);
15980 return (typeA == typeB);
15984 * xmlSchemaCheckCOSCTDerivedOK:
15985 * @ctxt: the schema parser context
15986 * @type: the to-be derived complex type definition
15987 * @baseType: the base complex type definition
15988 * @set: the given set
15990 * Schema Component Constraint:
15991 * Type Derivation OK (Complex) (cos-ct-derived-ok)
15993 * STATUS: completed
15995 * Returns 0 if the constraints are satisfied, or 1
15996 * if not.
15998 static int
15999 xmlSchemaCheckCOSCTDerivedOK(xmlSchemaAbstractCtxtPtr actxt,
16000 xmlSchemaTypePtr type,
16001 xmlSchemaTypePtr baseType,
16002 int set)
16004 int equal = xmlSchemaAreEqualTypes(type, baseType);
16005 /* TODO: Error codes. */
16007 * SPEC "For a complex type definition (call it D, for derived)
16008 * to be validly derived from a type definition (call this
16009 * B, for base) given a subset of {extension, restriction}
16010 * all of the following must be true:"
16012 if (! equal) {
16014 * SPEC (1) "If B and D are not the same type definition, then the
16015 * {derivation method} of D must not be in the subset."
16017 if (((set & SUBSET_EXTENSION) && (WXS_IS_EXTENSION(type))) ||
16018 ((set & SUBSET_RESTRICTION) && (WXS_IS_RESTRICTION(type))))
16019 return (1);
16020 } else {
16022 * SPEC (2.1) "B and D must be the same type definition."
16024 return (0);
16027 * SPEC (2.2) "B must be D's {base type definition}."
16029 if (type->baseType == baseType)
16030 return (0);
16032 * SPEC (2.3.1) "D's {base type definition} must not be the �ur-type
16033 * definition�."
16035 if (WXS_IS_ANYTYPE(type->baseType))
16036 return (1);
16038 if (WXS_IS_COMPLEX(type->baseType)) {
16040 * SPEC (2.3.2.1) "If D's {base type definition} is complex, then it
16041 * must be validly derived from B given the subset as defined by this
16042 * constraint."
16044 return (xmlSchemaCheckCOSCTDerivedOK(actxt, type->baseType,
16045 baseType, set));
16046 } else {
16048 * SPEC (2.3.2.2) "If D's {base type definition} is simple, then it
16049 * must be validly derived from B given the subset as defined in Type
16050 * Derivation OK (Simple) (�3.14.6).
16052 return (xmlSchemaCheckCOSSTDerivedOK(actxt, type->baseType,
16053 baseType, set));
16058 * xmlSchemaCheckCOSDerivedOK:
16059 * @type: the derived simple type definition
16060 * @baseType: the base type definition
16062 * Calls:
16063 * Type Derivation OK (Simple) AND Type Derivation OK (Complex)
16065 * Checks wheter @type can be validly derived from @baseType.
16067 * Returns 0 on success, an positive error code otherwise.
16069 static int
16070 xmlSchemaCheckCOSDerivedOK(xmlSchemaAbstractCtxtPtr actxt,
16071 xmlSchemaTypePtr type,
16072 xmlSchemaTypePtr baseType,
16073 int set)
16075 if (WXS_IS_SIMPLE(type))
16076 return (xmlSchemaCheckCOSSTDerivedOK(actxt, type, baseType, set));
16077 else
16078 return (xmlSchemaCheckCOSCTDerivedOK(actxt, type, baseType, set));
16082 * xmlSchemaCheckCOSCTExtends:
16083 * @ctxt: the schema parser context
16084 * @type: the complex type definition
16086 * (3.4.6) Constraints on Complex Type Definition Schema Components
16087 * Schema Component Constraint:
16088 * Derivation Valid (Extension) (cos-ct-extends)
16090 * STATUS:
16091 * missing:
16092 * (1.5)
16093 * (1.4.3.2.2.2) "Particle Valid (Extension)"
16095 * Returns 0 if the constraints are satisfied, a positive
16096 * error code if not and -1 if an internal error occured.
16098 static int
16099 xmlSchemaCheckCOSCTExtends(xmlSchemaParserCtxtPtr ctxt,
16100 xmlSchemaTypePtr type)
16102 xmlSchemaTypePtr base = type->baseType;
16104 * TODO: Correct the error code; XML_SCHEMAP_COS_CT_EXTENDS_1_1 is used
16105 * temporarily only.
16108 * SPEC (1) "If the {base type definition} is a complex type definition,
16109 * then all of the following must be true:"
16111 if (WXS_IS_COMPLEX(base)) {
16113 * SPEC (1.1) "The {final} of the {base type definition} must not
16114 * contain extension."
16116 if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
16117 xmlSchemaPCustomErr(ctxt,
16118 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
16119 WXS_BASIC_CAST type, NULL,
16120 "The 'final' of the base type definition "
16121 "contains 'extension'", NULL);
16122 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16126 * ATTENTION: The constrains (1.2) and (1.3) are not applied,
16127 * since they are automatically satisfied through the
16128 * inheriting mechanism.
16129 * Note that even if redefining components, the inheriting mechanism
16130 * is used.
16132 #if 0
16134 * SPEC (1.2) "Its {attribute uses} must be a subset of the {attribute
16135 * uses}
16136 * of the complex type definition itself, that is, for every attribute
16137 * use in the {attribute uses} of the {base type definition}, there
16138 * must be an attribute use in the {attribute uses} of the complex
16139 * type definition itself whose {attribute declaration} has the same
16140 * {name}, {target namespace} and {type definition} as its attribute
16141 * declaration"
16143 if (base->attrUses != NULL) {
16144 int i, j, found;
16145 xmlSchemaAttributeUsePtr use, buse;
16147 for (i = 0; i < (WXS_LIST_CAST base->attrUses)->nbItems; i ++) {
16148 buse = (WXS_LIST_CAST base->attrUses)->items[i];
16149 found = 0;
16150 if (type->attrUses != NULL) {
16151 use = (WXS_LIST_CAST type->attrUses)->items[j];
16152 for (j = 0; j < (WXS_LIST_CAST type->attrUses)->nbItems; j ++)
16154 if ((WXS_ATTRUSE_DECL_NAME(use) ==
16155 WXS_ATTRUSE_DECL_NAME(buse)) &&
16156 (WXS_ATTRUSE_DECL_TNS(use) ==
16157 WXS_ATTRUSE_DECL_TNS(buse)) &&
16158 (WXS_ATTRUSE_TYPEDEF(use) ==
16159 WXS_ATTRUSE_TYPEDEF(buse))
16161 found = 1;
16162 break;
16166 if (! found) {
16167 xmlChar *str = NULL;
16169 xmlSchemaCustomErr(ACTXT_CAST ctxt,
16170 XML_SCHEMAP_COS_CT_EXTENDS_1_2,
16171 NULL, WXS_BASIC_CAST type,
16173 * TODO: The report does not indicate that also the
16174 * type needs to be the same.
16176 "This type is missing a matching correspondent "
16177 "for its {base type}'s %s in its {attribute uses}",
16178 xmlSchemaGetComponentDesignation(&str,
16179 buse->children),
16180 NULL);
16181 FREE_AND_NULL(str)
16186 * SPEC (1.3) "If it has an {attribute wildcard}, the complex type
16187 * definition must also have one, and the base type definition's
16188 * {attribute wildcard}'s {namespace constraint} must be a subset
16189 * of the complex type definition's {attribute wildcard}'s {namespace
16190 * constraint}, as defined by Wildcard Subset (�3.10.6)."
16194 * MAYBE TODO: Enable if ever needed. But this will be needed only
16195 * if created the type via a schema construction API.
16197 if (base->attributeWildcard != NULL) {
16198 if (type->attributeWilcard == NULL) {
16199 xmlChar *str = NULL;
16201 xmlSchemaCustomErr(ACTXT_CAST pctxt,
16202 XML_SCHEMAP_COS_CT_EXTENDS_1_3,
16203 NULL, type,
16204 "The base %s has an attribute wildcard, "
16205 "but this type is missing an attribute wildcard",
16206 xmlSchemaGetComponentDesignation(&str, base));
16207 FREE_AND_NULL(str)
16209 } else if (xmlSchemaCheckCOSNSSubset(
16210 base->attributeWildcard, type->attributeWildcard))
16212 xmlChar *str = NULL;
16214 xmlSchemaCustomErr(ACTXT_CAST pctxt,
16215 XML_SCHEMAP_COS_CT_EXTENDS_1_3,
16216 NULL, type,
16217 "The attribute wildcard is not a valid "
16218 "superset of the one in the base %s",
16219 xmlSchemaGetComponentDesignation(&str, base));
16220 FREE_AND_NULL(str)
16223 #endif
16225 * SPEC (1.4) "One of the following must be true:"
16227 if ((type->contentTypeDef != NULL) &&
16228 (type->contentTypeDef == base->contentTypeDef)) {
16230 * SPEC (1.4.1) "The {content type} of the {base type definition}
16231 * and the {content type} of the complex type definition itself
16232 * must be the same simple type definition"
16233 * PASS
16235 } else if ((type->contentType == XML_SCHEMA_CONTENT_EMPTY) &&
16236 (base->contentType == XML_SCHEMA_CONTENT_EMPTY) ) {
16238 * SPEC (1.4.2) "The {content type} of both the {base type
16239 * definition} and the complex type definition itself must
16240 * be empty."
16241 * PASS
16243 } else {
16245 * SPEC (1.4.3) "All of the following must be true:"
16247 if (type->subtypes == NULL) {
16249 * SPEC 1.4.3.1 The {content type} of the complex type
16250 * definition itself must specify a particle.
16252 xmlSchemaPCustomErr(ctxt,
16253 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
16254 WXS_BASIC_CAST type, NULL,
16255 "The content type must specify a particle", NULL);
16256 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16259 * SPEC (1.4.3.2) "One of the following must be true:"
16261 if (base->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16263 * SPEC (1.4.3.2.1) "The {content type} of the {base type
16264 * definition} must be empty.
16265 * PASS
16267 } else {
16269 * SPEC (1.4.3.2.2) "All of the following must be true:"
16271 if ((type->contentType != base->contentType) ||
16272 ((type->contentType != XML_SCHEMA_CONTENT_MIXED) &&
16273 (type->contentType != XML_SCHEMA_CONTENT_ELEMENTS))) {
16275 * SPEC (1.4.3.2.2.1) "Both {content type}s must be mixed
16276 * or both must be element-only."
16278 xmlSchemaPCustomErr(ctxt,
16279 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
16280 WXS_BASIC_CAST type, NULL,
16281 "The content type of both, the type and its base "
16282 "type, must either 'mixed' or 'element-only'", NULL);
16283 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16286 * URGENT TODO SPEC (1.4.3.2.2.2) "The particle of the
16287 * complex type definition must be a �valid extension�
16288 * of the {base type definition}'s particle, as defined
16289 * in Particle Valid (Extension) (�3.9.6)."
16291 * NOTE that we won't check "Particle Valid (Extension)",
16292 * since it is ensured by the derivation process in
16293 * xmlSchemaTypeFixup(). We need to implement this when heading
16294 * for a construction API
16295 * TODO: !! This is needed to be checked if redefining a type !!
16299 * URGENT TODO (1.5)
16302 } else {
16304 * SPEC (2) "If the {base type definition} is a simple type definition,
16305 * then all of the following must be true:"
16307 if (type->contentTypeDef != base) {
16309 * SPEC (2.1) "The {content type} must be the same simple type
16310 * definition."
16312 xmlSchemaPCustomErr(ctxt,
16313 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
16314 WXS_BASIC_CAST type, NULL,
16315 "The content type must be the simple base type", NULL);
16316 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16318 if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
16320 * SPEC (2.2) "The {final} of the {base type definition} must not
16321 * contain extension"
16322 * NOTE that this is the same as (1.1).
16324 xmlSchemaPCustomErr(ctxt,
16325 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
16326 WXS_BASIC_CAST type, NULL,
16327 "The 'final' of the base type definition "
16328 "contains 'extension'", NULL);
16329 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16332 return (0);
16336 * xmlSchemaCheckDerivationOKRestriction:
16337 * @ctxt: the schema parser context
16338 * @type: the complex type definition
16340 * (3.4.6) Constraints on Complex Type Definition Schema Components
16341 * Schema Component Constraint:
16342 * Derivation Valid (Restriction, Complex) (derivation-ok-restriction)
16344 * STATUS:
16345 * missing:
16346 * (5.4.2) ???
16348 * ATTENTION:
16349 * In XML Schema 1.1 this will be:
16350 * Validation Rule: Checking complex type subsumption
16352 * Returns 0 if the constraints are satisfied, a positive
16353 * error code if not and -1 if an internal error occured.
16355 static int
16356 xmlSchemaCheckDerivationOKRestriction(xmlSchemaParserCtxtPtr ctxt,
16357 xmlSchemaTypePtr type)
16359 xmlSchemaTypePtr base;
16362 * TODO: Correct the error code; XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1 is used
16363 * temporarily only.
16365 base = type->baseType;
16366 if (! WXS_IS_COMPLEX(base)) {
16367 xmlSchemaCustomErr(ACTXT_CAST ctxt,
16368 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16369 type->node, WXS_BASIC_CAST type,
16370 "The base type must be a complex type", NULL, NULL);
16371 return(ctxt->err);
16373 if (base->flags & XML_SCHEMAS_TYPE_FINAL_RESTRICTION) {
16375 * SPEC (1) "The {base type definition} must be a complex type
16376 * definition whose {final} does not contain restriction."
16378 xmlSchemaCustomErr(ACTXT_CAST ctxt,
16379 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16380 type->node, WXS_BASIC_CAST type,
16381 "The 'final' of the base type definition "
16382 "contains 'restriction'", NULL, NULL);
16383 return (ctxt->err);
16386 * SPEC (2), (3) and (4)
16387 * Those are handled in a separate function, since the
16388 * same constraints are needed for redefinition of
16389 * attribute groups as well.
16391 if (xmlSchemaCheckDerivationOKRestriction2to4(ctxt,
16392 XML_SCHEMA_ACTION_DERIVE,
16393 WXS_BASIC_CAST type, WXS_BASIC_CAST base,
16394 type->attrUses, base->attrUses,
16395 type->attributeWildcard,
16396 base->attributeWildcard) == -1)
16398 return(-1);
16401 * SPEC (5) "One of the following must be true:"
16403 if (base->builtInType == XML_SCHEMAS_ANYTYPE) {
16405 * SPEC (5.1) "The {base type definition} must be the
16406 * �ur-type definition�."
16407 * PASS
16409 } else if ((type->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
16410 (type->contentType == XML_SCHEMA_CONTENT_BASIC)) {
16412 * SPEC (5.2.1) "The {content type} of the complex type definition
16413 * must be a simple type definition"
16415 * SPEC (5.2.2) "One of the following must be true:"
16417 if ((base->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
16418 (base->contentType == XML_SCHEMA_CONTENT_BASIC))
16420 int err;
16422 * SPEC (5.2.2.1) "The {content type} of the {base type
16423 * definition} must be a simple type definition from which
16424 * the {content type} is validly derived given the empty
16425 * set as defined in Type Derivation OK (Simple) (�3.14.6)."
16427 * ATTENTION TODO: This seems not needed if the type implicitely
16428 * derived from the base type.
16431 err = xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST ctxt,
16432 type->contentTypeDef, base->contentTypeDef, 0);
16433 if (err != 0) {
16434 xmlChar *strA = NULL, *strB = NULL;
16436 if (err == -1)
16437 return(-1);
16438 xmlSchemaCustomErr(ACTXT_CAST ctxt,
16439 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16440 NULL, WXS_BASIC_CAST type,
16441 "The {content type} %s is not validly derived from the "
16442 "base type's {content type} %s",
16443 xmlSchemaGetComponentDesignation(&strA,
16444 type->contentTypeDef),
16445 xmlSchemaGetComponentDesignation(&strB,
16446 base->contentTypeDef));
16447 FREE_AND_NULL(strA);
16448 FREE_AND_NULL(strB);
16449 return(ctxt->err);
16451 } else if ((base->contentType == XML_SCHEMA_CONTENT_MIXED) &&
16452 (xmlSchemaIsParticleEmptiable(
16453 (xmlSchemaParticlePtr) base->subtypes))) {
16455 * SPEC (5.2.2.2) "The {base type definition} must be mixed
16456 * and have a particle which is �emptiable� as defined in
16457 * Particle Emptiable (�3.9.6)."
16458 * PASS
16460 } else {
16461 xmlSchemaPCustomErr(ctxt,
16462 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16463 WXS_BASIC_CAST type, NULL,
16464 "The content type of the base type must be either "
16465 "a simple type or 'mixed' and an emptiable particle", NULL);
16466 return (ctxt->err);
16468 } else if (type->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16470 * SPEC (5.3.1) "The {content type} of the complex type itself must
16471 * be empty"
16473 if (base->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16475 * SPEC (5.3.2.1) "The {content type} of the {base type
16476 * definition} must also be empty."
16477 * PASS
16479 } else if (((base->contentType == XML_SCHEMA_CONTENT_ELEMENTS) ||
16480 (base->contentType == XML_SCHEMA_CONTENT_MIXED)) &&
16481 xmlSchemaIsParticleEmptiable(
16482 (xmlSchemaParticlePtr) base->subtypes)) {
16484 * SPEC (5.3.2.2) "The {content type} of the {base type
16485 * definition} must be elementOnly or mixed and have a particle
16486 * which is �emptiable� as defined in Particle Emptiable (�3.9.6)."
16487 * PASS
16489 } else {
16490 xmlSchemaPCustomErr(ctxt,
16491 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16492 WXS_BASIC_CAST type, NULL,
16493 "The content type of the base type must be either "
16494 "empty or 'mixed' (or 'elements-only') and an emptiable "
16495 "particle", NULL);
16496 return (ctxt->err);
16498 } else if ((type->contentType == XML_SCHEMA_CONTENT_ELEMENTS) ||
16499 WXS_HAS_MIXED_CONTENT(type)) {
16501 * SPEC (5.4.1.1) "The {content type} of the complex type definition
16502 * itself must be element-only"
16504 if (WXS_HAS_MIXED_CONTENT(type) && (! WXS_HAS_MIXED_CONTENT(base))) {
16506 * SPEC (5.4.1.2) "The {content type} of the complex type
16507 * definition itself and of the {base type definition} must be
16508 * mixed"
16510 xmlSchemaPCustomErr(ctxt,
16511 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16512 WXS_BASIC_CAST type, NULL,
16513 "If the content type is 'mixed', then the content type of the "
16514 "base type must also be 'mixed'", NULL);
16515 return (ctxt->err);
16518 * SPEC (5.4.2) "The particle of the complex type definition itself
16519 * must be a �valid restriction� of the particle of the {content
16520 * type} of the {base type definition} as defined in Particle Valid
16521 * (Restriction) (�3.9.6).
16523 * URGENT TODO: (5.4.2)
16525 } else {
16526 xmlSchemaPCustomErr(ctxt,
16527 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16528 WXS_BASIC_CAST type, NULL,
16529 "The type is not a valid restriction of its base type", NULL);
16530 return (ctxt->err);
16532 return (0);
16536 * xmlSchemaCheckCTComponent:
16537 * @ctxt: the schema parser context
16538 * @type: the complex type definition
16540 * (3.4.6) Constraints on Complex Type Definition Schema Components
16542 * Returns 0 if the constraints are satisfied, a positive
16543 * error code if not and -1 if an internal error occured.
16545 static int
16546 xmlSchemaCheckCTComponent(xmlSchemaParserCtxtPtr ctxt,
16547 xmlSchemaTypePtr type)
16549 int ret;
16551 * Complex Type Definition Properties Correct
16553 ret = xmlSchemaCheckCTPropsCorrect(ctxt, type);
16554 if (ret != 0)
16555 return (ret);
16556 if (WXS_IS_EXTENSION(type))
16557 ret = xmlSchemaCheckCOSCTExtends(ctxt, type);
16558 else
16559 ret = xmlSchemaCheckDerivationOKRestriction(ctxt, type);
16560 return (ret);
16564 * xmlSchemaCheckSRCCT:
16565 * @ctxt: the schema parser context
16566 * @type: the complex type definition
16568 * (3.4.3) Constraints on XML Representations of Complex Type Definitions:
16569 * Schema Representation Constraint:
16570 * Complex Type Definition Representation OK (src-ct)
16572 * Returns 0 if the constraints are satisfied, a positive
16573 * error code if not and -1 if an internal error occured.
16575 static int
16576 xmlSchemaCheckSRCCT(xmlSchemaParserCtxtPtr ctxt,
16577 xmlSchemaTypePtr type)
16579 xmlSchemaTypePtr base;
16580 int ret = 0;
16583 * TODO: Adjust the error codes here, as I used
16584 * XML_SCHEMAP_SRC_CT_1 only yet.
16586 base = type->baseType;
16587 if (! WXS_HAS_SIMPLE_CONTENT(type)) {
16589 * 1 If the <complexContent> alternative is chosen, the type definition
16590 * �resolved� to by the �actual value� of the base [attribute]
16591 * must be a complex type definition;
16593 if (! WXS_IS_COMPLEX(base)) {
16594 xmlChar *str = NULL;
16595 xmlSchemaPCustomErr(ctxt,
16596 XML_SCHEMAP_SRC_CT_1,
16597 WXS_BASIC_CAST type, type->node,
16598 "If using <complexContent>, the base type is expected to be "
16599 "a complex type. The base type '%s' is a simple type",
16600 xmlSchemaFormatQName(&str, base->targetNamespace,
16601 base->name));
16602 FREE_AND_NULL(str)
16603 return (XML_SCHEMAP_SRC_CT_1);
16605 } else {
16607 * SPEC
16608 * 2 If the <simpleContent> alternative is chosen, all of the
16609 * following must be true:
16610 * 2.1 The type definition �resolved� to by the �actual value� of the
16611 * base [attribute] must be one of the following:
16613 if (WXS_IS_SIMPLE(base)) {
16614 if (WXS_IS_EXTENSION(type) == 0) {
16615 xmlChar *str = NULL;
16617 * 2.1.3 only if the <extension> alternative is also
16618 * chosen, a simple type definition.
16620 /* TODO: Change error code to ..._SRC_CT_2_1_3. */
16621 xmlSchemaPCustomErr(ctxt,
16622 XML_SCHEMAP_SRC_CT_1,
16623 WXS_BASIC_CAST type, NULL,
16624 "If using <simpleContent> and <restriction>, the base "
16625 "type must be a complex type. The base type '%s' is "
16626 "a simple type",
16627 xmlSchemaFormatQName(&str, base->targetNamespace,
16628 base->name));
16629 FREE_AND_NULL(str)
16630 return (XML_SCHEMAP_SRC_CT_1);
16632 } else {
16633 /* Base type is a complex type. */
16634 if ((base->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
16635 (base->contentType == XML_SCHEMA_CONTENT_BASIC)) {
16637 * 2.1.1 a complex type definition whose {content type} is a
16638 * simple type definition;
16639 * PASS
16641 if (base->contentTypeDef == NULL) {
16642 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
16643 WXS_BASIC_CAST type, NULL,
16644 "Internal error: xmlSchemaCheckSRCCT, "
16645 "'%s', base type has no content type",
16646 type->name);
16647 return (-1);
16649 } else if ((base->contentType == XML_SCHEMA_CONTENT_MIXED) &&
16650 (WXS_IS_RESTRICTION(type))) {
16653 * 2.1.2 only if the <restriction> alternative is also
16654 * chosen, a complex type definition whose {content type}
16655 * is mixed and a particle emptiable.
16657 if (! xmlSchemaIsParticleEmptiable(
16658 (xmlSchemaParticlePtr) base->subtypes)) {
16659 ret = XML_SCHEMAP_SRC_CT_1;
16660 } else
16662 * Attention: at this point the <simpleType> child is in
16663 * ->contentTypeDef (put there during parsing).
16665 if (type->contentTypeDef == NULL) {
16666 xmlChar *str = NULL;
16668 * 2.2 If clause 2.1.2 above is satisfied, then there
16669 * must be a <simpleType> among the [children] of
16670 * <restriction>.
16672 /* TODO: Change error code to ..._SRC_CT_2_2. */
16673 xmlSchemaPCustomErr(ctxt,
16674 XML_SCHEMAP_SRC_CT_1,
16675 WXS_BASIC_CAST type, NULL,
16676 "A <simpleType> is expected among the children "
16677 "of <restriction>, if <simpleContent> is used and "
16678 "the base type '%s' is a complex type",
16679 xmlSchemaFormatQName(&str, base->targetNamespace,
16680 base->name));
16681 FREE_AND_NULL(str)
16682 return (XML_SCHEMAP_SRC_CT_1);
16684 } else {
16685 ret = XML_SCHEMAP_SRC_CT_1;
16688 if (ret > 0) {
16689 xmlChar *str = NULL;
16690 if (WXS_IS_RESTRICTION(type)) {
16691 xmlSchemaPCustomErr(ctxt,
16692 XML_SCHEMAP_SRC_CT_1,
16693 WXS_BASIC_CAST type, NULL,
16694 "If <simpleContent> and <restriction> is used, the "
16695 "base type must be a simple type or a complex type with "
16696 "mixed content and particle emptiable. The base type "
16697 "'%s' is none of those",
16698 xmlSchemaFormatQName(&str, base->targetNamespace,
16699 base->name));
16700 } else {
16701 xmlSchemaPCustomErr(ctxt,
16702 XML_SCHEMAP_SRC_CT_1,
16703 WXS_BASIC_CAST type, NULL,
16704 "If <simpleContent> and <extension> is used, the "
16705 "base type must be a simple type. The base type '%s' "
16706 "is a complex type",
16707 xmlSchemaFormatQName(&str, base->targetNamespace,
16708 base->name));
16710 FREE_AND_NULL(str)
16714 * SPEC (3) "The corresponding complex type definition component must
16715 * satisfy the conditions set out in Constraints on Complex Type
16716 * Definition Schema Components (�3.4.6);"
16717 * NOTE (3) will be done in xmlSchemaTypeFixup().
16720 * SPEC (4) If clause 2.2.1 or clause 2.2.2 in the correspondence specification
16721 * above for {attribute wildcard} is satisfied, the intensional
16722 * intersection must be expressible, as defined in Attribute Wildcard
16723 * Intersection (�3.10.6).
16724 * NOTE (4) is done in xmlSchemaFixupTypeAttributeUses().
16726 return (ret);
16729 #ifdef ENABLE_PARTICLE_RESTRICTION
16731 * xmlSchemaCheckParticleRangeOK:
16732 * @ctxt: the schema parser context
16733 * @type: the complex type definition
16735 * (3.9.6) Constraints on Particle Schema Components
16736 * Schema Component Constraint:
16737 * Occurrence Range OK (range-ok)
16739 * STATUS: complete
16741 * Returns 0 if the constraints are satisfied, a positive
16742 * error code if not and -1 if an internal error occured.
16744 static int
16745 xmlSchemaCheckParticleRangeOK(int rmin, int rmax,
16746 int bmin, int bmax)
16748 if (rmin < bmin)
16749 return (1);
16750 if ((bmax != UNBOUNDED) &&
16751 (rmax > bmax))
16752 return (1);
16753 return (0);
16757 * xmlSchemaCheckRCaseNameAndTypeOK:
16758 * @ctxt: the schema parser context
16759 * @r: the restricting element declaration particle
16760 * @b: the base element declaration particle
16762 * (3.9.6) Constraints on Particle Schema Components
16763 * Schema Component Constraint:
16764 * Particle Restriction OK (Elt:Elt -- NameAndTypeOK)
16765 * (rcase-NameAndTypeOK)
16767 * STATUS:
16768 * MISSING (3.2.3)
16769 * CLARIFY: (3.2.2)
16771 * Returns 0 if the constraints are satisfied, a positive
16772 * error code if not and -1 if an internal error occured.
16774 static int
16775 xmlSchemaCheckRCaseNameAndTypeOK(xmlSchemaParserCtxtPtr ctxt,
16776 xmlSchemaParticlePtr r,
16777 xmlSchemaParticlePtr b)
16779 xmlSchemaElementPtr elemR, elemB;
16781 /* TODO: Error codes (rcase-NameAndTypeOK). */
16782 elemR = (xmlSchemaElementPtr) r->children;
16783 elemB = (xmlSchemaElementPtr) b->children;
16785 * SPEC (1) "The declarations' {name}s and {target namespace}s are
16786 * the same."
16788 if ((elemR != elemB) &&
16789 ((! xmlStrEqual(elemR->name, elemB->name)) ||
16790 (! xmlStrEqual(elemR->targetNamespace, elemB->targetNamespace))))
16791 return (1);
16793 * SPEC (2) "R's occurrence range is a valid restriction of B's
16794 * occurrence range as defined by Occurrence Range OK (�3.9.6)."
16796 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
16797 b->minOccurs, b->maxOccurs) != 0)
16798 return (1);
16800 * SPEC (3.1) "Both B's declaration's {scope} and R's declaration's
16801 * {scope} are global."
16803 if (elemR == elemB)
16804 return (0);
16806 * SPEC (3.2.1) "Either B's {nillable} is true or R's {nillable} is false."
16808 if (((elemB->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) &&
16809 (elemR->flags & XML_SCHEMAS_ELEM_NILLABLE))
16810 return (1);
16812 * SPEC (3.2.2) "either B's declaration's {value constraint} is absent,
16813 * or is not fixed, or R's declaration's {value constraint} is fixed
16814 * with the same value."
16816 if ((elemB->value != NULL) && (elemB->flags & XML_SCHEMAS_ELEM_FIXED) &&
16817 ((elemR->value == NULL) ||
16818 ((elemR->flags & XML_SCHEMAS_ELEM_FIXED) == 0) ||
16819 /* TODO: Equality of the initial value or normalized or canonical? */
16820 (! xmlStrEqual(elemR->value, elemB->value))))
16821 return (1);
16823 * TODO: SPEC (3.2.3) "R's declaration's {identity-constraint
16824 * definitions} is a subset of B's declaration's {identity-constraint
16825 * definitions}, if any."
16827 if (elemB->idcs != NULL) {
16828 /* TODO */
16831 * SPEC (3.2.4) "R's declaration's {disallowed substitutions} is a
16832 * superset of B's declaration's {disallowed substitutions}."
16834 if (((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) &&
16835 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) == 0)) ||
16836 ((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) &&
16837 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) == 0)) ||
16838 ((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION) &&
16839 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION) == 0)))
16840 return (1);
16842 * SPEC (3.2.5) "R's {type definition} is validly derived given
16843 * {extension, list, union} from B's {type definition}"
16845 * BADSPEC TODO: What's the point of adding "list" and "union" to the
16846 * set, if the corresponding constraints handle "restriction" and
16847 * "extension" only?
16851 int set = 0;
16853 set |= SUBSET_EXTENSION;
16854 set |= SUBSET_LIST;
16855 set |= SUBSET_UNION;
16856 if (xmlSchemaCheckCOSDerivedOK(ACTXT_CAST ctxt, elemR->subtypes,
16857 elemB->subtypes, set) != 0)
16858 return (1);
16860 return (0);
16864 * xmlSchemaCheckRCaseNSCompat:
16865 * @ctxt: the schema parser context
16866 * @r: the restricting element declaration particle
16867 * @b: the base wildcard particle
16869 * (3.9.6) Constraints on Particle Schema Components
16870 * Schema Component Constraint:
16871 * Particle Derivation OK (Elt:Any -- NSCompat)
16872 * (rcase-NSCompat)
16874 * STATUS: complete
16876 * Returns 0 if the constraints are satisfied, a positive
16877 * error code if not and -1 if an internal error occured.
16879 static int
16880 xmlSchemaCheckRCaseNSCompat(xmlSchemaParserCtxtPtr ctxt,
16881 xmlSchemaParticlePtr r,
16882 xmlSchemaParticlePtr b)
16884 /* TODO:Error codes (rcase-NSCompat). */
16886 * SPEC "For an element declaration particle to be a �valid restriction�
16887 * of a wildcard particle all of the following must be true:"
16889 * SPEC (1) "The element declaration's {target namespace} is �valid�
16890 * with respect to the wildcard's {namespace constraint} as defined by
16891 * Wildcard allows Namespace Name (�3.10.4)."
16893 if (xmlSchemaCheckCVCWildcardNamespace((xmlSchemaWildcardPtr) b->children,
16894 ((xmlSchemaElementPtr) r->children)->targetNamespace) != 0)
16895 return (1);
16897 * SPEC (2) "R's occurrence range is a valid restriction of B's
16898 * occurrence range as defined by Occurrence Range OK (�3.9.6)."
16900 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
16901 b->minOccurs, b->maxOccurs) != 0)
16902 return (1);
16904 return (0);
16908 * xmlSchemaCheckRCaseRecurseAsIfGroup:
16909 * @ctxt: the schema parser context
16910 * @r: the restricting element declaration particle
16911 * @b: the base model group particle
16913 * (3.9.6) Constraints on Particle Schema Components
16914 * Schema Component Constraint:
16915 * Particle Derivation OK (Elt:All/Choice/Sequence -- RecurseAsIfGroup)
16916 * (rcase-RecurseAsIfGroup)
16918 * STATUS: TODO
16920 * Returns 0 if the constraints are satisfied, a positive
16921 * error code if not and -1 if an internal error occured.
16923 static int
16924 xmlSchemaCheckRCaseRecurseAsIfGroup(xmlSchemaParserCtxtPtr ctxt,
16925 xmlSchemaParticlePtr r,
16926 xmlSchemaParticlePtr b)
16928 /* TODO: Error codes (rcase-RecurseAsIfGroup). */
16929 TODO
16930 return (0);
16934 * xmlSchemaCheckRCaseNSSubset:
16935 * @ctxt: the schema parser context
16936 * @r: the restricting wildcard particle
16937 * @b: the base wildcard particle
16939 * (3.9.6) Constraints on Particle Schema Components
16940 * Schema Component Constraint:
16941 * Particle Derivation OK (Any:Any -- NSSubset)
16942 * (rcase-NSSubset)
16944 * STATUS: complete
16946 * Returns 0 if the constraints are satisfied, a positive
16947 * error code if not and -1 if an internal error occured.
16949 static int
16950 xmlSchemaCheckRCaseNSSubset(xmlSchemaParserCtxtPtr ctxt,
16951 xmlSchemaParticlePtr r,
16952 xmlSchemaParticlePtr b,
16953 int isAnyTypeBase)
16955 /* TODO: Error codes (rcase-NSSubset). */
16957 * SPEC (1) "R's occurrence range is a valid restriction of B's
16958 * occurrence range as defined by Occurrence Range OK (�3.9.6)."
16960 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
16961 b->minOccurs, b->maxOccurs))
16962 return (1);
16964 * SPEC (2) "R's {namespace constraint} must be an intensional subset
16965 * of B's {namespace constraint} as defined by Wildcard Subset (�3.10.6)."
16967 if (xmlSchemaCheckCOSNSSubset((xmlSchemaWildcardPtr) r->children,
16968 (xmlSchemaWildcardPtr) b->children))
16969 return (1);
16971 * SPEC (3) "Unless B is the content model wildcard of the �ur-type
16972 * definition�, R's {process contents} must be identical to or stronger
16973 * than B's {process contents}, where strict is stronger than lax is
16974 * stronger than skip."
16976 if (! isAnyTypeBase) {
16977 if ( ((xmlSchemaWildcardPtr) r->children)->processContents <
16978 ((xmlSchemaWildcardPtr) b->children)->processContents)
16979 return (1);
16982 return (0);
16986 * xmlSchemaCheckCOSParticleRestrict:
16987 * @ctxt: the schema parser context
16988 * @type: the complex type definition
16990 * (3.9.6) Constraints on Particle Schema Components
16991 * Schema Component Constraint:
16992 * Particle Valid (Restriction) (cos-particle-restrict)
16994 * STATUS: TODO
16996 * Returns 0 if the constraints are satisfied, a positive
16997 * error code if not and -1 if an internal error occured.
16999 static int
17000 xmlSchemaCheckCOSParticleRestrict(xmlSchemaParserCtxtPtr ctxt,
17001 xmlSchemaParticlePtr r,
17002 xmlSchemaParticlePtr b)
17004 int ret = 0;
17006 /*part = WXS_TYPE_PARTICLE(type);
17007 basePart = WXS_TYPE_PARTICLE(base);
17010 TODO
17013 * SPEC (1) "They are the same particle."
17015 if (r == b)
17016 return (0);
17019 return (0);
17022 #if 0
17024 * xmlSchemaCheckRCaseNSRecurseCheckCardinality:
17025 * @ctxt: the schema parser context
17026 * @r: the model group particle
17027 * @b: the base wildcard particle
17029 * (3.9.6) Constraints on Particle Schema Components
17030 * Schema Component Constraint:
17031 * Particle Derivation OK (All/Choice/Sequence:Any --
17032 * NSRecurseCheckCardinality)
17033 * (rcase-NSRecurseCheckCardinality)
17035 * STATUS: TODO: subst-groups
17037 * Returns 0 if the constraints are satisfied, a positive
17038 * error code if not and -1 if an internal error occured.
17040 static int
17041 xmlSchemaCheckRCaseNSRecurseCheckCardinality(xmlSchemaParserCtxtPtr ctxt,
17042 xmlSchemaParticlePtr r,
17043 xmlSchemaParticlePtr b)
17045 xmlSchemaParticlePtr part;
17046 /* TODO: Error codes (rcase-NSRecurseCheckCardinality). */
17047 if ((r->children == NULL) || (r->children->children == NULL))
17048 return (-1);
17050 * SPEC "For a group particle to be a �valid restriction� of a
17051 * wildcard particle..."
17053 * SPEC (1) "Every member of the {particles} of the group is a �valid
17054 * restriction� of the wildcard as defined by
17055 * Particle Valid (Restriction) (�3.9.6)."
17057 part = (xmlSchemaParticlePtr) r->children->children;
17058 do {
17059 if (xmlSchemaCheckCOSParticleRestrict(ctxt, part, b))
17060 return (1);
17061 part = (xmlSchemaParticlePtr) part->next;
17062 } while (part != NULL);
17064 * SPEC (2) "The effective total range of the group [...] is a
17065 * valid restriction of B's occurrence range as defined by
17066 * Occurrence Range OK (�3.9.6)."
17068 if (xmlSchemaCheckParticleRangeOK(
17069 xmlSchemaGetParticleTotalRangeMin(r),
17070 xmlSchemaGetParticleTotalRangeMax(r),
17071 b->minOccurs, b->maxOccurs) != 0)
17072 return (1);
17073 return (0);
17075 #endif
17078 * xmlSchemaCheckRCaseRecurse:
17079 * @ctxt: the schema parser context
17080 * @r: the <all> or <sequence> model group particle
17081 * @b: the base <all> or <sequence> model group particle
17083 * (3.9.6) Constraints on Particle Schema Components
17084 * Schema Component Constraint:
17085 * Particle Derivation OK (All:All,Sequence:Sequence --
17086 Recurse)
17087 * (rcase-Recurse)
17089 * STATUS: ?
17090 * TODO: subst-groups
17092 * Returns 0 if the constraints are satisfied, a positive
17093 * error code if not and -1 if an internal error occured.
17095 static int
17096 xmlSchemaCheckRCaseRecurse(xmlSchemaParserCtxtPtr ctxt,
17097 xmlSchemaParticlePtr r,
17098 xmlSchemaParticlePtr b)
17100 /* xmlSchemaParticlePtr part; */
17101 /* TODO: Error codes (rcase-Recurse). */
17102 if ((r->children == NULL) || (b->children == NULL) ||
17103 (r->children->type != b->children->type))
17104 return (-1);
17106 * SPEC "For an all or sequence group particle to be a �valid
17107 * restriction� of another group particle with the same {compositor}..."
17109 * SPEC (1) "R's occurrence range is a valid restriction of B's
17110 * occurrence range as defined by Occurrence Range OK (�3.9.6)."
17112 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
17113 b->minOccurs, b->maxOccurs))
17114 return (1);
17117 return (0);
17120 #endif
17122 #define FACET_RESTR_MUTUAL_ERR(fac1, fac2) \
17123 xmlSchemaPCustomErrExt(pctxt, \
17124 XML_SCHEMAP_INVALID_FACET_VALUE, \
17125 WXS_BASIC_CAST fac1, fac1->node, \
17126 "It is an error for both '%s' and '%s' to be specified on the "\
17127 "same type definition", \
17128 BAD_CAST xmlSchemaFacetTypeToString(fac1->type), \
17129 BAD_CAST xmlSchemaFacetTypeToString(fac2->type), NULL);
17131 #define FACET_RESTR_ERR(fac1, msg) \
17132 xmlSchemaPCustomErr(pctxt, \
17133 XML_SCHEMAP_INVALID_FACET_VALUE, \
17134 WXS_BASIC_CAST fac1, fac1->node, \
17135 msg, NULL);
17137 #define FACET_RESTR_FIXED_ERR(fac) \
17138 xmlSchemaPCustomErr(pctxt, \
17139 XML_SCHEMAP_INVALID_FACET_VALUE, \
17140 WXS_BASIC_CAST fac, fac->node, \
17141 "The base type's facet is 'fixed', thus the value must not " \
17142 "differ", NULL);
17144 static void
17145 xmlSchemaDeriveFacetErr(xmlSchemaParserCtxtPtr pctxt,
17146 xmlSchemaFacetPtr facet1,
17147 xmlSchemaFacetPtr facet2,
17148 int lessGreater,
17149 int orEqual,
17150 int ofBase)
17152 xmlChar *msg = NULL;
17154 msg = xmlStrdup(BAD_CAST "'");
17155 msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facet1->type));
17156 msg = xmlStrcat(msg, BAD_CAST "' has to be");
17157 if (lessGreater == 0)
17158 msg = xmlStrcat(msg, BAD_CAST " equal to");
17159 if (lessGreater == 1)
17160 msg = xmlStrcat(msg, BAD_CAST " greater than");
17161 else
17162 msg = xmlStrcat(msg, BAD_CAST " less than");
17164 if (orEqual)
17165 msg = xmlStrcat(msg, BAD_CAST " or equal to");
17166 msg = xmlStrcat(msg, BAD_CAST " '");
17167 msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facet2->type));
17168 if (ofBase)
17169 msg = xmlStrcat(msg, BAD_CAST "' of the base type");
17170 else
17171 msg = xmlStrcat(msg, BAD_CAST "'");
17173 xmlSchemaPCustomErr(pctxt,
17174 XML_SCHEMAP_INVALID_FACET_VALUE,
17175 WXS_BASIC_CAST facet1, NULL,
17176 (const char *) msg, NULL);
17178 if (msg != NULL)
17179 xmlFree(msg);
17183 * xmlSchemaDeriveAndValidateFacets:
17185 * Schema Component Constraint: Simple Type Restriction (Facets)
17186 * (st-restrict-facets)
17188 static int
17189 xmlSchemaDeriveAndValidateFacets(xmlSchemaParserCtxtPtr pctxt,
17190 xmlSchemaTypePtr type)
17192 xmlSchemaTypePtr base = type->baseType;
17193 xmlSchemaFacetLinkPtr link, cur, last = NULL;
17194 xmlSchemaFacetPtr facet, bfacet,
17195 flength = NULL, ftotdig = NULL, ffracdig = NULL,
17196 fmaxlen = NULL, fminlen = NULL, /* facets of the current type */
17197 fmininc = NULL, fmaxinc = NULL,
17198 fminexc = NULL, fmaxexc = NULL,
17199 bflength = NULL, bftotdig = NULL, bffracdig = NULL,
17200 bfmaxlen = NULL, bfminlen = NULL, /* facets of the base type */
17201 bfmininc = NULL, bfmaxinc = NULL,
17202 bfminexc = NULL, bfmaxexc = NULL;
17203 int res; /* err = 0, fixedErr; */
17206 * SPEC st-restrict-facets 1:
17207 * "The {variety} of R is the same as that of B."
17210 * SPEC st-restrict-facets 2:
17211 * "If {variety} is atomic, the {primitive type definition}
17212 * of R is the same as that of B."
17214 * NOTE: we leave 1 & 2 out for now, since this will be
17215 * satisfied by the derivation process.
17216 * CONSTRUCTION TODO: Maybe needed if using a construction API.
17219 * SPEC st-restrict-facets 3:
17220 * "The {facets} of R are the union of S and the {facets}
17221 * of B, eliminating duplicates. To eliminate duplicates,
17222 * when a facet of the same kind occurs in both S and the
17223 * {facets} of B, the one in the {facets} of B is not
17224 * included, with the exception of enumeration and pattern
17225 * facets, for which multiple occurrences with distinct values
17226 * are allowed."
17229 if ((type->facetSet == NULL) && (base->facetSet == NULL))
17230 return (0);
17232 last = type->facetSet;
17233 if (last != NULL)
17234 while (last->next != NULL)
17235 last = last->next;
17237 for (cur = type->facetSet; cur != NULL; cur = cur->next) {
17238 facet = cur->facet;
17239 switch (facet->type) {
17240 case XML_SCHEMA_FACET_LENGTH:
17241 flength = facet; break;
17242 case XML_SCHEMA_FACET_MINLENGTH:
17243 fminlen = facet; break;
17244 case XML_SCHEMA_FACET_MININCLUSIVE:
17245 fmininc = facet; break;
17246 case XML_SCHEMA_FACET_MINEXCLUSIVE:
17247 fminexc = facet; break;
17248 case XML_SCHEMA_FACET_MAXLENGTH:
17249 fmaxlen = facet; break;
17250 case XML_SCHEMA_FACET_MAXINCLUSIVE:
17251 fmaxinc = facet; break;
17252 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
17253 fmaxexc = facet; break;
17254 case XML_SCHEMA_FACET_TOTALDIGITS:
17255 ftotdig = facet; break;
17256 case XML_SCHEMA_FACET_FRACTIONDIGITS:
17257 ffracdig = facet; break;
17258 default:
17259 break;
17262 for (cur = base->facetSet; cur != NULL; cur = cur->next) {
17263 facet = cur->facet;
17264 switch (facet->type) {
17265 case XML_SCHEMA_FACET_LENGTH:
17266 bflength = facet; break;
17267 case XML_SCHEMA_FACET_MINLENGTH:
17268 bfminlen = facet; break;
17269 case XML_SCHEMA_FACET_MININCLUSIVE:
17270 bfmininc = facet; break;
17271 case XML_SCHEMA_FACET_MINEXCLUSIVE:
17272 bfminexc = facet; break;
17273 case XML_SCHEMA_FACET_MAXLENGTH:
17274 bfmaxlen = facet; break;
17275 case XML_SCHEMA_FACET_MAXINCLUSIVE:
17276 bfmaxinc = facet; break;
17277 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
17278 bfmaxexc = facet; break;
17279 case XML_SCHEMA_FACET_TOTALDIGITS:
17280 bftotdig = facet; break;
17281 case XML_SCHEMA_FACET_FRACTIONDIGITS:
17282 bffracdig = facet; break;
17283 default:
17284 break;
17288 * length and minLength or maxLength (2.2) + (3.2)
17290 if (flength && (fminlen || fmaxlen)) {
17291 FACET_RESTR_ERR(flength, "It is an error for both 'length' and "
17292 "either of 'minLength' or 'maxLength' to be specified on "
17293 "the same type definition")
17296 * Mutual exclusions in the same derivation step.
17298 if ((fmaxinc) && (fmaxexc)) {
17300 * SCC "maxInclusive and maxExclusive"
17302 FACET_RESTR_MUTUAL_ERR(fmaxinc, fmaxexc)
17304 if ((fmininc) && (fminexc)) {
17306 * SCC "minInclusive and minExclusive"
17308 FACET_RESTR_MUTUAL_ERR(fmininc, fminexc)
17311 if (flength && bflength) {
17313 * SCC "length valid restriction"
17314 * The values have to be equal.
17316 res = xmlSchemaCompareValues(flength->val, bflength->val);
17317 if (res == -2)
17318 goto internal_error;
17319 if (res != 0)
17320 xmlSchemaDeriveFacetErr(pctxt, flength, bflength, 0, 0, 1);
17321 if ((res != 0) && (bflength->fixed)) {
17322 FACET_RESTR_FIXED_ERR(flength)
17326 if (fminlen && bfminlen) {
17328 * SCC "minLength valid restriction"
17329 * minLength >= BASE minLength
17331 res = xmlSchemaCompareValues(fminlen->val, bfminlen->val);
17332 if (res == -2)
17333 goto internal_error;
17334 if (res == -1)
17335 xmlSchemaDeriveFacetErr(pctxt, fminlen, bfminlen, 1, 1, 1);
17336 if ((res != 0) && (bfminlen->fixed)) {
17337 FACET_RESTR_FIXED_ERR(fminlen)
17340 if (fmaxlen && bfmaxlen) {
17342 * SCC "maxLength valid restriction"
17343 * maxLength <= BASE minLength
17345 res = xmlSchemaCompareValues(fmaxlen->val, bfmaxlen->val);
17346 if (res == -2)
17347 goto internal_error;
17348 if (res == 1)
17349 xmlSchemaDeriveFacetErr(pctxt, fmaxlen, bfmaxlen, -1, 1, 1);
17350 if ((res != 0) && (bfmaxlen->fixed)) {
17351 FACET_RESTR_FIXED_ERR(fmaxlen)
17355 * SCC "length and minLength or maxLength"
17357 if (! flength)
17358 flength = bflength;
17359 if (flength) {
17360 if (! fminlen)
17361 fminlen = bfminlen;
17362 if (fminlen) {
17363 /* (1.1) length >= minLength */
17364 res = xmlSchemaCompareValues(flength->val, fminlen->val);
17365 if (res == -2)
17366 goto internal_error;
17367 if (res == -1)
17368 xmlSchemaDeriveFacetErr(pctxt, flength, fminlen, 1, 1, 0);
17370 if (! fmaxlen)
17371 fmaxlen = bfmaxlen;
17372 if (fmaxlen) {
17373 /* (2.1) length <= maxLength */
17374 res = xmlSchemaCompareValues(flength->val, fmaxlen->val);
17375 if (res == -2)
17376 goto internal_error;
17377 if (res == 1)
17378 xmlSchemaDeriveFacetErr(pctxt, flength, fmaxlen, -1, 1, 0);
17381 if (fmaxinc) {
17383 * "maxInclusive"
17385 if (fmininc) {
17386 /* SCC "maxInclusive >= minInclusive" */
17387 res = xmlSchemaCompareValues(fmaxinc->val, fmininc->val);
17388 if (res == -2)
17389 goto internal_error;
17390 if (res == -1) {
17391 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, fmininc, 1, 1, 0);
17395 * SCC "maxInclusive valid restriction"
17397 if (bfmaxinc) {
17398 /* maxInclusive <= BASE maxInclusive */
17399 res = xmlSchemaCompareValues(fmaxinc->val, bfmaxinc->val);
17400 if (res == -2)
17401 goto internal_error;
17402 if (res == 1)
17403 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmaxinc, -1, 1, 1);
17404 if ((res != 0) && (bfmaxinc->fixed)) {
17405 FACET_RESTR_FIXED_ERR(fmaxinc)
17408 if (bfmaxexc) {
17409 /* maxInclusive < BASE maxExclusive */
17410 res = xmlSchemaCompareValues(fmaxinc->val, bfmaxexc->val);
17411 if (res == -2)
17412 goto internal_error;
17413 if (res != -1) {
17414 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmaxexc, -1, 0, 1);
17417 if (bfmininc) {
17418 /* maxInclusive >= BASE minInclusive */
17419 res = xmlSchemaCompareValues(fmaxinc->val, bfmininc->val);
17420 if (res == -2)
17421 goto internal_error;
17422 if (res == -1) {
17423 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmininc, 1, 1, 1);
17426 if (bfminexc) {
17427 /* maxInclusive > BASE minExclusive */
17428 res = xmlSchemaCompareValues(fmaxinc->val, bfminexc->val);
17429 if (res == -2)
17430 goto internal_error;
17431 if (res != 1) {
17432 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfminexc, 1, 0, 1);
17436 if (fmaxexc) {
17438 * "maxExclusive >= minExclusive"
17440 if (fminexc) {
17441 res = xmlSchemaCompareValues(fmaxexc->val, fminexc->val);
17442 if (res == -2)
17443 goto internal_error;
17444 if (res == -1) {
17445 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, fminexc, 1, 1, 0);
17449 * "maxExclusive valid restriction"
17451 if (bfmaxexc) {
17452 /* maxExclusive <= BASE maxExclusive */
17453 res = xmlSchemaCompareValues(fmaxexc->val, bfmaxexc->val);
17454 if (res == -2)
17455 goto internal_error;
17456 if (res == 1) {
17457 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmaxexc, -1, 1, 1);
17459 if ((res != 0) && (bfmaxexc->fixed)) {
17460 FACET_RESTR_FIXED_ERR(fmaxexc)
17463 if (bfmaxinc) {
17464 /* maxExclusive <= BASE maxInclusive */
17465 res = xmlSchemaCompareValues(fmaxexc->val, bfmaxinc->val);
17466 if (res == -2)
17467 goto internal_error;
17468 if (res == 1) {
17469 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmaxinc, -1, 1, 1);
17472 if (bfmininc) {
17473 /* maxExclusive > BASE minInclusive */
17474 res = xmlSchemaCompareValues(fmaxexc->val, bfmininc->val);
17475 if (res == -2)
17476 goto internal_error;
17477 if (res != 1) {
17478 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmininc, 1, 0, 1);
17481 if (bfminexc) {
17482 /* maxExclusive > BASE minExclusive */
17483 res = xmlSchemaCompareValues(fmaxexc->val, bfminexc->val);
17484 if (res == -2)
17485 goto internal_error;
17486 if (res != 1) {
17487 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfminexc, 1, 0, 1);
17491 if (fminexc) {
17493 * "minExclusive < maxInclusive"
17495 if (fmaxinc) {
17496 res = xmlSchemaCompareValues(fminexc->val, fmaxinc->val);
17497 if (res == -2)
17498 goto internal_error;
17499 if (res != -1) {
17500 xmlSchemaDeriveFacetErr(pctxt, fminexc, fmaxinc, -1, 0, 0);
17504 * "minExclusive valid restriction"
17506 if (bfminexc) {
17507 /* minExclusive >= BASE minExclusive */
17508 res = xmlSchemaCompareValues(fminexc->val, bfminexc->val);
17509 if (res == -2)
17510 goto internal_error;
17511 if (res == -1) {
17512 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfminexc, 1, 1, 1);
17514 if ((res != 0) && (bfminexc->fixed)) {
17515 FACET_RESTR_FIXED_ERR(fminexc)
17518 if (bfmaxinc) {
17519 /* minExclusive <= BASE maxInclusive */
17520 res = xmlSchemaCompareValues(fminexc->val, bfmaxinc->val);
17521 if (res == -2)
17522 goto internal_error;
17523 if (res == 1) {
17524 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmaxinc, -1, 1, 1);
17527 if (bfmininc) {
17528 /* minExclusive >= BASE minInclusive */
17529 res = xmlSchemaCompareValues(fminexc->val, bfmininc->val);
17530 if (res == -2)
17531 goto internal_error;
17532 if (res == -1) {
17533 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmininc, 1, 1, 1);
17536 if (bfmaxexc) {
17537 /* minExclusive < BASE maxExclusive */
17538 res = xmlSchemaCompareValues(fminexc->val, bfmaxexc->val);
17539 if (res == -2)
17540 goto internal_error;
17541 if (res != -1) {
17542 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmaxexc, -1, 0, 1);
17546 if (fmininc) {
17548 * "minInclusive < maxExclusive"
17550 if (fmaxexc) {
17551 res = xmlSchemaCompareValues(fmininc->val, fmaxexc->val);
17552 if (res == -2)
17553 goto internal_error;
17554 if (res != -1) {
17555 xmlSchemaDeriveFacetErr(pctxt, fmininc, fmaxexc, -1, 0, 0);
17559 * "minExclusive valid restriction"
17561 if (bfmininc) {
17562 /* minInclusive >= BASE minInclusive */
17563 res = xmlSchemaCompareValues(fmininc->val, bfmininc->val);
17564 if (res == -2)
17565 goto internal_error;
17566 if (res == -1) {
17567 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmininc, 1, 1, 1);
17569 if ((res != 0) && (bfmininc->fixed)) {
17570 FACET_RESTR_FIXED_ERR(fmininc)
17573 if (bfmaxinc) {
17574 /* minInclusive <= BASE maxInclusive */
17575 res = xmlSchemaCompareValues(fmininc->val, bfmaxinc->val);
17576 if (res == -2)
17577 goto internal_error;
17578 if (res == 1) {
17579 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmaxinc, -1, 1, 1);
17582 if (bfminexc) {
17583 /* minInclusive > BASE minExclusive */
17584 res = xmlSchemaCompareValues(fmininc->val, bfminexc->val);
17585 if (res == -2)
17586 goto internal_error;
17587 if (res != 1)
17588 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfminexc, 1, 0, 1);
17590 if (bfmaxexc) {
17591 /* minInclusive < BASE maxExclusive */
17592 res = xmlSchemaCompareValues(fmininc->val, bfmaxexc->val);
17593 if (res == -2)
17594 goto internal_error;
17595 if (res != -1)
17596 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmaxexc, -1, 0, 1);
17599 if (ftotdig && bftotdig) {
17601 * SCC " totalDigits valid restriction"
17602 * totalDigits <= BASE totalDigits
17604 res = xmlSchemaCompareValues(ftotdig->val, bftotdig->val);
17605 if (res == -2)
17606 goto internal_error;
17607 if (res == 1)
17608 xmlSchemaDeriveFacetErr(pctxt, ftotdig, bftotdig,
17609 -1, 1, 1);
17610 if ((res != 0) && (bftotdig->fixed)) {
17611 FACET_RESTR_FIXED_ERR(ftotdig)
17614 if (ffracdig && bffracdig) {
17616 * SCC "fractionDigits valid restriction"
17617 * fractionDigits <= BASE fractionDigits
17619 res = xmlSchemaCompareValues(ffracdig->val, bffracdig->val);
17620 if (res == -2)
17621 goto internal_error;
17622 if (res == 1)
17623 xmlSchemaDeriveFacetErr(pctxt, ffracdig, bffracdig,
17624 -1, 1, 1);
17625 if ((res != 0) && (bffracdig->fixed)) {
17626 FACET_RESTR_FIXED_ERR(ffracdig)
17630 * SCC "fractionDigits less than or equal to totalDigits"
17632 if (! ftotdig)
17633 ftotdig = bftotdig;
17634 if (! ffracdig)
17635 ffracdig = bffracdig;
17636 if (ftotdig && ffracdig) {
17637 res = xmlSchemaCompareValues(ffracdig->val, ftotdig->val);
17638 if (res == -2)
17639 goto internal_error;
17640 if (res == 1)
17641 xmlSchemaDeriveFacetErr(pctxt, ffracdig, ftotdig,
17642 -1, 1, 0);
17645 * *Enumerations* won' be added here, since only the first set
17646 * of enumerations in the ancestor-or-self axis is used
17647 * for validation, plus we need to use the base type of those
17648 * enumerations for whitespace.
17650 * *Patterns*: won't be add here, since they are ORed at
17651 * type level and ANDed at ancestor level. This will
17652 * happed during validation by walking the base axis
17653 * of the type.
17655 for (cur = base->facetSet; cur != NULL; cur = cur->next) {
17656 bfacet = cur->facet;
17658 * Special handling of enumerations and patterns.
17659 * TODO: hmm, they should not appear in the set, so remove this.
17661 if ((bfacet->type == XML_SCHEMA_FACET_PATTERN) ||
17662 (bfacet->type == XML_SCHEMA_FACET_ENUMERATION))
17663 continue;
17665 * Search for a duplicate facet in the current type.
17667 link = type->facetSet;
17668 /* err = 0; */
17669 /* fixedErr = 0; */
17670 while (link != NULL) {
17671 facet = link->facet;
17672 if (facet->type == bfacet->type) {
17673 switch (facet->type) {
17674 case XML_SCHEMA_FACET_WHITESPACE:
17676 * The whitespace must be stronger.
17678 if (facet->whitespace < bfacet->whitespace) {
17679 FACET_RESTR_ERR(facet,
17680 "The 'whitespace' value has to be equal to "
17681 "or stronger than the 'whitespace' value of "
17682 "the base type")
17684 if ((bfacet->fixed) &&
17685 (facet->whitespace != bfacet->whitespace)) {
17686 FACET_RESTR_FIXED_ERR(facet)
17688 break;
17689 default:
17690 break;
17692 /* Duplicate found. */
17693 break;
17695 link = link->next;
17698 * If no duplicate was found: add the base types's facet
17699 * to the set.
17701 if (link == NULL) {
17702 link = (xmlSchemaFacetLinkPtr)
17703 xmlMalloc(sizeof(xmlSchemaFacetLink));
17704 if (link == NULL) {
17705 xmlSchemaPErrMemory(pctxt,
17706 "deriving facets, creating a facet link", NULL);
17707 return (-1);
17709 link->facet = cur->facet;
17710 link->next = NULL;
17711 if (last == NULL)
17712 type->facetSet = link;
17713 else
17714 last->next = link;
17715 last = link;
17720 return (0);
17721 internal_error:
17722 PERROR_INT("xmlSchemaDeriveAndValidateFacets",
17723 "an error occured");
17724 return (-1);
17727 static int
17728 xmlSchemaFinishMemberTypeDefinitionsProperty(xmlSchemaParserCtxtPtr pctxt,
17729 xmlSchemaTypePtr type)
17731 xmlSchemaTypeLinkPtr link, lastLink, prevLink, subLink, newLink;
17733 * The actual value is then formed by replacing any union type
17734 * definition in the �explicit members� with the members of their
17735 * {member type definitions}, in order.
17737 * TODO: There's a bug entry at
17738 * "http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005JulSep/0287.html"
17739 * which indicates that we'll keep the union types the future.
17741 link = type->memberTypes;
17742 while (link != NULL) {
17744 if (WXS_IS_TYPE_NOT_FIXED(link->type))
17745 xmlSchemaTypeFixup(link->type, ACTXT_CAST pctxt);
17747 if (WXS_IS_UNION(link->type)) {
17748 subLink = xmlSchemaGetUnionSimpleTypeMemberTypes(link->type);
17749 if (subLink != NULL) {
17750 link->type = subLink->type;
17751 if (subLink->next != NULL) {
17752 lastLink = link->next;
17753 subLink = subLink->next;
17754 prevLink = link;
17755 while (subLink != NULL) {
17756 newLink = (xmlSchemaTypeLinkPtr)
17757 xmlMalloc(sizeof(xmlSchemaTypeLink));
17758 if (newLink == NULL) {
17759 xmlSchemaPErrMemory(pctxt, "allocating a type link",
17760 NULL);
17761 return (-1);
17763 newLink->type = subLink->type;
17764 prevLink->next = newLink;
17765 prevLink = newLink;
17766 newLink->next = lastLink;
17768 subLink = subLink->next;
17773 link = link->next;
17775 return (0);
17778 static void
17779 xmlSchemaTypeFixupOptimFacets(xmlSchemaTypePtr type)
17781 int has = 0, needVal = 0, normVal = 0;
17783 has = (type->baseType->flags & XML_SCHEMAS_TYPE_HAS_FACETS) ? 1 : 0;
17784 if (has) {
17785 needVal = (type->baseType->flags &
17786 XML_SCHEMAS_TYPE_FACETSNEEDVALUE) ? 1 : 0;
17787 normVal = (type->baseType->flags &
17788 XML_SCHEMAS_TYPE_NORMVALUENEEDED) ? 1 : 0;
17790 if (type->facets != NULL) {
17791 xmlSchemaFacetPtr fac;
17793 for (fac = type->facets; fac != NULL; fac = fac->next) {
17794 switch (fac->type) {
17795 case XML_SCHEMA_FACET_WHITESPACE:
17796 break;
17797 case XML_SCHEMA_FACET_PATTERN:
17798 normVal = 1;
17799 has = 1;
17800 break;
17801 case XML_SCHEMA_FACET_ENUMERATION:
17802 needVal = 1;
17803 normVal = 1;
17804 has = 1;
17805 break;
17806 default:
17807 has = 1;
17808 break;
17812 if (normVal)
17813 type->flags |= XML_SCHEMAS_TYPE_NORMVALUENEEDED;
17814 if (needVal)
17815 type->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
17816 if (has)
17817 type->flags |= XML_SCHEMAS_TYPE_HAS_FACETS;
17819 if (has && (! needVal) && WXS_IS_ATOMIC(type)) {
17820 xmlSchemaTypePtr prim = xmlSchemaGetPrimitiveType(type);
17822 * OPTIMIZE VAL TODO: Some facets need a computed value.
17824 if ((prim->builtInType != XML_SCHEMAS_ANYSIMPLETYPE) &&
17825 (prim->builtInType != XML_SCHEMAS_STRING)) {
17826 type->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
17831 static int
17832 xmlSchemaTypeFixupWhitespace(xmlSchemaTypePtr type)
17837 * Evaluate the whitespace-facet value.
17839 if (WXS_IS_LIST(type)) {
17840 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
17841 return (0);
17842 } else if (WXS_IS_UNION(type))
17843 return (0);
17845 if (type->facetSet != NULL) {
17846 xmlSchemaFacetLinkPtr lin;
17848 for (lin = type->facetSet; lin != NULL; lin = lin->next) {
17849 if (lin->facet->type == XML_SCHEMA_FACET_WHITESPACE) {
17850 switch (lin->facet->whitespace) {
17851 case XML_SCHEMAS_FACET_PRESERVE:
17852 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE;
17853 break;
17854 case XML_SCHEMAS_FACET_REPLACE:
17855 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_REPLACE;
17856 break;
17857 case XML_SCHEMAS_FACET_COLLAPSE:
17858 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
17859 break;
17860 default:
17861 return (-1);
17863 return (0);
17868 * For all �atomic� datatypes other than string (and types �derived�
17869 * by �restriction� from it) the value of whiteSpace is fixed to
17870 * collapse
17873 xmlSchemaTypePtr anc;
17875 for (anc = type->baseType; anc != NULL &&
17876 anc->builtInType != XML_SCHEMAS_ANYTYPE;
17877 anc = anc->baseType) {
17879 if (anc->type == XML_SCHEMA_TYPE_BASIC) {
17880 if (anc->builtInType == XML_SCHEMAS_NORMSTRING) {
17881 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_REPLACE;
17883 } else if ((anc->builtInType == XML_SCHEMAS_STRING) ||
17884 (anc->builtInType == XML_SCHEMAS_ANYSIMPLETYPE)) {
17885 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE;
17887 } else
17888 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
17889 break;
17893 return (0);
17896 static int
17897 xmlSchemaFixupSimpleTypeStageOne(xmlSchemaParserCtxtPtr pctxt,
17898 xmlSchemaTypePtr type)
17900 if (type->type != XML_SCHEMA_TYPE_SIMPLE)
17901 return(0);
17902 if (! WXS_IS_TYPE_NOT_FIXED_1(type))
17903 return(0);
17904 type->flags |= XML_SCHEMAS_TYPE_FIXUP_1;
17906 if (WXS_IS_LIST(type)) {
17908 * Corresponds to <simpleType><list>...
17910 if (type->subtypes == NULL) {
17912 * This one is really needed, so get out.
17914 PERROR_INT("xmlSchemaFixupSimpleTypeStageOne",
17915 "list type has no item-type assigned");
17916 return(-1);
17918 } else if (WXS_IS_UNION(type)) {
17920 * Corresponds to <simpleType><union>...
17922 if (type->memberTypes == NULL) {
17924 * This one is really needed, so get out.
17926 PERROR_INT("xmlSchemaFixupSimpleTypeStageOne",
17927 "union type has no member-types assigned");
17928 return(-1);
17930 } else {
17932 * Corresponds to <simpleType><restriction>...
17934 if (type->baseType == NULL) {
17935 PERROR_INT("xmlSchemaFixupSimpleTypeStageOne",
17936 "type has no base-type assigned");
17937 return(-1);
17939 if (WXS_IS_TYPE_NOT_FIXED_1(type->baseType))
17940 if (xmlSchemaFixupSimpleTypeStageOne(pctxt, type->baseType) == -1)
17941 return(-1);
17943 * Variety
17944 * If the <restriction> alternative is chosen, then the
17945 * {variety} of the {base type definition}.
17947 if (WXS_IS_ATOMIC(type->baseType))
17948 type->flags |= XML_SCHEMAS_TYPE_VARIETY_ATOMIC;
17949 else if (WXS_IS_LIST(type->baseType)) {
17950 type->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
17952 * Inherit the itemType.
17954 type->subtypes = type->baseType->subtypes;
17955 } else if (WXS_IS_UNION(type->baseType)) {
17956 type->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
17958 * NOTE that we won't assign the memberTypes of the base,
17959 * since this will make trouble when freeing them; we will
17960 * use a lookup function to access them instead.
17964 return(0);
17967 #ifdef DEBUG_TYPE
17968 static void
17969 xmlSchemaDebugFixedType(xmlSchemaParserCtxtPtr pctxt,
17970 xmlSchemaTypePtr type)
17972 if (type->node != NULL) {
17973 xmlGenericError(xmlGenericErrorContext,
17974 "Type of %s : %s:%d :", name,
17975 type->node->doc->URL,
17976 xmlGetLineNo(type->node));
17977 } else {
17978 xmlGenericError(xmlGenericErrorContext, "Type of %s :", name);
17980 if ((WXS_IS_SIMPLE(type)) || (WXS_IS_COMPLEX(type))) {
17981 switch (type->contentType) {
17982 case XML_SCHEMA_CONTENT_SIMPLE:
17983 xmlGenericError(xmlGenericErrorContext, "simple\n");
17984 break;
17985 case XML_SCHEMA_CONTENT_ELEMENTS:
17986 xmlGenericError(xmlGenericErrorContext, "elements\n");
17987 break;
17988 case XML_SCHEMA_CONTENT_UNKNOWN:
17989 xmlGenericError(xmlGenericErrorContext, "unknown !!!\n");
17990 break;
17991 case XML_SCHEMA_CONTENT_EMPTY:
17992 xmlGenericError(xmlGenericErrorContext, "empty\n");
17993 break;
17994 case XML_SCHEMA_CONTENT_MIXED:
17995 if (xmlSchemaIsParticleEmptiable((xmlSchemaParticlePtr)
17996 type->subtypes))
17997 xmlGenericError(xmlGenericErrorContext,
17998 "mixed as emptiable particle\n");
17999 else
18000 xmlGenericError(xmlGenericErrorContext, "mixed\n");
18001 break;
18002 /* Removed, since not used. */
18004 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
18005 xmlGenericError(xmlGenericErrorContext, "mixed or elems\n");
18006 break;
18008 case XML_SCHEMA_CONTENT_BASIC:
18009 xmlGenericError(xmlGenericErrorContext, "basic\n");
18010 break;
18011 default:
18012 xmlGenericError(xmlGenericErrorContext,
18013 "not registered !!!\n");
18014 break;
18018 #endif
18021 * 3.14.6 Constraints on Simple Type Definition Schema Components
18023 static int
18024 xmlSchemaFixupSimpleTypeStageTwo(xmlSchemaParserCtxtPtr pctxt,
18025 xmlSchemaTypePtr type)
18027 int res, olderrs = pctxt->nberrors;
18029 if (type->type != XML_SCHEMA_TYPE_SIMPLE)
18030 return(-1);
18032 if (! WXS_IS_TYPE_NOT_FIXED(type))
18033 return(0);
18035 type->flags |= XML_SCHEMAS_TYPE_INTERNAL_RESOLVED;
18036 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
18038 if (type->baseType == NULL) {
18039 PERROR_INT("xmlSchemaFixupSimpleTypeStageTwo",
18040 "missing baseType");
18041 goto exit_failure;
18043 if (WXS_IS_TYPE_NOT_FIXED(type->baseType))
18044 xmlSchemaTypeFixup(type->baseType, ACTXT_CAST pctxt);
18046 * If a member type of a union is a union itself, we need to substitute
18047 * that member type for its member types.
18048 * NOTE that this might change in WXS 1.1; i.e. we will keep the union
18049 * types in WXS 1.1.
18051 if ((type->memberTypes != NULL) &&
18052 (xmlSchemaFinishMemberTypeDefinitionsProperty(pctxt, type) == -1))
18053 return(-1);
18055 * SPEC src-simple-type 1
18056 * "The corresponding simple type definition, if any, must satisfy
18057 * the conditions set out in Constraints on Simple Type Definition
18058 * Schema Components (�3.14.6)."
18061 * Schema Component Constraint: Simple Type Definition Properties Correct
18062 * (st-props-correct)
18064 res = xmlSchemaCheckSTPropsCorrect(pctxt, type);
18065 HFAILURE HERROR
18067 * Schema Component Constraint: Derivation Valid (Restriction, Simple)
18068 * (cos-st-restricts)
18070 res = xmlSchemaCheckCOSSTRestricts(pctxt, type);
18071 HFAILURE HERROR
18073 * TODO: Removed the error report, since it got annoying to get an
18074 * extra error report, if anything failed until now.
18075 * Enable this if needed.
18077 * xmlSchemaPErr(ctxt, type->node,
18078 * XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
18079 * "Simple type '%s' does not satisfy the constraints "
18080 * "on simple type definitions.\n",
18081 * type->name, NULL);
18084 * Schema Component Constraint: Simple Type Restriction (Facets)
18085 * (st-restrict-facets)
18087 res = xmlSchemaCheckFacetValues(type, pctxt);
18088 HFAILURE HERROR
18089 if ((type->facetSet != NULL) ||
18090 (type->baseType->facetSet != NULL)) {
18091 res = xmlSchemaDeriveAndValidateFacets(pctxt, type);
18092 HFAILURE HERROR
18095 * Whitespace value.
18097 res = xmlSchemaTypeFixupWhitespace(type);
18098 HFAILURE HERROR
18099 xmlSchemaTypeFixupOptimFacets(type);
18101 exit_error:
18102 #ifdef DEBUG_TYPE
18103 xmlSchemaDebugFixedType(pctxt, type);
18104 #endif
18105 if (olderrs != pctxt->nberrors)
18106 return(pctxt->err);
18107 return(0);
18109 exit_failure:
18110 #ifdef DEBUG_TYPE
18111 xmlSchemaDebugFixedType(pctxt, type);
18112 #endif
18113 return(-1);
18116 static int
18117 xmlSchemaFixupComplexType(xmlSchemaParserCtxtPtr pctxt,
18118 xmlSchemaTypePtr type)
18120 int res = 0, olderrs = pctxt->nberrors;
18121 xmlSchemaTypePtr baseType = type->baseType;
18123 if (! WXS_IS_TYPE_NOT_FIXED(type))
18124 return(0);
18125 type->flags |= XML_SCHEMAS_TYPE_INTERNAL_RESOLVED;
18126 if (baseType == NULL) {
18127 PERROR_INT("xmlSchemaFixupComplexType",
18128 "missing baseType");
18129 goto exit_failure;
18132 * Fixup the base type.
18134 if (WXS_IS_TYPE_NOT_FIXED(baseType))
18135 xmlSchemaTypeFixup(baseType, ACTXT_CAST pctxt);
18136 if (baseType->flags & XML_SCHEMAS_TYPE_INTERNAL_INVALID) {
18138 * Skip fixup if the base type is invalid.
18139 * TODO: Generate a warning!
18141 return(0);
18144 * This basically checks if the base type can be derived.
18146 res = xmlSchemaCheckSRCCT(pctxt, type);
18147 HFAILURE HERROR
18149 * Fixup the content type.
18151 if (type->contentType == XML_SCHEMA_CONTENT_SIMPLE) {
18153 * Corresponds to <complexType><simpleContent>...
18155 if ((WXS_IS_COMPLEX(baseType)) &&
18156 (baseType->contentTypeDef != NULL) &&
18157 (WXS_IS_RESTRICTION(type))) {
18158 xmlSchemaTypePtr contentBase, content;
18159 #ifdef ENABLE_NAMED_LOCALS
18160 char buf[30];
18161 const xmlChar *tmpname;
18162 #endif
18164 * SPEC (1) If <restriction> + base type is <complexType>,
18165 * "whose own {content type} is a simple type..."
18167 if (type->contentTypeDef != NULL) {
18169 * SPEC (1.1) "the simple type definition corresponding to the
18170 * <simpleType> among the [children] of <restriction> if there
18171 * is one;"
18172 * Note that this "<simpleType> among the [children]" was put
18173 * into ->contentTypeDef during parsing.
18175 contentBase = type->contentTypeDef;
18176 type->contentTypeDef = NULL;
18177 } else {
18179 * (1.2) "...otherwise (<restriction> has no <simpleType>
18180 * among its [children]), the simple type definition which
18181 * is the {content type} of the ... base type."
18183 contentBase = baseType->contentTypeDef;
18186 * SPEC
18187 * "... a simple type definition which restricts the simple
18188 * type definition identified in clause 1.1 or clause 1.2
18189 * with a set of facet components"
18191 * Create the anonymous simple type, which will be the content
18192 * type of the complex type.
18194 #ifdef ENABLE_NAMED_LOCALS
18195 snprintf(buf, 29, "#scST%d", ++(pctxt->counter));
18196 tmpname = xmlDictLookup(pctxt->dict, BAD_CAST buf, -1);
18197 content = xmlSchemaAddType(pctxt, pctxt->schema,
18198 XML_SCHEMA_TYPE_SIMPLE, tmpname, type->targetNamespace,
18199 type->node, 0);
18200 #else
18201 content = xmlSchemaAddType(pctxt, pctxt->schema,
18202 XML_SCHEMA_TYPE_SIMPLE, NULL, type->targetNamespace,
18203 type->node, 0);
18204 #endif
18205 if (content == NULL)
18206 goto exit_failure;
18208 * We will use the same node as for the <complexType>
18209 * to have it somehow anchored in the schema doc.
18211 content->type = XML_SCHEMA_TYPE_SIMPLE;
18212 content->baseType = contentBase;
18214 * Move the facets, previously anchored on the
18215 * complexType during parsing.
18217 content->facets = type->facets;
18218 type->facets = NULL;
18219 content->facetSet = type->facetSet;
18220 type->facetSet = NULL;
18222 type->contentTypeDef = content;
18223 if (WXS_IS_TYPE_NOT_FIXED(contentBase))
18224 xmlSchemaTypeFixup(contentBase, ACTXT_CAST pctxt);
18226 * Fixup the newly created type. We don't need to check
18227 * for circularity here.
18229 res = xmlSchemaFixupSimpleTypeStageOne(pctxt, content);
18230 HFAILURE HERROR
18231 res = xmlSchemaFixupSimpleTypeStageTwo(pctxt, content);
18232 HFAILURE HERROR
18234 } else if ((WXS_IS_COMPLEX(baseType)) &&
18235 (baseType->contentType == XML_SCHEMA_CONTENT_MIXED) &&
18236 (WXS_IS_RESTRICTION(type))) {
18238 * SPEC (2) If <restriction> + base is a mixed <complexType> with
18239 * an emptiable particle, then a simple type definition which
18240 * restricts the <restriction>'s <simpleType> child.
18242 if ((type->contentTypeDef == NULL) ||
18243 (type->contentTypeDef->baseType == NULL)) {
18245 * TODO: Check if this ever happens.
18247 xmlSchemaPCustomErr(pctxt,
18248 XML_SCHEMAP_INTERNAL,
18249 WXS_BASIC_CAST type, NULL,
18250 "Internal error: xmlSchemaTypeFixup, "
18251 "complex type '%s': the <simpleContent><restriction> "
18252 "is missing a <simpleType> child, but was not catched "
18253 "by xmlSchemaCheckSRCCT()", type->name);
18254 goto exit_failure;
18256 } else if ((WXS_IS_COMPLEX(baseType)) && WXS_IS_EXTENSION(type)) {
18258 * SPEC (3) If <extension> + base is <complexType> with
18259 * <simpleType> content, "...then the {content type} of that
18260 * complex type definition"
18262 if (baseType->contentTypeDef == NULL) {
18264 * TODO: Check if this ever happens. xmlSchemaCheckSRCCT
18265 * should have catched this already.
18267 xmlSchemaPCustomErr(pctxt,
18268 XML_SCHEMAP_INTERNAL,
18269 WXS_BASIC_CAST type, NULL,
18270 "Internal error: xmlSchemaTypeFixup, "
18271 "complex type '%s': the <extension>ed base type is "
18272 "a complex type with no simple content type",
18273 type->name);
18274 goto exit_failure;
18276 type->contentTypeDef = baseType->contentTypeDef;
18277 } else if ((WXS_IS_SIMPLE(baseType)) && WXS_IS_EXTENSION(type)) {
18279 * SPEC (4) <extension> + base is <simpleType>
18280 * "... then that simple type definition"
18282 type->contentTypeDef = baseType;
18283 } else {
18285 * TODO: Check if this ever happens.
18287 xmlSchemaPCustomErr(pctxt,
18288 XML_SCHEMAP_INTERNAL,
18289 WXS_BASIC_CAST type, NULL,
18290 "Internal error: xmlSchemaTypeFixup, "
18291 "complex type '%s' with <simpleContent>: unhandled "
18292 "derivation case", type->name);
18293 goto exit_failure;
18295 } else {
18296 int dummySequence = 0;
18297 xmlSchemaParticlePtr particle =
18298 (xmlSchemaParticlePtr) type->subtypes;
18300 * Corresponds to <complexType><complexContent>...
18302 * NOTE that the effective mixed was already set during parsing of
18303 * <complexType> and <complexContent>; its flag value is
18304 * XML_SCHEMAS_TYPE_MIXED.
18306 * Compute the "effective content":
18307 * (2.1.1) + (2.1.2) + (2.1.3)
18309 if ((particle == NULL) ||
18310 ((particle->type == XML_SCHEMA_TYPE_PARTICLE) &&
18311 ((particle->children->type == XML_SCHEMA_TYPE_ALL) ||
18312 (particle->children->type == XML_SCHEMA_TYPE_SEQUENCE) ||
18313 ((particle->children->type == XML_SCHEMA_TYPE_CHOICE) &&
18314 (particle->minOccurs == 0))) &&
18315 ( ((xmlSchemaTreeItemPtr) particle->children)->children == NULL))) {
18316 if (type->flags & XML_SCHEMAS_TYPE_MIXED) {
18318 * SPEC (2.1.4) "If the �effective mixed� is true, then
18319 * a particle whose properties are as follows:..."
18321 * Empty sequence model group with
18322 * minOccurs/maxOccurs = 1 (i.e. a "particle emptiable").
18323 * NOTE that we sill assign it the <complexType> node to
18324 * somehow anchor it in the doc.
18326 if ((particle == NULL) ||
18327 (particle->children->type != XML_SCHEMA_TYPE_SEQUENCE)) {
18329 * Create the particle.
18331 particle = xmlSchemaAddParticle(pctxt,
18332 type->node, 1, 1);
18333 if (particle == NULL)
18334 goto exit_failure;
18336 * Create the model group.
18337 */ /* URGENT TODO: avoid adding to pending items. */
18338 particle->children = (xmlSchemaTreeItemPtr)
18339 xmlSchemaAddModelGroup(pctxt, pctxt->schema,
18340 XML_SCHEMA_TYPE_SEQUENCE, type->node);
18341 if (particle->children == NULL)
18342 goto exit_failure;
18344 type->subtypes = (xmlSchemaTypePtr) particle;
18346 dummySequence = 1;
18347 type->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
18348 } else {
18350 * SPEC (2.1.5) "otherwise empty"
18352 type->contentType = XML_SCHEMA_CONTENT_EMPTY;
18354 } else {
18356 * SPEC (2.2) "otherwise the particle corresponding to the
18357 * <all>, <choice>, <group> or <sequence> among the
18358 * [children]."
18360 type->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
18363 * Compute the "content type".
18365 if (WXS_IS_RESTRICTION(type)) {
18367 * SPEC (3.1) "If <restriction>..."
18368 * (3.1.1) + (3.1.2) */
18369 if (type->contentType != XML_SCHEMA_CONTENT_EMPTY) {
18370 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
18371 type->contentType = XML_SCHEMA_CONTENT_MIXED;
18373 } else {
18375 * SPEC (3.2) "If <extension>..."
18377 if (type->contentType == XML_SCHEMA_CONTENT_EMPTY) {
18379 * SPEC (3.2.1)
18380 * "If the �effective content� is empty, then the
18381 * {content type} of the [...] base ..."
18383 type->contentType = baseType->contentType;
18384 type->subtypes = baseType->subtypes;
18386 * Fixes bug #347316:
18387 * This is the case when the base type has a simple
18388 * type definition as content.
18390 type->contentTypeDef = baseType->contentTypeDef;
18392 * NOTE that the effective mixed is ignored here.
18394 } else if (baseType->contentType == XML_SCHEMA_CONTENT_EMPTY) {
18396 * SPEC (3.2.2)
18398 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
18399 type->contentType = XML_SCHEMA_CONTENT_MIXED;
18400 } else {
18402 * SPEC (3.2.3)
18404 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
18405 type->contentType = XML_SCHEMA_CONTENT_MIXED;
18407 * "A model group whose {compositor} is sequence and whose
18408 * {particles} are..."
18410 if ((WXS_TYPE_PARTICLE(type) != NULL) &&
18411 (WXS_TYPE_PARTICLE_TERM(type) != NULL) &&
18412 ((WXS_TYPE_PARTICLE_TERM(type))->type ==
18413 XML_SCHEMA_TYPE_ALL))
18416 * SPEC cos-all-limited (1)
18418 xmlSchemaCustomErr(ACTXT_CAST pctxt,
18419 /* TODO: error code */
18420 XML_SCHEMAP_COS_ALL_LIMITED,
18421 WXS_ITEM_NODE(type), NULL,
18422 "The type has an 'all' model group in its "
18423 "{content type} and thus cannot be derived from "
18424 "a non-empty type, since this would produce a "
18425 "'sequence' model group containing the 'all' "
18426 "model group; 'all' model groups are not "
18427 "allowed to appear inside other model groups",
18428 NULL, NULL);
18430 } else if ((WXS_TYPE_PARTICLE(baseType) != NULL) &&
18431 (WXS_TYPE_PARTICLE_TERM(baseType) != NULL) &&
18432 ((WXS_TYPE_PARTICLE_TERM(baseType))->type ==
18433 XML_SCHEMA_TYPE_ALL))
18436 * SPEC cos-all-limited (1)
18438 xmlSchemaCustomErr(ACTXT_CAST pctxt,
18439 /* TODO: error code */
18440 XML_SCHEMAP_COS_ALL_LIMITED,
18441 WXS_ITEM_NODE(type), NULL,
18442 "A type cannot be derived by extension from a type "
18443 "which has an 'all' model group in its "
18444 "{content type}, since this would produce a "
18445 "'sequence' model group containing the 'all' "
18446 "model group; 'all' model groups are not "
18447 "allowed to appear inside other model groups",
18448 NULL, NULL);
18450 } else if (! dummySequence) {
18451 xmlSchemaTreeItemPtr effectiveContent =
18452 (xmlSchemaTreeItemPtr) type->subtypes;
18454 * Create the particle.
18456 particle = xmlSchemaAddParticle(pctxt,
18457 type->node, 1, 1);
18458 if (particle == NULL)
18459 goto exit_failure;
18461 * Create the "sequence" model group.
18463 particle->children = (xmlSchemaTreeItemPtr)
18464 xmlSchemaAddModelGroup(pctxt, pctxt->schema,
18465 XML_SCHEMA_TYPE_SEQUENCE, type->node);
18466 if (particle->children == NULL)
18467 goto exit_failure;
18468 WXS_TYPE_CONTENTTYPE(type) = (xmlSchemaTypePtr) particle;
18470 * SPEC "the particle of the {content type} of
18471 * the ... base ..."
18472 * Create a duplicate of the base type's particle
18473 * and assign its "term" to it.
18475 particle->children->children =
18476 (xmlSchemaTreeItemPtr) xmlSchemaAddParticle(pctxt,
18477 type->node,
18478 ((xmlSchemaParticlePtr) type->subtypes)->minOccurs,
18479 ((xmlSchemaParticlePtr) type->subtypes)->maxOccurs);
18480 if (particle->children->children == NULL)
18481 goto exit_failure;
18482 particle = (xmlSchemaParticlePtr)
18483 particle->children->children;
18484 particle->children =
18485 ((xmlSchemaParticlePtr) baseType->subtypes)->children;
18487 * SPEC "followed by the �effective content�."
18489 particle->next = effectiveContent;
18491 * This all will result in:
18492 * new-particle
18493 * --> new-sequence(
18494 * new-particle
18495 * --> base-model,
18496 * this-particle
18497 * --> this-model
18500 } else {
18502 * This is the case when there is already an empty
18503 * <sequence> with minOccurs==maxOccurs==1.
18504 * Just add the base types's content type.
18505 * NOTE that, although we miss to add an intermediate
18506 * <sequence>, this should produce no difference to
18507 * neither the regex compilation of the content model,
18508 * nor to the complex type contraints.
18510 particle->children->children =
18511 (xmlSchemaTreeItemPtr) baseType->subtypes;
18517 * Now fixup attribute uses:
18518 * - expand attr. group references
18519 * - intersect attribute wildcards
18520 * - inherit attribute uses of the base type
18521 * - inherit or union attr. wildcards if extending
18522 * - apply attr. use prohibitions if restricting
18524 res = xmlSchemaFixupTypeAttributeUses(pctxt, type);
18525 HFAILURE HERROR
18527 * Apply the complex type component constraints; this will not
18528 * check attributes, since this is done in
18529 * xmlSchemaFixupTypeAttributeUses().
18531 res = xmlSchemaCheckCTComponent(pctxt, type);
18532 HFAILURE HERROR
18534 #ifdef DEBUG_TYPE
18535 xmlSchemaDebugFixedType(pctxt, type);
18536 #endif
18537 if (olderrs != pctxt->nberrors)
18538 return(pctxt->err);
18539 else
18540 return(0);
18542 exit_error:
18543 type->flags |= XML_SCHEMAS_TYPE_INTERNAL_INVALID;
18544 #ifdef DEBUG_TYPE
18545 xmlSchemaDebugFixedType(pctxt, type);
18546 #endif
18547 return(pctxt->err);
18549 exit_failure:
18550 type->flags |= XML_SCHEMAS_TYPE_INTERNAL_INVALID;
18551 #ifdef DEBUG_TYPE
18552 xmlSchemaDebugFixedType(pctxt, type);
18553 #endif
18554 return(-1);
18559 * xmlSchemaTypeFixup:
18560 * @typeDecl: the schema type definition
18561 * @ctxt: the schema parser context
18563 * Fixes the content model of the type.
18564 * URGENT TODO: We need an int result!
18566 static int
18567 xmlSchemaTypeFixup(xmlSchemaTypePtr type,
18568 xmlSchemaAbstractCtxtPtr actxt)
18570 if (type == NULL)
18571 return(0);
18572 if (actxt->type != XML_SCHEMA_CTXT_PARSER) {
18573 AERROR_INT("xmlSchemaTypeFixup",
18574 "this function needs a parser context");
18575 return(-1);
18577 if (! WXS_IS_TYPE_NOT_FIXED(type))
18578 return(0);
18579 if (type->type == XML_SCHEMA_TYPE_COMPLEX)
18580 return(xmlSchemaFixupComplexType(PCTXT_CAST actxt, type));
18581 else if (type->type == XML_SCHEMA_TYPE_SIMPLE)
18582 return(xmlSchemaFixupSimpleTypeStageTwo(PCTXT_CAST actxt, type));
18583 return(0);
18587 * xmlSchemaCheckFacet:
18588 * @facet: the facet
18589 * @typeDecl: the schema type definition
18590 * @pctxt: the schema parser context or NULL
18591 * @name: the optional name of the type
18593 * Checks and computes the values of facets.
18595 * Returns 0 if valid, a positive error code if not valid and
18596 * -1 in case of an internal or API error.
18599 xmlSchemaCheckFacet(xmlSchemaFacetPtr facet,
18600 xmlSchemaTypePtr typeDecl,
18601 xmlSchemaParserCtxtPtr pctxt,
18602 const xmlChar * name ATTRIBUTE_UNUSED)
18604 int ret = 0, ctxtGiven;
18606 if ((facet == NULL) || (typeDecl == NULL))
18607 return(-1);
18609 * TODO: will the parser context be given if used from
18610 * the relaxNG module?
18612 if (pctxt == NULL)
18613 ctxtGiven = 0;
18614 else
18615 ctxtGiven = 1;
18617 switch (facet->type) {
18618 case XML_SCHEMA_FACET_MININCLUSIVE:
18619 case XML_SCHEMA_FACET_MINEXCLUSIVE:
18620 case XML_SCHEMA_FACET_MAXINCLUSIVE:
18621 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
18622 case XML_SCHEMA_FACET_ENUMERATION: {
18624 * Okay we need to validate the value
18625 * at that point.
18627 xmlSchemaTypePtr base;
18629 /* 4.3.5.5 Constraints on enumeration Schema Components
18630 * Schema Component Constraint: enumeration valid restriction
18631 * It is an �error� if any member of {value} is not in the
18632 * �value space� of {base type definition}.
18634 * minInclusive, maxInclusive, minExclusive, maxExclusive:
18635 * The value �must� be in the
18636 * �value space� of the �base type�.
18639 * This function is intended to deliver a compiled value
18640 * on the facet. In this implementation of XML Schemata the
18641 * type holding a facet, won't be a built-in type.
18642 * Thus to ensure that other API
18643 * calls (relaxng) do work, if the given type is a built-in
18644 * type, we will assume that the given built-in type *is
18645 * already* the base type.
18647 if (typeDecl->type != XML_SCHEMA_TYPE_BASIC) {
18648 base = typeDecl->baseType;
18649 if (base == NULL) {
18650 PERROR_INT("xmlSchemaCheckFacet",
18651 "a type user derived type has no base type");
18652 return (-1);
18654 } else
18655 base = typeDecl;
18657 if (! ctxtGiven) {
18659 * A context is needed if called from RelaxNG.
18661 pctxt = xmlSchemaNewParserCtxt("*");
18662 if (pctxt == NULL)
18663 return (-1);
18666 * NOTE: This call does not check the content nodes,
18667 * since they are not available:
18668 * facet->node is just the node holding the facet
18669 * definition, *not* the attribute holding the *value*
18670 * of the facet.
18672 ret = xmlSchemaVCheckCVCSimpleType(
18673 ACTXT_CAST pctxt, facet->node, base,
18674 facet->value, &(facet->val), 1, 1, 0);
18675 if (ret != 0) {
18676 if (ret < 0) {
18677 /* No error message for RelaxNG. */
18678 if (ctxtGiven) {
18679 xmlSchemaCustomErr(ACTXT_CAST pctxt,
18680 XML_SCHEMAP_INTERNAL, facet->node, NULL,
18681 "Internal error: xmlSchemaCheckFacet, "
18682 "failed to validate the value '%s' of the "
18683 "facet '%s' against the base type",
18684 facet->value, xmlSchemaFacetTypeToString(facet->type));
18686 goto internal_error;
18688 ret = XML_SCHEMAP_INVALID_FACET_VALUE;
18689 /* No error message for RelaxNG. */
18690 if (ctxtGiven) {
18691 xmlChar *str = NULL;
18693 xmlSchemaCustomErr(ACTXT_CAST pctxt,
18694 ret, facet->node, WXS_BASIC_CAST facet,
18695 "The value '%s' of the facet does not validate "
18696 "against the base type '%s'",
18697 facet->value,
18698 xmlSchemaFormatQName(&str,
18699 base->targetNamespace, base->name));
18700 FREE_AND_NULL(str);
18702 goto exit;
18703 } else if (facet->val == NULL) {
18704 if (ctxtGiven) {
18705 PERROR_INT("xmlSchemaCheckFacet",
18706 "value was not computed");
18708 TODO
18710 break;
18712 case XML_SCHEMA_FACET_PATTERN:
18713 facet->regexp = xmlRegexpCompile(facet->value);
18714 if (facet->regexp == NULL) {
18715 ret = XML_SCHEMAP_REGEXP_INVALID;
18716 /* No error message for RelaxNG. */
18717 if (ctxtGiven) {
18718 xmlSchemaCustomErr(ACTXT_CAST pctxt,
18719 ret, facet->node, WXS_BASIC_CAST typeDecl,
18720 "The value '%s' of the facet 'pattern' is not a "
18721 "valid regular expression",
18722 facet->value, NULL);
18725 break;
18726 case XML_SCHEMA_FACET_TOTALDIGITS:
18727 case XML_SCHEMA_FACET_FRACTIONDIGITS:
18728 case XML_SCHEMA_FACET_LENGTH:
18729 case XML_SCHEMA_FACET_MAXLENGTH:
18730 case XML_SCHEMA_FACET_MINLENGTH:
18732 if (facet->type == XML_SCHEMA_FACET_TOTALDIGITS) {
18733 ret = xmlSchemaValidatePredefinedType(
18734 xmlSchemaGetBuiltInType(XML_SCHEMAS_PINTEGER),
18735 facet->value, &(facet->val));
18736 } else {
18737 ret = xmlSchemaValidatePredefinedType(
18738 xmlSchemaGetBuiltInType(XML_SCHEMAS_NNINTEGER),
18739 facet->value, &(facet->val));
18741 if (ret != 0) {
18742 if (ret < 0) {
18743 /* No error message for RelaxNG. */
18744 if (ctxtGiven) {
18745 PERROR_INT("xmlSchemaCheckFacet",
18746 "validating facet value");
18748 goto internal_error;
18750 ret = XML_SCHEMAP_INVALID_FACET_VALUE;
18751 /* No error message for RelaxNG. */
18752 if (ctxtGiven) {
18753 /* error code */
18754 xmlSchemaCustomErr4(ACTXT_CAST pctxt,
18755 ret, facet->node, WXS_BASIC_CAST typeDecl,
18756 "The value '%s' of the facet '%s' is not a valid '%s'",
18757 facet->value,
18758 xmlSchemaFacetTypeToString(facet->type),
18759 (facet->type != XML_SCHEMA_FACET_TOTALDIGITS) ?
18760 BAD_CAST "nonNegativeInteger" :
18761 BAD_CAST "positiveInteger",
18762 NULL);
18765 break;
18767 case XML_SCHEMA_FACET_WHITESPACE:{
18768 if (xmlStrEqual(facet->value, BAD_CAST "preserve")) {
18769 facet->whitespace = XML_SCHEMAS_FACET_PRESERVE;
18770 } else if (xmlStrEqual(facet->value, BAD_CAST "replace")) {
18771 facet->whitespace = XML_SCHEMAS_FACET_REPLACE;
18772 } else if (xmlStrEqual(facet->value, BAD_CAST "collapse")) {
18773 facet->whitespace = XML_SCHEMAS_FACET_COLLAPSE;
18774 } else {
18775 ret = XML_SCHEMAP_INVALID_FACET_VALUE;
18776 /* No error message for RelaxNG. */
18777 if (ctxtGiven) {
18778 /* error was previously: XML_SCHEMAP_INVALID_WHITE_SPACE */
18779 xmlSchemaCustomErr(ACTXT_CAST pctxt,
18780 ret, facet->node, WXS_BASIC_CAST typeDecl,
18781 "The value '%s' of the facet 'whitespace' is not "
18782 "valid", facet->value, NULL);
18786 default:
18787 break;
18789 exit:
18790 if ((! ctxtGiven) && (pctxt != NULL))
18791 xmlSchemaFreeParserCtxt(pctxt);
18792 return (ret);
18793 internal_error:
18794 if ((! ctxtGiven) && (pctxt != NULL))
18795 xmlSchemaFreeParserCtxt(pctxt);
18796 return (-1);
18800 * xmlSchemaCheckFacetValues:
18801 * @typeDecl: the schema type definition
18802 * @ctxt: the schema parser context
18804 * Checks the default values types, especially for facets
18806 static int
18807 xmlSchemaCheckFacetValues(xmlSchemaTypePtr typeDecl,
18808 xmlSchemaParserCtxtPtr pctxt)
18810 int res, olderrs = pctxt->nberrors;
18811 const xmlChar *name = typeDecl->name;
18813 * NOTE: It is intended to use the facets list, instead
18814 * of facetSet.
18816 if (typeDecl->facets != NULL) {
18817 xmlSchemaFacetPtr facet = typeDecl->facets;
18820 * Temporarily assign the "schema" to the validation context
18821 * of the parser context. This is needed for NOTATION validation.
18823 if (pctxt->vctxt == NULL) {
18824 if (xmlSchemaCreateVCtxtOnPCtxt(pctxt) == -1)
18825 return(-1);
18827 pctxt->vctxt->schema = pctxt->schema;
18828 while (facet != NULL) {
18829 res = xmlSchemaCheckFacet(facet, typeDecl, pctxt, name);
18830 HFAILURE
18831 facet = facet->next;
18833 pctxt->vctxt->schema = NULL;
18835 if (olderrs != pctxt->nberrors)
18836 return(pctxt->err);
18837 return(0);
18838 exit_failure:
18839 return(-1);
18843 * xmlSchemaGetCircModelGrDefRef:
18844 * @ctxtMGroup: the searched model group
18845 * @selfMGroup: the second searched model group
18846 * @particle: the first particle
18848 * This one is intended to be used by
18849 * xmlSchemaCheckGroupDefCircular only.
18851 * Returns the particle with the circular model group definition reference,
18852 * otherwise NULL.
18854 static xmlSchemaTreeItemPtr
18855 xmlSchemaGetCircModelGrDefRef(xmlSchemaModelGroupDefPtr groupDef,
18856 xmlSchemaTreeItemPtr particle)
18858 xmlSchemaTreeItemPtr circ = NULL;
18859 xmlSchemaTreeItemPtr term;
18860 xmlSchemaModelGroupDefPtr gdef;
18862 for (; particle != NULL; particle = particle->next) {
18863 term = particle->children;
18864 if (term == NULL)
18865 continue;
18866 switch (term->type) {
18867 case XML_SCHEMA_TYPE_GROUP:
18868 gdef = (xmlSchemaModelGroupDefPtr) term;
18869 if (gdef == groupDef)
18870 return (particle);
18872 * Mark this model group definition to avoid infinite
18873 * recursion on circular references not yet examined.
18875 if (gdef->flags & XML_SCHEMA_MODEL_GROUP_DEF_MARKED)
18876 continue;
18877 if (gdef->children != NULL) {
18878 gdef->flags |= XML_SCHEMA_MODEL_GROUP_DEF_MARKED;
18879 circ = xmlSchemaGetCircModelGrDefRef(groupDef,
18880 gdef->children->children);
18881 gdef->flags ^= XML_SCHEMA_MODEL_GROUP_DEF_MARKED;
18882 if (circ != NULL)
18883 return (circ);
18885 break;
18886 case XML_SCHEMA_TYPE_SEQUENCE:
18887 case XML_SCHEMA_TYPE_CHOICE:
18888 case XML_SCHEMA_TYPE_ALL:
18889 circ = xmlSchemaGetCircModelGrDefRef(groupDef, term->children);
18890 if (circ != NULL)
18891 return (circ);
18892 break;
18893 default:
18894 break;
18897 return (NULL);
18901 * xmlSchemaCheckGroupDefCircular:
18902 * @item: the model group definition
18903 * @ctxt: the parser context
18904 * @name: the name
18906 * Checks for circular references to model group definitions.
18908 static void
18909 xmlSchemaCheckGroupDefCircular(xmlSchemaModelGroupDefPtr item,
18910 xmlSchemaParserCtxtPtr ctxt)
18913 * Schema Component Constraint: Model Group Correct
18914 * 2 Circular groups are disallowed. That is, within the {particles}
18915 * of a group there must not be at any depth a particle whose {term}
18916 * is the group itself.
18918 if ((item == NULL) ||
18919 (item->type != XML_SCHEMA_TYPE_GROUP) ||
18920 (item->children == NULL))
18921 return;
18923 xmlSchemaTreeItemPtr circ;
18925 circ = xmlSchemaGetCircModelGrDefRef(item, item->children->children);
18926 if (circ != NULL) {
18927 xmlChar *str = NULL;
18929 * TODO: The error report is not adequate: this constraint
18930 * is defined for model groups but not definitions, but since
18931 * there cannot be any circular model groups without a model group
18932 * definition (if not using a construction API), we check those
18933 * defintions only.
18935 xmlSchemaPCustomErr(ctxt,
18936 XML_SCHEMAP_MG_PROPS_CORRECT_2,
18937 NULL, WXS_ITEM_NODE(circ),
18938 "Circular reference to the model group definition '%s' "
18939 "defined", xmlSchemaFormatQName(&str,
18940 item->targetNamespace, item->name));
18941 FREE_AND_NULL(str)
18943 * NOTE: We will cut the reference to avoid further
18944 * confusion of the processor. This is a fatal error.
18946 circ->children = NULL;
18952 * xmlSchemaModelGroupToModelGroupDefFixup:
18953 * @ctxt: the parser context
18954 * @mg: the model group
18956 * Assigns the model group of model group definitions to the "term"
18957 * of the referencing particle.
18958 * In xmlSchemaResolveModelGroupParticleReferences the model group
18959 * definitions were assigned to the "term", since needed for the
18960 * circularity check.
18962 * Schema Component Constraint:
18963 * All Group Limited (cos-all-limited) (1.2)
18965 static void
18966 xmlSchemaModelGroupToModelGroupDefFixup(
18967 xmlSchemaParserCtxtPtr ctxt ATTRIBUTE_UNUSED,
18968 xmlSchemaModelGroupPtr mg)
18970 xmlSchemaParticlePtr particle = WXS_MODELGROUP_PARTICLE(mg);
18972 while (particle != NULL) {
18973 if ((WXS_PARTICLE_TERM(particle) == NULL) ||
18974 ((WXS_PARTICLE_TERM(particle))->type !=
18975 XML_SCHEMA_TYPE_GROUP))
18977 particle = WXS_PTC_CAST particle->next;
18978 continue;
18980 if (WXS_MODELGROUPDEF_MODEL(WXS_PARTICLE_TERM(particle)) == NULL) {
18982 * TODO: Remove the particle.
18984 WXS_PARTICLE_TERM(particle) = NULL;
18985 particle = WXS_PTC_CAST particle->next;
18986 continue;
18989 * Assign the model group to the {term} of the particle.
18991 WXS_PARTICLE_TERM(particle) =
18992 WXS_TREE_CAST WXS_MODELGROUPDEF_MODEL(WXS_PARTICLE_TERM(particle));
18994 particle = WXS_PTC_CAST particle->next;
18999 * xmlSchemaCheckAttrGroupCircularRecur:
19000 * @ctxtGr: the searched attribute group
19001 * @attr: the current attribute list to be processed
19003 * This one is intended to be used by
19004 * xmlSchemaCheckAttrGroupCircular only.
19006 * Returns the circular attribute grou reference, otherwise NULL.
19008 static xmlSchemaQNameRefPtr
19009 xmlSchemaCheckAttrGroupCircularRecur(xmlSchemaAttributeGroupPtr ctxtGr,
19010 xmlSchemaItemListPtr list)
19012 xmlSchemaAttributeGroupPtr gr;
19013 xmlSchemaQNameRefPtr ref, circ;
19014 int i;
19016 * We will search for an attribute group reference which
19017 * references the context attribute group.
19019 for (i = 0; i < list->nbItems; i++) {
19020 ref = list->items[i];
19021 if ((ref->type == XML_SCHEMA_EXTRA_QNAMEREF) &&
19022 (ref->itemType == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) &&
19023 (ref->item != NULL))
19025 gr = WXS_ATTR_GROUP_CAST ref->item;
19026 if (gr == ctxtGr)
19027 return(ref);
19028 if (gr->flags & XML_SCHEMAS_ATTRGROUP_MARKED)
19029 continue;
19031 * Mark as visited to avoid infinite recursion on
19032 * circular references not yet examined.
19034 if ((gr->attrUses) &&
19035 (gr->flags & XML_SCHEMAS_ATTRGROUP_HAS_REFS))
19037 gr->flags |= XML_SCHEMAS_ATTRGROUP_MARKED;
19038 circ = xmlSchemaCheckAttrGroupCircularRecur(ctxtGr,
19039 (xmlSchemaItemListPtr) gr->attrUses);
19040 gr->flags ^= XML_SCHEMAS_ATTRGROUP_MARKED;
19041 if (circ != NULL)
19042 return (circ);
19047 return (NULL);
19051 * xmlSchemaCheckAttrGroupCircular:
19052 * attrGr: the attribute group definition
19053 * @ctxt: the parser context
19054 * @name: the name
19056 * Checks for circular references of attribute groups.
19058 static int
19059 xmlSchemaCheckAttrGroupCircular(xmlSchemaAttributeGroupPtr attrGr,
19060 xmlSchemaParserCtxtPtr ctxt)
19063 * Schema Representation Constraint:
19064 * Attribute Group Definition Representation OK
19065 * 3 Circular group reference is disallowed outside <redefine>.
19066 * That is, unless this element information item's parent is
19067 * <redefine>, then among the [children], if any, there must
19068 * not be an <attributeGroup> with ref [attribute] which resolves
19069 * to the component corresponding to this <attributeGroup>. Indirect
19070 * circularity is also ruled out. That is, when QName resolution
19071 * (Schema Document) (�3.15.3) is applied to a �QName� arising from
19072 * any <attributeGroup>s with a ref [attribute] among the [children],
19073 * it must not be the case that a �QName� is encountered at any depth
19074 * which resolves to the component corresponding to this <attributeGroup>.
19076 if (attrGr->attrUses == NULL)
19077 return(0);
19078 else if ((attrGr->flags & XML_SCHEMAS_ATTRGROUP_HAS_REFS) == 0)
19079 return(0);
19080 else {
19081 xmlSchemaQNameRefPtr circ;
19083 circ = xmlSchemaCheckAttrGroupCircularRecur(attrGr,
19084 (xmlSchemaItemListPtr) attrGr->attrUses);
19085 if (circ != NULL) {
19086 xmlChar *str = NULL;
19088 * TODO: Report the referenced attr group as QName.
19090 xmlSchemaPCustomErr(ctxt,
19091 XML_SCHEMAP_SRC_ATTRIBUTE_GROUP_3,
19092 NULL, WXS_ITEM_NODE(WXS_BASIC_CAST circ),
19093 "Circular reference to the attribute group '%s' "
19094 "defined", xmlSchemaGetComponentQName(&str, attrGr));
19095 FREE_AND_NULL(str);
19097 * NOTE: We will cut the reference to avoid further
19098 * confusion of the processor.
19099 * BADSPEC TODO: The spec should define how to process in this case.
19101 circ->item = NULL;
19102 return(ctxt->err);
19105 return(0);
19108 static int
19109 xmlSchemaAttributeGroupExpandRefs(xmlSchemaParserCtxtPtr pctxt,
19110 xmlSchemaAttributeGroupPtr attrGr);
19113 * xmlSchemaExpandAttributeGroupRefs:
19114 * @pctxt: the parser context
19115 * @node: the node of the component holding the attribute uses
19116 * @completeWild: the intersected wildcard to be returned
19117 * @list: the attribute uses
19119 * Substitutes contained attribute group references
19120 * for their attribute uses. Wilcards are intersected.
19121 * Attribute use prohibitions are removed from the list
19122 * and returned via the @prohibs list.
19123 * Pointlessness of attr. prohibs, if a matching attr. decl
19124 * is existent a well, are checked.
19126 static int
19127 xmlSchemaExpandAttributeGroupRefs(xmlSchemaParserCtxtPtr pctxt,
19128 xmlSchemaBasicItemPtr item,
19129 xmlSchemaWildcardPtr *completeWild,
19130 xmlSchemaItemListPtr list,
19131 xmlSchemaItemListPtr prohibs)
19133 xmlSchemaAttributeGroupPtr gr;
19134 xmlSchemaAttributeUsePtr use;
19135 xmlSchemaItemListPtr sublist;
19136 int i, j;
19137 int created = (*completeWild == NULL) ? 0 : 1;
19139 if (prohibs)
19140 prohibs->nbItems = 0;
19142 for (i = 0; i < list->nbItems; i++) {
19143 use = list->items[i];
19145 if (use->type == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB) {
19146 if (prohibs == NULL) {
19147 PERROR_INT("xmlSchemaExpandAttributeGroupRefs",
19148 "unexpected attr prohibition found");
19149 return(-1);
19152 * Remove from attribute uses.
19154 if (xmlSchemaItemListRemove(list, i) == -1)
19155 return(-1);
19156 i--;
19158 * Note that duplicate prohibitions were already
19159 * handled at parsing time.
19162 * Add to list of prohibitions.
19164 xmlSchemaItemListAddSize(prohibs, 2, use);
19165 continue;
19167 if ((use->type == XML_SCHEMA_EXTRA_QNAMEREF) &&
19168 ((WXS_QNAME_CAST use)->itemType == XML_SCHEMA_TYPE_ATTRIBUTEGROUP))
19170 if ((WXS_QNAME_CAST use)->item == NULL)
19171 return(-1);
19172 gr = WXS_ATTR_GROUP_CAST (WXS_QNAME_CAST use)->item;
19174 * Expand the referenced attr. group.
19175 * TODO: remove this, this is done in a previous step, so
19176 * already done here.
19178 if ((gr->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED) == 0) {
19179 if (xmlSchemaAttributeGroupExpandRefs(pctxt, gr) == -1)
19180 return(-1);
19183 * Build the 'complete' wildcard; i.e. intersect multiple
19184 * wildcards.
19186 if (gr->attributeWildcard != NULL) {
19187 if (*completeWild == NULL) {
19188 *completeWild = gr->attributeWildcard;
19189 } else {
19190 if (! created) {
19191 xmlSchemaWildcardPtr tmpWild;
19194 * Copy the first encountered wildcard as context,
19195 * except for the annotation.
19197 * Although the complete wildcard might not correspond
19198 * to any node in the schema, we will anchor it on
19199 * the node of the owner component.
19201 tmpWild = xmlSchemaAddWildcard(pctxt, pctxt->schema,
19202 XML_SCHEMA_TYPE_ANY_ATTRIBUTE,
19203 WXS_ITEM_NODE(item));
19204 if (tmpWild == NULL)
19205 return(-1);
19206 if (xmlSchemaCloneWildcardNsConstraints(pctxt,
19207 tmpWild, *completeWild) == -1)
19208 return (-1);
19209 tmpWild->processContents = (*completeWild)->processContents;
19210 *completeWild = tmpWild;
19211 created = 1;
19214 if (xmlSchemaIntersectWildcards(pctxt, *completeWild,
19215 gr->attributeWildcard) == -1)
19216 return(-1);
19220 * Just remove the reference if the referenced group does not
19221 * contain any attribute uses.
19223 sublist = ((xmlSchemaItemListPtr) gr->attrUses);
19224 if ((sublist == NULL) || sublist->nbItems == 0) {
19225 if (xmlSchemaItemListRemove(list, i) == -1)
19226 return(-1);
19227 i--;
19228 continue;
19231 * Add the attribute uses.
19233 list->items[i] = sublist->items[0];
19234 if (sublist->nbItems != 1) {
19235 for (j = 1; j < sublist->nbItems; j++) {
19236 i++;
19237 if (xmlSchemaItemListInsert(list,
19238 sublist->items[j], i) == -1)
19239 return(-1);
19246 * Handle pointless prohibitions of declared attributes.
19248 if (prohibs && (prohibs->nbItems != 0) && (list->nbItems != 0)) {
19249 xmlSchemaAttributeUseProhibPtr prohib;
19251 for (i = prohibs->nbItems -1; i >= 0; i--) {
19252 prohib = prohibs->items[i];
19253 for (j = 0; j < list->nbItems; j++) {
19254 use = list->items[j];
19256 if ((prohib->name == WXS_ATTRUSE_DECL_NAME(use)) &&
19257 (prohib->targetNamespace == WXS_ATTRUSE_DECL_TNS(use)))
19259 xmlChar *str = NULL;
19261 xmlSchemaCustomWarning(ACTXT_CAST pctxt,
19262 XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
19263 prohib->node, NULL,
19264 "Skipping pointless attribute use prohibition "
19265 "'%s', since a corresponding attribute use "
19266 "exists already in the type definition",
19267 xmlSchemaFormatQName(&str,
19268 prohib->targetNamespace, prohib->name),
19269 NULL, NULL);
19270 FREE_AND_NULL(str);
19272 * Remove the prohibition.
19274 if (xmlSchemaItemListRemove(prohibs, i) == -1)
19275 return(-1);
19276 break;
19281 return(0);
19285 * xmlSchemaAttributeGroupExpandRefs:
19286 * @pctxt: the parser context
19287 * @attrGr: the attribute group definition
19289 * Computation of:
19290 * {attribute uses} property
19291 * {attribute wildcard} property
19293 * Substitutes contained attribute group references
19294 * for their attribute uses. Wilcards are intersected.
19296 static int
19297 xmlSchemaAttributeGroupExpandRefs(xmlSchemaParserCtxtPtr pctxt,
19298 xmlSchemaAttributeGroupPtr attrGr)
19300 if ((attrGr->attrUses == NULL) ||
19301 (attrGr->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED))
19302 return(0);
19304 attrGr->flags |= XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED;
19305 if (xmlSchemaExpandAttributeGroupRefs(pctxt, WXS_BASIC_CAST attrGr,
19306 &(attrGr->attributeWildcard), attrGr->attrUses, NULL) == -1)
19307 return(-1);
19308 return(0);
19312 * xmlSchemaAttributeGroupExpandRefs:
19313 * @pctxt: the parser context
19314 * @attrGr: the attribute group definition
19316 * Substitutes contained attribute group references
19317 * for their attribute uses. Wilcards are intersected.
19319 * Schema Component Constraint:
19320 * Attribute Group Definition Properties Correct (ag-props-correct)
19322 static int
19323 xmlSchemaCheckAGPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
19324 xmlSchemaAttributeGroupPtr attrGr)
19327 * SPEC ag-props-correct
19328 * (1) "The values of the properties of an attribute group definition
19329 * must be as described in the property tableau in The Attribute
19330 * Group Definition Schema Component (�3.6.1), modulo the impact of
19331 * Missing Sub-components (�5.3);"
19334 if ((attrGr->attrUses != NULL) &&
19335 (WXS_LIST_CAST attrGr->attrUses)->nbItems > 1)
19337 xmlSchemaItemListPtr uses = WXS_LIST_CAST attrGr->attrUses;
19338 xmlSchemaAttributeUsePtr use, tmp;
19339 int i, j, hasId = 0;
19341 for (i = uses->nbItems -1; i >= 0; i--) {
19342 use = uses->items[i];
19344 * SPEC ag-props-correct
19345 * (2) "Two distinct members of the {attribute uses} must not have
19346 * {attribute declaration}s both of whose {name}s match and whose
19347 * {target namespace}s are identical."
19349 if (i > 0) {
19350 for (j = i -1; j >= 0; j--) {
19351 tmp = uses->items[j];
19352 if ((WXS_ATTRUSE_DECL_NAME(use) ==
19353 WXS_ATTRUSE_DECL_NAME(tmp)) &&
19354 (WXS_ATTRUSE_DECL_TNS(use) ==
19355 WXS_ATTRUSE_DECL_TNS(tmp)))
19357 xmlChar *str = NULL;
19359 xmlSchemaCustomErr(ACTXT_CAST pctxt,
19360 XML_SCHEMAP_AG_PROPS_CORRECT,
19361 attrGr->node, WXS_BASIC_CAST attrGr,
19362 "Duplicate %s",
19363 xmlSchemaGetComponentDesignation(&str, use),
19364 NULL);
19365 FREE_AND_NULL(str);
19367 * Remove the duplicate.
19369 if (xmlSchemaItemListRemove(uses, i) == -1)
19370 return(-1);
19371 goto next_use;
19376 * SPEC ag-props-correct
19377 * (3) "Two distinct members of the {attribute uses} must not have
19378 * {attribute declaration}s both of whose {type definition}s are or
19379 * are derived from ID."
19380 * TODO: Does 'derived' include member-types of unions?
19382 if (WXS_ATTRUSE_TYPEDEF(use) != NULL) {
19383 if (xmlSchemaIsDerivedFromBuiltInType(
19384 WXS_ATTRUSE_TYPEDEF(use), XML_SCHEMAS_ID))
19386 if (hasId) {
19387 xmlChar *str = NULL;
19389 xmlSchemaCustomErr(ACTXT_CAST pctxt,
19390 XML_SCHEMAP_AG_PROPS_CORRECT,
19391 attrGr->node, WXS_BASIC_CAST attrGr,
19392 "There must not exist more than one attribute "
19393 "declaration of type 'xs:ID' "
19394 "(or derived from 'xs:ID'). The %s violates this "
19395 "constraint",
19396 xmlSchemaGetComponentDesignation(&str, use),
19397 NULL);
19398 FREE_AND_NULL(str);
19399 if (xmlSchemaItemListRemove(uses, i) == -1)
19400 return(-1);
19402 hasId = 1;
19405 next_use: {}
19408 return(0);
19412 * xmlSchemaResolveAttrGroupReferences:
19413 * @attrgrpDecl: the schema attribute definition
19414 * @ctxt: the schema parser context
19415 * @name: the attribute name
19417 * Resolves references to attribute group definitions.
19419 static int
19420 xmlSchemaResolveAttrGroupReferences(xmlSchemaQNameRefPtr ref,
19421 xmlSchemaParserCtxtPtr ctxt)
19423 xmlSchemaAttributeGroupPtr group;
19425 if (ref->item != NULL)
19426 return(0);
19427 group = xmlSchemaGetAttributeGroup(ctxt->schema,
19428 ref->name,
19429 ref->targetNamespace);
19430 if (group == NULL) {
19431 xmlSchemaPResCompAttrErr(ctxt,
19432 XML_SCHEMAP_SRC_RESOLVE,
19433 NULL, ref->node,
19434 "ref", ref->name, ref->targetNamespace,
19435 ref->itemType, NULL);
19436 return(ctxt->err);
19438 ref->item = WXS_BASIC_CAST group;
19439 return(0);
19443 * xmlSchemaCheckAttrPropsCorrect:
19444 * @item: an schema attribute declaration/use
19445 * @ctxt: a schema parser context
19446 * @name: the name of the attribute
19449 * Schema Component Constraint:
19450 * Attribute Declaration Properties Correct (a-props-correct)
19452 * Validates the value constraints of an attribute declaration/use.
19453 * NOTE that this needs the simle type definitions to be already
19454 * builded and checked.
19456 static int
19457 xmlSchemaCheckAttrPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
19458 xmlSchemaAttributePtr attr)
19462 * SPEC a-props-correct (1)
19463 * "The values of the properties of an attribute declaration must
19464 * be as described in the property tableau in The Attribute
19465 * Declaration Schema Component (�3.2.1), modulo the impact of
19466 * Missing Sub-components (�5.3)."
19469 if (WXS_ATTR_TYPEDEF(attr) == NULL)
19470 return(0);
19472 if (attr->defValue != NULL) {
19473 int ret;
19476 * SPEC a-props-correct (3)
19477 * "If the {type definition} is or is derived from ID then there
19478 * must not be a {value constraint}."
19480 if (xmlSchemaIsDerivedFromBuiltInType(
19481 WXS_ATTR_TYPEDEF(attr), XML_SCHEMAS_ID))
19483 xmlSchemaCustomErr(ACTXT_CAST pctxt,
19484 XML_SCHEMAP_A_PROPS_CORRECT_3,
19485 NULL, WXS_BASIC_CAST attr,
19486 "Value constraints are not allowed if the type definition "
19487 "is or is derived from xs:ID",
19488 NULL, NULL);
19489 return(pctxt->err);
19492 * SPEC a-props-correct (2)
19493 * "if there is a {value constraint}, the canonical lexical
19494 * representation of its value must be �valid� with respect
19495 * to the {type definition} as defined in String Valid (�3.14.4)."
19496 * TODO: Don't care about the *cononical* stuff here, this requirement
19497 * will be removed in WXS 1.1 anyway.
19499 ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST pctxt,
19500 attr->node, WXS_ATTR_TYPEDEF(attr),
19501 attr->defValue, &(attr->defVal),
19502 1, 1, 0);
19503 if (ret != 0) {
19504 if (ret < 0) {
19505 PERROR_INT("xmlSchemaCheckAttrPropsCorrect",
19506 "calling xmlSchemaVCheckCVCSimpleType()");
19507 return(-1);
19509 xmlSchemaCustomErr(ACTXT_CAST pctxt,
19510 XML_SCHEMAP_A_PROPS_CORRECT_2,
19511 NULL, WXS_BASIC_CAST attr,
19512 "The value of the value constraint is not valid",
19513 NULL, NULL);
19514 return(pctxt->err);
19518 return(0);
19521 static xmlSchemaElementPtr
19522 xmlSchemaCheckSubstGroupCircular(xmlSchemaElementPtr elemDecl,
19523 xmlSchemaElementPtr ancestor)
19525 xmlSchemaElementPtr ret;
19527 if (WXS_SUBST_HEAD(ancestor) == NULL)
19528 return (NULL);
19529 if (WXS_SUBST_HEAD(ancestor) == elemDecl)
19530 return (ancestor);
19532 if (WXS_SUBST_HEAD(ancestor)->flags & XML_SCHEMAS_ELEM_CIRCULAR)
19533 return (NULL);
19534 WXS_SUBST_HEAD(ancestor)->flags |= XML_SCHEMAS_ELEM_CIRCULAR;
19535 ret = xmlSchemaCheckSubstGroupCircular(elemDecl,
19536 WXS_SUBST_HEAD(ancestor));
19537 WXS_SUBST_HEAD(ancestor)->flags ^= XML_SCHEMAS_ELEM_CIRCULAR;
19539 return (ret);
19543 * xmlSchemaCheckElemPropsCorrect:
19544 * @ctxt: a schema parser context
19545 * @decl: the element declaration
19546 * @name: the name of the attribute
19548 * Schema Component Constraint:
19549 * Element Declaration Properties Correct (e-props-correct)
19551 * STATUS:
19552 * missing: (6)
19554 static int
19555 xmlSchemaCheckElemPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
19556 xmlSchemaElementPtr elemDecl)
19558 int ret = 0;
19559 xmlSchemaTypePtr typeDef = WXS_ELEM_TYPEDEF(elemDecl);
19561 * SPEC (1) "The values of the properties of an element declaration
19562 * must be as described in the property tableau in The Element
19563 * Declaration Schema Component (�3.3.1), modulo the impact of Missing
19564 * Sub-components (�5.3)."
19566 if (WXS_SUBST_HEAD(elemDecl) != NULL) {
19567 xmlSchemaElementPtr head = WXS_SUBST_HEAD(elemDecl), circ;
19569 xmlSchemaCheckElementDeclComponent(head, pctxt);
19571 * SPEC (3) "If there is a non-�absent� {substitution group
19572 * affiliation}, then {scope} must be global."
19574 if ((elemDecl->flags & XML_SCHEMAS_ELEM_GLOBAL) == 0) {
19575 xmlSchemaPCustomErr(pctxt,
19576 XML_SCHEMAP_E_PROPS_CORRECT_3,
19577 WXS_BASIC_CAST elemDecl, NULL,
19578 "Only global element declarations can have a "
19579 "substitution group affiliation", NULL);
19580 ret = XML_SCHEMAP_E_PROPS_CORRECT_3;
19583 * TODO: SPEC (6) "Circular substitution groups are disallowed.
19584 * That is, it must not be possible to return to an element declaration
19585 * by repeatedly following the {substitution group affiliation}
19586 * property."
19588 if (head == elemDecl)
19589 circ = head;
19590 else if (WXS_SUBST_HEAD(head) != NULL)
19591 circ = xmlSchemaCheckSubstGroupCircular(head, head);
19592 else
19593 circ = NULL;
19594 if (circ != NULL) {
19595 xmlChar *strA = NULL, *strB = NULL;
19597 xmlSchemaPCustomErrExt(pctxt,
19598 XML_SCHEMAP_E_PROPS_CORRECT_6,
19599 WXS_BASIC_CAST circ, NULL,
19600 "The element declaration '%s' defines a circular "
19601 "substitution group to element declaration '%s'",
19602 xmlSchemaGetComponentQName(&strA, circ),
19603 xmlSchemaGetComponentQName(&strB, head),
19604 NULL);
19605 FREE_AND_NULL(strA)
19606 FREE_AND_NULL(strB)
19607 ret = XML_SCHEMAP_E_PROPS_CORRECT_6;
19610 * SPEC (4) "If there is a {substitution group affiliation},
19611 * the {type definition}
19612 * of the element declaration must be validly derived from the {type
19613 * definition} of the {substitution group affiliation}, given the value
19614 * of the {substitution group exclusions} of the {substitution group
19615 * affiliation}, as defined in Type Derivation OK (Complex) (�3.4.6)
19616 * (if the {type definition} is complex) or as defined in
19617 * Type Derivation OK (Simple) (�3.14.6) (if the {type definition} is
19618 * simple)."
19620 * NOTE: {substitution group exclusions} means the values of the
19621 * attribute "final".
19624 if (typeDef != WXS_ELEM_TYPEDEF(WXS_SUBST_HEAD(elemDecl))) {
19625 int set = 0;
19627 if (head->flags & XML_SCHEMAS_ELEM_FINAL_EXTENSION)
19628 set |= SUBSET_EXTENSION;
19629 if (head->flags & XML_SCHEMAS_ELEM_FINAL_RESTRICTION)
19630 set |= SUBSET_RESTRICTION;
19632 if (xmlSchemaCheckCOSDerivedOK(ACTXT_CAST pctxt, typeDef,
19633 WXS_ELEM_TYPEDEF(head), set) != 0) {
19634 xmlChar *strA = NULL, *strB = NULL, *strC = NULL;
19636 ret = XML_SCHEMAP_E_PROPS_CORRECT_4;
19637 xmlSchemaPCustomErrExt(pctxt,
19638 XML_SCHEMAP_E_PROPS_CORRECT_4,
19639 WXS_BASIC_CAST elemDecl, NULL,
19640 "The type definition '%s' was "
19641 "either rejected by the substitution group "
19642 "affiliation '%s', or not validly derived from its type "
19643 "definition '%s'",
19644 xmlSchemaGetComponentQName(&strA, typeDef),
19645 xmlSchemaGetComponentQName(&strB, head),
19646 xmlSchemaGetComponentQName(&strC, WXS_ELEM_TYPEDEF(head)));
19647 FREE_AND_NULL(strA)
19648 FREE_AND_NULL(strB)
19649 FREE_AND_NULL(strC)
19654 * SPEC (5) "If the {type definition} or {type definition}'s
19655 * {content type}
19656 * is or is derived from ID then there must not be a {value constraint}.
19657 * Note: The use of ID as a type definition for elements goes beyond
19658 * XML 1.0, and should be avoided if backwards compatibility is desired"
19660 if ((elemDecl->value != NULL) &&
19661 ((WXS_IS_SIMPLE(typeDef) &&
19662 xmlSchemaIsDerivedFromBuiltInType(typeDef, XML_SCHEMAS_ID)) ||
19663 (WXS_IS_COMPLEX(typeDef) &&
19664 WXS_HAS_SIMPLE_CONTENT(typeDef) &&
19665 xmlSchemaIsDerivedFromBuiltInType(typeDef->contentTypeDef,
19666 XML_SCHEMAS_ID)))) {
19668 ret = XML_SCHEMAP_E_PROPS_CORRECT_5;
19669 xmlSchemaPCustomErr(pctxt,
19670 XML_SCHEMAP_E_PROPS_CORRECT_5,
19671 WXS_BASIC_CAST elemDecl, NULL,
19672 "The type definition (or type definition's content type) is or "
19673 "is derived from ID; value constraints are not allowed in "
19674 "conjunction with such a type definition", NULL);
19675 } else if (elemDecl->value != NULL) {
19676 int vcret;
19677 xmlNodePtr node = NULL;
19680 * SPEC (2) "If there is a {value constraint}, the canonical lexical
19681 * representation of its value must be �valid� with respect to the
19682 * {type definition} as defined in Element Default Valid (Immediate)
19683 * (�3.3.6)."
19685 if (typeDef == NULL) {
19686 xmlSchemaPErr(pctxt, elemDecl->node,
19687 XML_SCHEMAP_INTERNAL,
19688 "Internal error: xmlSchemaCheckElemPropsCorrect, "
19689 "type is missing... skipping validation of "
19690 "the value constraint", NULL, NULL);
19691 return (-1);
19693 if (elemDecl->node != NULL) {
19694 if (elemDecl->flags & XML_SCHEMAS_ELEM_FIXED)
19695 node = (xmlNodePtr) xmlHasProp(elemDecl->node,
19696 BAD_CAST "fixed");
19697 else
19698 node = (xmlNodePtr) xmlHasProp(elemDecl->node,
19699 BAD_CAST "default");
19701 vcret = xmlSchemaParseCheckCOSValidDefault(pctxt, node,
19702 typeDef, elemDecl->value, &(elemDecl->defVal));
19703 if (vcret != 0) {
19704 if (vcret < 0) {
19705 PERROR_INT("xmlSchemaElemCheckValConstr",
19706 "failed to validate the value constraint of an "
19707 "element declaration");
19708 return (-1);
19710 return (vcret);
19714 return (ret);
19718 * xmlSchemaCheckElemSubstGroup:
19719 * @ctxt: a schema parser context
19720 * @decl: the element declaration
19721 * @name: the name of the attribute
19723 * Schema Component Constraint:
19724 * Substitution Group (cos-equiv-class)
19726 * In Libxml2 the subst. groups will be precomputed, in terms of that
19727 * a list will be built for each subst. group head, holding all direct
19728 * referents to this head.
19729 * NOTE that this function needs:
19730 * 1. circular subst. groups to be checked beforehand
19731 * 2. the declaration's type to be derived from the head's type
19733 * STATUS:
19736 static void
19737 xmlSchemaCheckElemSubstGroup(xmlSchemaParserCtxtPtr ctxt,
19738 xmlSchemaElementPtr elemDecl)
19740 if ((WXS_SUBST_HEAD(elemDecl) == NULL) ||
19741 /* SPEC (1) "Its {abstract} is false." */
19742 (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT))
19743 return;
19745 xmlSchemaElementPtr head;
19746 xmlSchemaTypePtr headType, type;
19747 int set, methSet;
19749 * SPEC (2) "It is validly substitutable for HEAD subject to HEAD's
19750 * {disallowed substitutions} as the blocking constraint, as defined in
19751 * Substitution Group OK (Transitive) (�3.3.6)."
19753 for (head = WXS_SUBST_HEAD(elemDecl); head != NULL;
19754 head = WXS_SUBST_HEAD(head)) {
19755 set = 0;
19756 methSet = 0;
19758 * The blocking constraints.
19760 if (head->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION)
19761 continue;
19762 headType = head->subtypes;
19763 type = elemDecl->subtypes;
19764 if (headType == type)
19765 goto add_member;
19766 if (head->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION)
19767 set |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
19768 if (head->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION)
19769 set |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
19771 * SPEC: Substitution Group OK (Transitive) (2.3)
19772 * "The set of all {derivation method}s involved in the
19773 * derivation of D's {type definition} from C's {type definition}
19774 * does not intersect with the union of the blocking constraint,
19775 * C's {prohibited substitutions} (if C is complex, otherwise the
19776 * empty set) and the {prohibited substitutions} (respectively the
19777 * empty set) of any intermediate {type definition}s in the
19778 * derivation of D's {type definition} from C's {type definition}."
19781 * OPTIMIZE TODO: Optimize this a bit, since, if traversing the
19782 * subst.head axis, the methSet does not need to be computed for
19783 * the full depth over and over.
19786 * The set of all {derivation method}s involved in the derivation
19788 while ((type != NULL) && (type != headType)) {
19789 if ((WXS_IS_EXTENSION(type)) &&
19790 ((methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
19791 methSet |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
19793 if (WXS_IS_RESTRICTION(type) &&
19794 ((methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
19795 methSet |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
19797 type = type->baseType;
19800 * The {prohibited substitutions} of all intermediate types +
19801 * the head's type.
19803 type = elemDecl->subtypes->baseType;
19804 while (type != NULL) {
19805 if (WXS_IS_COMPLEX(type)) {
19806 if ((type->flags &
19807 XML_SCHEMAS_TYPE_BLOCK_EXTENSION) &&
19808 ((set & XML_SCHEMAS_TYPE_BLOCK_EXTENSION) == 0))
19809 set |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
19810 if ((type->flags &
19811 XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) &&
19812 ((set & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
19813 set |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
19814 } else
19815 break;
19816 if (type == headType)
19817 break;
19818 type = type->baseType;
19820 if ((set != 0) &&
19821 (((set & XML_SCHEMAS_TYPE_BLOCK_EXTENSION) &&
19822 (methSet & XML_SCHEMAS_TYPE_BLOCK_EXTENSION)) ||
19823 ((set & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) &&
19824 (methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION)))) {
19825 continue;
19827 add_member:
19828 xmlSchemaAddElementSubstitutionMember(ctxt, head, elemDecl);
19829 if ((head->flags & XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) == 0)
19830 head->flags |= XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD;
19835 #ifdef WXS_ELEM_DECL_CONS_ENABLED /* enable when finished */
19837 * xmlSchemaCheckElementDeclComponent
19838 * @pctxt: the schema parser context
19839 * @ctxtComponent: the context component (an element declaration)
19840 * @ctxtParticle: the first particle of the context component
19841 * @searchParticle: the element declaration particle to be analysed
19843 * Schema Component Constraint: Element Declarations Consistent
19845 static int
19846 xmlSchemaCheckElementDeclConsistent(xmlSchemaParserCtxtPtr pctxt,
19847 xmlSchemaBasicItemPtr ctxtComponent,
19848 xmlSchemaParticlePtr ctxtParticle,
19849 xmlSchemaParticlePtr searchParticle,
19850 xmlSchemaParticlePtr curParticle,
19851 int search)
19853 return(0);
19855 int ret = 0;
19856 xmlSchemaParticlePtr cur = curParticle;
19857 if (curParticle == NULL) {
19858 return(0);
19860 if (WXS_PARTICLE_TERM(curParticle) == NULL) {
19862 * Just return in this case. A missing "term" of the particle
19863 * might arise due to an invalid "term" component.
19865 return(0);
19867 while (cur != NULL) {
19868 switch (WXS_PARTICLE_TERM(cur)->type) {
19869 case XML_SCHEMA_TYPE_ANY:
19870 break;
19871 case XML_SCHEMA_TYPE_ELEMENT:
19872 if (search == 0) {
19873 ret = xmlSchemaCheckElementDeclConsistent(pctxt,
19874 ctxtComponent, ctxtParticle, cur, ctxtParticle, 1);
19875 if (ret != 0)
19876 return(ret);
19877 } else {
19878 xmlSchemaElementPtr elem =
19879 WXS_ELEM_CAST(WXS_PARTICLE_TERM(cur));
19881 * SPEC Element Declarations Consistent:
19882 * "If the {particles} contains, either directly,
19883 * indirectly (that is, within the {particles} of a
19884 * contained model group, recursively) or �implicitly�
19885 * two or more element declaration particles with
19886 * the same {name} and {target namespace}, then
19887 * all their type definitions must be the same
19888 * top-level definition [...]"
19890 if (xmlStrEqual(WXS_PARTICLE_TERM_AS_ELEM(cur)->name,
19891 WXS_PARTICLE_TERM_AS_ELEM(searchParticle)->name) &&
19892 xmlStrEqual(WXS_PARTICLE_TERM_AS_ELEM(cur)->targetNamespace,
19893 WXS_PARTICLE_TERM_AS_ELEM(searchParticle)->targetNamespace))
19895 xmlChar *strA = NULL, *strB = NULL;
19897 xmlSchemaCustomErr(ACTXT_CAST pctxt,
19898 /* TODO: error code */
19899 XML_SCHEMAP_COS_NONAMBIG,
19900 WXS_ITEM_NODE(cur), NULL,
19901 "In the content model of %s, there are multiple "
19902 "element declarations for '%s' with different "
19903 "type definitions",
19904 xmlSchemaGetComponentDesignation(&strA,
19905 ctxtComponent),
19906 xmlSchemaFormatQName(&strB,
19907 WXS_PARTICLE_TERM_AS_ELEM(cur)->targetNamespace,
19908 WXS_PARTICLE_TERM_AS_ELEM(cur)->name));
19909 FREE_AND_NULL(strA);
19910 FREE_AND_NULL(strB);
19911 return(XML_SCHEMAP_COS_NONAMBIG);
19914 break;
19915 case XML_SCHEMA_TYPE_SEQUENCE: {
19916 break;
19918 case XML_SCHEMA_TYPE_CHOICE:{
19920 xmlSchemaTreeItemPtr sub;
19922 sub = WXS_PARTICLE_TERM(particle)->children; (xmlSchemaParticlePtr)
19923 while (sub != NULL) {
19924 ret = xmlSchemaCheckElementDeclConsistent(pctxt, ctxtComponent,
19925 ctxtParticle, ctxtElem);
19926 if (ret != 0)
19927 return(ret);
19928 sub = sub->next;
19931 break;
19933 case XML_SCHEMA_TYPE_ALL:
19934 break;
19935 case XML_SCHEMA_TYPE_GROUP:
19936 break;
19937 default:
19938 xmlSchemaInternalErr2(ACTXT_CAST pctxt,
19939 "xmlSchemaCheckElementDeclConsistent",
19940 "found unexpected term of type '%s' in content model",
19941 WXS_ITEM_TYPE_NAME(WXS_PARTICLE_TERM(cur)), NULL);
19942 return(-1);
19944 cur = (xmlSchemaParticlePtr) cur->next;
19947 exit:
19948 return(ret);
19950 #endif
19953 * xmlSchemaCheckElementDeclComponent
19954 * @item: an schema element declaration/particle
19955 * @ctxt: a schema parser context
19956 * @name: the name of the attribute
19958 * Validates the value constraints of an element declaration.
19959 * Adds substitution group members.
19961 static void
19962 xmlSchemaCheckElementDeclComponent(xmlSchemaElementPtr elemDecl,
19963 xmlSchemaParserCtxtPtr ctxt)
19965 if (elemDecl == NULL)
19966 return;
19967 if (elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_CHECKED)
19968 return;
19969 elemDecl->flags |= XML_SCHEMAS_ELEM_INTERNAL_CHECKED;
19970 if (xmlSchemaCheckElemPropsCorrect(ctxt, elemDecl) == 0) {
19972 * Adds substitution group members.
19974 xmlSchemaCheckElemSubstGroup(ctxt, elemDecl);
19979 * xmlSchemaResolveModelGroupParticleReferences:
19980 * @particle: a particle component
19981 * @ctxt: a parser context
19983 * Resolves references of a model group's {particles} to
19984 * model group definitions and to element declarations.
19986 static void
19987 xmlSchemaResolveModelGroupParticleReferences(
19988 xmlSchemaParserCtxtPtr ctxt,
19989 xmlSchemaModelGroupPtr mg)
19991 xmlSchemaParticlePtr particle = WXS_MODELGROUP_PARTICLE(mg);
19992 xmlSchemaQNameRefPtr ref;
19993 xmlSchemaBasicItemPtr refItem;
19996 * URGENT TODO: Test this.
19998 while (particle != NULL) {
19999 if ((WXS_PARTICLE_TERM(particle) == NULL) ||
20000 ((WXS_PARTICLE_TERM(particle))->type !=
20001 XML_SCHEMA_EXTRA_QNAMEREF))
20003 goto next_particle;
20005 ref = WXS_QNAME_CAST WXS_PARTICLE_TERM(particle);
20007 * Resolve the reference.
20008 * NULL the {term} by default.
20010 particle->children = NULL;
20012 refItem = xmlSchemaGetNamedComponent(ctxt->schema,
20013 ref->itemType, ref->name, ref->targetNamespace);
20014 if (refItem == NULL) {
20015 xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
20016 NULL, WXS_ITEM_NODE(particle), "ref", ref->name,
20017 ref->targetNamespace, ref->itemType, NULL);
20018 /* TODO: remove the particle. */
20019 goto next_particle;
20021 if (refItem->type == XML_SCHEMA_TYPE_GROUP) {
20022 if (WXS_MODELGROUPDEF_MODEL(refItem) == NULL)
20023 /* TODO: remove the particle. */
20024 goto next_particle;
20026 * NOTE that we will assign the model group definition
20027 * itself to the "term" of the particle. This will ease
20028 * the check for circular model group definitions. After
20029 * that the "term" will be assigned the model group of the
20030 * model group definition.
20032 if ((WXS_MODELGROUPDEF_MODEL(refItem))->type ==
20033 XML_SCHEMA_TYPE_ALL) {
20035 * SPEC cos-all-limited (1)
20036 * SPEC cos-all-limited (1.2)
20037 * "It appears only as the value of one or both of the
20038 * following properties:"
20039 * (1.1) "the {model group} property of a model group
20040 * definition."
20041 * (1.2) "the {term} property of a particle [... of] the "
20042 * {content type} of a complex type definition."
20044 xmlSchemaCustomErr(ACTXT_CAST ctxt,
20045 /* TODO: error code */
20046 XML_SCHEMAP_COS_ALL_LIMITED,
20047 WXS_ITEM_NODE(particle), NULL,
20048 "A model group definition is referenced, but "
20049 "it contains an 'all' model group, which "
20050 "cannot be contained by model groups",
20051 NULL, NULL);
20052 /* TODO: remove the particle. */
20053 goto next_particle;
20055 particle->children = (xmlSchemaTreeItemPtr) refItem;
20056 } else {
20058 * TODO: Are referenced element declarations the only
20059 * other components we expect here?
20061 particle->children = (xmlSchemaTreeItemPtr) refItem;
20063 next_particle:
20064 particle = WXS_PTC_CAST particle->next;
20068 static int
20069 xmlSchemaAreValuesEqual(xmlSchemaValPtr x,
20070 xmlSchemaValPtr y)
20072 xmlSchemaTypePtr tx, ty, ptx, pty;
20073 int ret;
20075 while (x != NULL) {
20076 /* Same types. */
20077 tx = xmlSchemaGetBuiltInType(xmlSchemaGetValType(x));
20078 ty = xmlSchemaGetBuiltInType(xmlSchemaGetValType(y));
20079 ptx = xmlSchemaGetPrimitiveType(tx);
20080 pty = xmlSchemaGetPrimitiveType(ty);
20082 * (1) if a datatype T' is �derived� by �restriction� from an
20083 * atomic datatype T then the �value space� of T' is a subset of
20084 * the �value space� of T. */
20086 * (2) if datatypes T' and T'' are �derived� by �restriction�
20087 * from a common atomic ancestor T then the �value space�s of T'
20088 * and T'' may overlap.
20090 if (ptx != pty)
20091 return(0);
20093 * We assume computed values to be normalized, so do a fast
20094 * string comparison for string based types.
20096 if ((ptx->builtInType == XML_SCHEMAS_STRING) ||
20097 WXS_IS_ANY_SIMPLE_TYPE(ptx)) {
20098 if (! xmlStrEqual(
20099 xmlSchemaValueGetAsString(x),
20100 xmlSchemaValueGetAsString(y)))
20101 return (0);
20102 } else {
20103 ret = xmlSchemaCompareValuesWhtsp(
20104 x, XML_SCHEMA_WHITESPACE_PRESERVE,
20105 y, XML_SCHEMA_WHITESPACE_PRESERVE);
20106 if (ret == -2)
20107 return(-1);
20108 if (ret != 0)
20109 return(0);
20112 * Lists.
20114 x = xmlSchemaValueGetNext(x);
20115 if (x != NULL) {
20116 y = xmlSchemaValueGetNext(y);
20117 if (y == NULL)
20118 return (0);
20119 } else if (xmlSchemaValueGetNext(y) != NULL)
20120 return (0);
20121 else
20122 return (1);
20124 return (0);
20128 * xmlSchemaResolveAttrUseReferences:
20129 * @item: an attribute use
20130 * @ctxt: a parser context
20132 * Resolves the referenced attribute declaration.
20134 static int
20135 xmlSchemaResolveAttrUseReferences(xmlSchemaAttributeUsePtr ause,
20136 xmlSchemaParserCtxtPtr ctxt)
20138 if ((ctxt == NULL) || (ause == NULL))
20139 return(-1);
20140 if ((ause->attrDecl == NULL) ||
20141 (ause->attrDecl->type != XML_SCHEMA_EXTRA_QNAMEREF))
20142 return(0);
20145 xmlSchemaQNameRefPtr ref = WXS_QNAME_CAST ause->attrDecl;
20148 * TODO: Evaluate, what errors could occur if the declaration is not
20149 * found.
20151 ause->attrDecl = xmlSchemaGetAttributeDecl(ctxt->schema,
20152 ref->name, ref->targetNamespace);
20153 if (ause->attrDecl == NULL) {
20154 xmlSchemaPResCompAttrErr(ctxt,
20155 XML_SCHEMAP_SRC_RESOLVE,
20156 WXS_BASIC_CAST ause, ause->node,
20157 "ref", ref->name, ref->targetNamespace,
20158 XML_SCHEMA_TYPE_ATTRIBUTE, NULL);
20159 return(ctxt->err);;
20162 return(0);
20166 * xmlSchemaCheckAttrUsePropsCorrect:
20167 * @ctxt: a parser context
20168 * @use: an attribute use
20170 * Schema Component Constraint:
20171 * Attribute Use Correct (au-props-correct)
20174 static int
20175 xmlSchemaCheckAttrUsePropsCorrect(xmlSchemaParserCtxtPtr ctxt,
20176 xmlSchemaAttributeUsePtr use)
20178 if ((ctxt == NULL) || (use == NULL))
20179 return(-1);
20180 if ((use->defValue == NULL) || (WXS_ATTRUSE_DECL(use) == NULL) ||
20181 ((WXS_ATTRUSE_DECL(use))->type != XML_SCHEMA_TYPE_ATTRIBUTE))
20182 return(0);
20185 * SPEC au-props-correct (1)
20186 * "The values of the properties of an attribute use must be as
20187 * described in the property tableau in The Attribute Use Schema
20188 * Component (�3.5.1), modulo the impact of Missing
20189 * Sub-components (�5.3)."
20192 if (((WXS_ATTRUSE_DECL(use))->defValue != NULL) &&
20193 ((WXS_ATTRUSE_DECL(use))->flags & XML_SCHEMAS_ATTR_FIXED) &&
20194 ((use->flags & XML_SCHEMA_ATTR_USE_FIXED) == 0))
20196 xmlSchemaPCustomErr(ctxt,
20197 XML_SCHEMAP_AU_PROPS_CORRECT_2,
20198 WXS_BASIC_CAST use, NULL,
20199 "The attribute declaration has a 'fixed' value constraint "
20200 ", thus the attribute use must also have a 'fixed' value "
20201 "constraint",
20202 NULL);
20203 return(ctxt->err);
20206 * Compute and check the value constraint's value.
20208 if ((use->defVal != NULL) && (WXS_ATTRUSE_TYPEDEF(use) != NULL)) {
20209 int ret;
20211 * TODO: The spec seems to be missing a check of the
20212 * value constraint of the attribute use. We will do it here.
20215 * SPEC a-props-correct (3)
20217 if (xmlSchemaIsDerivedFromBuiltInType(
20218 WXS_ATTRUSE_TYPEDEF(use), XML_SCHEMAS_ID))
20220 xmlSchemaCustomErr(ACTXT_CAST ctxt,
20221 XML_SCHEMAP_AU_PROPS_CORRECT,
20222 NULL, WXS_BASIC_CAST use,
20223 "Value constraints are not allowed if the type definition "
20224 "is or is derived from xs:ID",
20225 NULL, NULL);
20226 return(ctxt->err);
20229 ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST ctxt,
20230 use->node, WXS_ATTRUSE_TYPEDEF(use),
20231 use->defValue, &(use->defVal),
20232 1, 1, 0);
20233 if (ret != 0) {
20234 if (ret < 0) {
20235 PERROR_INT2("xmlSchemaCheckAttrUsePropsCorrect",
20236 "calling xmlSchemaVCheckCVCSimpleType()");
20237 return(-1);
20239 xmlSchemaCustomErr(ACTXT_CAST ctxt,
20240 XML_SCHEMAP_AU_PROPS_CORRECT,
20241 NULL, WXS_BASIC_CAST use,
20242 "The value of the value constraint is not valid",
20243 NULL, NULL);
20244 return(ctxt->err);
20248 * SPEC au-props-correct (2)
20249 * "If the {attribute declaration} has a fixed
20250 * {value constraint}, then if the attribute use itself has a
20251 * {value constraint}, it must also be fixed and its value must match
20252 * that of the {attribute declaration}'s {value constraint}."
20254 if (((WXS_ATTRUSE_DECL(use))->defVal != NULL) &&
20255 (((WXS_ATTRUSE_DECL(use))->flags & XML_SCHEMA_ATTR_USE_FIXED) == 0))
20257 if (! xmlSchemaAreValuesEqual(use->defVal,
20258 (WXS_ATTRUSE_DECL(use))->defVal))
20260 xmlSchemaPCustomErr(ctxt,
20261 XML_SCHEMAP_AU_PROPS_CORRECT_2,
20262 WXS_BASIC_CAST use, NULL,
20263 "The 'fixed' value constraint of the attribute use "
20264 "must match the attribute declaration's value "
20265 "constraint '%s'",
20266 (WXS_ATTRUSE_DECL(use))->defValue);
20268 return(ctxt->err);
20270 return(0);
20277 * xmlSchemaResolveAttrTypeReferences:
20278 * @item: an attribute declaration
20279 * @ctxt: a parser context
20281 * Resolves the referenced type definition component.
20283 static int
20284 xmlSchemaResolveAttrTypeReferences(xmlSchemaAttributePtr item,
20285 xmlSchemaParserCtxtPtr ctxt)
20288 * The simple type definition corresponding to the <simpleType> element
20289 * information item in the [children], if present, otherwise the simple
20290 * type definition �resolved� to by the �actual value� of the type
20291 * [attribute], if present, otherwise the �simple ur-type definition�.
20293 if (item->flags & XML_SCHEMAS_ATTR_INTERNAL_RESOLVED)
20294 return(0);
20295 item->flags |= XML_SCHEMAS_ATTR_INTERNAL_RESOLVED;
20296 if (item->subtypes != NULL)
20297 return(0);
20298 if (item->typeName != NULL) {
20299 xmlSchemaTypePtr type;
20301 type = xmlSchemaGetType(ctxt->schema, item->typeName,
20302 item->typeNs);
20303 if ((type == NULL) || (! WXS_IS_SIMPLE(type))) {
20304 xmlSchemaPResCompAttrErr(ctxt,
20305 XML_SCHEMAP_SRC_RESOLVE,
20306 WXS_BASIC_CAST item, item->node,
20307 "type", item->typeName, item->typeNs,
20308 XML_SCHEMA_TYPE_SIMPLE, NULL);
20309 return(ctxt->err);
20310 } else
20311 item->subtypes = type;
20313 } else {
20315 * The type defaults to the xs:anySimpleType.
20317 item->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
20319 return(0);
20323 * xmlSchemaResolveIDCKeyReferences:
20324 * @idc: the identity-constraint definition
20325 * @ctxt: the schema parser context
20326 * @name: the attribute name
20328 * Resolve keyRef references to key/unique IDCs.
20329 * Schema Component Constraint:
20330 * Identity-constraint Definition Properties Correct (c-props-correct)
20332 static int
20333 xmlSchemaResolveIDCKeyReferences(xmlSchemaIDCPtr idc,
20334 xmlSchemaParserCtxtPtr pctxt)
20336 if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF)
20337 return(0);
20338 if (idc->ref->name != NULL) {
20339 idc->ref->item = (xmlSchemaBasicItemPtr)
20340 xmlSchemaGetIDC(pctxt->schema, idc->ref->name,
20341 idc->ref->targetNamespace);
20342 if (idc->ref->item == NULL) {
20344 * TODO: It is actually not an error to fail to resolve
20345 * at this stage. BUT we need to be that strict!
20347 xmlSchemaPResCompAttrErr(pctxt,
20348 XML_SCHEMAP_SRC_RESOLVE,
20349 WXS_BASIC_CAST idc, idc->node,
20350 "refer", idc->ref->name,
20351 idc->ref->targetNamespace,
20352 XML_SCHEMA_TYPE_IDC_KEY, NULL);
20353 return(pctxt->err);
20354 } else if (idc->ref->item->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
20356 * SPEC c-props-correct (1)
20358 xmlSchemaCustomErr(ACTXT_CAST pctxt,
20359 XML_SCHEMAP_C_PROPS_CORRECT,
20360 NULL, WXS_BASIC_CAST idc,
20361 "The keyref references a keyref",
20362 NULL, NULL);
20363 idc->ref->item = NULL;
20364 return(pctxt->err);
20365 } else {
20366 if (idc->nbFields !=
20367 ((xmlSchemaIDCPtr) idc->ref->item)->nbFields) {
20368 xmlChar *str = NULL;
20369 xmlSchemaIDCPtr refer;
20371 refer = (xmlSchemaIDCPtr) idc->ref->item;
20373 * SPEC c-props-correct(2)
20374 * "If the {identity-constraint category} is keyref,
20375 * the cardinality of the {fields} must equal that of
20376 * the {fields} of the {referenced key}.
20378 xmlSchemaCustomErr(ACTXT_CAST pctxt,
20379 XML_SCHEMAP_C_PROPS_CORRECT,
20380 NULL, WXS_BASIC_CAST idc,
20381 "The cardinality of the keyref differs from the "
20382 "cardinality of the referenced key/unique '%s'",
20383 xmlSchemaFormatQName(&str, refer->targetNamespace,
20384 refer->name),
20385 NULL);
20386 FREE_AND_NULL(str)
20387 return(pctxt->err);
20391 return(0);
20394 static int
20395 xmlSchemaResolveAttrUseProhibReferences(xmlSchemaAttributeUseProhibPtr prohib,
20396 xmlSchemaParserCtxtPtr pctxt)
20398 if (xmlSchemaGetAttributeDecl(pctxt->schema, prohib->name,
20399 prohib->targetNamespace) == NULL) {
20401 xmlSchemaPResCompAttrErr(pctxt,
20402 XML_SCHEMAP_SRC_RESOLVE,
20403 NULL, prohib->node,
20404 "ref", prohib->name, prohib->targetNamespace,
20405 XML_SCHEMA_TYPE_ATTRIBUTE, NULL);
20406 return(XML_SCHEMAP_SRC_RESOLVE);
20408 return(0);
20411 #define WXS_REDEFINED_TYPE(c) \
20412 (((xmlSchemaTypePtr) item)->flags & XML_SCHEMAS_TYPE_REDEFINED)
20414 #define WXS_REDEFINED_MODEL_GROUP_DEF(c) \
20415 (((xmlSchemaModelGroupDefPtr) item)->flags & XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED)
20417 #define WXS_REDEFINED_ATTR_GROUP(c) \
20418 (((xmlSchemaAttributeGroupPtr) item)->flags & XML_SCHEMAS_ATTRGROUP_REDEFINED)
20420 static int
20421 xmlSchemaCheckSRCRedefineFirst(xmlSchemaParserCtxtPtr pctxt)
20423 int err = 0;
20424 xmlSchemaRedefPtr redef = WXS_CONSTRUCTOR(pctxt)->redefs;
20425 xmlSchemaBasicItemPtr prev, item;
20426 int wasRedefined;
20428 if (redef == NULL)
20429 return(0);
20431 do {
20432 item = redef->item;
20434 * First try to locate the redefined component in the
20435 * schema graph starting with the redefined schema.
20436 * NOTE: According to this schema bug entry:
20437 * http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005OctDec/0019.html
20438 * it's not clear if the referenced component needs to originate
20439 * from the <redefine>d schema _document_ or the schema; the latter
20440 * would include all imported and included sub-schemas of the
20441 * <redefine>d schema. Currenlty we latter approach is used.
20442 * SUPPLEMENT: It seems that the WG moves towards the latter
20443 * approach, so we are doing it right.
20446 prev = xmlSchemaFindRedefCompInGraph(
20447 redef->targetBucket, item->type,
20448 redef->refName, redef->refTargetNs);
20449 if (prev == NULL) {
20450 xmlChar *str = NULL;
20451 xmlNodePtr node;
20454 * SPEC src-redefine:
20455 * (6.2.1) "The �actual value� of its own name attribute plus
20456 * target namespace must successfully �resolve� to a model
20457 * group definition in I."
20458 * (7.2.1) "The �actual value� of its own name attribute plus
20459 * target namespace must successfully �resolve� to an attribute
20460 * group definition in I."
20463 * Note that, if we are redefining with the use of references
20464 * to components, the spec assumes the src-resolve to be used;
20465 * but this won't assure that we search only *inside* the
20466 * redefined schema.
20468 if (redef->reference)
20469 node = WXS_ITEM_NODE(redef->reference);
20470 else
20471 node = WXS_ITEM_NODE(item);
20472 xmlSchemaCustomErr(ACTXT_CAST pctxt,
20474 * TODO: error code.
20475 * Probably XML_SCHEMAP_SRC_RESOLVE, if this is using the
20476 * reference kind.
20478 XML_SCHEMAP_SRC_REDEFINE, node, NULL,
20479 "The %s '%s' to be redefined could not be found in "
20480 "the redefined schema",
20481 WXS_ITEM_TYPE_NAME(item),
20482 xmlSchemaFormatQName(&str, redef->refTargetNs,
20483 redef->refName));
20484 FREE_AND_NULL(str);
20485 err = pctxt->err;
20486 redef = redef->next;
20487 continue;
20490 * TODO: Obtaining and setting the redefinition state is really
20491 * clumsy.
20493 wasRedefined = 0;
20494 switch (item->type) {
20495 case XML_SCHEMA_TYPE_COMPLEX:
20496 case XML_SCHEMA_TYPE_SIMPLE:
20497 if ((WXS_TYPE_CAST prev)->flags &
20498 XML_SCHEMAS_TYPE_REDEFINED)
20500 wasRedefined = 1;
20501 break;
20503 /* Mark it as redefined. */
20504 (WXS_TYPE_CAST prev)->flags |= XML_SCHEMAS_TYPE_REDEFINED;
20506 * Assign the redefined type to the
20507 * base type of the redefining type.
20508 * TODO: How
20510 ((xmlSchemaTypePtr) item)->baseType =
20511 (xmlSchemaTypePtr) prev;
20512 break;
20513 case XML_SCHEMA_TYPE_GROUP:
20514 if ((WXS_MODEL_GROUPDEF_CAST prev)->flags &
20515 XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED)
20517 wasRedefined = 1;
20518 break;
20520 /* Mark it as redefined. */
20521 (WXS_MODEL_GROUPDEF_CAST prev)->flags |=
20522 XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED;
20523 if (redef->reference != NULL) {
20525 * Overwrite the QName-reference with the
20526 * referenced model group def.
20528 (WXS_PTC_CAST redef->reference)->children =
20529 WXS_TREE_CAST prev;
20531 redef->target = prev;
20532 break;
20533 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20534 if ((WXS_ATTR_GROUP_CAST prev)->flags &
20535 XML_SCHEMAS_ATTRGROUP_REDEFINED)
20537 wasRedefined = 1;
20538 break;
20540 (WXS_ATTR_GROUP_CAST prev)->flags |=
20541 XML_SCHEMAS_ATTRGROUP_REDEFINED;
20542 if (redef->reference != NULL) {
20544 * Assign the redefined attribute group to the
20545 * QName-reference component.
20546 * This is the easy case, since we will just
20547 * expand the redefined group.
20549 (WXS_QNAME_CAST redef->reference)->item = prev;
20550 redef->target = NULL;
20551 } else {
20553 * This is the complicated case: we need
20554 * to apply src-redefine (7.2.2) at a later
20555 * stage, i.e. when attribute group references
20556 * have beed expanded and simple types have
20557 * beed fixed.
20559 redef->target = prev;
20561 break;
20562 default:
20563 PERROR_INT("xmlSchemaResolveRedefReferences",
20564 "Unexpected redefined component type");
20565 return(-1);
20567 if (wasRedefined) {
20568 xmlChar *str = NULL;
20569 xmlNodePtr node;
20571 if (redef->reference)
20572 node = WXS_ITEM_NODE(redef->reference);
20573 else
20574 node = WXS_ITEM_NODE(redef->item);
20576 xmlSchemaCustomErr(ACTXT_CAST pctxt,
20577 /* TODO: error code. */
20578 XML_SCHEMAP_SRC_REDEFINE,
20579 node, NULL,
20580 "The referenced %s was already redefined. Multiple "
20581 "redefinition of the same component is not supported",
20582 xmlSchemaGetComponentDesignation(&str, prev),
20583 NULL);
20584 FREE_AND_NULL(str)
20585 err = pctxt->err;
20586 redef = redef->next;
20587 continue;
20589 redef = redef->next;
20590 } while (redef != NULL);
20592 return(err);
20595 static int
20596 xmlSchemaCheckSRCRedefineSecond(xmlSchemaParserCtxtPtr pctxt)
20598 int err = 0;
20599 xmlSchemaRedefPtr redef = WXS_CONSTRUCTOR(pctxt)->redefs;
20600 xmlSchemaBasicItemPtr item;
20602 if (redef == NULL)
20603 return(0);
20605 do {
20606 if (redef->target == NULL) {
20607 redef = redef->next;
20608 continue;
20610 item = redef->item;
20612 switch (item->type) {
20613 case XML_SCHEMA_TYPE_SIMPLE:
20614 case XML_SCHEMA_TYPE_COMPLEX:
20616 * Since the spec wants the {name} of the redefined
20617 * type to be 'absent', we'll NULL it.
20619 (WXS_TYPE_CAST redef->target)->name = NULL;
20622 * TODO: Seems like there's nothing more to do. The normal
20623 * inheritance mechanism is used. But not 100% sure.
20625 break;
20626 case XML_SCHEMA_TYPE_GROUP:
20628 * URGENT TODO:
20629 * SPEC src-redefine:
20630 * (6.2.2) "The {model group} of the model group definition
20631 * which corresponds to it per XML Representation of Model
20632 * Group Definition Schema Components (�3.7.2) must be a
20633 * �valid restriction� of the {model group} of that model
20634 * group definition in I, as defined in Particle Valid
20635 * (Restriction) (�3.9.6)."
20637 break;
20638 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20640 * SPEC src-redefine:
20641 * (7.2.2) "The {attribute uses} and {attribute wildcard} of
20642 * the attribute group definition which corresponds to it
20643 * per XML Representation of Attribute Group Definition Schema
20644 * Components (�3.6.2) must be �valid restrictions� of the
20645 * {attribute uses} and {attribute wildcard} of that attribute
20646 * group definition in I, as defined in clause 2, clause 3 and
20647 * clause 4 of Derivation Valid (Restriction, Complex)
20648 * (�3.4.6) (where references to the base type definition are
20649 * understood as references to the attribute group definition
20650 * in I)."
20652 err = xmlSchemaCheckDerivationOKRestriction2to4(pctxt,
20653 XML_SCHEMA_ACTION_REDEFINE,
20654 item, redef->target,
20655 (WXS_ATTR_GROUP_CAST item)->attrUses,
20656 (WXS_ATTR_GROUP_CAST redef->target)->attrUses,
20657 (WXS_ATTR_GROUP_CAST item)->attributeWildcard,
20658 (WXS_ATTR_GROUP_CAST redef->target)->attributeWildcard);
20659 if (err == -1)
20660 return(-1);
20661 break;
20662 default:
20663 break;
20665 redef = redef->next;
20666 } while (redef != NULL);
20667 return(0);
20671 static int
20672 xmlSchemaAddComponents(xmlSchemaParserCtxtPtr pctxt,
20673 xmlSchemaBucketPtr bucket)
20675 xmlSchemaBasicItemPtr item;
20676 int err;
20677 xmlHashTablePtr *table;
20678 const xmlChar *name;
20679 int i;
20681 #define WXS_GET_GLOBAL_HASH(c, slot) { \
20682 if (WXS_IS_BUCKET_IMPMAIN((c)->type)) \
20683 table = &(WXS_IMPBUCKET((c))->schema->slot); \
20684 else \
20685 table = &(WXS_INCBUCKET((c))->ownerImport->schema->slot); }
20688 * Add global components to the schema's hash tables.
20689 * This is the place where duplicate components will be
20690 * detected.
20691 * TODO: I think normally we should support imports of the
20692 * same namespace from multiple locations. We don't do currently,
20693 * but if we do then according to:
20694 * http://www.w3.org/Bugs/Public/show_bug.cgi?id=2224
20695 * we would need, if imported directly, to import redefined
20696 * components as well to be able to catch clashing components.
20697 * (I hope I'll still know what this means after some months :-()
20699 if (bucket == NULL)
20700 return(-1);
20701 if (bucket->flags & XML_SCHEMA_BUCKET_COMPS_ADDED)
20702 return(0);
20703 bucket->flags |= XML_SCHEMA_BUCKET_COMPS_ADDED;
20705 for (i = 0; i < bucket->globals->nbItems; i++) {
20706 item = bucket->globals->items[i];
20707 table = NULL;
20708 switch (item->type) {
20709 case XML_SCHEMA_TYPE_COMPLEX:
20710 case XML_SCHEMA_TYPE_SIMPLE:
20711 if (WXS_REDEFINED_TYPE(item))
20712 continue;
20713 name = (WXS_TYPE_CAST item)->name;
20714 WXS_GET_GLOBAL_HASH(bucket, typeDecl)
20715 break;
20716 case XML_SCHEMA_TYPE_ELEMENT:
20717 name = (WXS_ELEM_CAST item)->name;
20718 WXS_GET_GLOBAL_HASH(bucket, elemDecl)
20719 break;
20720 case XML_SCHEMA_TYPE_ATTRIBUTE:
20721 name = (WXS_ATTR_CAST item)->name;
20722 WXS_GET_GLOBAL_HASH(bucket, attrDecl)
20723 break;
20724 case XML_SCHEMA_TYPE_GROUP:
20725 if (WXS_REDEFINED_MODEL_GROUP_DEF(item))
20726 continue;
20727 name = (WXS_MODEL_GROUPDEF_CAST item)->name;
20728 WXS_GET_GLOBAL_HASH(bucket, groupDecl)
20729 break;
20730 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20731 if (WXS_REDEFINED_ATTR_GROUP(item))
20732 continue;
20733 name = (WXS_ATTR_GROUP_CAST item)->name;
20734 WXS_GET_GLOBAL_HASH(bucket, attrgrpDecl)
20735 break;
20736 case XML_SCHEMA_TYPE_IDC_KEY:
20737 case XML_SCHEMA_TYPE_IDC_UNIQUE:
20738 case XML_SCHEMA_TYPE_IDC_KEYREF:
20739 name = (WXS_IDC_CAST item)->name;
20740 WXS_GET_GLOBAL_HASH(bucket, idcDef)
20741 break;
20742 case XML_SCHEMA_TYPE_NOTATION:
20743 name = ((xmlSchemaNotationPtr) item)->name;
20744 WXS_GET_GLOBAL_HASH(bucket, notaDecl)
20745 break;
20746 default:
20747 PERROR_INT("xmlSchemaAddComponents",
20748 "Unexpected global component type");
20749 continue;
20751 if (*table == NULL) {
20752 *table = xmlHashCreateDict(10, pctxt->dict);
20753 if (*table == NULL) {
20754 PERROR_INT("xmlSchemaAddComponents",
20755 "failed to create a component hash table");
20756 return(-1);
20759 err = xmlHashAddEntry(*table, name, item);
20760 if (err != 0) {
20761 xmlChar *str = NULL;
20763 xmlSchemaCustomErr(ACTXT_CAST pctxt,
20764 XML_SCHEMAP_REDEFINED_TYPE,
20765 WXS_ITEM_NODE(item),
20766 WXS_BASIC_CAST item,
20767 "A global %s '%s' does already exist",
20768 WXS_ITEM_TYPE_NAME(item),
20769 xmlSchemaGetComponentQName(&str, item));
20770 FREE_AND_NULL(str);
20774 * Process imported/included schemas.
20776 if (bucket->relations != NULL) {
20777 xmlSchemaSchemaRelationPtr rel = bucket->relations;
20778 do {
20779 if ((rel->bucket != NULL) &&
20780 ((rel->bucket->flags & XML_SCHEMA_BUCKET_COMPS_ADDED) == 0)) {
20781 if (xmlSchemaAddComponents(pctxt, rel->bucket) == -1)
20782 return(-1);
20784 rel = rel->next;
20785 } while (rel != NULL);
20787 return(0);
20790 static int
20791 xmlSchemaFixupComponents(xmlSchemaParserCtxtPtr pctxt,
20792 xmlSchemaBucketPtr rootBucket)
20794 xmlSchemaConstructionCtxtPtr con = pctxt->constructor;
20795 xmlSchemaTreeItemPtr item, *items;
20796 int nbItems, i, ret = 0;
20797 xmlSchemaBucketPtr oldbucket = con->bucket;
20798 xmlSchemaElementPtr elemDecl;
20800 #define FIXHFAILURE if (pctxt->err == XML_SCHEMAP_INTERNAL) goto exit_failure;
20802 if ((con->pending == NULL) ||
20803 (con->pending->nbItems == 0))
20804 return(0);
20807 * Since xmlSchemaFixupComplexType() will create new particles
20808 * (local components), and those particle components need a bucket
20809 * on the constructor, we'll assure here that the constructor has
20810 * a bucket.
20811 * TODO: Think about storing locals _only_ on the main bucket.
20813 if (con->bucket == NULL)
20814 con->bucket = rootBucket;
20816 /* TODO:
20817 * SPEC (src-redefine):
20818 * (6.2) "If it has no such self-reference, then all of the
20819 * following must be true:"
20821 * (6.2.2) The {model group} of the model group definition which
20822 * corresponds to it per XML Representation of Model Group
20823 * Definition Schema Components (�3.7.2) must be a �valid
20824 * restriction� of the {model group} of that model group definition
20825 * in I, as defined in Particle Valid (Restriction) (�3.9.6)."
20827 xmlSchemaCheckSRCRedefineFirst(pctxt);
20830 * Add global components to the schemata's hash tables.
20832 xmlSchemaAddComponents(pctxt, rootBucket);
20834 pctxt->ctxtType = NULL;
20835 items = (xmlSchemaTreeItemPtr *) con->pending->items;
20836 nbItems = con->pending->nbItems;
20838 * Now that we have parsed *all* the schema document(s) and converted
20839 * them to schema components, we can resolve references, apply component
20840 * constraints, create the FSA from the content model, etc.
20843 * Resolve references of..
20845 * 1. element declarations:
20846 * - the type definition
20847 * - the substitution group affiliation
20848 * 2. simple/complex types:
20849 * - the base type definition
20850 * - the memberTypes of union types
20851 * - the itemType of list types
20852 * 3. attributes declarations and attribute uses:
20853 * - the type definition
20854 * - if an attribute use, then the attribute declaration
20855 * 4. attribute group references:
20856 * - the attribute group definition
20857 * 5. particles:
20858 * - the term of the particle (e.g. a model group)
20859 * 6. IDC key-references:
20860 * - the referenced IDC 'key' or 'unique' definition
20861 * 7. Attribute prohibitions which had a "ref" attribute.
20863 for (i = 0; i < nbItems; i++) {
20864 item = items[i];
20865 switch (item->type) {
20866 case XML_SCHEMA_TYPE_ELEMENT:
20867 xmlSchemaResolveElementReferences(
20868 (xmlSchemaElementPtr) item, pctxt);
20869 FIXHFAILURE;
20870 break;
20871 case XML_SCHEMA_TYPE_COMPLEX:
20872 case XML_SCHEMA_TYPE_SIMPLE:
20873 xmlSchemaResolveTypeReferences(
20874 (xmlSchemaTypePtr) item, pctxt);
20875 FIXHFAILURE;
20876 break;
20877 case XML_SCHEMA_TYPE_ATTRIBUTE:
20878 xmlSchemaResolveAttrTypeReferences(
20879 (xmlSchemaAttributePtr) item, pctxt);
20880 FIXHFAILURE;
20881 break;
20882 case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
20883 xmlSchemaResolveAttrUseReferences(
20884 (xmlSchemaAttributeUsePtr) item, pctxt);
20885 FIXHFAILURE;
20886 break;
20887 case XML_SCHEMA_EXTRA_QNAMEREF:
20888 if ((WXS_QNAME_CAST item)->itemType ==
20889 XML_SCHEMA_TYPE_ATTRIBUTEGROUP)
20891 xmlSchemaResolveAttrGroupReferences(
20892 WXS_QNAME_CAST item, pctxt);
20894 FIXHFAILURE;
20895 break;
20896 case XML_SCHEMA_TYPE_SEQUENCE:
20897 case XML_SCHEMA_TYPE_CHOICE:
20898 case XML_SCHEMA_TYPE_ALL:
20899 xmlSchemaResolveModelGroupParticleReferences(pctxt,
20900 WXS_MODEL_GROUP_CAST item);
20901 FIXHFAILURE;
20902 break;
20903 case XML_SCHEMA_TYPE_IDC_KEY:
20904 case XML_SCHEMA_TYPE_IDC_UNIQUE:
20905 case XML_SCHEMA_TYPE_IDC_KEYREF:
20906 xmlSchemaResolveIDCKeyReferences(
20907 (xmlSchemaIDCPtr) item, pctxt);
20908 FIXHFAILURE;
20909 break;
20910 case XML_SCHEMA_EXTRA_ATTR_USE_PROHIB:
20912 * Handle attribue prohibition which had a
20913 * "ref" attribute.
20915 xmlSchemaResolveAttrUseProhibReferences(
20916 WXS_ATTR_PROHIB_CAST item, pctxt);
20917 FIXHFAILURE;
20918 break;
20919 default:
20920 break;
20923 if (pctxt->nberrors != 0)
20924 goto exit_error;
20927 * Now that all references are resolved we
20928 * can check for circularity of...
20929 * 1. the base axis of type definitions
20930 * 2. nested model group definitions
20931 * 3. nested attribute group definitions
20932 * TODO: check for circual substitution groups.
20934 for (i = 0; i < nbItems; i++) {
20935 item = items[i];
20937 * Let's better stop on the first error here.
20939 switch (item->type) {
20940 case XML_SCHEMA_TYPE_COMPLEX:
20941 case XML_SCHEMA_TYPE_SIMPLE:
20942 xmlSchemaCheckTypeDefCircular(
20943 (xmlSchemaTypePtr) item, pctxt);
20944 FIXHFAILURE;
20945 if (pctxt->nberrors != 0)
20946 goto exit_error;
20947 break;
20948 case XML_SCHEMA_TYPE_GROUP:
20949 xmlSchemaCheckGroupDefCircular(
20950 (xmlSchemaModelGroupDefPtr) item, pctxt);
20951 FIXHFAILURE;
20952 if (pctxt->nberrors != 0)
20953 goto exit_error;
20954 break;
20955 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20956 xmlSchemaCheckAttrGroupCircular(
20957 (xmlSchemaAttributeGroupPtr) item, pctxt);
20958 FIXHFAILURE;
20959 if (pctxt->nberrors != 0)
20960 goto exit_error;
20961 break;
20962 default:
20963 break;
20966 if (pctxt->nberrors != 0)
20967 goto exit_error;
20969 * Model group definition references:
20970 * Such a reference is reflected by a particle at the component
20971 * level. Until now the 'term' of such particles pointed
20972 * to the model group definition; this was done, in order to
20973 * ease circularity checks. Now we need to set the 'term' of
20974 * such particles to the model group of the model group definition.
20976 for (i = 0; i < nbItems; i++) {
20977 item = items[i];
20978 switch (item->type) {
20979 case XML_SCHEMA_TYPE_SEQUENCE:
20980 case XML_SCHEMA_TYPE_CHOICE:
20981 xmlSchemaModelGroupToModelGroupDefFixup(pctxt,
20982 WXS_MODEL_GROUP_CAST item);
20983 break;
20984 default:
20985 break;
20988 if (pctxt->nberrors != 0)
20989 goto exit_error;
20991 * Expand attribute group references of attribute group definitions.
20993 for (i = 0; i < nbItems; i++) {
20994 item = items[i];
20995 switch (item->type) {
20996 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20997 if ((! WXS_ATTR_GROUP_EXPANDED(item)) &&
20998 WXS_ATTR_GROUP_HAS_REFS(item))
21000 xmlSchemaAttributeGroupExpandRefs(pctxt,
21001 WXS_ATTR_GROUP_CAST item);
21002 FIXHFAILURE;
21004 break;
21005 default:
21006 break;
21009 if (pctxt->nberrors != 0)
21010 goto exit_error;
21012 * First compute the variety of simple types. This is needed as
21013 * a seperate step, since otherwise we won't be able to detect
21014 * circular union types in all cases.
21016 for (i = 0; i < nbItems; i++) {
21017 item = items[i];
21018 switch (item->type) {
21019 case XML_SCHEMA_TYPE_SIMPLE:
21020 if (WXS_IS_TYPE_NOT_FIXED_1((xmlSchemaTypePtr) item)) {
21021 xmlSchemaFixupSimpleTypeStageOne(pctxt,
21022 (xmlSchemaTypePtr) item);
21023 FIXHFAILURE;
21025 break;
21026 default:
21027 break;
21030 if (pctxt->nberrors != 0)
21031 goto exit_error;
21033 * Detect circular union types. Note that this needs the variety to
21034 * be already computed.
21036 for (i = 0; i < nbItems; i++) {
21037 item = items[i];
21038 switch (item->type) {
21039 case XML_SCHEMA_TYPE_SIMPLE:
21040 if (((xmlSchemaTypePtr) item)->memberTypes != NULL) {
21041 xmlSchemaCheckUnionTypeDefCircular(pctxt,
21042 (xmlSchemaTypePtr) item);
21043 FIXHFAILURE;
21045 break;
21046 default:
21047 break;
21050 if (pctxt->nberrors != 0)
21051 goto exit_error;
21054 * Do the complete type fixup for simple types.
21056 for (i = 0; i < nbItems; i++) {
21057 item = items[i];
21058 switch (item->type) {
21059 case XML_SCHEMA_TYPE_SIMPLE:
21060 if (WXS_IS_TYPE_NOT_FIXED(WXS_TYPE_CAST item)) {
21061 xmlSchemaFixupSimpleTypeStageTwo(pctxt, WXS_TYPE_CAST item);
21062 FIXHFAILURE;
21064 break;
21065 default:
21066 break;
21069 if (pctxt->nberrors != 0)
21070 goto exit_error;
21072 * At this point we need build and check all simple types.
21075 * Apply contraints for attribute declarations.
21077 for (i = 0; i < nbItems; i++) {
21078 item = items[i];
21079 switch (item->type) {
21080 case XML_SCHEMA_TYPE_ATTRIBUTE:
21081 xmlSchemaCheckAttrPropsCorrect(pctxt, WXS_ATTR_CAST item);
21082 FIXHFAILURE;
21083 break;
21084 default:
21085 break;
21088 if (pctxt->nberrors != 0)
21089 goto exit_error;
21091 * Apply constraints for attribute uses.
21093 for (i = 0; i < nbItems; i++) {
21094 item = items[i];
21095 switch (item->type) {
21096 case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
21097 if (((xmlSchemaAttributeUsePtr)item)->defValue != NULL) {
21098 xmlSchemaCheckAttrUsePropsCorrect(pctxt,
21099 WXS_ATTR_USE_CAST item);
21100 FIXHFAILURE;
21102 break;
21103 default:
21104 break;
21107 if (pctxt->nberrors != 0)
21108 goto exit_error;
21111 * Apply constraints for attribute group definitions.
21113 for (i = 0; i < nbItems; i++) {
21114 item = items[i];
21115 switch (item->type) {
21116 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
21117 if (( (WXS_ATTR_GROUP_CAST item)->attrUses != NULL) &&
21118 ( (WXS_LIST_CAST (WXS_ATTR_GROUP_CAST item)->attrUses)->nbItems > 1))
21120 xmlSchemaCheckAGPropsCorrect(pctxt, WXS_ATTR_GROUP_CAST item);
21121 FIXHFAILURE;
21123 break;
21124 default:
21125 break;
21128 if (pctxt->nberrors != 0)
21129 goto exit_error;
21132 * Apply constraints for redefinitions.
21134 if (WXS_CONSTRUCTOR(pctxt)->redefs != NULL)
21135 xmlSchemaCheckSRCRedefineSecond(pctxt);
21136 if (pctxt->nberrors != 0)
21137 goto exit_error;
21140 * Complex types are builded and checked.
21142 for (i = 0; i < nbItems; i++) {
21143 item = con->pending->items[i];
21144 switch (item->type) {
21145 case XML_SCHEMA_TYPE_COMPLEX:
21146 if (WXS_IS_TYPE_NOT_FIXED(WXS_TYPE_CAST item)) {
21147 xmlSchemaFixupComplexType(pctxt, WXS_TYPE_CAST item);
21148 FIXHFAILURE;
21150 break;
21151 default:
21152 break;
21155 if (pctxt->nberrors != 0)
21156 goto exit_error;
21159 * The list could have changed, since xmlSchemaFixupComplexType()
21160 * will create particles and model groups in some cases.
21162 items = (xmlSchemaTreeItemPtr *) con->pending->items;
21163 nbItems = con->pending->nbItems;
21166 * Apply some constraints for element declarations.
21168 for (i = 0; i < nbItems; i++) {
21169 item = items[i];
21170 switch (item->type) {
21171 case XML_SCHEMA_TYPE_ELEMENT:
21172 elemDecl = (xmlSchemaElementPtr) item;
21174 if ((elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_CHECKED) == 0)
21176 xmlSchemaCheckElementDeclComponent(
21177 (xmlSchemaElementPtr) elemDecl, pctxt);
21178 FIXHFAILURE;
21181 #ifdef WXS_ELEM_DECL_CONS_ENABLED
21183 * Schema Component Constraint: Element Declarations Consistent
21184 * Apply this constraint to local types of element declarations.
21186 if ((WXS_ELEM_TYPEDEF(elemDecl) != NULL) &&
21187 (WXS_IS_COMPLEX(WXS_ELEM_TYPEDEF(elemDecl))) &&
21188 (WXS_TYPE_IS_LOCAL(WXS_ELEM_TYPEDEF(elemDecl))))
21190 xmlSchemaCheckElementDeclConsistent(pctxt,
21191 WXS_BASIC_CAST elemDecl,
21192 WXS_TYPE_PARTICLE(WXS_ELEM_TYPEDEF(elemDecl)),
21193 NULL, NULL, 0);
21195 #endif
21196 break;
21197 default:
21198 break;
21201 if (pctxt->nberrors != 0)
21202 goto exit_error;
21205 * Finally we can build the automaton from the content model of
21206 * complex types.
21209 for (i = 0; i < nbItems; i++) {
21210 item = items[i];
21211 switch (item->type) {
21212 case XML_SCHEMA_TYPE_COMPLEX:
21213 xmlSchemaBuildContentModel((xmlSchemaTypePtr) item, pctxt);
21214 /* FIXHFAILURE; */
21215 break;
21216 default:
21217 break;
21220 if (pctxt->nberrors != 0)
21221 goto exit_error;
21223 * URGENT TODO: cos-element-consistent
21225 goto exit;
21227 exit_error:
21228 ret = pctxt->err;
21229 goto exit;
21231 exit_failure:
21232 ret = -1;
21234 exit:
21236 * Reset the constructor. This is needed for XSI acquisition, since
21237 * those items will be processed over and over again for every XSI
21238 * if not cleared here.
21240 con->bucket = oldbucket;
21241 con->pending->nbItems = 0;
21242 if (con->substGroups != NULL) {
21243 xmlHashFree(con->substGroups,
21244 (xmlHashDeallocator) xmlSchemaSubstGroupFree);
21245 con->substGroups = NULL;
21247 if (con->redefs != NULL) {
21248 xmlSchemaRedefListFree(con->redefs);
21249 con->redefs = NULL;
21251 return(ret);
21254 * xmlSchemaParse:
21255 * @ctxt: a schema validation context
21257 * parse a schema definition resource and build an internal
21258 * XML Shema struture which can be used to validate instances.
21260 * Returns the internal XML Schema structure built from the resource or
21261 * NULL in case of error
21263 xmlSchemaPtr
21264 xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt)
21266 xmlSchemaPtr mainSchema = NULL;
21267 xmlSchemaBucketPtr bucket = NULL;
21268 int res;
21271 * This one is used if the schema to be parsed was specified via
21272 * the API; i.e. not automatically by the validated instance document.
21275 xmlSchemaInitTypes();
21277 if (ctxt == NULL)
21278 return (NULL);
21280 /* TODO: Init the context. Is this all we need?*/
21281 ctxt->nberrors = 0;
21282 ctxt->err = 0;
21283 ctxt->counter = 0;
21285 /* Create the *main* schema. */
21286 mainSchema = xmlSchemaNewSchema(ctxt);
21287 if (mainSchema == NULL)
21288 goto exit_failure;
21290 * Create the schema constructor.
21292 if (ctxt->constructor == NULL) {
21293 ctxt->constructor = xmlSchemaConstructionCtxtCreate(ctxt->dict);
21294 if (ctxt->constructor == NULL)
21295 return(NULL);
21296 /* Take ownership of the constructor to be able to free it. */
21297 ctxt->ownsConstructor = 1;
21299 ctxt->constructor->mainSchema = mainSchema;
21301 * Locate and add the schema document.
21303 res = xmlSchemaAddSchemaDoc(ctxt, XML_SCHEMA_SCHEMA_MAIN,
21304 ctxt->URL, ctxt->doc, ctxt->buffer, ctxt->size, NULL,
21305 NULL, NULL, &bucket);
21306 if (res == -1)
21307 goto exit_failure;
21308 if (res != 0)
21309 goto exit;
21311 if (bucket == NULL) {
21312 /* TODO: Error code, actually we failed to *locate* the schema. */
21313 if (ctxt->URL)
21314 xmlSchemaCustomErr(ACTXT_CAST ctxt, XML_SCHEMAP_FAILED_LOAD,
21315 NULL, NULL,
21316 "Failed to locate the main schema resource at '%s'",
21317 ctxt->URL, NULL);
21318 else
21319 xmlSchemaCustomErr(ACTXT_CAST ctxt, XML_SCHEMAP_FAILED_LOAD,
21320 NULL, NULL,
21321 "Failed to locate the main schema resource",
21322 NULL, NULL);
21323 goto exit;
21325 /* Then do the parsing for good. */
21326 if (xmlSchemaParseNewDocWithContext(ctxt, mainSchema, bucket) == -1)
21327 goto exit_failure;
21328 if (ctxt->nberrors != 0)
21329 goto exit;
21331 mainSchema->doc = bucket->doc;
21332 mainSchema->preserve = ctxt->preserve;
21334 ctxt->schema = mainSchema;
21336 if (xmlSchemaFixupComponents(ctxt, WXS_CONSTRUCTOR(ctxt)->mainBucket) == -1)
21337 goto exit_failure;
21340 * TODO: This is not nice, since we cannot distinguish from the
21341 * result if there was an internal error or not.
21343 exit:
21344 if (ctxt->nberrors != 0) {
21345 if (mainSchema) {
21346 xmlSchemaFree(mainSchema);
21347 mainSchema = NULL;
21349 if (ctxt->constructor) {
21350 xmlSchemaConstructionCtxtFree(ctxt->constructor);
21351 ctxt->constructor = NULL;
21352 ctxt->ownsConstructor = 0;
21355 ctxt->schema = NULL;
21356 return(mainSchema);
21357 exit_failure:
21359 * Quite verbose, but should catch internal errors, which were
21360 * not communitated.
21362 if (mainSchema) {
21363 xmlSchemaFree(mainSchema);
21364 mainSchema = NULL;
21366 if (ctxt->constructor) {
21367 xmlSchemaConstructionCtxtFree(ctxt->constructor);
21368 ctxt->constructor = NULL;
21369 ctxt->ownsConstructor = 0;
21371 PERROR_INT2("xmlSchemaParse",
21372 "An internal error occured");
21373 ctxt->schema = NULL;
21374 return(NULL);
21378 * xmlSchemaSetParserErrors:
21379 * @ctxt: a schema validation context
21380 * @err: the error callback
21381 * @warn: the warning callback
21382 * @ctx: contextual data for the callbacks
21384 * Set the callback functions used to handle errors for a validation context
21386 void
21387 xmlSchemaSetParserErrors(xmlSchemaParserCtxtPtr ctxt,
21388 xmlSchemaValidityErrorFunc err,
21389 xmlSchemaValidityWarningFunc warn, void *ctx)
21391 if (ctxt == NULL)
21392 return;
21393 ctxt->error = err;
21394 ctxt->warning = warn;
21395 ctxt->errCtxt = ctx;
21396 if (ctxt->vctxt != NULL)
21397 xmlSchemaSetValidErrors(ctxt->vctxt, err, warn, ctx);
21401 * xmlSchemaSetParserStructuredErrors:
21402 * @ctxt: a schema parser context
21403 * @serror: the structured error function
21404 * @ctx: the functions context
21406 * Set the structured error callback
21408 void
21409 xmlSchemaSetParserStructuredErrors(xmlSchemaParserCtxtPtr ctxt,
21410 xmlStructuredErrorFunc serror,
21411 void *ctx)
21413 if (ctxt == NULL)
21414 return;
21415 ctxt->serror = serror;
21416 ctxt->errCtxt = ctx;
21417 if (ctxt->vctxt != NULL)
21418 xmlSchemaSetValidStructuredErrors(ctxt->vctxt, serror, ctx);
21422 * xmlSchemaGetParserErrors:
21423 * @ctxt: a XMl-Schema parser context
21424 * @err: the error callback result
21425 * @warn: the warning callback result
21426 * @ctx: contextual data for the callbacks result
21428 * Get the callback information used to handle errors for a parser context
21430 * Returns -1 in case of failure, 0 otherwise
21433 xmlSchemaGetParserErrors(xmlSchemaParserCtxtPtr ctxt,
21434 xmlSchemaValidityErrorFunc * err,
21435 xmlSchemaValidityWarningFunc * warn, void **ctx)
21437 if (ctxt == NULL)
21438 return(-1);
21439 if (err != NULL)
21440 *err = ctxt->error;
21441 if (warn != NULL)
21442 *warn = ctxt->warning;
21443 if (ctx != NULL)
21444 *ctx = ctxt->errCtxt;
21445 return(0);
21449 * xmlSchemaFacetTypeToString:
21450 * @type: the facet type
21452 * Convert the xmlSchemaTypeType to a char string.
21454 * Returns the char string representation of the facet type if the
21455 * type is a facet and an "Internal Error" string otherwise.
21457 static const xmlChar *
21458 xmlSchemaFacetTypeToString(xmlSchemaTypeType type)
21460 switch (type) {
21461 case XML_SCHEMA_FACET_PATTERN:
21462 return (BAD_CAST "pattern");
21463 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
21464 return (BAD_CAST "maxExclusive");
21465 case XML_SCHEMA_FACET_MAXINCLUSIVE:
21466 return (BAD_CAST "maxInclusive");
21467 case XML_SCHEMA_FACET_MINEXCLUSIVE:
21468 return (BAD_CAST "minExclusive");
21469 case XML_SCHEMA_FACET_MININCLUSIVE:
21470 return (BAD_CAST "minInclusive");
21471 case XML_SCHEMA_FACET_WHITESPACE:
21472 return (BAD_CAST "whiteSpace");
21473 case XML_SCHEMA_FACET_ENUMERATION:
21474 return (BAD_CAST "enumeration");
21475 case XML_SCHEMA_FACET_LENGTH:
21476 return (BAD_CAST "length");
21477 case XML_SCHEMA_FACET_MAXLENGTH:
21478 return (BAD_CAST "maxLength");
21479 case XML_SCHEMA_FACET_MINLENGTH:
21480 return (BAD_CAST "minLength");
21481 case XML_SCHEMA_FACET_TOTALDIGITS:
21482 return (BAD_CAST "totalDigits");
21483 case XML_SCHEMA_FACET_FRACTIONDIGITS:
21484 return (BAD_CAST "fractionDigits");
21485 default:
21486 break;
21488 return (BAD_CAST "Internal Error");
21491 static xmlSchemaWhitespaceValueType
21492 xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type)
21495 * The normalization type can be changed only for types which are derived
21496 * from xsd:string.
21498 if (type->type == XML_SCHEMA_TYPE_BASIC) {
21500 * Note that we assume a whitespace of preserve for anySimpleType.
21502 if ((type->builtInType == XML_SCHEMAS_STRING) ||
21503 (type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE))
21504 return(XML_SCHEMA_WHITESPACE_PRESERVE);
21505 else if (type->builtInType == XML_SCHEMAS_NORMSTRING)
21506 return(XML_SCHEMA_WHITESPACE_REPLACE);
21507 else {
21509 * For all �atomic� datatypes other than string (and types �derived�
21510 * by �restriction� from it) the value of whiteSpace is fixed to
21511 * collapse
21512 * Note that this includes built-in list datatypes.
21514 return(XML_SCHEMA_WHITESPACE_COLLAPSE);
21516 } else if (WXS_IS_LIST(type)) {
21518 * For list types the facet "whiteSpace" is fixed to "collapse".
21520 return (XML_SCHEMA_WHITESPACE_COLLAPSE);
21521 } else if (WXS_IS_UNION(type)) {
21522 return (XML_SCHEMA_WHITESPACE_UNKNOWN);
21523 } else if (WXS_IS_ATOMIC(type)) {
21524 if (type->flags & XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE)
21525 return (XML_SCHEMA_WHITESPACE_PRESERVE);
21526 else if (type->flags & XML_SCHEMAS_TYPE_WHITESPACE_REPLACE)
21527 return (XML_SCHEMA_WHITESPACE_REPLACE);
21528 else
21529 return (XML_SCHEMA_WHITESPACE_COLLAPSE);
21531 return (-1);
21534 /************************************************************************
21536 * Simple type validation *
21538 ************************************************************************/
21541 /************************************************************************
21543 * DOM Validation code *
21545 ************************************************************************/
21548 * xmlSchemaAssembleByLocation:
21549 * @pctxt: a schema parser context
21550 * @vctxt: a schema validation context
21551 * @schema: the existing schema
21552 * @node: the node that fired the assembling
21553 * @nsName: the namespace name of the new schema
21554 * @location: the location of the schema
21556 * Expands an existing schema by an additional schema.
21558 * Returns 0 if the new schema is correct, a positive error code
21559 * number otherwise and -1 in case of an internal or API error.
21561 static int
21562 xmlSchemaAssembleByLocation(xmlSchemaValidCtxtPtr vctxt,
21563 xmlSchemaPtr schema,
21564 xmlNodePtr node,
21565 const xmlChar *nsName,
21566 const xmlChar *location)
21568 int ret = 0;
21569 xmlSchemaParserCtxtPtr pctxt;
21570 xmlSchemaBucketPtr bucket = NULL;
21572 if ((vctxt == NULL) || (schema == NULL))
21573 return (-1);
21575 if (vctxt->pctxt == NULL) {
21576 VERROR_INT("xmlSchemaAssembleByLocation",
21577 "no parser context available");
21578 return(-1);
21580 pctxt = vctxt->pctxt;
21581 if (pctxt->constructor == NULL) {
21582 PERROR_INT("xmlSchemaAssembleByLocation",
21583 "no constructor");
21584 return(-1);
21587 * Acquire the schema document.
21589 location = xmlSchemaBuildAbsoluteURI(pctxt->dict,
21590 location, node);
21592 * Note that we pass XML_SCHEMA_SCHEMA_IMPORT here;
21593 * the process will automatically change this to
21594 * XML_SCHEMA_SCHEMA_MAIN if it is the first schema document.
21596 ret = xmlSchemaAddSchemaDoc(pctxt, XML_SCHEMA_SCHEMA_IMPORT,
21597 location, NULL, NULL, 0, node, NULL, nsName,
21598 &bucket);
21599 if (ret != 0)
21600 return(ret);
21601 if (bucket == NULL) {
21603 * Generate a warning that the document could not be located.
21605 xmlSchemaCustomWarning(ACTXT_CAST vctxt, XML_SCHEMAV_MISC,
21606 node, NULL,
21607 "The document at location '%s' could not be acquired",
21608 location, NULL, NULL);
21609 return(ret);
21612 * The first located schema will be handled as if all other
21613 * schemas imported by XSI were imported by this first schema.
21615 if ((bucket != NULL) &&
21616 (WXS_CONSTRUCTOR(pctxt)->bucket == NULL))
21617 WXS_CONSTRUCTOR(pctxt)->bucket = bucket;
21619 * TODO: Is this handled like an import? I.e. is it not an error
21620 * if the schema cannot be located?
21622 if ((bucket == NULL) || (! CAN_PARSE_SCHEMA(bucket)))
21623 return(0);
21625 * We will reuse the parser context for every schema imported
21626 * directly via XSI. So reset the context.
21628 pctxt->nberrors = 0;
21629 pctxt->err = 0;
21630 pctxt->doc = bucket->doc;
21632 ret = xmlSchemaParseNewDocWithContext(pctxt, schema, bucket);
21633 if (ret == -1) {
21634 pctxt->doc = NULL;
21635 goto exit_failure;
21637 /* Paranoid error channelling. */
21638 if ((ret == 0) && (pctxt->nberrors != 0))
21639 ret = pctxt->err;
21640 if (pctxt->nberrors == 0) {
21642 * Only bother to fixup pending components, if there was
21643 * no error yet.
21644 * For every XSI acquired schema (and its sub-schemata) we will
21645 * fixup the components.
21647 xmlSchemaFixupComponents(pctxt, bucket);
21648 ret = pctxt->err;
21650 * Not nice, but we need somehow to channel the schema parser
21651 * error to the validation context.
21653 if ((ret != 0) && (vctxt->err == 0))
21654 vctxt->err = ret;
21655 vctxt->nberrors += pctxt->nberrors;
21656 } else {
21657 /* Add to validation error sum. */
21658 vctxt->nberrors += pctxt->nberrors;
21660 pctxt->doc = NULL;
21661 return(ret);
21662 exit_failure:
21663 pctxt->doc = NULL;
21664 return (-1);
21667 static xmlSchemaAttrInfoPtr
21668 xmlSchemaGetMetaAttrInfo(xmlSchemaValidCtxtPtr vctxt,
21669 int metaType)
21671 if (vctxt->nbAttrInfos == 0)
21672 return (NULL);
21674 int i;
21675 xmlSchemaAttrInfoPtr iattr;
21677 for (i = 0; i < vctxt->nbAttrInfos; i++) {
21678 iattr = vctxt->attrInfos[i];
21679 if (iattr->metaType == metaType)
21680 return (iattr);
21684 return (NULL);
21688 * xmlSchemaAssembleByXSI:
21689 * @vctxt: a schema validation context
21691 * Expands an existing schema by an additional schema using
21692 * the xsi:schemaLocation or xsi:noNamespaceSchemaLocation attribute
21693 * of an instance. If xsi:noNamespaceSchemaLocation is used, @noNamespace
21694 * must be set to 1.
21696 * Returns 0 if the new schema is correct, a positive error code
21697 * number otherwise and -1 in case of an internal or API error.
21699 static int
21700 xmlSchemaAssembleByXSI(xmlSchemaValidCtxtPtr vctxt)
21702 const xmlChar *cur, *end;
21703 const xmlChar *nsname = NULL, *location;
21704 int count = 0;
21705 int ret = 0;
21706 xmlSchemaAttrInfoPtr iattr;
21709 * Parse the value; we will assume an even number of values
21710 * to be given (this is how Xerces and XSV work).
21712 * URGENT TODO: !! This needs to work for both
21713 * @noNamespaceSchemaLocation AND @schemaLocation on the same
21714 * element !!
21716 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
21717 XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC);
21718 if (iattr == NULL)
21719 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
21720 XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC);
21721 if (iattr == NULL)
21722 return (0);
21723 cur = iattr->value;
21724 do {
21726 * TODO: Move the string parsing mechanism away from here.
21728 if (iattr->metaType == XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC) {
21730 * Get the namespace name.
21732 while (IS_BLANK_CH(*cur))
21733 cur++;
21734 end = cur;
21735 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
21736 end++;
21737 if (end == cur)
21738 break;
21739 count++; /* TODO: Don't use the schema's dict. */
21740 nsname = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
21741 cur = end;
21744 * Get the URI.
21746 while (IS_BLANK_CH(*cur))
21747 cur++;
21748 end = cur;
21749 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
21750 end++;
21751 if (end == cur) {
21752 if (iattr->metaType ==
21753 XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC)
21756 * If using @schemaLocation then tuples are expected.
21757 * I.e. the namespace name *and* the document's URI.
21759 xmlSchemaCustomWarning(ACTXT_CAST vctxt, XML_SCHEMAV_MISC,
21760 iattr->node, NULL,
21761 "The value must consist of tuples: the target namespace "
21762 "name and the document's URI", NULL, NULL, NULL);
21764 break;
21766 count++; /* TODO: Don't use the schema's dict. */
21767 location = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
21768 cur = end;
21769 ret = xmlSchemaAssembleByLocation(vctxt, vctxt->schema,
21770 iattr->node, nsname, location);
21771 if (ret == -1) {
21772 VERROR_INT("xmlSchemaAssembleByXSI",
21773 "assembling schemata");
21774 return (-1);
21776 } while (*cur != 0);
21777 return (ret);
21780 static const xmlChar *
21781 xmlSchemaLookupNamespace(xmlSchemaValidCtxtPtr vctxt,
21782 const xmlChar *prefix)
21784 if (vctxt->sax != NULL) {
21785 int i, j;
21786 xmlSchemaNodeInfoPtr inode;
21788 for (i = vctxt->depth; i >= 0; i--) {
21789 if (vctxt->elemInfos[i]->nbNsBindings != 0) {
21790 inode = vctxt->elemInfos[i];
21791 for (j = 0; j < inode->nbNsBindings * 2; j += 2) {
21792 if (((prefix == NULL) &&
21793 (inode->nsBindings[j] == NULL)) ||
21794 ((prefix != NULL) && xmlStrEqual(prefix,
21795 inode->nsBindings[j]))) {
21798 * Note that the namespace bindings are already
21799 * in a string dict.
21801 return (inode->nsBindings[j+1]);
21806 return (NULL);
21807 #ifdef LIBXML_READER_ENABLED
21808 } else if (vctxt->reader != NULL) {
21809 xmlChar *nsName;
21811 nsName = xmlTextReaderLookupNamespace(vctxt->reader, prefix);
21812 if (nsName != NULL) {
21813 const xmlChar *ret;
21815 ret = xmlDictLookup(vctxt->dict, nsName, -1);
21816 xmlFree(nsName);
21817 return (ret);
21818 } else
21819 return (NULL);
21820 #endif
21821 } else {
21822 xmlNsPtr ns;
21824 if ((vctxt->inode->node == NULL) ||
21825 (vctxt->inode->node->doc == NULL)) {
21826 VERROR_INT("xmlSchemaLookupNamespace",
21827 "no node or node's doc avaliable");
21828 return (NULL);
21830 ns = xmlSearchNs(vctxt->inode->node->doc,
21831 vctxt->inode->node, prefix);
21832 if (ns != NULL)
21833 return (ns->href);
21834 return (NULL);
21839 * This one works on the schema of the validation context.
21841 static int
21842 xmlSchemaValidateNotation(xmlSchemaValidCtxtPtr vctxt,
21843 xmlSchemaPtr schema,
21844 xmlNodePtr node,
21845 const xmlChar *value,
21846 xmlSchemaValPtr *val,
21847 int valNeeded)
21849 int ret;
21851 if (vctxt && (vctxt->schema == NULL)) {
21852 VERROR_INT("xmlSchemaValidateNotation",
21853 "a schema is needed on the validation context");
21854 return (-1);
21856 ret = xmlValidateQName(value, 1);
21857 if (ret != 0)
21858 return (ret);
21860 xmlChar *localName = NULL;
21861 xmlChar *prefix = NULL;
21863 localName = xmlSplitQName2(value, &prefix);
21864 if (prefix != NULL) {
21865 const xmlChar *nsName = NULL;
21867 if (vctxt != NULL)
21868 nsName = xmlSchemaLookupNamespace(vctxt, BAD_CAST prefix);
21869 else if (node != NULL) {
21870 xmlNsPtr ns = xmlSearchNs(node->doc, node, prefix);
21871 if (ns != NULL)
21872 nsName = ns->href;
21873 } else {
21874 xmlFree(prefix);
21875 xmlFree(localName);
21876 return (1);
21878 if (nsName == NULL) {
21879 xmlFree(prefix);
21880 xmlFree(localName);
21881 return (1);
21883 if (xmlSchemaGetNotation(schema, localName, nsName) != NULL) {
21884 if ((valNeeded) && (val != NULL)) {
21885 (*val) = xmlSchemaNewNOTATIONValue(xmlStrdup(localName),
21886 xmlStrdup(nsName));
21887 if (*val == NULL)
21888 ret = -1;
21890 } else
21891 ret = 1;
21892 xmlFree(prefix);
21893 xmlFree(localName);
21894 } else {
21895 if (xmlSchemaGetNotation(schema, value, NULL) != NULL) {
21896 if (valNeeded && (val != NULL)) {
21897 (*val) = xmlSchemaNewNOTATIONValue(
21898 BAD_CAST xmlStrdup(value), NULL);
21899 if (*val == NULL)
21900 ret = -1;
21902 } else
21903 return (1);
21906 return (ret);
21909 static int
21910 xmlSchemaVAddNodeQName(xmlSchemaValidCtxtPtr vctxt,
21911 const xmlChar* lname,
21912 const xmlChar* nsname)
21914 int i;
21916 lname = xmlDictLookup(vctxt->dict, lname, -1);
21917 if (lname == NULL)
21918 return(-1);
21919 if (nsname != NULL) {
21920 nsname = xmlDictLookup(vctxt->dict, nsname, -1);
21921 if (nsname == NULL)
21922 return(-1);
21924 for (i = 0; i < vctxt->nodeQNames->nbItems; i += 2) {
21925 if ((vctxt->nodeQNames->items [i] == lname) &&
21926 (vctxt->nodeQNames->items[i +1] == nsname))
21927 /* Already there */
21928 return(i);
21930 /* Add new entry. */
21931 i = vctxt->nodeQNames->nbItems;
21932 xmlSchemaItemListAdd(vctxt->nodeQNames, (void *) lname);
21933 xmlSchemaItemListAdd(vctxt->nodeQNames, (void *) nsname);
21934 return(i);
21937 /************************************************************************
21939 * Validation of identity-constraints (IDC) *
21941 ************************************************************************/
21944 * xmlSchemaAugmentIDC:
21945 * @idcDef: the IDC definition
21947 * Creates an augmented IDC definition item.
21949 * Returns the item, or NULL on internal errors.
21951 static void
21952 xmlSchemaAugmentIDC(xmlSchemaIDCPtr idcDef,
21953 xmlSchemaValidCtxtPtr vctxt)
21955 xmlSchemaIDCAugPtr aidc;
21957 aidc = (xmlSchemaIDCAugPtr) xmlMalloc(sizeof(xmlSchemaIDCAug));
21958 if (aidc == NULL) {
21959 xmlSchemaVErrMemory(vctxt,
21960 "xmlSchemaAugmentIDC: allocating an augmented IDC definition",
21961 NULL);
21962 return;
21964 aidc->keyrefDepth = -1;
21965 aidc->def = idcDef;
21966 aidc->next = NULL;
21967 if (vctxt->aidcs == NULL)
21968 vctxt->aidcs = aidc;
21969 else {
21970 aidc->next = vctxt->aidcs;
21971 vctxt->aidcs = aidc;
21974 * Save if we have keyrefs at all.
21976 if ((vctxt->hasKeyrefs == 0) &&
21977 (idcDef->type == XML_SCHEMA_TYPE_IDC_KEYREF))
21978 vctxt->hasKeyrefs = 1;
21982 * xmlSchemaAugmentImportedIDC:
21983 * @imported: the imported schema
21985 * Creates an augmented IDC definition for the imported schema.
21987 static void
21988 xmlSchemaAugmentImportedIDC(xmlSchemaImportPtr imported, xmlSchemaValidCtxtPtr vctxt) {
21989 if (imported->schema->idcDef != NULL) {
21990 xmlHashScan(imported->schema->idcDef ,
21991 (xmlHashScanner) xmlSchemaAugmentIDC, vctxt);
21996 * xmlSchemaIDCNewBinding:
21997 * @idcDef: the IDC definition of this binding
21999 * Creates a new IDC binding.
22001 * Returns the new IDC binding, NULL on internal errors.
22003 static xmlSchemaPSVIIDCBindingPtr
22004 xmlSchemaIDCNewBinding(xmlSchemaIDCPtr idcDef)
22006 xmlSchemaPSVIIDCBindingPtr ret;
22008 ret = (xmlSchemaPSVIIDCBindingPtr) xmlMalloc(
22009 sizeof(xmlSchemaPSVIIDCBinding));
22010 if (ret == NULL) {
22011 xmlSchemaVErrMemory(NULL,
22012 "allocating a PSVI IDC binding item", NULL);
22013 return (NULL);
22015 memset(ret, 0, sizeof(xmlSchemaPSVIIDCBinding));
22016 ret->definition = idcDef;
22017 return (ret);
22021 * xmlSchemaIDCStoreNodeTableItem:
22022 * @vctxt: the WXS validation context
22023 * @item: the IDC node table item
22025 * The validation context is used to store IDC node table items.
22026 * They are stored to avoid copying them if IDC node-tables are merged
22027 * with corresponding parent IDC node-tables (bubbling).
22029 * Returns 0 if succeeded, -1 on internal errors.
22031 static int
22032 xmlSchemaIDCStoreNodeTableItem(xmlSchemaValidCtxtPtr vctxt,
22033 xmlSchemaPSVIIDCNodePtr item)
22036 * Add to gobal list.
22038 if (vctxt->idcNodes == NULL) {
22039 vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
22040 xmlMalloc(20 * sizeof(xmlSchemaPSVIIDCNodePtr));
22041 if (vctxt->idcNodes == NULL) {
22042 xmlSchemaVErrMemory(vctxt,
22043 "allocating the IDC node table item list", NULL);
22044 return (-1);
22046 vctxt->sizeIdcNodes = 20;
22047 } else if (vctxt->sizeIdcNodes <= vctxt->nbIdcNodes) {
22048 vctxt->sizeIdcNodes *= 2;
22049 vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
22050 xmlRealloc(vctxt->idcNodes, vctxt->sizeIdcNodes *
22051 sizeof(xmlSchemaPSVIIDCNodePtr));
22052 if (vctxt->idcNodes == NULL) {
22053 xmlSchemaVErrMemory(vctxt,
22054 "re-allocating the IDC node table item list", NULL);
22055 return (-1);
22058 vctxt->idcNodes[vctxt->nbIdcNodes++] = item;
22060 return (0);
22064 * xmlSchemaIDCStoreKey:
22065 * @vctxt: the WXS validation context
22066 * @item: the IDC key
22068 * The validation context is used to store an IDC key.
22070 * Returns 0 if succeeded, -1 on internal errors.
22072 static int
22073 xmlSchemaIDCStoreKey(xmlSchemaValidCtxtPtr vctxt,
22074 xmlSchemaPSVIIDCKeyPtr key)
22077 * Add to gobal list.
22079 if (vctxt->idcKeys == NULL) {
22080 vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
22081 xmlMalloc(40 * sizeof(xmlSchemaPSVIIDCKeyPtr));
22082 if (vctxt->idcKeys == NULL) {
22083 xmlSchemaVErrMemory(vctxt,
22084 "allocating the IDC key storage list", NULL);
22085 return (-1);
22087 vctxt->sizeIdcKeys = 40;
22088 } else if (vctxt->sizeIdcKeys <= vctxt->nbIdcKeys) {
22089 vctxt->sizeIdcKeys *= 2;
22090 vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
22091 xmlRealloc(vctxt->idcKeys, vctxt->sizeIdcKeys *
22092 sizeof(xmlSchemaPSVIIDCKeyPtr));
22093 if (vctxt->idcKeys == NULL) {
22094 xmlSchemaVErrMemory(vctxt,
22095 "re-allocating the IDC key storage list", NULL);
22096 return (-1);
22099 vctxt->idcKeys[vctxt->nbIdcKeys++] = key;
22101 return (0);
22105 * xmlSchemaIDCAppendNodeTableItem:
22106 * @bind: the IDC binding
22107 * @ntItem: the node-table item
22109 * Appends the IDC node-table item to the binding.
22111 * Returns 0 on success and -1 on internal errors.
22113 static int
22114 xmlSchemaIDCAppendNodeTableItem(xmlSchemaPSVIIDCBindingPtr bind,
22115 xmlSchemaPSVIIDCNodePtr ntItem)
22117 if (bind->nodeTable == NULL) {
22118 bind->sizeNodes = 10;
22119 bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
22120 xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr));
22121 if (bind->nodeTable == NULL) {
22122 xmlSchemaVErrMemory(NULL,
22123 "allocating an array of IDC node-table items", NULL);
22124 return(-1);
22126 } else if (bind->sizeNodes <= bind->nbNodes) {
22127 bind->sizeNodes *= 2;
22128 bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
22129 xmlRealloc(bind->nodeTable, bind->sizeNodes *
22130 sizeof(xmlSchemaPSVIIDCNodePtr));
22131 if (bind->nodeTable == NULL) {
22132 xmlSchemaVErrMemory(NULL,
22133 "re-allocating an array of IDC node-table items", NULL);
22134 return(-1);
22137 bind->nodeTable[bind->nbNodes++] = ntItem;
22138 return(0);
22142 * xmlSchemaIDCAcquireBinding:
22143 * @vctxt: the WXS validation context
22144 * @matcher: the IDC matcher
22146 * Looks up an PSVI IDC binding, for the IDC definition and
22147 * of the given matcher. If none found, a new one is created
22148 * and added to the IDC table.
22150 * Returns an IDC binding or NULL on internal errors.
22152 static xmlSchemaPSVIIDCBindingPtr
22153 xmlSchemaIDCAcquireBinding(xmlSchemaValidCtxtPtr vctxt,
22154 xmlSchemaIDCMatcherPtr matcher)
22156 xmlSchemaNodeInfoPtr ielem;
22158 ielem = vctxt->elemInfos[matcher->depth];
22160 if (ielem->idcTable == NULL) {
22161 ielem->idcTable = xmlSchemaIDCNewBinding(matcher->aidc->def);
22162 if (ielem->idcTable == NULL)
22163 return (NULL);
22164 return(ielem->idcTable);
22165 } else {
22166 xmlSchemaPSVIIDCBindingPtr bind = NULL;
22168 bind = ielem->idcTable;
22169 do {
22170 if (bind->definition == matcher->aidc->def)
22171 return(bind);
22172 if (bind->next == NULL) {
22173 bind->next = xmlSchemaIDCNewBinding(matcher->aidc->def);
22174 if (bind->next == NULL)
22175 return (NULL);
22176 return(bind->next);
22178 bind = bind->next;
22179 } while (bind != NULL);
22181 return (NULL);
22184 static xmlSchemaItemListPtr
22185 xmlSchemaIDCAcquireTargetList(xmlSchemaValidCtxtPtr vctxt ATTRIBUTE_UNUSED,
22186 xmlSchemaIDCMatcherPtr matcher)
22188 if (matcher->targets == NULL)
22189 matcher->targets = xmlSchemaItemListCreate();
22190 return(matcher->targets);
22194 * xmlSchemaIDCFreeKey:
22195 * @key: the IDC key
22197 * Frees an IDC key together with its compiled value.
22199 static void
22200 xmlSchemaIDCFreeKey(xmlSchemaPSVIIDCKeyPtr key)
22202 if (key->val != NULL)
22203 xmlSchemaFreeValue(key->val);
22204 xmlFree(key);
22208 * xmlSchemaIDCFreeBinding:
22210 * Frees an IDC binding. Note that the node table-items
22211 * are not freed.
22213 static void
22214 xmlSchemaIDCFreeBinding(xmlSchemaPSVIIDCBindingPtr bind)
22216 if (bind->nodeTable != NULL)
22217 xmlFree(bind->nodeTable);
22218 if (bind->dupls != NULL)
22219 xmlSchemaItemListFree(bind->dupls);
22220 xmlFree(bind);
22224 * xmlSchemaIDCFreeIDCTable:
22225 * @bind: the first IDC binding in the list
22227 * Frees an IDC table, i.e. all the IDC bindings in the list.
22229 static void
22230 xmlSchemaIDCFreeIDCTable(xmlSchemaPSVIIDCBindingPtr bind)
22232 xmlSchemaPSVIIDCBindingPtr prev;
22234 while (bind != NULL) {
22235 prev = bind;
22236 bind = bind->next;
22237 xmlSchemaIDCFreeBinding(prev);
22242 * xmlSchemaIDCFreeMatcherList:
22243 * @matcher: the first IDC matcher in the list
22245 * Frees a list of IDC matchers.
22247 static void
22248 xmlSchemaIDCFreeMatcherList(xmlSchemaIDCMatcherPtr matcher)
22250 xmlSchemaIDCMatcherPtr next;
22252 while (matcher != NULL) {
22253 next = matcher->next;
22254 if (matcher->keySeqs != NULL) {
22255 int i;
22256 for (i = 0; i < matcher->sizeKeySeqs; i++)
22257 if (matcher->keySeqs[i] != NULL)
22258 xmlFree(matcher->keySeqs[i]);
22259 xmlFree(matcher->keySeqs);
22261 if (matcher->targets != NULL) {
22262 if (matcher->idcType == XML_SCHEMA_TYPE_IDC_KEYREF) {
22263 int i;
22264 xmlSchemaPSVIIDCNodePtr idcNode;
22266 * Node-table items for keyrefs are not stored globally
22267 * to the validation context, since they are not bubbled.
22268 * We need to free them here.
22270 for (i = 0; i < matcher->targets->nbItems; i++) {
22271 idcNode =
22272 (xmlSchemaPSVIIDCNodePtr) matcher->targets->items[i];
22273 xmlFree(idcNode->keys);
22274 xmlFree(idcNode);
22277 xmlSchemaItemListFree(matcher->targets);
22279 xmlFree(matcher);
22280 matcher = next;
22285 * xmlSchemaIDCReleaseMatcherList:
22286 * @vctxt: the WXS validation context
22287 * @matcher: the first IDC matcher in the list
22289 * Caches a list of IDC matchers for reuse.
22291 static void
22292 xmlSchemaIDCReleaseMatcherList(xmlSchemaValidCtxtPtr vctxt,
22293 xmlSchemaIDCMatcherPtr matcher)
22295 xmlSchemaIDCMatcherPtr next;
22297 while (matcher != NULL) {
22298 next = matcher->next;
22299 if (matcher->keySeqs != NULL) {
22300 int i;
22302 * Don't free the array, but only the content.
22304 for (i = 0; i < matcher->sizeKeySeqs; i++)
22305 if (matcher->keySeqs[i] != NULL) {
22306 xmlFree(matcher->keySeqs[i]);
22307 matcher->keySeqs[i] = NULL;
22310 if (matcher->targets) {
22311 if (matcher->idcType == XML_SCHEMA_TYPE_IDC_KEYREF) {
22312 int i;
22313 xmlSchemaPSVIIDCNodePtr idcNode;
22315 * Node-table items for keyrefs are not stored globally
22316 * to the validation context, since they are not bubbled.
22317 * We need to free them here.
22319 for (i = 0; i < matcher->targets->nbItems; i++) {
22320 idcNode =
22321 (xmlSchemaPSVIIDCNodePtr) matcher->targets->items[i];
22322 xmlFree(idcNode->keys);
22323 xmlFree(idcNode);
22326 xmlSchemaItemListFree(matcher->targets);
22327 matcher->targets = NULL;
22329 matcher->next = NULL;
22331 * Cache the matcher.
22333 if (vctxt->idcMatcherCache != NULL)
22334 matcher->nextCached = vctxt->idcMatcherCache;
22335 vctxt->idcMatcherCache = matcher;
22337 matcher = next;
22342 * xmlSchemaIDCAddStateObject:
22343 * @vctxt: the WXS validation context
22344 * @matcher: the IDC matcher
22345 * @sel: the XPath information
22346 * @parent: the parent "selector" state object if any
22347 * @type: "selector" or "field"
22349 * Creates/reuses and activates state objects for the given
22350 * XPath information; if the XPath expression consists of unions,
22351 * multiple state objects are created for every unioned expression.
22353 * Returns 0 on success and -1 on internal errors.
22355 static int
22356 xmlSchemaIDCAddStateObject(xmlSchemaValidCtxtPtr vctxt,
22357 xmlSchemaIDCMatcherPtr matcher,
22358 xmlSchemaIDCSelectPtr sel,
22359 int type)
22361 xmlSchemaIDCStateObjPtr sto;
22364 * Reuse the state objects from the pool.
22366 if (vctxt->xpathStatePool != NULL) {
22367 sto = vctxt->xpathStatePool;
22368 vctxt->xpathStatePool = sto->next;
22369 sto->next = NULL;
22370 } else {
22372 * Create a new state object.
22374 sto = (xmlSchemaIDCStateObjPtr) xmlMalloc(sizeof(xmlSchemaIDCStateObj));
22375 if (sto == NULL) {
22376 xmlSchemaVErrMemory(NULL,
22377 "allocating an IDC state object", NULL);
22378 return (-1);
22380 memset(sto, 0, sizeof(xmlSchemaIDCStateObj));
22383 * Add to global list.
22385 if (vctxt->xpathStates != NULL)
22386 sto->next = vctxt->xpathStates;
22387 vctxt->xpathStates = sto;
22390 * Free the old xpath validation context.
22392 if (sto->xpathCtxt != NULL)
22393 xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
22396 * Create a new XPath (pattern) validation context.
22398 sto->xpathCtxt = (void *) xmlPatternGetStreamCtxt(
22399 (xmlPatternPtr) sel->xpathComp);
22400 if (sto->xpathCtxt == NULL) {
22401 VERROR_INT("xmlSchemaIDCAddStateObject",
22402 "failed to create an XPath validation context");
22403 return (-1);
22405 sto->type = type;
22406 sto->depth = vctxt->depth;
22407 sto->matcher = matcher;
22408 sto->sel = sel;
22409 sto->nbHistory = 0;
22411 #ifdef DEBUG_IDC
22412 xmlGenericError(xmlGenericErrorContext, "IDC: STO push '%s'\n",
22413 sto->sel->xpath);
22414 #endif
22415 return (0);
22419 * xmlSchemaXPathEvaluate:
22420 * @vctxt: the WXS validation context
22421 * @nodeType: the nodeType of the current node
22423 * Evaluates all active XPath state objects.
22425 * Returns the number of IC "field" state objects which resolved to
22426 * this node, 0 if none resolved and -1 on internal errors.
22428 static int
22429 xmlSchemaXPathEvaluate(xmlSchemaValidCtxtPtr vctxt,
22430 xmlElementType nodeType)
22432 xmlSchemaIDCStateObjPtr sto, head = NULL, first;
22433 int res, resolved = 0, depth = vctxt->depth;
22435 if (vctxt->xpathStates == NULL)
22436 return (0);
22438 if (nodeType == XML_ATTRIBUTE_NODE)
22439 depth++;
22440 #ifdef DEBUG_IDC
22442 xmlChar *str = NULL;
22443 xmlGenericError(xmlGenericErrorContext,
22444 "IDC: EVAL on %s, depth %d, type %d\n",
22445 xmlSchemaFormatQName(&str, vctxt->inode->nsName,
22446 vctxt->inode->localName), depth, nodeType);
22447 FREE_AND_NULL(str)
22449 #endif
22451 * Process all active XPath state objects.
22453 first = vctxt->xpathStates;
22454 sto = first;
22455 while (sto != head) {
22456 #ifdef DEBUG_IDC
22457 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR)
22458 xmlGenericError(xmlGenericErrorContext, "IDC: ['%s'] selector '%s'\n",
22459 sto->matcher->aidc->def->name, sto->sel->xpath);
22460 else
22461 xmlGenericError(xmlGenericErrorContext, "IDC: ['%s'] field '%s'\n",
22462 sto->matcher->aidc->def->name, sto->sel->xpath);
22463 #endif
22464 if (nodeType == XML_ELEMENT_NODE)
22465 res = xmlStreamPush((xmlStreamCtxtPtr) sto->xpathCtxt,
22466 vctxt->inode->localName, vctxt->inode->nsName);
22467 else
22468 res = xmlStreamPushAttr((xmlStreamCtxtPtr) sto->xpathCtxt,
22469 vctxt->inode->localName, vctxt->inode->nsName);
22471 if (res == -1) {
22472 VERROR_INT("xmlSchemaXPathEvaluate",
22473 "calling xmlStreamPush()");
22474 return (-1);
22476 if (res == 0)
22477 goto next_sto;
22479 * Full match.
22481 #ifdef DEBUG_IDC
22482 xmlGenericError(xmlGenericErrorContext, "IDC: "
22483 "MATCH\n");
22484 #endif
22486 * Register a match in the state object history.
22488 if (sto->history == NULL) {
22489 sto->history = (int *) xmlMalloc(5 * sizeof(int));
22490 if (sto->history == NULL) {
22491 xmlSchemaVErrMemory(NULL,
22492 "allocating the state object history", NULL);
22493 return(-1);
22495 sto->sizeHistory = 5;
22496 } else if (sto->sizeHistory <= sto->nbHistory) {
22497 sto->sizeHistory *= 2;
22498 sto->history = (int *) xmlRealloc(sto->history,
22499 sto->sizeHistory * sizeof(int));
22500 if (sto->history == NULL) {
22501 xmlSchemaVErrMemory(NULL,
22502 "re-allocating the state object history", NULL);
22503 return(-1);
22506 sto->history[sto->nbHistory++] = depth;
22508 #ifdef DEBUG_IDC
22509 xmlGenericError(xmlGenericErrorContext, "IDC: push match '%d'\n",
22510 vctxt->depth);
22511 #endif
22513 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
22514 xmlSchemaIDCSelectPtr sel;
22516 * Activate state objects for the IDC fields of
22517 * the IDC selector.
22519 #ifdef DEBUG_IDC
22520 xmlGenericError(xmlGenericErrorContext, "IDC: "
22521 "activating field states\n");
22522 #endif
22523 sel = sto->matcher->aidc->def->fields;
22524 while (sel != NULL) {
22525 if (xmlSchemaIDCAddStateObject(vctxt, sto->matcher,
22526 sel, XPATH_STATE_OBJ_TYPE_IDC_FIELD) == -1)
22527 return (-1);
22528 sel = sel->next;
22530 } else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
22532 * An IDC key node was found by the IDC field.
22534 #ifdef DEBUG_IDC
22535 xmlGenericError(xmlGenericErrorContext,
22536 "IDC: key found\n");
22537 #endif
22539 * Notify that the character value of this node is
22540 * needed.
22542 if (resolved == 0) {
22543 if ((vctxt->inode->flags &
22544 XML_SCHEMA_NODE_INFO_VALUE_NEEDED) == 0)
22545 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_VALUE_NEEDED;
22547 resolved++;
22549 next_sto:
22550 if (sto->next == NULL) {
22552 * Evaluate field state objects created on this node as well.
22554 head = first;
22555 sto = vctxt->xpathStates;
22556 } else
22557 sto = sto->next;
22559 return (resolved);
22562 static const xmlChar *
22563 xmlSchemaFormatIDCKeySequence(xmlSchemaValidCtxtPtr vctxt,
22564 xmlChar **buf,
22565 xmlSchemaPSVIIDCKeyPtr *seq,
22566 int count)
22568 int i, res;
22569 xmlChar *value = NULL;
22571 *buf = xmlStrdup(BAD_CAST "[");
22572 for (i = 0; i < count; i++) {
22573 *buf = xmlStrcat(*buf, BAD_CAST "'");
22574 res = xmlSchemaGetCanonValueWhtspExt(seq[i]->val,
22575 xmlSchemaGetWhiteSpaceFacetValue(seq[i]->type),
22576 &value);
22577 if (res == 0)
22578 *buf = xmlStrcat(*buf, BAD_CAST value);
22579 else {
22580 VERROR_INT("xmlSchemaFormatIDCKeySequence",
22581 "failed to compute a canonical value");
22582 *buf = xmlStrcat(*buf, BAD_CAST "???");
22584 if (i < count -1)
22585 *buf = xmlStrcat(*buf, BAD_CAST "', ");
22586 else
22587 *buf = xmlStrcat(*buf, BAD_CAST "'");
22588 if (value != NULL) {
22589 xmlFree(value);
22590 value = NULL;
22593 *buf = xmlStrcat(*buf, BAD_CAST "]");
22595 return (BAD_CAST *buf);
22599 * xmlSchemaXPathPop:
22600 * @vctxt: the WXS validation context
22602 * Pops all XPath states.
22604 * Returns 0 on success and -1 on internal errors.
22606 static int
22607 xmlSchemaXPathPop(xmlSchemaValidCtxtPtr vctxt)
22609 xmlSchemaIDCStateObjPtr sto;
22610 int res;
22612 if (vctxt->xpathStates == NULL)
22613 return(0);
22614 sto = vctxt->xpathStates;
22615 do {
22616 res = xmlStreamPop((xmlStreamCtxtPtr) sto->xpathCtxt);
22617 if (res == -1)
22618 return (-1);
22619 sto = sto->next;
22620 } while (sto != NULL);
22621 return(0);
22625 * xmlSchemaXPathProcessHistory:
22626 * @vctxt: the WXS validation context
22627 * @type: the simple/complex type of the current node if any at all
22628 * @val: the precompiled value
22630 * Processes and pops the history items of the IDC state objects.
22631 * IDC key-sequences are validated/created on IDC bindings.
22633 * Returns 0 on success and -1 on internal errors.
22635 static int
22636 xmlSchemaXPathProcessHistory(xmlSchemaValidCtxtPtr vctxt,
22637 int depth)
22639 xmlSchemaIDCStateObjPtr sto, nextsto;
22640 int res, matchDepth;
22641 xmlSchemaPSVIIDCKeyPtr key = NULL;
22642 xmlSchemaTypePtr type = vctxt->inode->typeDef, simpleType = NULL;
22644 if (vctxt->xpathStates == NULL)
22645 return (0);
22646 sto = vctxt->xpathStates;
22648 #ifdef DEBUG_IDC
22650 xmlChar *str = NULL;
22651 xmlGenericError(xmlGenericErrorContext,
22652 "IDC: BACK on %s, depth %d\n",
22653 xmlSchemaFormatQName(&str, vctxt->inode->nsName,
22654 vctxt->inode->localName), vctxt->depth);
22655 FREE_AND_NULL(str)
22657 #endif
22659 * Evaluate the state objects.
22661 while (sto != NULL) {
22662 res = xmlStreamPop((xmlStreamCtxtPtr) sto->xpathCtxt);
22663 if (res == -1) {
22664 VERROR_INT("xmlSchemaXPathProcessHistory",
22665 "calling xmlStreamPop()");
22666 return (-1);
22668 #ifdef DEBUG_IDC
22669 xmlGenericError(xmlGenericErrorContext, "IDC: stream pop '%s'\n",
22670 sto->sel->xpath);
22671 #endif
22672 if (sto->nbHistory == 0)
22673 goto deregister_check;
22675 matchDepth = sto->history[sto->nbHistory -1];
22678 * Only matches at the current depth are of interest.
22680 if (matchDepth != depth) {
22681 sto = sto->next;
22682 continue;
22684 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
22686 * NOTE: According to
22687 * http://www.w3.org/Bugs/Public/show_bug.cgi?id=2198
22688 * ... the simple-content of complex types is also allowed.
22691 if (WXS_IS_COMPLEX(type)) {
22692 if (WXS_HAS_SIMPLE_CONTENT(type)) {
22694 * Sanity check for complex types with simple content.
22696 simpleType = type->contentTypeDef;
22697 if (simpleType == NULL) {
22698 VERROR_INT("xmlSchemaXPathProcessHistory",
22699 "field resolves to a CT with simple content "
22700 "but the CT is missing the ST definition");
22701 return (-1);
22703 } else
22704 simpleType = NULL;
22705 } else
22706 simpleType = type;
22707 if (simpleType == NULL) {
22708 xmlChar *str = NULL;
22711 * Not qualified if the field resolves to a node of non
22712 * simple type.
22714 xmlSchemaCustomErr(ACTXT_CAST vctxt,
22715 XML_SCHEMAV_CVC_IDC, NULL,
22716 WXS_BASIC_CAST sto->matcher->aidc->def,
22717 "The XPath '%s' of a field of %s does evaluate to a node of "
22718 "non-simple type",
22719 sto->sel->xpath,
22720 xmlSchemaGetIDCDesignation(&str, sto->matcher->aidc->def));
22721 FREE_AND_NULL(str);
22722 sto->nbHistory--;
22723 goto deregister_check;
22726 if ((key == NULL) && (vctxt->inode->val == NULL)) {
22728 * Failed to provide the normalized value; maybe
22729 * the value was invalid.
22731 VERROR(XML_SCHEMAV_CVC_IDC,
22732 WXS_BASIC_CAST sto->matcher->aidc->def,
22733 "Warning: No precomputed value available, the value "
22734 "was either invalid or something strange happend");
22735 sto->nbHistory--;
22736 goto deregister_check;
22737 } else {
22738 xmlSchemaIDCMatcherPtr matcher = sto->matcher;
22739 xmlSchemaPSVIIDCKeyPtr *keySeq;
22740 int pos, idx;
22743 * The key will be anchored on the matcher's list of
22744 * key-sequences. The position in this list is determined
22745 * by the target node's depth relative to the matcher's
22746 * depth of creation (i.e. the depth of the scope element).
22748 * Element Depth Pos List-entries
22749 * <scope> 0 NULL
22750 * <bar> 1 NULL
22751 * <target/> 2 2 target
22752 * <bar>
22753 * </scope>
22755 * The size of the list is only dependant on the depth of
22756 * the tree.
22757 * An entry will be NULLed in selector_leave, i.e. when
22758 * we hit the target's
22760 pos = sto->depth - matcher->depth;
22761 idx = sto->sel->index;
22764 * Create/grow the array of key-sequences.
22766 if (matcher->keySeqs == NULL) {
22767 if (pos > 9)
22768 matcher->sizeKeySeqs = pos * 2;
22769 else
22770 matcher->sizeKeySeqs = 10;
22771 matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
22772 xmlMalloc(matcher->sizeKeySeqs *
22773 sizeof(xmlSchemaPSVIIDCKeyPtr *));
22774 if (matcher->keySeqs == NULL) {
22775 xmlSchemaVErrMemory(NULL,
22776 "allocating an array of key-sequences",
22777 NULL);
22778 return(-1);
22780 memset(matcher->keySeqs, 0,
22781 matcher->sizeKeySeqs *
22782 sizeof(xmlSchemaPSVIIDCKeyPtr *));
22783 } else if (pos >= matcher->sizeKeySeqs) {
22784 int i = matcher->sizeKeySeqs;
22786 matcher->sizeKeySeqs *= 2;
22787 matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
22788 xmlRealloc(matcher->keySeqs,
22789 matcher->sizeKeySeqs *
22790 sizeof(xmlSchemaPSVIIDCKeyPtr *));
22791 if (matcher->keySeqs == NULL) {
22792 xmlSchemaVErrMemory(NULL,
22793 "reallocating an array of key-sequences",
22794 NULL);
22795 return (-1);
22798 * The array needs to be NULLed.
22799 * TODO: Use memset?
22801 for (; i < matcher->sizeKeySeqs; i++)
22802 matcher->keySeqs[i] = NULL;
22806 * Get/create the key-sequence.
22808 keySeq = matcher->keySeqs[pos];
22809 if (keySeq == NULL) {
22810 goto create_sequence;
22811 } else if (keySeq[idx] != NULL) {
22812 xmlChar *str = NULL;
22814 * cvc-identity-constraint:
22815 * 3 For each node in the �target node set� all
22816 * of the {fields}, with that node as the context
22817 * node, evaluate to either an empty node-set or
22818 * a node-set with exactly one member, which must
22819 * have a simple type.
22821 * The key was already set; report an error.
22823 xmlSchemaCustomErr(ACTXT_CAST vctxt,
22824 XML_SCHEMAV_CVC_IDC, NULL,
22825 WXS_BASIC_CAST matcher->aidc->def,
22826 "The XPath '%s' of a field of %s evaluates to a "
22827 "node-set with more than one member",
22828 sto->sel->xpath,
22829 xmlSchemaGetIDCDesignation(&str, matcher->aidc->def));
22830 FREE_AND_NULL(str);
22831 sto->nbHistory--;
22832 goto deregister_check;
22833 } else
22834 goto create_key;
22836 create_sequence:
22838 * Create a key-sequence.
22840 keySeq = (xmlSchemaPSVIIDCKeyPtr *) xmlMalloc(
22841 matcher->aidc->def->nbFields *
22842 sizeof(xmlSchemaPSVIIDCKeyPtr));
22843 if (keySeq == NULL) {
22844 xmlSchemaVErrMemory(NULL,
22845 "allocating an IDC key-sequence", NULL);
22846 return(-1);
22848 memset(keySeq, 0, matcher->aidc->def->nbFields *
22849 sizeof(xmlSchemaPSVIIDCKeyPtr));
22850 matcher->keySeqs[pos] = keySeq;
22851 create_key:
22853 * Create a key once per node only.
22855 if (key == NULL) {
22856 key = (xmlSchemaPSVIIDCKeyPtr) xmlMalloc(
22857 sizeof(xmlSchemaPSVIIDCKey));
22858 if (key == NULL) {
22859 xmlSchemaVErrMemory(NULL,
22860 "allocating a IDC key", NULL);
22861 xmlFree(keySeq);
22862 matcher->keySeqs[pos] = NULL;
22863 return(-1);
22866 * Consume the compiled value.
22868 key->type = simpleType;
22869 key->val = vctxt->inode->val;
22870 vctxt->inode->val = NULL;
22872 * Store the key in a global list.
22874 if (xmlSchemaIDCStoreKey(vctxt, key) == -1) {
22875 xmlSchemaIDCFreeKey(key);
22876 return (-1);
22879 keySeq[idx] = key;
22881 } else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
22883 xmlSchemaPSVIIDCKeyPtr **keySeq = NULL;
22884 /* xmlSchemaPSVIIDCBindingPtr bind; */
22885 xmlSchemaPSVIIDCNodePtr ntItem;
22886 xmlSchemaIDCMatcherPtr matcher;
22887 xmlSchemaIDCPtr idc;
22888 xmlSchemaItemListPtr targets;
22889 int pos, i, j, nbKeys;
22891 * Here we have the following scenario:
22892 * An IDC 'selector' state object resolved to a target node,
22893 * during the time this target node was in the
22894 * ancestor-or-self axis, the 'field' state object(s) looked
22895 * out for matching nodes to create a key-sequence for this
22896 * target node. Now we are back to this target node and need
22897 * to put the key-sequence, together with the target node
22898 * itself, into the node-table of the corresponding IDC
22899 * binding.
22901 matcher = sto->matcher;
22902 idc = matcher->aidc->def;
22903 nbKeys = idc->nbFields;
22904 pos = depth - matcher->depth;
22906 * Check if the matcher has any key-sequences at all, plus
22907 * if it has a key-sequence for the current target node.
22909 if ((matcher->keySeqs == NULL) ||
22910 (matcher->sizeKeySeqs <= pos)) {
22911 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
22912 goto selector_key_error;
22913 else
22914 goto selector_leave;
22917 keySeq = &(matcher->keySeqs[pos]);
22918 if (*keySeq == NULL) {
22919 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
22920 goto selector_key_error;
22921 else
22922 goto selector_leave;
22925 for (i = 0; i < nbKeys; i++) {
22926 if ((*keySeq)[i] == NULL) {
22928 * Not qualified, if not all fields did resolve.
22930 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY) {
22932 * All fields of a "key" IDC must resolve.
22934 goto selector_key_error;
22936 goto selector_leave;
22940 * All fields did resolve.
22944 * 4.1 If the {identity-constraint category} is unique(/key),
22945 * then no two members of the �qualified node set� have
22946 * �key-sequences� whose members are pairwise equal, as
22947 * defined by Equal in [XML Schemas: Datatypes].
22949 * Get the IDC binding from the matcher and check for
22950 * duplicate key-sequences.
22952 #if 0
22953 bind = xmlSchemaIDCAcquireBinding(vctxt, matcher);
22954 #endif
22955 targets = xmlSchemaIDCAcquireTargetList(vctxt, matcher);
22956 if ((idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) &&
22957 (targets->nbItems != 0)) {
22958 xmlSchemaPSVIIDCKeyPtr ckey, bkey, *bkeySeq;
22960 i = 0;
22961 res = 0;
22963 * Compare the key-sequences, key by key.
22965 do {
22966 bkeySeq =
22967 ((xmlSchemaPSVIIDCNodePtr) targets->items[i])->keys;
22968 for (j = 0; j < nbKeys; j++) {
22969 ckey = (*keySeq)[j];
22970 bkey = bkeySeq[j];
22971 res = xmlSchemaAreValuesEqual(ckey->val, bkey->val);
22972 if (res == -1) {
22973 return (-1);
22974 } else if (res == 0) {
22976 * One of the keys differs, so the key-sequence
22977 * won't be equal; get out.
22979 break;
22982 if (res == 1) {
22984 * Duplicate key-sequence found.
22986 break;
22988 i++;
22989 } while (i < targets->nbItems);
22990 if (i != targets->nbItems) {
22991 xmlChar *str = NULL, *strB = NULL;
22993 * TODO: Try to report the key-sequence.
22995 xmlSchemaCustomErr(ACTXT_CAST vctxt,
22996 XML_SCHEMAV_CVC_IDC, NULL,
22997 WXS_BASIC_CAST idc,
22998 "Duplicate key-sequence %s in %s",
22999 xmlSchemaFormatIDCKeySequence(vctxt, &str,
23000 (*keySeq), nbKeys),
23001 xmlSchemaGetIDCDesignation(&strB, idc));
23002 FREE_AND_NULL(str);
23003 FREE_AND_NULL(strB);
23004 goto selector_leave;
23008 * Add a node-table item to the IDC binding.
23010 ntItem = (xmlSchemaPSVIIDCNodePtr) xmlMalloc(
23011 sizeof(xmlSchemaPSVIIDCNode));
23012 if (ntItem == NULL) {
23013 xmlSchemaVErrMemory(NULL,
23014 "allocating an IDC node-table item", NULL);
23015 xmlFree(*keySeq);
23016 *keySeq = NULL;
23017 return(-1);
23019 memset(ntItem, 0, sizeof(xmlSchemaPSVIIDCNode));
23022 * Store the node-table item in a global list.
23024 if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) {
23025 if (xmlSchemaIDCStoreNodeTableItem(vctxt, ntItem) == -1) {
23026 xmlFree(ntItem);
23027 xmlFree(*keySeq);
23028 *keySeq = NULL;
23029 return (-1);
23031 ntItem->nodeQNameID = -1;
23032 } else {
23034 * Save a cached QName for this node on the IDC node, to be
23035 * able to report it, even if the node is not saved.
23037 ntItem->nodeQNameID = xmlSchemaVAddNodeQName(vctxt,
23038 vctxt->inode->localName, vctxt->inode->nsName);
23039 if (ntItem->nodeQNameID == -1) {
23040 xmlFree(ntItem);
23041 xmlFree(*keySeq);
23042 *keySeq = NULL;
23043 return (-1);
23047 * Init the node-table item: Save the node, position and
23048 * consume the key-sequence.
23050 ntItem->node = vctxt->node;
23051 ntItem->nodeLine = vctxt->inode->nodeLine;
23052 ntItem->keys = *keySeq;
23053 *keySeq = NULL;
23054 #if 0
23055 if (xmlSchemaIDCAppendNodeTableItem(bind, ntItem) == -1)
23056 #endif
23057 if (xmlSchemaItemListAdd(targets, ntItem) == -1) {
23058 if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
23060 * Free the item, since keyref items won't be
23061 * put on a global list.
23063 xmlFree(ntItem->keys);
23064 xmlFree(ntItem);
23066 return (-1);
23069 goto selector_leave;
23070 selector_key_error:
23072 xmlChar *str = NULL;
23074 * 4.2.1 (KEY) The �target node set� and the
23075 * �qualified node set� are equal, that is, every
23076 * member of the �target node set� is also a member
23077 * of the �qualified node set� and vice versa.
23079 xmlSchemaCustomErr(ACTXT_CAST vctxt,
23080 XML_SCHEMAV_CVC_IDC, NULL,
23081 WXS_BASIC_CAST idc,
23082 "Not all fields of %s evaluate to a node",
23083 xmlSchemaGetIDCDesignation(&str, idc), NULL);
23084 FREE_AND_NULL(str);
23086 selector_leave:
23088 * Free the key-sequence if not added to the IDC table.
23090 if ((keySeq != NULL) && (*keySeq != NULL)) {
23091 xmlFree(*keySeq);
23092 *keySeq = NULL;
23094 } /* if selector */
23096 sto->nbHistory--;
23098 deregister_check:
23100 * Deregister state objects if they reach the depth of creation.
23102 if ((sto->nbHistory == 0) && (sto->depth == depth)) {
23103 #ifdef DEBUG_IDC
23104 xmlGenericError(xmlGenericErrorContext, "IDC: STO pop '%s'\n",
23105 sto->sel->xpath);
23106 #endif
23107 if (vctxt->xpathStates != sto) {
23108 VERROR_INT("xmlSchemaXPathProcessHistory",
23109 "The state object to be removed is not the first "
23110 "in the list");
23112 nextsto = sto->next;
23114 * Unlink from the list of active XPath state objects.
23116 vctxt->xpathStates = sto->next;
23117 sto->next = vctxt->xpathStatePool;
23119 * Link it to the pool of reusable state objects.
23121 vctxt->xpathStatePool = sto;
23122 sto = nextsto;
23123 } else
23124 sto = sto->next;
23125 } /* while (sto != NULL) */
23126 return (0);
23130 * xmlSchemaIDCRegisterMatchers:
23131 * @vctxt: the WXS validation context
23132 * @elemDecl: the element declaration
23134 * Creates helper objects to evaluate IDC selectors/fields
23135 * successively.
23137 * Returns 0 if OK and -1 on internal errors.
23139 static int
23140 xmlSchemaIDCRegisterMatchers(xmlSchemaValidCtxtPtr vctxt,
23141 xmlSchemaElementPtr elemDecl)
23143 xmlSchemaIDCMatcherPtr matcher, last = NULL;
23144 xmlSchemaIDCPtr idc, refIdc;
23145 xmlSchemaIDCAugPtr aidc;
23147 idc = (xmlSchemaIDCPtr) elemDecl->idcs;
23148 if (idc == NULL)
23149 return (0);
23151 #ifdef DEBUG_IDC
23153 xmlChar *str = NULL;
23154 xmlGenericError(xmlGenericErrorContext,
23155 "IDC: REGISTER on %s, depth %d\n",
23156 (char *) xmlSchemaFormatQName(&str, vctxt->inode->nsName,
23157 vctxt->inode->localName), vctxt->depth);
23158 FREE_AND_NULL(str)
23160 #endif
23161 if (vctxt->inode->idcMatchers != NULL) {
23162 VERROR_INT("xmlSchemaIDCRegisterMatchers",
23163 "The chain of IDC matchers is expected to be empty");
23164 return (-1);
23166 do {
23167 if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
23169 * Since IDCs bubbles are expensive we need to know the
23170 * depth at which the bubbles should stop; this will be
23171 * the depth of the top-most keyref IDC. If no keyref
23172 * references a key/unique IDC, the keyrefDepth will
23173 * be -1, indicating that no bubbles are needed.
23175 refIdc = (xmlSchemaIDCPtr) idc->ref->item;
23176 if (refIdc != NULL) {
23178 * Remember that we have keyrefs on this node.
23180 vctxt->inode->hasKeyrefs = 1;
23182 * Lookup the referenced augmented IDC info.
23184 aidc = vctxt->aidcs;
23185 while (aidc != NULL) {
23186 if (aidc->def == refIdc)
23187 break;
23188 aidc = aidc->next;
23190 if (aidc == NULL) {
23191 VERROR_INT("xmlSchemaIDCRegisterMatchers",
23192 "Could not find an augmented IDC item for an IDC "
23193 "definition");
23194 return (-1);
23196 if ((aidc->keyrefDepth == -1) ||
23197 (vctxt->depth < aidc->keyrefDepth))
23198 aidc->keyrefDepth = vctxt->depth;
23202 * Lookup the augmented IDC item for the IDC definition.
23204 aidc = vctxt->aidcs;
23205 while (aidc != NULL) {
23206 if (aidc->def == idc)
23207 break;
23208 aidc = aidc->next;
23210 if (aidc == NULL) {
23211 VERROR_INT("xmlSchemaIDCRegisterMatchers",
23212 "Could not find an augmented IDC item for an IDC definition");
23213 return (-1);
23216 * Create an IDC matcher for every IDC definition.
23218 if (vctxt->idcMatcherCache != NULL) {
23220 * Reuse a cached matcher.
23222 matcher = vctxt->idcMatcherCache;
23223 vctxt->idcMatcherCache = matcher->nextCached;
23224 matcher->nextCached = NULL;
23225 } else {
23226 matcher = (xmlSchemaIDCMatcherPtr)
23227 xmlMalloc(sizeof(xmlSchemaIDCMatcher));
23228 if (matcher == NULL) {
23229 xmlSchemaVErrMemory(vctxt,
23230 "allocating an IDC matcher", NULL);
23231 return (-1);
23233 memset(matcher, 0, sizeof(xmlSchemaIDCMatcher));
23235 if (last == NULL)
23236 vctxt->inode->idcMatchers = matcher;
23237 else
23238 last->next = matcher;
23239 last = matcher;
23241 matcher->type = IDC_MATCHER;
23242 matcher->depth = vctxt->depth;
23243 matcher->aidc = aidc;
23244 matcher->idcType = aidc->def->type;
23245 #ifdef DEBUG_IDC
23246 xmlGenericError(xmlGenericErrorContext, "IDC: register matcher\n");
23247 #endif
23249 * Init the automaton state object.
23251 if (xmlSchemaIDCAddStateObject(vctxt, matcher,
23252 idc->selector, XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) == -1)
23253 return (-1);
23255 idc = idc->next;
23256 } while (idc != NULL);
23257 return (0);
23260 static int
23261 xmlSchemaIDCFillNodeTables(xmlSchemaValidCtxtPtr vctxt,
23262 xmlSchemaNodeInfoPtr ielem)
23264 xmlSchemaPSVIIDCBindingPtr bind;
23265 int res, i, j, k, nbTargets, nbFields, nbDupls, nbNodeTable;
23266 xmlSchemaPSVIIDCKeyPtr *keys, *ntkeys;
23267 xmlSchemaPSVIIDCNodePtr *targets, *dupls;
23269 xmlSchemaIDCMatcherPtr matcher = ielem->idcMatchers;
23270 /* vctxt->createIDCNodeTables */
23271 while (matcher != NULL) {
23273 * Skip keyref IDCs and empty IDC target-lists.
23275 if ((matcher->aidc->def->type == XML_SCHEMA_TYPE_IDC_KEYREF) ||
23276 WXS_ILIST_IS_EMPTY(matcher->targets))
23278 matcher = matcher->next;
23279 continue;
23282 * If we _want_ the IDC node-table to be created in any case
23283 * then do so. Otherwise create them only if keyrefs need them.
23285 if ((! vctxt->createIDCNodeTables) &&
23286 ((matcher->aidc->keyrefDepth == -1) ||
23287 (matcher->aidc->keyrefDepth > vctxt->depth)))
23289 matcher = matcher->next;
23290 continue;
23293 * Get/create the IDC binding on this element for the IDC definition.
23295 bind = xmlSchemaIDCAcquireBinding(vctxt, matcher);
23297 if (! WXS_ILIST_IS_EMPTY(bind->dupls)) {
23298 dupls = (xmlSchemaPSVIIDCNodePtr *) bind->dupls->items;
23299 nbDupls = bind->dupls->nbItems;
23300 } else {
23301 dupls = NULL;
23302 nbDupls = 0;
23304 if (bind->nodeTable != NULL) {
23305 nbNodeTable = bind->nbNodes;
23306 } else {
23307 nbNodeTable = 0;
23310 if ((nbNodeTable == 0) && (nbDupls == 0)) {
23312 * Transfer all IDC target-nodes to the IDC node-table.
23314 bind->nodeTable =
23315 (xmlSchemaPSVIIDCNodePtr *) matcher->targets->items;
23316 bind->sizeNodes = matcher->targets->sizeItems;
23317 bind->nbNodes = matcher->targets->nbItems;
23319 matcher->targets->items = NULL;
23320 matcher->targets->sizeItems = 0;
23321 matcher->targets->nbItems = 0;
23322 } else {
23324 * Compare the key-sequences and add to the IDC node-table.
23326 nbTargets = matcher->targets->nbItems;
23327 targets = (xmlSchemaPSVIIDCNodePtr *) matcher->targets->items;
23328 nbFields = matcher->aidc->def->nbFields;
23329 i = 0;
23330 do {
23331 keys = targets[i]->keys;
23332 if (nbDupls) {
23334 * Search in already found duplicates first.
23336 j = 0;
23337 do {
23338 if (nbFields == 1) {
23339 res = xmlSchemaAreValuesEqual(keys[0]->val,
23340 dupls[j]->keys[0]->val);
23341 if (res == -1)
23342 goto internal_error;
23343 if (res == 1) {
23345 * Equal key-sequence.
23347 goto next_target;
23349 } else {
23350 res = 0;
23351 ntkeys = dupls[j]->keys;
23352 for (k = 0; k < nbFields; k++) {
23353 res = xmlSchemaAreValuesEqual(keys[k]->val,
23354 ntkeys[k]->val);
23355 if (res == -1)
23356 goto internal_error;
23357 if (res == 0) {
23359 * One of the keys differs.
23361 break;
23364 if (res == 1) {
23366 * Equal key-sequence found.
23368 goto next_target;
23371 j++;
23372 } while (j < nbDupls);
23374 if (nbNodeTable) {
23375 j = 0;
23376 do {
23377 if (nbFields == 1) {
23378 res = xmlSchemaAreValuesEqual(keys[0]->val,
23379 bind->nodeTable[j]->keys[0]->val);
23380 if (res == -1)
23381 goto internal_error;
23382 if (res == 0) {
23384 * The key-sequence differs.
23386 goto next_node_table_entry;
23388 } else {
23389 res = 0;
23390 ntkeys = bind->nodeTable[j]->keys;
23391 for (k = 0; k < nbFields; k++) {
23392 res = xmlSchemaAreValuesEqual(keys[k]->val,
23393 ntkeys[k]->val);
23394 if (res == -1)
23395 goto internal_error;
23396 if (res == 0) {
23398 * One of the keys differs.
23400 goto next_node_table_entry;
23405 * Add the duplicate to the list of duplicates.
23407 if (bind->dupls == NULL) {
23408 bind->dupls = xmlSchemaItemListCreate();
23409 if (bind->dupls == NULL)
23410 goto internal_error;
23412 if (xmlSchemaItemListAdd(bind->dupls, bind->nodeTable[j]) == -1)
23413 goto internal_error;
23415 * Remove the duplicate entry from the IDC node-table.
23417 bind->nodeTable[j] = bind->nodeTable[bind->nbNodes -1];
23418 bind->nbNodes--;
23420 goto next_target;
23422 next_node_table_entry:
23423 j++;
23424 } while (j < nbNodeTable);
23427 * If everything is fine, then add the IDC target-node to
23428 * the IDC node-table.
23430 if (xmlSchemaIDCAppendNodeTableItem(bind, targets[i]) == -1)
23431 goto internal_error;
23433 next_target:
23434 i++;
23435 } while (i < nbTargets);
23437 matcher = matcher->next;
23439 return(0);
23441 internal_error:
23442 return(-1);
23446 * xmlSchemaBubbleIDCNodeTables:
23447 * @depth: the current tree depth
23449 * Merges IDC bindings of an element at @depth into the corresponding IDC
23450 * bindings of its parent element. If a duplicate note-table entry is found,
23451 * both, the parent node-table entry and child entry are discarded from the
23452 * node-table of the parent.
23454 * Returns 0 if OK and -1 on internal errors.
23456 static int
23457 xmlSchemaBubbleIDCNodeTables(xmlSchemaValidCtxtPtr vctxt)
23459 xmlSchemaPSVIIDCBindingPtr bind; /* IDC bindings of the current node. */
23460 xmlSchemaPSVIIDCBindingPtr *parTable, parBind = NULL; /* parent IDC bindings. */
23461 xmlSchemaPSVIIDCNodePtr node, parNode = NULL, *dupls, *parNodes; /* node-table entries. */
23462 xmlSchemaIDCAugPtr aidc;
23463 int i, j, k, ret = 0, nbFields, oldNum, oldDupls;
23465 bind = vctxt->inode->idcTable;
23466 if (bind == NULL) {
23467 /* Fine, no table, no bubbles. */
23468 return (0);
23471 parTable = &(vctxt->elemInfos[vctxt->depth -1]->idcTable);
23473 * Walk all bindings; create new or add to existing bindings.
23474 * Remove duplicate key-sequences.
23476 while (bind != NULL) {
23478 if ((bind->nbNodes == 0) && WXS_ILIST_IS_EMPTY(bind->dupls))
23479 goto next_binding;
23481 * Check if the key/unique IDC table needs to be bubbled.
23483 if (! vctxt->createIDCNodeTables) {
23484 aidc = vctxt->aidcs;
23485 do {
23486 if (aidc->def == bind->definition) {
23487 if ((aidc->keyrefDepth == -1) ||
23488 (aidc->keyrefDepth >= vctxt->depth)) {
23489 goto next_binding;
23491 break;
23493 aidc = aidc->next;
23494 } while (aidc != NULL);
23497 if (parTable != NULL)
23498 parBind = *parTable;
23500 * Search a matching parent binding for the
23501 * IDC definition.
23503 while (parBind != NULL) {
23504 if (parBind->definition == bind->definition)
23505 break;
23506 parBind = parBind->next;
23509 if (parBind != NULL) {
23511 * Compare every node-table entry of the child node,
23512 * i.e. the key-sequence within, ...
23514 oldNum = parBind->nbNodes; /* Skip newly added items. */
23516 if (! WXS_ILIST_IS_EMPTY(parBind->dupls)) {
23517 oldDupls = parBind->dupls->nbItems;
23518 dupls = (xmlSchemaPSVIIDCNodePtr *) parBind->dupls->items;
23519 } else {
23520 dupls = NULL;
23521 oldDupls = 0;
23524 parNodes = parBind->nodeTable;
23525 nbFields = bind->definition->nbFields;
23527 for (i = 0; i < bind->nbNodes; i++) {
23528 node = bind->nodeTable[i];
23529 if (node == NULL)
23530 continue;
23532 * ...with every key-sequence of the parent node, already
23533 * evaluated to be a duplicate key-sequence.
23535 if (oldDupls) {
23536 j = 0;
23537 while (j < oldDupls) {
23538 if (nbFields == 1) {
23539 ret = xmlSchemaAreValuesEqual(
23540 node->keys[0]->val,
23541 dupls[j]->keys[0]->val);
23542 if (ret == -1)
23543 goto internal_error;
23544 if (ret == 0) {
23545 j++;
23546 continue;
23548 } else {
23549 parNode = dupls[j];
23550 for (k = 0; k < nbFields; k++) {
23551 ret = xmlSchemaAreValuesEqual(
23552 node->keys[k]->val,
23553 parNode->keys[k]->val);
23554 if (ret == -1)
23555 goto internal_error;
23556 if (ret == 0)
23557 break;
23560 if (ret == 1)
23561 /* Duplicate found. */
23562 break;
23563 j++;
23565 if (j != oldDupls) {
23566 /* Duplicate found. Skip this entry. */
23567 continue;
23571 * ... and with every key-sequence of the parent node.
23573 if (oldNum) {
23574 j = 0;
23575 while (j < oldNum) {
23576 parNode = parNodes[j];
23577 if (nbFields == 1) {
23578 ret = xmlSchemaAreValuesEqual(
23579 node->keys[0]->val,
23580 parNode->keys[0]->val);
23581 if (ret == -1)
23582 goto internal_error;
23583 if (ret == 0) {
23584 j++;
23585 continue;
23587 } else {
23588 for (k = 0; k < nbFields; k++) {
23589 ret = xmlSchemaAreValuesEqual(
23590 node->keys[k]->val,
23591 parNode->keys[k]->val);
23592 if (ret == -1)
23593 goto internal_error;
23594 if (ret == 0)
23595 break;
23598 if (ret == 1)
23599 /* Duplicate found. */
23600 break;
23601 j++;
23603 if (j != oldNum) {
23605 * Handle duplicates. Move the duplicate in
23606 * the parent's node-table to the list of
23607 * duplicates.
23609 oldNum--;
23610 parBind->nbNodes--;
23612 * Move last old item to pos of duplicate.
23614 parNodes[j] = parNodes[oldNum];
23616 if (parBind->nbNodes != oldNum) {
23618 * If new items exist, move last new item to
23619 * last of old items.
23621 parNodes[oldNum] =
23622 parNodes[parBind->nbNodes];
23624 if (parBind->dupls == NULL) {
23625 parBind->dupls = xmlSchemaItemListCreate();
23626 if (parBind->dupls == NULL)
23627 goto internal_error;
23629 xmlSchemaItemListAdd(parBind->dupls, parNode);
23630 } else {
23632 * Add the node-table entry (node and key-sequence) of
23633 * the child node to the node table of the parent node.
23635 if (parBind->nodeTable == NULL) {
23636 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
23637 xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr));
23638 if (parBind->nodeTable == NULL) {
23639 xmlSchemaVErrMemory(NULL,
23640 "allocating IDC list of node-table items", NULL);
23641 goto internal_error;
23643 parBind->sizeNodes = 1;
23644 } else if (parBind->nbNodes >= parBind->sizeNodes) {
23645 parBind->sizeNodes *= 2;
23646 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
23647 xmlRealloc(parBind->nodeTable, parBind->sizeNodes *
23648 sizeof(xmlSchemaPSVIIDCNodePtr));
23649 if (parBind->nodeTable == NULL) {
23650 xmlSchemaVErrMemory(NULL,
23651 "re-allocating IDC list of node-table items", NULL);
23652 goto internal_error;
23655 parNodes = parBind->nodeTable;
23657 * Append the new node-table entry to the 'new node-table
23658 * entries' section.
23660 parNodes[parBind->nbNodes++] = node;
23666 } else {
23668 * No binding for the IDC was found: create a new one and
23669 * copy all node-tables.
23671 parBind = xmlSchemaIDCNewBinding(bind->definition);
23672 if (parBind == NULL)
23673 goto internal_error;
23676 * TODO: Hmm, how to optimize the initial number of
23677 * allocated entries?
23679 if (bind->nbNodes != 0) {
23681 * Add all IDC node-table entries.
23683 if (! vctxt->psviExposeIDCNodeTables) {
23685 * Just move the entries.
23686 * NOTE: this is quite save here, since
23687 * all the keyref lookups have already been
23688 * performed.
23690 parBind->nodeTable = bind->nodeTable;
23691 bind->nodeTable = NULL;
23692 parBind->sizeNodes = bind->sizeNodes;
23693 bind->sizeNodes = 0;
23694 parBind->nbNodes = bind->nbNodes;
23695 bind->nbNodes = 0;
23696 } else {
23698 * Copy the entries.
23700 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
23701 xmlMalloc(bind->nbNodes *
23702 sizeof(xmlSchemaPSVIIDCNodePtr));
23703 if (parBind->nodeTable == NULL) {
23704 xmlSchemaVErrMemory(NULL,
23705 "allocating an array of IDC node-table "
23706 "items", NULL);
23707 xmlSchemaIDCFreeBinding(parBind);
23708 goto internal_error;
23710 parBind->sizeNodes = bind->nbNodes;
23711 parBind->nbNodes = bind->nbNodes;
23712 memcpy(parBind->nodeTable, bind->nodeTable,
23713 bind->nbNodes * sizeof(xmlSchemaPSVIIDCNodePtr));
23716 if (bind->dupls) {
23718 * Move the duplicates.
23720 if (parBind->dupls != NULL)
23721 xmlSchemaItemListFree(parBind->dupls);
23722 parBind->dupls = bind->dupls;
23723 bind->dupls = NULL;
23725 if (parTable != NULL) {
23726 if (*parTable == NULL)
23727 *parTable = parBind;
23728 else {
23729 parBind->next = *parTable;
23730 *parTable = parBind;
23735 next_binding:
23736 bind = bind->next;
23738 return (0);
23740 internal_error:
23741 return(-1);
23745 * xmlSchemaCheckCVCIDCKeyRef:
23746 * @vctxt: the WXS validation context
23747 * @elemDecl: the element declaration
23749 * Check the cvc-idc-keyref constraints.
23751 static int
23752 xmlSchemaCheckCVCIDCKeyRef(xmlSchemaValidCtxtPtr vctxt)
23754 xmlSchemaIDCMatcherPtr matcher;
23755 xmlSchemaPSVIIDCBindingPtr bind;
23757 matcher = vctxt->inode->idcMatchers;
23759 * Find a keyref.
23761 while (matcher != NULL) {
23762 if ((matcher->idcType == XML_SCHEMA_TYPE_IDC_KEYREF) &&
23763 matcher->targets &&
23764 matcher->targets->nbItems)
23766 int i, j, k, res, nbFields, hasDupls;
23767 xmlSchemaPSVIIDCKeyPtr *refKeys, *keys;
23768 xmlSchemaPSVIIDCNodePtr refNode = NULL;
23770 nbFields = matcher->aidc->def->nbFields;
23773 * Find the IDC node-table for the referenced IDC key/unique.
23775 bind = vctxt->inode->idcTable;
23776 while (bind != NULL) {
23777 if ((xmlSchemaIDCPtr) matcher->aidc->def->ref->item ==
23778 bind->definition)
23779 break;
23780 bind = bind->next;
23782 hasDupls = (bind && bind->dupls && bind->dupls->nbItems) ? 1 : 0;
23784 * Search for a matching key-sequences.
23786 for (i = 0; i < matcher->targets->nbItems; i++) {
23787 res = 0;
23788 refNode = matcher->targets->items[i];
23789 if (bind != NULL) {
23790 refKeys = refNode->keys;
23791 for (j = 0; j < bind->nbNodes; j++) {
23792 keys = bind->nodeTable[j]->keys;
23793 for (k = 0; k < nbFields; k++) {
23794 res = xmlSchemaAreValuesEqual(keys[k]->val,
23795 refKeys[k]->val);
23796 if (res == 0)
23797 break;
23798 else if (res == -1) {
23799 return (-1);
23802 if (res == 1) {
23804 * Match found.
23806 break;
23809 if ((res == 0) && hasDupls) {
23811 * Search in duplicates
23813 for (j = 0; j < bind->dupls->nbItems; j++) {
23814 keys = ((xmlSchemaPSVIIDCNodePtr)
23815 bind->dupls->items[j])->keys;
23816 for (k = 0; k < nbFields; k++) {
23817 res = xmlSchemaAreValuesEqual(keys[k]->val,
23818 refKeys[k]->val);
23819 if (res == 0)
23820 break;
23821 else if (res == -1) {
23822 return (-1);
23825 if (res == 1) {
23827 * Match in duplicates found.
23829 xmlChar *str = NULL, *strB = NULL;
23830 xmlSchemaKeyrefErr(vctxt,
23831 XML_SCHEMAV_CVC_IDC, refNode,
23832 (xmlSchemaTypePtr) matcher->aidc->def,
23833 "More than one match found for "
23834 "key-sequence %s of keyref '%s'",
23835 xmlSchemaFormatIDCKeySequence(vctxt, &str,
23836 refNode->keys, nbFields),
23837 xmlSchemaGetComponentQName(&strB,
23838 matcher->aidc->def));
23839 FREE_AND_NULL(str);
23840 FREE_AND_NULL(strB);
23841 break;
23847 if (res == 0) {
23848 xmlChar *str = NULL, *strB = NULL;
23849 xmlSchemaKeyrefErr(vctxt,
23850 XML_SCHEMAV_CVC_IDC, refNode,
23851 (xmlSchemaTypePtr) matcher->aidc->def,
23852 "No match found for key-sequence %s of keyref '%s'",
23853 xmlSchemaFormatIDCKeySequence(vctxt, &str,
23854 refNode->keys, nbFields),
23855 xmlSchemaGetComponentQName(&strB, matcher->aidc->def));
23856 FREE_AND_NULL(str);
23857 FREE_AND_NULL(strB);
23861 matcher = matcher->next;
23863 /* TODO: Return an error if any error encountered. */
23864 return (0);
23867 /************************************************************************
23869 * XML Reader validation code *
23871 ************************************************************************/
23873 static xmlSchemaAttrInfoPtr
23874 xmlSchemaGetFreshAttrInfo(xmlSchemaValidCtxtPtr vctxt)
23876 xmlSchemaAttrInfoPtr iattr;
23878 * Grow/create list of attribute infos.
23880 if (vctxt->attrInfos == NULL) {
23881 vctxt->attrInfos = (xmlSchemaAttrInfoPtr *)
23882 xmlMalloc(sizeof(xmlSchemaAttrInfoPtr));
23883 vctxt->sizeAttrInfos = 1;
23884 if (vctxt->attrInfos == NULL) {
23885 xmlSchemaVErrMemory(vctxt,
23886 "allocating attribute info list", NULL);
23887 return (NULL);
23889 } else if (vctxt->sizeAttrInfos <= vctxt->nbAttrInfos) {
23890 vctxt->sizeAttrInfos++;
23891 vctxt->attrInfos = (xmlSchemaAttrInfoPtr *)
23892 xmlRealloc(vctxt->attrInfos,
23893 vctxt->sizeAttrInfos * sizeof(xmlSchemaAttrInfoPtr));
23894 if (vctxt->attrInfos == NULL) {
23895 xmlSchemaVErrMemory(vctxt,
23896 "re-allocating attribute info list", NULL);
23897 return (NULL);
23899 } else {
23900 iattr = vctxt->attrInfos[vctxt->nbAttrInfos++];
23901 if (iattr->localName != NULL) {
23902 VERROR_INT("xmlSchemaGetFreshAttrInfo",
23903 "attr info not cleared");
23904 return (NULL);
23906 iattr->nodeType = XML_ATTRIBUTE_NODE;
23907 return (iattr);
23910 * Create an attribute info.
23912 iattr = (xmlSchemaAttrInfoPtr)
23913 xmlMalloc(sizeof(xmlSchemaAttrInfo));
23914 if (iattr == NULL) {
23915 xmlSchemaVErrMemory(vctxt, "creating new attribute info", NULL);
23916 return (NULL);
23918 memset(iattr, 0, sizeof(xmlSchemaAttrInfo));
23919 iattr->nodeType = XML_ATTRIBUTE_NODE;
23920 vctxt->attrInfos[vctxt->nbAttrInfos++] = iattr;
23922 return (iattr);
23925 static int
23926 xmlSchemaValidatorPushAttribute(xmlSchemaValidCtxtPtr vctxt,
23927 xmlNodePtr attrNode,
23928 int nodeLine,
23929 const xmlChar *localName,
23930 const xmlChar *nsName,
23931 int ownedNames,
23932 xmlChar *value,
23933 int ownedValue)
23935 xmlSchemaAttrInfoPtr attr;
23937 attr = xmlSchemaGetFreshAttrInfo(vctxt);
23938 if (attr == NULL) {
23939 VERROR_INT("xmlSchemaPushAttribute",
23940 "calling xmlSchemaGetFreshAttrInfo()");
23941 return (-1);
23943 attr->node = attrNode;
23944 attr->nodeLine = nodeLine;
23945 attr->state = XML_SCHEMAS_ATTR_UNKNOWN;
23946 attr->localName = localName;
23947 attr->nsName = nsName;
23948 if (ownedNames)
23949 attr->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES;
23951 * Evaluate if it's an XSI attribute.
23953 if (nsName != NULL) {
23954 if (xmlStrEqual(localName, BAD_CAST "nil")) {
23955 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
23956 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_NIL;
23958 } else if (xmlStrEqual(localName, BAD_CAST "type")) {
23959 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
23960 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_TYPE;
23962 } else if (xmlStrEqual(localName, BAD_CAST "schemaLocation")) {
23963 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
23964 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC;
23966 } else if (xmlStrEqual(localName, BAD_CAST "noNamespaceSchemaLocation")) {
23967 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
23968 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC;
23970 } else if (xmlStrEqual(attr->nsName, xmlNamespaceNs)) {
23971 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XMLNS;
23974 attr->value = value;
23975 if (ownedValue)
23976 attr->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
23977 if (attr->metaType != 0)
23978 attr->state = XML_SCHEMAS_ATTR_META;
23979 return (0);
23983 * xmlSchemaClearElemInfo:
23984 * @vctxt: the WXS validation context
23985 * @ielem: the element information item
23987 static void
23988 xmlSchemaClearElemInfo(xmlSchemaValidCtxtPtr vctxt,
23989 xmlSchemaNodeInfoPtr ielem)
23991 ielem->hasKeyrefs = 0;
23992 ielem->appliedXPath = 0;
23993 if (ielem->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES) {
23994 FREE_AND_NULL(ielem->localName);
23995 FREE_AND_NULL(ielem->nsName);
23996 } else {
23997 ielem->localName = NULL;
23998 ielem->nsName = NULL;
24000 if (ielem->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
24001 FREE_AND_NULL(ielem->value);
24002 } else {
24003 ielem->value = NULL;
24005 if (ielem->val != NULL) {
24007 * PSVI TODO: Be careful not to free it when the value is
24008 * exposed via PSVI.
24010 xmlSchemaFreeValue(ielem->val);
24011 ielem->val = NULL;
24013 if (ielem->idcMatchers != NULL) {
24015 * REVISIT OPTIMIZE TODO: Use a pool of IDC matchers.
24016 * Does it work?
24018 xmlSchemaIDCReleaseMatcherList(vctxt, ielem->idcMatchers);
24019 #if 0
24020 xmlSchemaIDCFreeMatcherList(ielem->idcMatchers);
24021 #endif
24022 ielem->idcMatchers = NULL;
24024 if (ielem->idcTable != NULL) {
24026 * OPTIMIZE TODO: Use a pool of IDC tables??.
24028 xmlSchemaIDCFreeIDCTable(ielem->idcTable);
24029 ielem->idcTable = NULL;
24031 if (ielem->regexCtxt != NULL) {
24032 xmlRegFreeExecCtxt(ielem->regexCtxt);
24033 ielem->regexCtxt = NULL;
24035 if (ielem->nsBindings != NULL) {
24036 xmlFree((xmlChar **)ielem->nsBindings);
24037 ielem->nsBindings = NULL;
24038 ielem->nbNsBindings = 0;
24039 ielem->sizeNsBindings = 0;
24044 * xmlSchemaGetFreshElemInfo:
24045 * @vctxt: the schema validation context
24047 * Creates/reuses and initializes the element info item for
24048 * the currect tree depth.
24050 * Returns the element info item or NULL on API or internal errors.
24052 static xmlSchemaNodeInfoPtr
24053 xmlSchemaGetFreshElemInfo(xmlSchemaValidCtxtPtr vctxt)
24055 xmlSchemaNodeInfoPtr info = NULL;
24057 if (vctxt->depth > vctxt->sizeElemInfos) {
24058 VERROR_INT("xmlSchemaGetFreshElemInfo",
24059 "inconsistent depth encountered");
24060 return (NULL);
24062 if (vctxt->elemInfos == NULL) {
24063 vctxt->elemInfos = (xmlSchemaNodeInfoPtr *)
24064 xmlMalloc(10 * sizeof(xmlSchemaNodeInfoPtr));
24065 if (vctxt->elemInfos == NULL) {
24066 xmlSchemaVErrMemory(vctxt,
24067 "allocating the element info array", NULL);
24068 return (NULL);
24070 memset(vctxt->elemInfos, 0, 10 * sizeof(xmlSchemaNodeInfoPtr));
24071 vctxt->sizeElemInfos = 10;
24072 } else if (vctxt->sizeElemInfos <= vctxt->depth) {
24073 int i = vctxt->sizeElemInfos;
24075 vctxt->sizeElemInfos *= 2;
24076 vctxt->elemInfos = (xmlSchemaNodeInfoPtr *)
24077 xmlRealloc(vctxt->elemInfos, vctxt->sizeElemInfos *
24078 sizeof(xmlSchemaNodeInfoPtr));
24079 if (vctxt->elemInfos == NULL) {
24080 xmlSchemaVErrMemory(vctxt,
24081 "re-allocating the element info array", NULL);
24082 return (NULL);
24085 * We need the new memory to be NULLed.
24086 * TODO: Use memset instead?
24088 for (; i < vctxt->sizeElemInfos; i++)
24089 vctxt->elemInfos[i] = NULL;
24090 } else
24091 info = vctxt->elemInfos[vctxt->depth];
24093 if (info == NULL) {
24094 info = (xmlSchemaNodeInfoPtr)
24095 xmlMalloc(sizeof(xmlSchemaNodeInfo));
24096 if (info == NULL) {
24097 xmlSchemaVErrMemory(vctxt,
24098 "allocating an element info", NULL);
24099 return (NULL);
24101 vctxt->elemInfos[vctxt->depth] = info;
24102 } else {
24103 if (info->localName != NULL) {
24104 VERROR_INT("xmlSchemaGetFreshElemInfo",
24105 "elem info has not been cleared");
24106 return (NULL);
24109 memset(info, 0, sizeof(xmlSchemaNodeInfo));
24110 info->nodeType = XML_ELEMENT_NODE;
24111 info->depth = vctxt->depth;
24113 return (info);
24116 #define ACTIVATE_ATTRIBUTE(item) vctxt->inode = (xmlSchemaNodeInfoPtr) item;
24117 #define ACTIVATE_ELEM vctxt->inode = vctxt->elemInfos[vctxt->depth];
24118 #define ACTIVATE_PARENT_ELEM vctxt->inode = vctxt->elemInfos[vctxt->depth -1];
24120 static int
24121 xmlSchemaValidateFacets(xmlSchemaAbstractCtxtPtr actxt,
24122 xmlNodePtr node,
24123 xmlSchemaTypePtr type,
24124 xmlSchemaValType valType,
24125 const xmlChar * value,
24126 xmlSchemaValPtr val,
24127 unsigned long length,
24128 int fireErrors)
24130 int ret, error = 0;
24132 xmlSchemaTypePtr tmpType;
24133 xmlSchemaFacetLinkPtr facetLink;
24134 xmlSchemaFacetPtr facet;
24135 unsigned long len = 0;
24136 xmlSchemaWhitespaceValueType ws;
24139 * In Libxml2, derived built-in types have currently no explicit facets.
24141 if (type->type == XML_SCHEMA_TYPE_BASIC)
24142 return (0);
24145 * NOTE: Do not jump away, if the facetSet of the given type is
24146 * empty: until now, "pattern" and "enumeration" facets of the
24147 * *base types* need to be checked as well.
24149 if (type->facetSet == NULL)
24150 goto pattern_and_enum;
24152 if (! WXS_IS_ATOMIC(type)) {
24153 if (WXS_IS_LIST(type))
24154 goto WXS_IS_LIST;
24155 else
24156 goto pattern_and_enum;
24159 * Whitespace handling is only of importance for string-based
24160 * types.
24162 tmpType = xmlSchemaGetPrimitiveType(type);
24163 if ((tmpType->builtInType == XML_SCHEMAS_STRING) ||
24164 WXS_IS_ANY_SIMPLE_TYPE(tmpType)) {
24165 ws = xmlSchemaGetWhiteSpaceFacetValue(type);
24166 } else
24167 ws = XML_SCHEMA_WHITESPACE_COLLAPSE;
24169 * If the value was not computed (for string or
24170 * anySimpleType based types), then use the provided
24171 * type.
24173 if (val == NULL)
24174 valType = valType;
24175 else
24176 valType = xmlSchemaGetValType(val);
24178 ret = 0;
24179 for (facetLink = type->facetSet; facetLink != NULL;
24180 facetLink = facetLink->next) {
24182 * Skip the pattern "whiteSpace": it is used to
24183 * format the character content beforehand.
24185 switch (facetLink->facet->type) {
24186 case XML_SCHEMA_FACET_WHITESPACE:
24187 case XML_SCHEMA_FACET_PATTERN:
24188 case XML_SCHEMA_FACET_ENUMERATION:
24189 continue;
24190 case XML_SCHEMA_FACET_LENGTH:
24191 case XML_SCHEMA_FACET_MINLENGTH:
24192 case XML_SCHEMA_FACET_MAXLENGTH:
24193 ret = xmlSchemaValidateLengthFacetWhtsp(facetLink->facet,
24194 valType, value, val, &len, ws);
24195 break;
24196 default:
24197 ret = xmlSchemaValidateFacetWhtsp(facetLink->facet, ws,
24198 valType, value, val, ws);
24199 break;
24201 if (ret < 0) {
24202 AERROR_INT("xmlSchemaValidateFacets",
24203 "validating against a atomic type facet");
24204 return (-1);
24205 } else if (ret > 0) {
24206 if (fireErrors)
24207 xmlSchemaFacetErr(actxt, ret, node,
24208 value, len, type, facetLink->facet, NULL, NULL, NULL);
24209 else
24210 return (ret);
24211 if (error == 0)
24212 error = ret;
24214 ret = 0;
24217 WXS_IS_LIST:
24218 if (! WXS_IS_LIST(type))
24219 goto pattern_and_enum;
24221 * "length", "minLength" and "maxLength" of list types.
24223 ret = 0;
24224 for (facetLink = type->facetSet; facetLink != NULL;
24225 facetLink = facetLink->next) {
24227 switch (facetLink->facet->type) {
24228 case XML_SCHEMA_FACET_LENGTH:
24229 case XML_SCHEMA_FACET_MINLENGTH:
24230 case XML_SCHEMA_FACET_MAXLENGTH:
24231 ret = xmlSchemaValidateListSimpleTypeFacet(facetLink->facet,
24232 value, length, NULL);
24233 break;
24234 default:
24235 continue;
24237 if (ret < 0) {
24238 AERROR_INT("xmlSchemaValidateFacets",
24239 "validating against a list type facet");
24240 return (-1);
24241 } else if (ret > 0) {
24242 if (fireErrors)
24243 xmlSchemaFacetErr(actxt, ret, node,
24244 value, length, type, facetLink->facet, NULL, NULL, NULL);
24245 else
24246 return (ret);
24247 if (error == 0)
24248 error = ret;
24250 ret = 0;
24253 pattern_and_enum:
24254 if (error >= 0) {
24255 int found = 0;
24257 * Process enumerations. Facet values are in the value space
24258 * of the defining type's base type. This seems to be a bug in the
24259 * XML Schema 1.0 spec. Use the whitespace type of the base type.
24260 * Only the first set of enumerations in the ancestor-or-self axis
24261 * is used for validation.
24263 ret = 0;
24264 tmpType = type;
24265 do {
24266 for (facet = tmpType->facets; facet != NULL; facet = facet->next) {
24267 if (facet->type != XML_SCHEMA_FACET_ENUMERATION)
24268 continue;
24269 found = 1;
24270 ret = xmlSchemaAreValuesEqual(facet->val, val);
24271 if (ret == 1)
24272 break;
24273 else if (ret < 0) {
24274 AERROR_INT("xmlSchemaValidateFacets",
24275 "validating against an enumeration facet");
24276 return (-1);
24279 if (ret != 0)
24280 break;
24282 * Break on the first set of enumerations. Any additional
24283 * enumerations which might be existent on the ancestors
24284 * of the current type are restricted by this set; thus
24285 * *must* *not* be taken into account.
24287 if (found)
24288 break;
24289 tmpType = tmpType->baseType;
24290 } while ((tmpType != NULL) &&
24291 (tmpType->type != XML_SCHEMA_TYPE_BASIC));
24292 if (found && (ret == 0)) {
24293 ret = XML_SCHEMAV_CVC_ENUMERATION_VALID;
24294 if (fireErrors) {
24295 xmlSchemaFacetErr(actxt, ret, node,
24296 value, 0, type, NULL, NULL, NULL, NULL);
24297 } else
24298 return (ret);
24299 if (error == 0)
24300 error = ret;
24304 if (error >= 0) {
24305 int found;
24307 * Process patters. Pattern facets are ORed at type level
24308 * and ANDed if derived. Walk the base type axis.
24310 tmpType = type;
24311 facet = NULL;
24312 do {
24313 found = 0;
24314 for (facetLink = tmpType->facetSet; facetLink != NULL;
24315 facetLink = facetLink->next) {
24316 if (facetLink->facet->type != XML_SCHEMA_FACET_PATTERN)
24317 continue;
24318 found = 1;
24320 * NOTE that for patterns, @value needs to be the
24321 * normalized vaule.
24323 ret = xmlRegexpExec(facetLink->facet->regexp, value);
24324 if (ret == 1)
24325 break;
24326 else if (ret < 0) {
24327 AERROR_INT("xmlSchemaValidateFacets",
24328 "validating against a pattern facet");
24329 return (-1);
24330 } else {
24332 * Save the last non-validating facet.
24334 facet = facetLink->facet;
24337 if (found && (ret != 1)) {
24338 ret = XML_SCHEMAV_CVC_PATTERN_VALID;
24339 if (fireErrors) {
24340 xmlSchemaFacetErr(actxt, ret, node,
24341 value, 0, type, facet, NULL, NULL, NULL);
24342 } else
24343 return (ret);
24344 if (error == 0)
24345 error = ret;
24346 break;
24348 tmpType = tmpType->baseType;
24349 } while ((tmpType != NULL) && (tmpType->type != XML_SCHEMA_TYPE_BASIC));
24352 return (error);
24355 static xmlChar *
24356 xmlSchemaNormalizeValue(xmlSchemaTypePtr type,
24357 const xmlChar *value)
24359 switch (xmlSchemaGetWhiteSpaceFacetValue(type)) {
24360 case XML_SCHEMA_WHITESPACE_COLLAPSE:
24361 return (xmlSchemaCollapseString(value));
24362 case XML_SCHEMA_WHITESPACE_REPLACE:
24363 return (xmlSchemaWhiteSpaceReplace(value));
24364 default:
24365 return (NULL);
24369 static int
24370 xmlSchemaValidateQName(xmlSchemaValidCtxtPtr vctxt,
24371 const xmlChar *value,
24372 xmlSchemaValPtr *val,
24373 int valNeeded)
24375 int ret;
24376 const xmlChar *nsName;
24377 xmlChar *local, *prefix = NULL;
24379 ret = xmlValidateQName(value, 1);
24380 if (ret != 0) {
24381 if (ret == -1) {
24382 VERROR_INT("xmlSchemaValidateQName",
24383 "calling xmlValidateQName()");
24384 return (-1);
24386 return( XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1);
24389 * NOTE: xmlSplitQName2 will always return a duplicated
24390 * strings.
24392 local = xmlSplitQName2(value, &prefix);
24393 if (local == NULL)
24394 local = xmlStrdup(value);
24396 * OPTIMIZE TODO: Use flags for:
24397 * - is there any namespace binding?
24398 * - is there a default namespace?
24400 nsName = xmlSchemaLookupNamespace(vctxt, prefix);
24402 if (prefix != NULL) {
24403 xmlFree(prefix);
24405 * A namespace must be found if the prefix is
24406 * NOT NULL.
24408 if (nsName == NULL) {
24409 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
24410 xmlSchemaCustomErr(ACTXT_CAST vctxt, ret, NULL,
24411 WXS_BASIC_CAST xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
24412 "The QName value '%s' has no "
24413 "corresponding namespace declaration in "
24414 "scope", value, NULL);
24415 if (local != NULL)
24416 xmlFree(local);
24417 return (ret);
24420 if (valNeeded && val) {
24421 if (nsName != NULL)
24422 *val = xmlSchemaNewQNameValue(
24423 BAD_CAST xmlStrdup(nsName), BAD_CAST local);
24424 else
24425 *val = xmlSchemaNewQNameValue(NULL,
24426 BAD_CAST local);
24427 } else
24428 xmlFree(local);
24429 return (0);
24433 * cvc-simple-type
24435 static int
24436 xmlSchemaVCheckCVCSimpleType(xmlSchemaAbstractCtxtPtr actxt,
24437 xmlNodePtr node,
24438 xmlSchemaTypePtr type,
24439 const xmlChar *value,
24440 xmlSchemaValPtr *retVal,
24441 int fireErrors,
24442 int normalize,
24443 int isNormalized)
24445 int ret = 0, valNeeded = (retVal) ? 1 : 0;
24446 xmlSchemaValPtr val = NULL;
24447 /* xmlSchemaWhitespaceValueType ws; */
24448 xmlChar *normValue = NULL;
24450 #define NORMALIZE(atype) \
24451 if ((! isNormalized) && \
24452 (normalize || (type->flags & XML_SCHEMAS_TYPE_NORMVALUENEEDED))) { \
24453 normValue = xmlSchemaNormalizeValue(atype, value); \
24454 if (normValue != NULL) \
24455 value = normValue; \
24456 isNormalized = 1; \
24459 if ((retVal != NULL) && (*retVal != NULL)) {
24460 xmlSchemaFreeValue(*retVal);
24461 *retVal = NULL;
24464 * 3.14.4 Simple Type Definition Validation Rules
24465 * Validation Rule: String Valid
24468 * 1 It is schema-valid with respect to that definition as defined
24469 * by Datatype Valid in [XML Schemas: Datatypes].
24472 * 2.1 If The definition is ENTITY or is validly derived from ENTITY given
24473 * the empty set, as defined in Type Derivation OK (Simple) (�3.14.6), then
24474 * the string must be a �declared entity name�.
24477 * 2.2 If The definition is ENTITIES or is validly derived from ENTITIES
24478 * given the empty set, as defined in Type Derivation OK (Simple) (�3.14.6),
24479 * then every whitespace-delimited substring of the string must be a �declared
24480 * entity name�.
24483 * 2.3 otherwise no further condition applies.
24485 if ((! valNeeded) && (type->flags & XML_SCHEMAS_TYPE_FACETSNEEDVALUE))
24486 valNeeded = 1;
24487 if (value == NULL)
24488 value = BAD_CAST "";
24489 if (WXS_IS_ANY_SIMPLE_TYPE(type) || WXS_IS_ATOMIC(type)) {
24490 xmlSchemaTypePtr biType; /* The built-in type. */
24492 * SPEC (1.2.1) "if {variety} is �atomic� then the string must �match�
24493 * a literal in the �lexical space� of {base type definition}"
24496 * Whitespace-normalize.
24498 NORMALIZE(type);
24499 if (type->type != XML_SCHEMA_TYPE_BASIC) {
24501 * Get the built-in type.
24503 biType = type->baseType;
24504 while ((biType != NULL) &&
24505 (biType->type != XML_SCHEMA_TYPE_BASIC))
24506 biType = biType->baseType;
24508 if (biType == NULL) {
24509 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24510 "could not get the built-in type");
24511 goto internal_error;
24513 } else
24514 biType = type;
24516 * NOTATIONs need to be processed here, since they need
24517 * to lookup in the hashtable of NOTATION declarations of the schema.
24519 if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
24520 switch (biType->builtInType) {
24521 case XML_SCHEMAS_NOTATION:
24522 ret = xmlSchemaValidateNotation(
24523 (xmlSchemaValidCtxtPtr) actxt,
24524 ((xmlSchemaValidCtxtPtr) actxt)->schema,
24525 NULL, value, &val, valNeeded);
24526 break;
24527 case XML_SCHEMAS_QNAME:
24528 ret = xmlSchemaValidateQName((xmlSchemaValidCtxtPtr) actxt,
24529 value, &val, valNeeded);
24530 break;
24531 default:
24532 /* ws = xmlSchemaGetWhiteSpaceFacetValue(type); */
24533 if (valNeeded)
24534 ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24535 value, &val, node);
24536 else
24537 ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24538 value, NULL, node);
24539 break;
24541 } else if (actxt->type == XML_SCHEMA_CTXT_PARSER) {
24542 switch (biType->builtInType) {
24543 case XML_SCHEMAS_NOTATION:
24544 ret = xmlSchemaValidateNotation(NULL,
24545 ((xmlSchemaParserCtxtPtr) actxt)->schema, node,
24546 value, &val, valNeeded);
24547 break;
24548 default:
24549 /* ws = xmlSchemaGetWhiteSpaceFacetValue(type); */
24550 if (valNeeded)
24551 ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24552 value, &val, node);
24553 else
24554 ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24555 value, NULL, node);
24556 break;
24558 } else {
24560 * Validation via a public API is not implemented yet.
24562 TODO
24563 goto internal_error;
24565 if (ret != 0) {
24566 if (ret < 0) {
24567 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24568 "validating against a built-in type");
24569 goto internal_error;
24571 if (WXS_IS_LIST(type))
24572 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24573 else
24574 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
24576 if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
24578 * Check facets.
24580 ret = xmlSchemaValidateFacets(actxt, node, type,
24581 (xmlSchemaValType) biType->builtInType, value, val,
24582 0, fireErrors);
24583 if (ret != 0) {
24584 if (ret < 0) {
24585 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24586 "validating facets of atomic simple type");
24587 goto internal_error;
24589 if (WXS_IS_LIST(type))
24590 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24591 else
24592 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
24595 if (fireErrors && (ret > 0))
24596 xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
24597 } else if (WXS_IS_LIST(type)) {
24599 xmlSchemaTypePtr itemType;
24600 const xmlChar *cur, *end;
24601 xmlChar *tmpValue = NULL;
24602 unsigned long len = 0;
24603 xmlSchemaValPtr prevVal = NULL, curVal = NULL;
24604 /* 1.2.2 if {variety} is �list� then the string must be a sequence
24605 * of white space separated tokens, each of which �match�es a literal
24606 * in the �lexical space� of {item type definition}
24609 * Note that XML_SCHEMAS_TYPE_NORMVALUENEEDED will be set if
24610 * the list type has an enum or pattern facet.
24612 NORMALIZE(type);
24614 * VAL TODO: Optimize validation of empty values.
24615 * VAL TODO: We do not have computed values for lists.
24617 itemType = WXS_LIST_ITEMTYPE(type);
24618 cur = value;
24619 do {
24620 while (IS_BLANK_CH(*cur))
24621 cur++;
24622 end = cur;
24623 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
24624 end++;
24625 if (end == cur)
24626 break;
24627 tmpValue = xmlStrndup(cur, end - cur);
24628 len++;
24630 if (valNeeded)
24631 ret = xmlSchemaVCheckCVCSimpleType(actxt, node, itemType,
24632 tmpValue, &curVal, fireErrors, 0, 1);
24633 else
24634 ret = xmlSchemaVCheckCVCSimpleType(actxt, node, itemType,
24635 tmpValue, NULL, fireErrors, 0, 1);
24636 FREE_AND_NULL(tmpValue);
24637 if (curVal != NULL) {
24639 * Add to list of computed values.
24641 if (val == NULL)
24642 val = curVal;
24643 else
24644 xmlSchemaValueAppend(prevVal, curVal);
24645 prevVal = curVal;
24646 curVal = NULL;
24648 if (ret != 0) {
24649 if (ret < 0) {
24650 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24651 "validating an item of list simple type");
24652 goto internal_error;
24654 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24655 break;
24657 cur = end;
24658 } while (*cur != 0);
24659 FREE_AND_NULL(tmpValue);
24660 if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
24662 * Apply facets (pattern, enumeration).
24664 ret = xmlSchemaValidateFacets(actxt, node, type,
24665 XML_SCHEMAS_UNKNOWN, value, val,
24666 len, fireErrors);
24667 if (ret != 0) {
24668 if (ret < 0) {
24669 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24670 "validating facets of list simple type");
24671 goto internal_error;
24673 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24676 if (fireErrors && (ret > 0)) {
24678 * Report the normalized value.
24680 normalize = 1;
24681 NORMALIZE(type);
24682 xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
24684 } else if (WXS_IS_UNION(type)) {
24685 xmlSchemaTypeLinkPtr memberLink;
24687 * TODO: For all datatypes �derived� by �union� whiteSpace does
24688 * not apply directly; however, the normalization behavior of �union�
24689 * types is controlled by the value of whiteSpace on that one of the
24690 * �memberTypes� against which the �union� is successfully validated.
24692 * This means that the value is normalized by the first validating
24693 * member type, then the facets of the union type are applied. This
24694 * needs changing of the value!
24698 * 1.2.3 if {variety} is �union� then the string must �match� a
24699 * literal in the �lexical space� of at least one member of
24700 * {member type definitions}
24702 memberLink = xmlSchemaGetUnionSimpleTypeMemberTypes(type);
24703 if (memberLink == NULL) {
24704 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24705 "union simple type has no member types");
24706 goto internal_error;
24709 * Always normalize union type values, since we currently
24710 * cannot store the whitespace information with the value
24711 * itself; otherwise a later value-comparison would be
24712 * not possible.
24714 while (memberLink != NULL) {
24715 if (valNeeded)
24716 ret = xmlSchemaVCheckCVCSimpleType(actxt, node,
24717 memberLink->type, value, &val, 0, 1, 0);
24718 else
24719 ret = xmlSchemaVCheckCVCSimpleType(actxt, node,
24720 memberLink->type, value, NULL, 0, 1, 0);
24721 if (ret <= 0)
24722 break;
24723 memberLink = memberLink->next;
24725 if (ret != 0) {
24726 if (ret < 0) {
24727 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24728 "validating members of union simple type");
24729 goto internal_error;
24731 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
24734 * Apply facets (pattern, enumeration).
24736 if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
24738 * The normalization behavior of �union� types is controlled by
24739 * the value of whiteSpace on that one of the �memberTypes�
24740 * against which the �union� is successfully validated.
24742 NORMALIZE(memberLink->type);
24743 ret = xmlSchemaValidateFacets(actxt, node, type,
24744 XML_SCHEMAS_UNKNOWN, value, val,
24745 0, fireErrors);
24746 if (ret != 0) {
24747 if (ret < 0) {
24748 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24749 "validating facets of union simple type");
24750 goto internal_error;
24752 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
24755 if (fireErrors && (ret > 0))
24756 xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
24759 if (normValue != NULL)
24760 xmlFree(normValue);
24761 if (ret == 0) {
24762 if (retVal != NULL)
24763 *retVal = val;
24764 else if (val != NULL)
24765 xmlSchemaFreeValue(val);
24766 } else if (val != NULL)
24767 xmlSchemaFreeValue(val);
24768 return (ret);
24769 internal_error:
24770 if (normValue != NULL)
24771 xmlFree(normValue);
24772 if (val != NULL)
24773 xmlSchemaFreeValue(val);
24774 return (-1);
24777 static int
24778 xmlSchemaVExpandQName(xmlSchemaValidCtxtPtr vctxt,
24779 const xmlChar *value,
24780 const xmlChar **nsName,
24781 const xmlChar **localName)
24783 int ret = 0;
24785 if ((nsName == NULL) || (localName == NULL))
24786 return (-1);
24787 *nsName = NULL;
24788 *localName = NULL;
24790 ret = xmlValidateQName(value, 1);
24791 if (ret == -1)
24792 return (-1);
24793 if (ret > 0) {
24794 xmlSchemaSimpleTypeErr(ACTXT_CAST vctxt,
24795 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1, NULL,
24796 value, xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), 1);
24797 return (1);
24800 xmlChar *local = NULL;
24801 xmlChar *prefix;
24804 * NOTE: xmlSplitQName2 will return a duplicated
24805 * string.
24807 local = xmlSplitQName2(value, &prefix);
24808 if (local == NULL)
24809 *localName = xmlDictLookup(vctxt->dict, value, -1);
24810 else {
24811 *localName = xmlDictLookup(vctxt->dict, local, -1);
24812 xmlFree(local);
24815 *nsName = xmlSchemaLookupNamespace(vctxt, prefix);
24817 if (prefix != NULL) {
24818 xmlFree(prefix);
24820 * A namespace must be found if the prefix is NOT NULL.
24822 if (*nsName == NULL) {
24823 xmlSchemaCustomErr(ACTXT_CAST vctxt,
24824 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1, NULL,
24825 WXS_BASIC_CAST xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
24826 "The QName value '%s' has no "
24827 "corresponding namespace declaration in scope",
24828 value, NULL);
24829 return (2);
24833 return (0);
24836 static int
24837 xmlSchemaProcessXSIType(xmlSchemaValidCtxtPtr vctxt,
24838 xmlSchemaAttrInfoPtr iattr,
24839 xmlSchemaTypePtr *localType,
24840 xmlSchemaElementPtr elemDecl)
24842 int ret = 0;
24844 * cvc-elt (3.3.4) : (4)
24845 * AND
24846 * Schema-Validity Assessment (Element) (cvc-assess-elt)
24847 * (1.2.1.2.1) - (1.2.1.2.4)
24848 * Handle 'xsi:type'.
24850 if (localType == NULL)
24851 return (-1);
24852 *localType = NULL;
24853 if (iattr == NULL)
24854 return (0);
24855 else {
24856 const xmlChar *nsName = NULL, *local = NULL;
24858 * TODO: We should report a *warning* that the type was overriden
24859 * by the instance.
24861 ACTIVATE_ATTRIBUTE(iattr);
24863 * (cvc-elt) (3.3.4) : (4.1)
24864 * (cvc-assess-elt) (1.2.1.2.2)
24866 ret = xmlSchemaVExpandQName(vctxt, iattr->value,
24867 &nsName, &local);
24868 if (ret != 0) {
24869 if (ret < 0) {
24870 VERROR_INT("xmlSchemaValidateElementByDeclaration",
24871 "calling xmlSchemaQNameExpand() to validate the "
24872 "attribute 'xsi:type'");
24873 goto internal_error;
24875 goto exit;
24878 * (cvc-elt) (3.3.4) : (4.2)
24879 * (cvc-assess-elt) (1.2.1.2.3)
24881 *localType = xmlSchemaGetType(vctxt->schema, local, nsName);
24882 if (*localType == NULL) {
24883 xmlChar *str = NULL;
24885 xmlSchemaCustomErr(ACTXT_CAST vctxt,
24886 XML_SCHEMAV_CVC_ELT_4_2, NULL,
24887 WXS_BASIC_CAST xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
24888 "The QName value '%s' of the xsi:type attribute does not "
24889 "resolve to a type definition",
24890 xmlSchemaFormatQName(&str, nsName, local), NULL);
24891 FREE_AND_NULL(str);
24892 ret = vctxt->err;
24893 goto exit;
24895 if (elemDecl != NULL) {
24896 int set = 0;
24899 * SPEC cvc-elt (3.3.4) : (4.3) (Type Derivation OK)
24900 * "The �local type definition� must be validly
24901 * derived from the {type definition} given the union of
24902 * the {disallowed substitutions} and the {type definition}'s
24903 * {prohibited substitutions}, as defined in
24904 * Type Derivation OK (Complex) (�3.4.6)
24905 * (if it is a complex type definition),
24906 * or given {disallowed substitutions} as defined in Type
24907 * Derivation OK (Simple) (�3.14.6) (if it is a simple type
24908 * definition)."
24910 * {disallowed substitutions}: the "block" on the element decl.
24911 * {prohibited substitutions}: the "block" on the type def.
24914 * OPTIMIZE TODO: We could map types already evaluated
24915 * to be validly derived from other types to avoid checking
24916 * this over and over for the same types.
24918 if ((elemDecl->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) ||
24919 (elemDecl->subtypes->flags &
24920 XML_SCHEMAS_TYPE_BLOCK_EXTENSION))
24921 set |= SUBSET_EXTENSION;
24923 if ((elemDecl->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) ||
24924 (elemDecl->subtypes->flags &
24925 XML_SCHEMAS_TYPE_BLOCK_RESTRICTION))
24926 set |= SUBSET_RESTRICTION;
24929 * REMOVED and CHANGED since this produced a parser context
24930 * which adds to the string dict of the schema. So this would
24931 * change the schema and we don't want this. We don't need
24932 * the parser context anymore.
24934 * if ((vctxt->pctxt == NULL) &&
24935 * (xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1))
24936 * return (-1);
24939 if (xmlSchemaCheckCOSDerivedOK(ACTXT_CAST vctxt, *localType,
24940 elemDecl->subtypes, set) != 0) {
24941 xmlChar *str = NULL;
24943 xmlSchemaCustomErr(ACTXT_CAST vctxt,
24944 XML_SCHEMAV_CVC_ELT_4_3, NULL, NULL,
24945 "The type definition '%s', specified by xsi:type, is "
24946 "blocked or not validly derived from the type definition "
24947 "of the element declaration",
24948 xmlSchemaFormatQName(&str,
24949 (*localType)->targetNamespace,
24950 (*localType)->name),
24951 NULL);
24952 FREE_AND_NULL(str);
24953 ret = vctxt->err;
24954 *localType = NULL;
24958 exit:
24959 ACTIVATE_ELEM;
24960 return (ret);
24961 internal_error:
24962 ACTIVATE_ELEM;
24963 return (-1);
24966 static int
24967 xmlSchemaValidateElemDecl(xmlSchemaValidCtxtPtr vctxt)
24969 xmlSchemaElementPtr elemDecl = vctxt->inode->decl;
24970 xmlSchemaTypePtr actualType;
24973 * cvc-elt (3.3.4) : 1
24975 if (elemDecl == NULL) {
24976 VERROR(XML_SCHEMAV_CVC_ELT_1, NULL,
24977 "No matching declaration available");
24978 return (vctxt->err);
24980 actualType = WXS_ELEM_TYPEDEF(elemDecl);
24982 * cvc-elt (3.3.4) : 2
24984 if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT) {
24985 VERROR(XML_SCHEMAV_CVC_ELT_2, NULL,
24986 "The element declaration is abstract");
24987 return (vctxt->err);
24989 if (actualType == NULL) {
24990 VERROR(XML_SCHEMAV_CVC_TYPE_1, NULL,
24991 "The type definition is absent");
24992 return (XML_SCHEMAV_CVC_TYPE_1);
24994 if (vctxt->nbAttrInfos != 0) {
24995 int ret;
24996 xmlSchemaAttrInfoPtr iattr;
24998 * cvc-elt (3.3.4) : 3
24999 * Handle 'xsi:nil'.
25001 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
25002 XML_SCHEMA_ATTR_INFO_META_XSI_NIL);
25003 if (iattr) {
25004 ACTIVATE_ATTRIBUTE(iattr);
25006 * Validate the value.
25008 ret = xmlSchemaVCheckCVCSimpleType(
25009 ACTXT_CAST vctxt, NULL,
25010 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
25011 iattr->value, &(iattr->val), 1, 0, 0);
25012 ACTIVATE_ELEM;
25013 if (ret < 0) {
25014 VERROR_INT("xmlSchemaValidateElemDecl",
25015 "calling xmlSchemaVCheckCVCSimpleType() to "
25016 "validate the attribute 'xsi:nil'");
25017 return (-1);
25019 if (ret == 0) {
25020 if ((elemDecl->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) {
25022 * cvc-elt (3.3.4) : 3.1
25024 VERROR(XML_SCHEMAV_CVC_ELT_3_1, NULL,
25025 "The element is not 'nillable'");
25026 /* Does not return an error on purpose. */
25027 } else {
25028 if (xmlSchemaValueGetAsBoolean(iattr->val)) {
25030 * cvc-elt (3.3.4) : 3.2.2
25032 if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) &&
25033 (elemDecl->value != NULL)) {
25034 VERROR(XML_SCHEMAV_CVC_ELT_3_2_2, NULL,
25035 "The element cannot be 'nilled' because "
25036 "there is a fixed value constraint defined "
25037 "for it");
25038 /* Does not return an error on purpose. */
25039 } else
25040 vctxt->inode->flags |=
25041 XML_SCHEMA_ELEM_INFO_NILLED;
25047 * cvc-elt (3.3.4) : 4
25048 * Handle 'xsi:type'.
25050 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
25051 XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
25052 if (iattr) {
25053 xmlSchemaTypePtr localType = NULL;
25055 ret = xmlSchemaProcessXSIType(vctxt, iattr, &localType,
25056 elemDecl);
25057 if (ret != 0) {
25058 if (ret == -1) {
25059 VERROR_INT("xmlSchemaValidateElemDecl",
25060 "calling xmlSchemaProcessXSIType() to "
25061 "process the attribute 'xsi:type'");
25062 return (-1);
25064 /* Does not return an error on purpose. */
25066 if (localType != NULL) {
25067 vctxt->inode->flags |= XML_SCHEMA_ELEM_INFO_LOCAL_TYPE;
25068 actualType = localType;
25073 * IDC: Register identity-constraint XPath matchers.
25075 if ((elemDecl->idcs != NULL) &&
25076 (xmlSchemaIDCRegisterMatchers(vctxt, elemDecl) == -1))
25077 return (-1);
25079 * No actual type definition.
25081 if (actualType == NULL) {
25082 VERROR(XML_SCHEMAV_CVC_TYPE_1, NULL,
25083 "The type definition is absent");
25084 return (XML_SCHEMAV_CVC_TYPE_1);
25087 * Remember the actual type definition.
25089 vctxt->inode->typeDef = actualType;
25091 return (0);
25094 static int
25095 xmlSchemaVAttributesSimple(xmlSchemaValidCtxtPtr vctxt)
25097 xmlSchemaAttrInfoPtr iattr;
25098 int ret = 0, i;
25101 * SPEC cvc-type (3.1.1)
25102 * "The attributes of must be empty, excepting those whose namespace
25103 * name is identical to http://www.w3.org/2001/XMLSchema-instance and
25104 * whose local name is one of type, nil, schemaLocation or
25105 * noNamespaceSchemaLocation."
25107 if (vctxt->nbAttrInfos == 0)
25108 return (0);
25109 for (i = 0; i < vctxt->nbAttrInfos; i++) {
25110 iattr = vctxt->attrInfos[i];
25111 if (! iattr->metaType) {
25112 ACTIVATE_ATTRIBUTE(iattr)
25113 xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt,
25114 XML_SCHEMAV_CVC_TYPE_3_1_1, iattr, NULL);
25115 ret = XML_SCHEMAV_CVC_TYPE_3_1_1;
25118 ACTIVATE_ELEM
25119 return (ret);
25123 * Cleanup currently used attribute infos.
25125 static void
25126 xmlSchemaClearAttrInfos(xmlSchemaValidCtxtPtr vctxt)
25128 int i;
25129 xmlSchemaAttrInfoPtr attr;
25131 if (vctxt->nbAttrInfos == 0)
25132 return;
25133 for (i = 0; i < vctxt->nbAttrInfos; i++) {
25134 attr = vctxt->attrInfos[i];
25135 if (attr->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES) {
25136 if (attr->localName != NULL)
25137 xmlFree((xmlChar *) attr->localName);
25138 if (attr->nsName != NULL)
25139 xmlFree((xmlChar *) attr->nsName);
25141 if (attr->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
25142 if (attr->value != NULL)
25143 xmlFree((xmlChar *) attr->value);
25145 if (attr->val != NULL) {
25146 xmlSchemaFreeValue(attr->val);
25147 attr->val = NULL;
25149 memset(attr, 0, sizeof(xmlSchemaAttrInfo));
25151 vctxt->nbAttrInfos = 0;
25155 * 3.4.4 Complex Type Definition Validation Rules
25156 * Element Locally Valid (Complex Type) (cvc-complex-type)
25157 * 3.2.4 Attribute Declaration Validation Rules
25158 * Validation Rule: Attribute Locally Valid (cvc-attribute)
25159 * Attribute Locally Valid (Use) (cvc-au)
25161 * Only "assessed" attribute information items will be visible to
25162 * IDCs. I.e. not "lax" (without declaration) and "skip" wild attributes.
25164 static int
25165 xmlSchemaVAttributesComplex(xmlSchemaValidCtxtPtr vctxt)
25167 xmlSchemaTypePtr type = vctxt->inode->typeDef;
25168 xmlSchemaItemListPtr attrUseList;
25169 xmlSchemaAttributeUsePtr attrUse = NULL;
25170 xmlSchemaAttributePtr attrDecl = NULL;
25171 xmlSchemaAttrInfoPtr iattr, tmpiattr;
25172 int i, j, found, nbAttrs, nbUses;
25173 int xpathRes = 0, res, wildIDs = 0, fixed;
25174 xmlNodePtr defAttrOwnerElem = NULL;
25177 * SPEC (cvc-attribute)
25178 * (1) "The declaration must not be �absent� (see Missing
25179 * Sub-components (�5.3) for how this can fail to be
25180 * the case)."
25181 * (2) "Its {type definition} must not be absent."
25183 * NOTE (1) + (2): This is not handled here, since we currently do not
25184 * allow validation against schemas which have missing sub-components.
25186 * SPEC (cvc-complex-type)
25187 * (3) "For each attribute information item in the element information
25188 * item's [attributes] excepting those whose [namespace name] is
25189 * identical to http://www.w3.org/2001/XMLSchema-instance and whose
25190 * [local name] is one of type, nil, schemaLocation or
25191 * noNamespaceSchemaLocation, the appropriate case among the following
25192 * must be true:
25195 attrUseList = (xmlSchemaItemListPtr) type->attrUses;
25197 * @nbAttrs is the number of attributes present in the instance.
25199 nbAttrs = vctxt->nbAttrInfos;
25200 if (attrUseList != NULL)
25201 nbUses = attrUseList->nbItems;
25202 else
25203 nbUses = 0;
25204 for (i = 0; i < nbUses; i++) {
25205 found = 0;
25206 attrUse = attrUseList->items[i];
25207 attrDecl = WXS_ATTRUSE_DECL(attrUse);
25208 for (j = 0; j < nbAttrs; j++) {
25209 iattr = vctxt->attrInfos[j];
25211 * SPEC (cvc-complex-type) (3)
25212 * Skip meta attributes.
25214 if (iattr->metaType)
25215 continue;
25216 if (iattr->localName[0] != attrDecl->name[0])
25217 continue;
25218 if (!xmlStrEqual(iattr->localName, attrDecl->name))
25219 continue;
25220 if (!xmlStrEqual(iattr->nsName, attrDecl->targetNamespace))
25221 continue;
25222 found = 1;
25224 * SPEC (cvc-complex-type)
25225 * (3.1) "If there is among the {attribute uses} an attribute
25226 * use with an {attribute declaration} whose {name} matches
25227 * the attribute information item's [local name] and whose
25228 * {target namespace} is identical to the attribute information
25229 * item's [namespace name] (where an �absent� {target namespace}
25230 * is taken to be identical to a [namespace name] with no value),
25231 * then the attribute information must be �valid� with respect
25232 * to that attribute use as per Attribute Locally Valid (Use)
25233 * (�3.5.4). In this case the {attribute declaration} of that
25234 * attribute use is the �context-determined declaration� for the
25235 * attribute information item with respect to Schema-Validity
25236 * Assessment (Attribute) (�3.2.4) and
25237 * Assessment Outcome (Attribute) (�3.2.5).
25239 iattr->state = XML_SCHEMAS_ATTR_ASSESSED;
25240 iattr->use = attrUse;
25242 * Context-determined declaration.
25244 iattr->decl = attrDecl;
25245 iattr->typeDef = attrDecl->subtypes;
25246 break;
25249 if (found)
25250 continue;
25252 if (attrUse->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED) {
25254 * Handle non-existent, required attributes.
25256 * SPEC (cvc-complex-type)
25257 * (4) "The {attribute declaration} of each attribute use in
25258 * the {attribute uses} whose {required} is true matches one
25259 * of the attribute information items in the element information
25260 * item's [attributes] as per clause 3.1 above."
25262 tmpiattr = xmlSchemaGetFreshAttrInfo(vctxt);
25263 if (tmpiattr == NULL) {
25264 VERROR_INT(
25265 "xmlSchemaVAttributesComplex",
25266 "calling xmlSchemaGetFreshAttrInfo()");
25267 return (-1);
25269 tmpiattr->state = XML_SCHEMAS_ATTR_ERR_MISSING;
25270 tmpiattr->use = attrUse;
25271 tmpiattr->decl = attrDecl;
25272 } else if ((attrUse->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
25273 ((attrUse->defValue != NULL) ||
25274 (attrDecl->defValue != NULL))) {
25276 * Handle non-existent, optional, default/fixed attributes.
25278 tmpiattr = xmlSchemaGetFreshAttrInfo(vctxt);
25279 if (tmpiattr == NULL) {
25280 VERROR_INT(
25281 "xmlSchemaVAttributesComplex",
25282 "calling xmlSchemaGetFreshAttrInfo()");
25283 return (-1);
25285 tmpiattr->state = XML_SCHEMAS_ATTR_DEFAULT;
25286 tmpiattr->use = attrUse;
25287 tmpiattr->decl = attrDecl;
25288 tmpiattr->typeDef = attrDecl->subtypes;
25289 tmpiattr->localName = attrDecl->name;
25290 tmpiattr->nsName = attrDecl->targetNamespace;
25294 if (vctxt->nbAttrInfos == 0)
25295 return (0);
25297 * Validate against the wildcard.
25299 if (type->attributeWildcard != NULL) {
25301 * SPEC (cvc-complex-type)
25302 * (3.2.1) "There must be an {attribute wildcard}."
25304 for (i = 0; i < nbAttrs; i++) {
25305 iattr = vctxt->attrInfos[i];
25307 * SPEC (cvc-complex-type) (3)
25308 * Skip meta attributes.
25310 if (iattr->state != XML_SCHEMAS_ATTR_UNKNOWN)
25311 continue;
25313 * SPEC (cvc-complex-type)
25314 * (3.2.2) "The attribute information item must be �valid� with
25315 * respect to it as defined in Item Valid (Wildcard) (�3.10.4)."
25317 * SPEC Item Valid (Wildcard) (cvc-wildcard)
25318 * "... its [namespace name] must be �valid� with respect to
25319 * the wildcard constraint, as defined in Wildcard allows
25320 * Namespace Name (�3.10.4)."
25322 if (xmlSchemaCheckCVCWildcardNamespace(type->attributeWildcard,
25323 iattr->nsName) == 0) {
25325 * Handle processContents.
25327 * SPEC (cvc-wildcard):
25328 * processContents | context-determined declaration:
25329 * "strict" "mustFind"
25330 * "lax" "none"
25331 * "skip" "skip"
25333 if (type->attributeWildcard->processContents ==
25334 XML_SCHEMAS_ANY_SKIP) {
25336 * context-determined declaration = "skip"
25338 * SPEC PSVI Assessment Outcome (Attribute)
25339 * [validity] = "notKnown"
25340 * [validation attempted] = "none"
25342 iattr->state = XML_SCHEMAS_ATTR_WILD_SKIP;
25343 continue;
25346 * Find an attribute declaration.
25348 iattr->decl = xmlSchemaGetAttributeDecl(vctxt->schema,
25349 iattr->localName, iattr->nsName);
25350 if (iattr->decl != NULL) {
25351 iattr->state = XML_SCHEMAS_ATTR_ASSESSED;
25353 * SPEC (cvc-complex-type)
25354 * (5) "Let [Definition:] the wild IDs be the set of
25355 * all attribute information item to which clause 3.2
25356 * applied and whose �validation� resulted in a
25357 * �context-determined declaration� of mustFind or no
25358 * �context-determined declaration� at all, and whose
25359 * [local name] and [namespace name] resolve (as
25360 * defined by QName resolution (Instance) (�3.15.4)) to
25361 * an attribute declaration whose {type definition} is
25362 * or is derived from ID. Then all of the following
25363 * must be true:"
25365 iattr->typeDef = WXS_ATTR_TYPEDEF(iattr->decl);
25366 if (xmlSchemaIsDerivedFromBuiltInType(
25367 iattr->typeDef, XML_SCHEMAS_ID)) {
25369 * SPEC (5.1) "There must be no more than one
25370 * item in �wild IDs�."
25372 if (wildIDs != 0) {
25373 /* VAL TODO */
25374 iattr->state = XML_SCHEMAS_ATTR_ERR_WILD_DUPLICATE_ID;
25375 TODO
25376 continue;
25378 wildIDs++;
25380 * SPEC (cvc-complex-type)
25381 * (5.2) "If �wild IDs� is non-empty, there must not
25382 * be any attribute uses among the {attribute uses}
25383 * whose {attribute declaration}'s {type definition}
25384 * is or is derived from ID."
25386 if (attrUseList != NULL) {
25387 for (j = 0; j < attrUseList->nbItems; j++) {
25388 if (xmlSchemaIsDerivedFromBuiltInType(
25389 WXS_ATTRUSE_TYPEDEF(attrUseList->items[j]),
25390 XML_SCHEMAS_ID)) {
25391 /* URGENT VAL TODO: implement */
25392 iattr->state = XML_SCHEMAS_ATTR_ERR_WILD_AND_USE_ID;
25393 TODO
25394 break;
25399 } else if (type->attributeWildcard->processContents ==
25400 XML_SCHEMAS_ANY_LAX) {
25401 iattr->state = XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL;
25403 * SPEC PSVI Assessment Outcome (Attribute)
25404 * [validity] = "notKnown"
25405 * [validation attempted] = "none"
25407 } else {
25408 iattr->state = XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL;
25414 if (vctxt->nbAttrInfos == 0)
25415 return (0);
25418 * Get the owner element; needed for creation of default attributes.
25419 * This fixes bug #341337, reported by David Grohmann.
25421 if (vctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) {
25422 xmlSchemaNodeInfoPtr ielem = vctxt->elemInfos[vctxt->depth];
25423 if (ielem && ielem->node && ielem->node->doc)
25424 defAttrOwnerElem = ielem->node;
25427 * Validate values, create default attributes, evaluate IDCs.
25429 for (i = 0; i < vctxt->nbAttrInfos; i++) {
25430 iattr = vctxt->attrInfos[i];
25432 * VAL TODO: Note that we won't try to resolve IDCs to
25433 * "lax" and "skip" validated attributes. Check what to
25434 * do in this case.
25436 if ((iattr->state != XML_SCHEMAS_ATTR_ASSESSED) &&
25437 (iattr->state != XML_SCHEMAS_ATTR_DEFAULT))
25438 continue;
25440 * VAL TODO: What to do if the type definition is missing?
25442 if (iattr->typeDef == NULL) {
25443 iattr->state = XML_SCHEMAS_ATTR_ERR_NO_TYPE;
25444 continue;
25447 ACTIVATE_ATTRIBUTE(iattr);
25448 fixed = 0;
25449 xpathRes = 0;
25451 if (vctxt->xpathStates != NULL) {
25453 * Evaluate IDCs.
25455 xpathRes = xmlSchemaXPathEvaluate(vctxt,
25456 XML_ATTRIBUTE_NODE);
25457 if (xpathRes == -1) {
25458 VERROR_INT("xmlSchemaVAttributesComplex",
25459 "calling xmlSchemaXPathEvaluate()");
25460 goto internal_error;
25464 if (iattr->state == XML_SCHEMAS_ATTR_DEFAULT) {
25466 * Default/fixed attributes.
25467 * We need the value only if we need to resolve IDCs or
25468 * will create default attributes.
25470 if ((xpathRes) || (defAttrOwnerElem)) {
25471 if (iattr->use->defValue != NULL) {
25472 iattr->value = (xmlChar *) iattr->use->defValue;
25473 iattr->val = iattr->use->defVal;
25474 } else {
25475 iattr->value = (xmlChar *) iattr->decl->defValue;
25476 iattr->val = iattr->decl->defVal;
25479 * IDCs will consume the precomputed default value,
25480 * so we need to clone it.
25482 if (iattr->val == NULL) {
25483 VERROR_INT("xmlSchemaVAttributesComplex",
25484 "default/fixed value on an attribute use was "
25485 "not precomputed");
25486 goto internal_error;
25488 iattr->val = xmlSchemaCopyValue(iattr->val);
25489 if (iattr->val == NULL) {
25490 VERROR_INT("xmlSchemaVAttributesComplex",
25491 "calling xmlSchemaCopyValue()");
25492 goto internal_error;
25496 * PSVI: Add the default attribute to the current element.
25497 * VAL TODO: Should we use the *normalized* value? This currently
25498 * uses the *initial* value.
25501 if (defAttrOwnerElem) {
25502 xmlChar *normValue;
25503 const xmlChar *value;
25505 value = iattr->value;
25507 * Normalize the value.
25509 normValue = xmlSchemaNormalizeValue(iattr->typeDef,
25510 iattr->value);
25511 if (normValue != NULL)
25512 value = BAD_CAST normValue;
25514 if (iattr->nsName == NULL) {
25515 if (xmlNewProp(defAttrOwnerElem,
25516 iattr->localName, value) == NULL) {
25517 VERROR_INT("xmlSchemaVAttributesComplex",
25518 "callling xmlNewProp()");
25519 if (normValue != NULL)
25520 xmlFree(normValue);
25521 goto internal_error;
25523 } else {
25524 xmlNsPtr ns;
25526 ns = xmlSearchNsByHref(defAttrOwnerElem->doc,
25527 defAttrOwnerElem, iattr->nsName);
25528 if (ns == NULL) {
25529 xmlChar prefix[12];
25530 int counter = 0;
25533 * Create a namespace declaration on the validation
25534 * root node if no namespace declaration is in scope.
25536 do {
25537 snprintf((char *) prefix, 12, "p%d", counter++);
25538 ns = xmlSearchNs(defAttrOwnerElem->doc,
25539 defAttrOwnerElem, BAD_CAST prefix);
25540 if (counter > 1000) {
25541 VERROR_INT(
25542 "xmlSchemaVAttributesComplex",
25543 "could not compute a ns prefix for a "
25544 "default/fixed attribute");
25545 if (normValue != NULL)
25546 xmlFree(normValue);
25547 goto internal_error;
25549 } while (ns != NULL);
25550 ns = xmlNewNs(vctxt->validationRoot,
25551 iattr->nsName, BAD_CAST prefix);
25554 * TODO:
25555 * http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005JulSep/0406.html
25556 * If we have QNames: do we need to ensure there's a
25557 * prefix defined for the QName?
25559 xmlNewNsProp(defAttrOwnerElem, ns, iattr->localName, value);
25561 if (normValue != NULL)
25562 xmlFree(normValue);
25565 * Go directly to IDC evaluation.
25567 goto eval_idcs;
25570 * Validate the value.
25572 if (vctxt->value != NULL) {
25574 * Free last computed value; just for safety reasons.
25576 xmlSchemaFreeValue(vctxt->value);
25577 vctxt->value = NULL;
25580 * Note that the attribute *use* can be unavailable, if
25581 * the attribute was a wild attribute.
25583 if ((iattr->decl->flags & XML_SCHEMAS_ATTR_FIXED) ||
25584 ((iattr->use != NULL) &&
25585 (iattr->use->flags & XML_SCHEMAS_ATTR_FIXED)))
25586 fixed = 1;
25587 else
25588 fixed = 0;
25590 * SPEC (cvc-attribute)
25591 * (3) "The item's �normalized value� must be locally �valid�
25592 * with respect to that {type definition} as per
25593 * String Valid (�3.14.4)."
25595 * VAL TODO: Do we already have the
25596 * "normalized attribute value" here?
25598 if (xpathRes || fixed) {
25599 iattr->flags |= XML_SCHEMA_NODE_INFO_VALUE_NEEDED;
25601 * Request a computed value.
25603 res = xmlSchemaVCheckCVCSimpleType(
25604 ACTXT_CAST vctxt,
25605 iattr->node, iattr->typeDef, iattr->value, &(iattr->val),
25606 1, 1, 0);
25607 } else {
25608 res = xmlSchemaVCheckCVCSimpleType(
25609 ACTXT_CAST vctxt,
25610 iattr->node, iattr->typeDef, iattr->value, NULL,
25611 1, 0, 0);
25614 if (res != 0) {
25615 if (res == -1) {
25616 VERROR_INT("xmlSchemaVAttributesComplex",
25617 "calling xmlSchemaStreamValidateSimpleTypeValue()");
25618 goto internal_error;
25620 iattr->state = XML_SCHEMAS_ATTR_INVALID_VALUE;
25622 * SPEC PSVI Assessment Outcome (Attribute)
25623 * [validity] = "invalid"
25625 goto eval_idcs;
25628 if (fixed) {
25630 * SPEC Attribute Locally Valid (Use) (cvc-au)
25631 * "For an attribute information item to be�valid�
25632 * with respect to an attribute use its *normalized*
25633 * value� must match the *canonical* lexical
25634 * representation of the attribute use's {value
25635 * constraint}value, if it is present and fixed."
25637 * VAL TODO: The requirement for the *canonical* value
25638 * will be removed in XML Schema 1.1.
25641 * SPEC Attribute Locally Valid (cvc-attribute)
25642 * (4) "The item's *actual* value� must match the *value* of
25643 * the {value constraint}, if it is present and fixed."
25645 if (iattr->val == NULL) {
25646 /* VAL TODO: A value was not precomputed. */
25647 TODO
25648 goto eval_idcs;
25650 if ((iattr->use != NULL) &&
25651 (iattr->use->defValue != NULL)) {
25652 if (iattr->use->defVal == NULL) {
25653 /* VAL TODO: A default value was not precomputed. */
25654 TODO
25655 goto eval_idcs;
25657 iattr->vcValue = iattr->use->defValue;
25659 if (xmlSchemaCompareValuesWhtsp(attr->val,
25660 (xmlSchemaWhitespaceValueType) ws,
25661 attr->use->defVal,
25662 (xmlSchemaWhitespaceValueType) ws) != 0) {
25664 if (! xmlSchemaAreValuesEqual(iattr->val, iattr->use->defVal))
25665 iattr->state = XML_SCHEMAS_ATTR_ERR_FIXED_VALUE;
25666 } else {
25667 if (iattr->decl->defVal == NULL) {
25668 /* VAL TODO: A default value was not precomputed. */
25669 TODO
25670 goto eval_idcs;
25672 iattr->vcValue = iattr->decl->defValue;
25674 if (xmlSchemaCompareValuesWhtsp(attr->val,
25675 (xmlSchemaWhitespaceValueType) ws,
25676 attrDecl->defVal,
25677 (xmlSchemaWhitespaceValueType) ws) != 0) {
25679 if (! xmlSchemaAreValuesEqual(iattr->val, iattr->decl->defVal))
25680 iattr->state = XML_SCHEMAS_ATTR_ERR_FIXED_VALUE;
25683 * [validity] = "valid"
25686 eval_idcs:
25688 * Evaluate IDCs.
25690 if (xpathRes) {
25691 if (xmlSchemaXPathProcessHistory(vctxt,
25692 vctxt->depth +1) == -1) {
25693 VERROR_INT("xmlSchemaVAttributesComplex",
25694 "calling xmlSchemaXPathEvaluate()");
25695 goto internal_error;
25697 } else if (vctxt->xpathStates != NULL)
25698 xmlSchemaXPathPop(vctxt);
25702 * Report errors.
25704 for (i = 0; i < vctxt->nbAttrInfos; i++) {
25705 iattr = vctxt->attrInfos[i];
25706 if ((iattr->state == XML_SCHEMAS_ATTR_META) ||
25707 (iattr->state == XML_SCHEMAS_ATTR_ASSESSED) ||
25708 (iattr->state == XML_SCHEMAS_ATTR_WILD_SKIP) ||
25709 (iattr->state == XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL))
25710 continue;
25711 ACTIVATE_ATTRIBUTE(iattr);
25712 switch (iattr->state) {
25713 case XML_SCHEMAS_ATTR_ERR_MISSING: {
25714 xmlChar *str = NULL;
25715 ACTIVATE_ELEM;
25716 xmlSchemaCustomErr(ACTXT_CAST vctxt,
25717 XML_SCHEMAV_CVC_COMPLEX_TYPE_4, NULL, NULL,
25718 "The attribute '%s' is required but missing",
25719 xmlSchemaFormatQName(&str,
25720 iattr->decl->targetNamespace,
25721 iattr->decl->name),
25722 NULL);
25723 FREE_AND_NULL(str)
25724 break;
25726 case XML_SCHEMAS_ATTR_ERR_NO_TYPE:
25727 VERROR(XML_SCHEMAV_CVC_ATTRIBUTE_2, NULL,
25728 "The type definition is absent");
25729 break;
25730 case XML_SCHEMAS_ATTR_ERR_FIXED_VALUE:
25731 xmlSchemaCustomErr(ACTXT_CAST vctxt,
25732 XML_SCHEMAV_CVC_AU, NULL, NULL,
25733 "The value '%s' does not match the fixed "
25734 "value constraint '%s'",
25735 iattr->value, iattr->vcValue);
25736 break;
25737 case XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL:
25738 VERROR(XML_SCHEMAV_CVC_WILDCARD, NULL,
25739 "No matching global attribute declaration available, but "
25740 "demanded by the strict wildcard");
25741 break;
25742 case XML_SCHEMAS_ATTR_UNKNOWN:
25743 if (iattr->metaType)
25744 break;
25746 * MAYBE VAL TODO: One might report different error messages
25747 * for the following errors.
25749 if (type->attributeWildcard == NULL) {
25750 xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt,
25751 XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_1, iattr, NULL);
25752 } else {
25753 xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt,
25754 XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_2, iattr, NULL);
25756 break;
25757 default:
25758 break;
25762 ACTIVATE_ELEM;
25763 return (0);
25764 internal_error:
25765 ACTIVATE_ELEM;
25766 return (-1);
25769 static int
25770 xmlSchemaValidateElemWildcard(xmlSchemaValidCtxtPtr vctxt,
25771 int *skip)
25773 xmlSchemaWildcardPtr wild = (xmlSchemaWildcardPtr) vctxt->inode->decl;
25775 * The namespace of the element was already identified to be
25776 * matching the wildcard.
25778 if ((skip == NULL) || (wild == NULL) ||
25779 (wild->type != XML_SCHEMA_TYPE_ANY)) {
25780 VERROR_INT("xmlSchemaValidateElemWildcard",
25781 "bad arguments");
25782 return (-1);
25784 *skip = 0;
25785 if (wild->processContents == XML_SCHEMAS_ANY_SKIP) {
25787 * URGENT VAL TODO: Either we need to position the stream to the
25788 * next sibling, or walk the whole subtree.
25790 *skip = 1;
25791 return (0);
25794 xmlSchemaElementPtr decl = NULL;
25796 decl = xmlSchemaGetElem(vctxt->schema,
25797 vctxt->inode->localName, vctxt->inode->nsName);
25798 if (decl != NULL) {
25799 vctxt->inode->decl = decl;
25800 return (0);
25803 if (wild->processContents == XML_SCHEMAS_ANY_STRICT) {
25804 /* VAL TODO: Change to proper error code. */
25805 VERROR(XML_SCHEMAV_CVC_ELT_1, NULL, /* WXS_BASIC_CAST wild */
25806 "No matching global element declaration available, but "
25807 "demanded by the strict wildcard");
25808 return (vctxt->err);
25810 if (vctxt->nbAttrInfos != 0) {
25811 xmlSchemaAttrInfoPtr iattr;
25813 * SPEC Validation Rule: Schema-Validity Assessment (Element)
25814 * (1.2.1.2.1) - (1.2.1.2.3 )
25816 * Use the xsi:type attribute for the type definition.
25818 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
25819 XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
25820 if (iattr != NULL) {
25821 if (xmlSchemaProcessXSIType(vctxt, iattr,
25822 &(vctxt->inode->typeDef), NULL) == -1) {
25823 VERROR_INT("xmlSchemaValidateElemWildcard",
25824 "calling xmlSchemaProcessXSIType() to "
25825 "process the attribute 'xsi:nil'");
25826 return (-1);
25829 * Don't return an error on purpose.
25831 return (0);
25835 * SPEC Validation Rule: Schema-Validity Assessment (Element)
25837 * Fallback to "anyType".
25839 vctxt->inode->typeDef =
25840 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
25841 return (0);
25845 * xmlSchemaCheckCOSValidDefault:
25847 * This will be called if: not nilled, no content and a default/fixed
25848 * value is provided.
25851 static int
25852 xmlSchemaCheckCOSValidDefault(xmlSchemaValidCtxtPtr vctxt,
25853 const xmlChar *value,
25854 xmlSchemaValPtr *val)
25856 int ret = 0;
25857 xmlSchemaNodeInfoPtr inode = vctxt->inode;
25860 * cos-valid-default:
25861 * Schema Component Constraint: Element Default Valid (Immediate)
25862 * For a string to be a valid default with respect to a type
25863 * definition the appropriate case among the following must be true:
25865 if WXS_IS_COMPLEX(inode->typeDef) {
25867 * Complex type.
25869 * SPEC (2.1) "its {content type} must be a simple type definition
25870 * or mixed."
25871 * SPEC (2.2.2) "If the {content type} is mixed, then the {content
25872 * type}'s particle must be �emptiable� as defined by
25873 * Particle Emptiable (�3.9.6)."
25875 if ((! WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) &&
25876 ((! WXS_HAS_MIXED_CONTENT(inode->typeDef)) ||
25877 (! WXS_EMPTIABLE(inode->typeDef)))) {
25878 ret = XML_SCHEMAP_COS_VALID_DEFAULT_2_1;
25879 /* NOTE that this covers (2.2.2) as well. */
25880 VERROR(ret, NULL,
25881 "For a string to be a valid default, the type definition "
25882 "must be a simple type or a complex type with simple content "
25883 "or mixed content and a particle emptiable");
25884 return(ret);
25888 * 1 If the type definition is a simple type definition, then the string
25889 * must be �valid� with respect to that definition as defined by String
25890 * Valid (�3.14.4).
25892 * AND
25894 * 2.2.1 If the {content type} is a simple type definition, then the
25895 * string must be �valid� with respect to that simple type definition
25896 * as defined by String Valid (�3.14.4).
25898 if (WXS_IS_SIMPLE(inode->typeDef)) {
25900 ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST vctxt,
25901 NULL, inode->typeDef, value, val, 1, 1, 0);
25903 } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
25905 ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST vctxt,
25906 NULL, inode->typeDef->contentTypeDef, value, val, 1, 1, 0);
25908 if (ret < 0) {
25909 VERROR_INT("xmlSchemaCheckCOSValidDefault",
25910 "calling xmlSchemaVCheckCVCSimpleType()");
25912 return (ret);
25915 static void
25916 xmlSchemaVContentModelCallback(xmlSchemaValidCtxtPtr vctxt ATTRIBUTE_UNUSED,
25917 const xmlChar * name ATTRIBUTE_UNUSED,
25918 xmlSchemaElementPtr item,
25919 xmlSchemaNodeInfoPtr inode)
25921 inode->decl = item;
25922 #ifdef DEBUG_CONTENT
25924 xmlChar *str = NULL;
25926 if (item->type == XML_SCHEMA_TYPE_ELEMENT) {
25927 xmlGenericError(xmlGenericErrorContext,
25928 "AUTOMATON callback for '%s' [declaration]\n",
25929 xmlSchemaFormatQName(&str,
25930 inode->localName, inode->nsName));
25931 } else {
25932 xmlGenericError(xmlGenericErrorContext,
25933 "AUTOMATON callback for '%s' [wildcard]\n",
25934 xmlSchemaFormatQName(&str,
25935 inode->localName, inode->nsName));
25938 FREE_AND_NULL(str)
25940 #endif
25943 static int
25944 xmlSchemaValidatorPushElem(xmlSchemaValidCtxtPtr vctxt)
25946 vctxt->inode = xmlSchemaGetFreshElemInfo(vctxt);
25947 if (vctxt->inode == NULL) {
25948 VERROR_INT("xmlSchemaValidatorPushElem",
25949 "calling xmlSchemaGetFreshElemInfo()");
25950 return (-1);
25952 vctxt->nbAttrInfos = 0;
25953 return (0);
25956 static int
25957 xmlSchemaVCheckINodeDataType(xmlSchemaValidCtxtPtr vctxt,
25958 xmlSchemaNodeInfoPtr inode,
25959 xmlSchemaTypePtr type,
25960 const xmlChar *value)
25962 if (inode->flags & XML_SCHEMA_NODE_INFO_VALUE_NEEDED)
25963 return (xmlSchemaVCheckCVCSimpleType(
25964 ACTXT_CAST vctxt, NULL,
25965 type, value, &(inode->val), 1, 1, 0));
25966 else
25967 return (xmlSchemaVCheckCVCSimpleType(
25968 ACTXT_CAST vctxt, NULL,
25969 type, value, NULL, 1, 0, 0));
25975 * Process END of element.
25977 static int
25978 xmlSchemaValidatorPopElem(xmlSchemaValidCtxtPtr vctxt)
25980 int ret = 0;
25981 xmlSchemaNodeInfoPtr inode = vctxt->inode;
25983 if (vctxt->nbAttrInfos != 0)
25984 xmlSchemaClearAttrInfos(vctxt);
25985 if (inode->flags & XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED) {
25987 * This element was not expected;
25988 * we will not validate child elements of broken parents.
25989 * Skip validation of all content of the parent.
25991 vctxt->skipDepth = vctxt->depth -1;
25992 goto end_elem;
25994 if ((inode->typeDef == NULL) ||
25995 (inode->flags & XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE)) {
25997 * 1. the type definition might be missing if the element was
25998 * error prone
25999 * 2. it might be abstract.
26001 goto end_elem;
26004 * Check the content model.
26006 if ((inode->typeDef->contentType == XML_SCHEMA_CONTENT_MIXED) ||
26007 (inode->typeDef->contentType == XML_SCHEMA_CONTENT_ELEMENTS)) {
26010 * Workaround for "anyType".
26012 if (inode->typeDef->builtInType == XML_SCHEMAS_ANYTYPE)
26013 goto character_content;
26015 if ((inode->flags & XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT) == 0) {
26016 xmlChar *values[10];
26017 int terminal, nbval = 10, nbneg;
26019 if (inode->regexCtxt == NULL) {
26021 * Create the regex context.
26023 inode->regexCtxt =
26024 xmlRegNewExecCtxt(inode->typeDef->contModel,
26025 (xmlRegExecCallbacks) xmlSchemaVContentModelCallback,
26026 vctxt);
26027 if (inode->regexCtxt == NULL) {
26028 VERROR_INT("xmlSchemaValidatorPopElem",
26029 "failed to create a regex context");
26030 goto internal_error;
26032 #ifdef DEBUG_AUTOMATA
26033 xmlGenericError(xmlGenericErrorContext,
26034 "AUTOMATON create on '%s'\n", inode->localName);
26035 #endif
26038 * Get hold of the still expected content, since a further
26039 * call to xmlRegExecPushString() will loose this information.
26041 xmlRegExecNextValues(inode->regexCtxt,
26042 &nbval, &nbneg, &values[0], &terminal);
26043 ret = xmlRegExecPushString(inode->regexCtxt, NULL, NULL);
26044 if ((ret<0) || ((ret==0) && (!INODE_NILLED(inode)))) {
26046 * Still missing something.
26048 ret = 1;
26049 inode->flags |=
26050 XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT;
26051 xmlSchemaComplexTypeErr(ACTXT_CAST vctxt,
26052 XML_SCHEMAV_ELEMENT_CONTENT, NULL, NULL,
26053 "Missing child element(s)",
26054 nbval, nbneg, values);
26055 #ifdef DEBUG_AUTOMATA
26056 xmlGenericError(xmlGenericErrorContext,
26057 "AUTOMATON missing ERROR on '%s'\n",
26058 inode->localName);
26059 #endif
26060 } else {
26062 * Content model is satisfied.
26064 ret = 0;
26065 #ifdef DEBUG_AUTOMATA
26066 xmlGenericError(xmlGenericErrorContext,
26067 "AUTOMATON succeeded on '%s'\n",
26068 inode->localName);
26069 #endif
26074 if (inode->typeDef->contentType == XML_SCHEMA_CONTENT_ELEMENTS)
26075 goto end_elem;
26077 character_content:
26079 if (vctxt->value != NULL) {
26080 xmlSchemaFreeValue(vctxt->value);
26081 vctxt->value = NULL;
26084 * Check character content.
26086 if (inode->decl == NULL) {
26088 * Speedup if no declaration exists.
26090 if (WXS_IS_SIMPLE(inode->typeDef)) {
26091 ret = xmlSchemaVCheckINodeDataType(vctxt,
26092 inode, inode->typeDef, inode->value);
26093 } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
26094 ret = xmlSchemaVCheckINodeDataType(vctxt,
26095 inode, inode->typeDef->contentTypeDef,
26096 inode->value);
26098 if (ret < 0) {
26099 VERROR_INT("xmlSchemaValidatorPopElem",
26100 "calling xmlSchemaVCheckCVCSimpleType()");
26101 goto internal_error;
26103 goto end_elem;
26106 * cvc-elt (3.3.4) : 5
26107 * The appropriate case among the following must be true:
26110 * cvc-elt (3.3.4) : 5.1
26111 * If the declaration has a {value constraint},
26112 * the item has neither element nor character [children] and
26113 * clause 3.2 has not applied, then all of the following must be true:
26115 if ((inode->decl->value != NULL) &&
26116 (inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY) &&
26117 (! INODE_NILLED(inode))) {
26119 * cvc-elt (3.3.4) : 5.1.1
26120 * If the �actual type definition� is a �local type definition�
26121 * then the canonical lexical representation of the {value constraint}
26122 * value must be a valid default for the �actual type definition� as
26123 * defined in Element Default Valid (Immediate) (�3.3.6).
26126 * NOTE: 'local' above means types acquired by xsi:type.
26127 * NOTE: Although the *canonical* value is stated, it is not
26128 * relevant if canonical or not. Additionally XML Schema 1.1
26129 * will removed this requirement as well.
26131 if (inode->flags & XML_SCHEMA_ELEM_INFO_LOCAL_TYPE) {
26133 ret = xmlSchemaCheckCOSValidDefault(vctxt,
26134 inode->decl->value, &(inode->val));
26135 if (ret != 0) {
26136 if (ret < 0) {
26137 VERROR_INT("xmlSchemaValidatorPopElem",
26138 "calling xmlSchemaCheckCOSValidDefault()");
26139 goto internal_error;
26141 goto end_elem;
26144 * Stop here, to avoid redundant validation of the value
26145 * (see following).
26147 goto default_psvi;
26150 * cvc-elt (3.3.4) : 5.1.2
26151 * The element information item with the canonical lexical
26152 * representation of the {value constraint} value used as its
26153 * �normalized value� must be �valid� with respect to the
26154 * �actual type definition� as defined by Element Locally Valid (Type)
26155 * (�3.3.4).
26157 if (WXS_IS_SIMPLE(inode->typeDef)) {
26158 ret = xmlSchemaVCheckINodeDataType(vctxt,
26159 inode, inode->typeDef, inode->decl->value);
26160 } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
26161 ret = xmlSchemaVCheckINodeDataType(vctxt,
26162 inode, inode->typeDef->contentTypeDef,
26163 inode->decl->value);
26165 if (ret != 0) {
26166 if (ret < 0) {
26167 VERROR_INT("xmlSchemaValidatorPopElem",
26168 "calling xmlSchemaVCheckCVCSimpleType()");
26169 goto internal_error;
26171 goto end_elem;
26174 default_psvi:
26176 * PSVI: Create a text node on the instance element.
26178 if ((vctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) &&
26179 (inode->node != NULL)) {
26180 xmlNodePtr textChild;
26181 xmlChar *normValue;
26183 * VAL TODO: Normalize the value.
26185 normValue = xmlSchemaNormalizeValue(inode->typeDef,
26186 inode->decl->value);
26187 if (normValue != NULL) {
26188 textChild = xmlNewText(BAD_CAST normValue);
26189 xmlFree(normValue);
26190 } else
26191 textChild = xmlNewText(inode->decl->value);
26192 if (textChild == NULL) {
26193 VERROR_INT("xmlSchemaValidatorPopElem",
26194 "calling xmlNewText()");
26195 goto internal_error;
26196 } else
26197 xmlAddChild(inode->node, textChild);
26200 } else if (! INODE_NILLED(inode)) {
26202 * 5.2.1 The element information item must be �valid� with respect
26203 * to the �actual type definition� as defined by Element Locally
26204 * Valid (Type) (�3.3.4).
26206 if (WXS_IS_SIMPLE(inode->typeDef)) {
26208 * SPEC (cvc-type) (3.1)
26209 * "If the type definition is a simple type definition, ..."
26210 * (3.1.3) "If clause 3.2 of Element Locally Valid
26211 * (Element) (�3.3.4) did not apply, then the �normalized value�
26212 * must be �valid� with respect to the type definition as defined
26213 * by String Valid (�3.14.4).
26215 ret = xmlSchemaVCheckINodeDataType(vctxt,
26216 inode, inode->typeDef, inode->value);
26217 } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
26219 * SPEC (cvc-type) (3.2) "If the type definition is a complex type
26220 * definition, then the element information item must be
26221 * �valid� with respect to the type definition as per
26222 * Element Locally Valid (Complex Type) (�3.4.4);"
26224 * SPEC (cvc-complex-type) (2.2)
26225 * "If the {content type} is a simple type definition, ...
26226 * the �normalized value� of the element information item is
26227 * �valid� with respect to that simple type definition as
26228 * defined by String Valid (�3.14.4)."
26230 ret = xmlSchemaVCheckINodeDataType(vctxt,
26231 inode, inode->typeDef->contentTypeDef, inode->value);
26233 if (ret != 0) {
26234 if (ret < 0) {
26235 VERROR_INT("xmlSchemaValidatorPopElem",
26236 "calling xmlSchemaVCheckCVCSimpleType()");
26237 goto internal_error;
26239 goto end_elem;
26242 * 5.2.2 If there is a fixed {value constraint} and clause 3.2 has
26243 * not applied, all of the following must be true:
26245 if ((inode->decl->value != NULL) &&
26246 (inode->decl->flags & XML_SCHEMAS_ELEM_FIXED)) {
26249 * TODO: We will need a computed value, when comparison is
26250 * done on computed values.
26253 * 5.2.2.1 The element information item must have no element
26254 * information item [children].
26256 if (inode->flags &
26257 XML_SCHEMA_ELEM_INFO_HAS_ELEM_CONTENT) {
26258 ret = XML_SCHEMAV_CVC_ELT_5_2_2_1;
26259 VERROR(ret, NULL,
26260 "The content must not containt element nodes since "
26261 "there is a fixed value constraint");
26262 goto end_elem;
26263 } else {
26265 * 5.2.2.2 The appropriate case among the following must
26266 * be true:
26268 if (WXS_HAS_MIXED_CONTENT(inode->typeDef)) {
26270 * 5.2.2.2.1 If the {content type} of the �actual type
26271 * definition� is mixed, then the *initial value* of the
26272 * item must match the canonical lexical representation
26273 * of the {value constraint} value.
26275 * ... the *initial value* of an element information
26276 * item is the string composed of, in order, the
26277 * [character code] of each character information item in
26278 * the [children] of that element information item.
26280 if (! xmlStrEqual(inode->value, inode->decl->value)){
26282 * VAL TODO: Report invalid & expected values as well.
26283 * VAL TODO: Implement the canonical stuff.
26285 ret = XML_SCHEMAV_CVC_ELT_5_2_2_2_1;
26286 xmlSchemaCustomErr(ACTXT_CAST vctxt,
26287 ret, NULL, NULL,
26288 "The initial value '%s' does not match the fixed "
26289 "value constraint '%s'",
26290 inode->value, inode->decl->value);
26291 goto end_elem;
26293 } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
26295 * 5.2.2.2.2 If the {content type} of the �actual type
26296 * definition� is a simple type definition, then the
26297 * *actual value* of the item must match the canonical
26298 * lexical representation of the {value constraint} value.
26301 * VAL TODO: *actual value* is the normalized value, impl.
26302 * this.
26303 * VAL TODO: Report invalid & expected values as well.
26304 * VAL TODO: Implement a comparison with the computed values.
26306 if (! xmlStrEqual(inode->value,
26307 inode->decl->value)) {
26308 ret = XML_SCHEMAV_CVC_ELT_5_2_2_2_2;
26309 xmlSchemaCustomErr(ACTXT_CAST vctxt,
26310 ret, NULL, NULL,
26311 "The actual value '%s' does not match the fixed "
26312 "value constraint '%s'",
26313 inode->value,
26314 inode->decl->value);
26315 goto end_elem;
26322 end_elem:
26323 if (vctxt->depth < 0) {
26324 /* TODO: raise error? */
26325 return (0);
26327 if (vctxt->depth == vctxt->skipDepth)
26328 vctxt->skipDepth = -1;
26330 * Evaluate the history of XPath state objects.
26332 if (inode->appliedXPath &&
26333 (xmlSchemaXPathProcessHistory(vctxt, vctxt->depth) == -1))
26334 goto internal_error;
26336 * MAYBE TODO:
26337 * SPEC (6) "The element information item must be �valid� with
26338 * respect to each of the {identity-constraint definitions} as per
26339 * Identity-constraint Satisfied (�3.11.4)."
26342 * PSVI TODO: If we expose IDC node-tables via PSVI then the tables
26343 * need to be built in any case.
26344 * We will currently build IDC node-tables and bubble them only if
26345 * keyrefs do exist.
26349 * Add the current IDC target-nodes to the IDC node-tables.
26351 if ((inode->idcMatchers != NULL) &&
26352 (vctxt->hasKeyrefs || vctxt->createIDCNodeTables))
26354 if (xmlSchemaIDCFillNodeTables(vctxt, inode) == -1)
26355 goto internal_error;
26358 * Validate IDC keyrefs.
26360 if (vctxt->inode->hasKeyrefs)
26361 if (xmlSchemaCheckCVCIDCKeyRef(vctxt) == -1)
26362 goto internal_error;
26364 * Merge/free the IDC table.
26366 if (inode->idcTable != NULL) {
26367 #ifdef DEBUG_IDC_NODE_TABLE
26368 xmlSchemaDebugDumpIDCTable(stdout,
26369 inode->nsName,
26370 inode->localName,
26371 inode->idcTable);
26372 #endif
26373 if ((vctxt->depth > 0) &&
26374 (vctxt->hasKeyrefs || vctxt->createIDCNodeTables))
26377 * Merge the IDC node table with the table of the parent node.
26379 if (xmlSchemaBubbleIDCNodeTables(vctxt) == -1)
26380 goto internal_error;
26384 * Clear the current ielem.
26385 * VAL TODO: Don't free the PSVI IDC tables if they are
26386 * requested for the PSVI.
26388 xmlSchemaClearElemInfo(vctxt, inode);
26390 * Skip further processing if we are on the validation root.
26392 if (vctxt->depth == 0) {
26393 vctxt->depth--;
26394 vctxt->inode = NULL;
26395 return (0);
26398 * Reset the keyrefDepth if needed.
26400 if (vctxt->aidcs != NULL) {
26401 xmlSchemaIDCAugPtr aidc = vctxt->aidcs;
26402 do {
26403 if (aidc->keyrefDepth == vctxt->depth) {
26405 * A 'keyrefDepth' of a key/unique IDC matches the current
26406 * depth, this means that we are leaving the scope of the
26407 * top-most keyref IDC which refers to this IDC.
26409 aidc->keyrefDepth = -1;
26411 aidc = aidc->next;
26412 } while (aidc != NULL);
26414 vctxt->depth--;
26415 vctxt->inode = vctxt->elemInfos[vctxt->depth];
26417 * VAL TODO: 7 If the element information item is the �validation root�, it must be
26418 * �valid� per Validation Root Valid (ID/IDREF) (�3.3.4).
26420 return (ret);
26422 internal_error:
26423 vctxt->err = -1;
26424 return (-1);
26428 * 3.4.4 Complex Type Definition Validation Rules
26429 * Validation Rule: Element Locally Valid (Complex Type) (cvc-complex-type)
26431 static int
26432 xmlSchemaValidateChildElem(xmlSchemaValidCtxtPtr vctxt)
26434 xmlSchemaNodeInfoPtr pielem;
26435 xmlSchemaTypePtr ptype;
26436 int ret = 0;
26438 if (vctxt->depth <= 0) {
26439 VERROR_INT("xmlSchemaValidateChildElem",
26440 "not intended for the validation root");
26441 return (-1);
26443 pielem = vctxt->elemInfos[vctxt->depth -1];
26444 if (pielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
26445 pielem->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
26447 * Handle 'nilled' elements.
26449 if (INODE_NILLED(pielem)) {
26451 * SPEC (cvc-elt) (3.3.4) : (3.2.1)
26453 ACTIVATE_PARENT_ELEM;
26454 ret = XML_SCHEMAV_CVC_ELT_3_2_1;
26455 VERROR(ret, NULL,
26456 "Neither character nor element content is allowed, "
26457 "because the element was 'nilled'");
26458 ACTIVATE_ELEM;
26459 goto unexpected_elem;
26462 ptype = pielem->typeDef;
26464 if (ptype->builtInType == XML_SCHEMAS_ANYTYPE) {
26466 * Workaround for "anyType": we have currently no content model
26467 * assigned for "anyType", so handle it explicitely.
26468 * "anyType" has an unbounded, lax "any" wildcard.
26470 vctxt->inode->decl = xmlSchemaGetElem(vctxt->schema,
26471 vctxt->inode->localName,
26472 vctxt->inode->nsName);
26474 if (vctxt->inode->decl == NULL) {
26475 xmlSchemaAttrInfoPtr iattr;
26477 * Process "xsi:type".
26478 * SPEC (cvc-assess-elt) (1.2.1.2.1) - (1.2.1.2.3)
26480 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
26481 XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
26482 if (iattr != NULL) {
26483 ret = xmlSchemaProcessXSIType(vctxt, iattr,
26484 &(vctxt->inode->typeDef), NULL);
26485 if (ret != 0) {
26486 if (ret == -1) {
26487 VERROR_INT("xmlSchemaValidateChildElem",
26488 "calling xmlSchemaProcessXSIType() to "
26489 "process the attribute 'xsi:nil'");
26490 return (-1);
26492 return (ret);
26494 } else {
26496 * Fallback to "anyType".
26498 * SPEC (cvc-assess-elt)
26499 * "If the item cannot be �strictly assessed�, [...]
26500 * an element information item's schema validity may be laxly
26501 * assessed if its �context-determined declaration� is not
26502 * skip by �validating� with respect to the �ur-type
26503 * definition� as per Element Locally Valid (Type) (�3.3.4)."
26505 vctxt->inode->typeDef =
26506 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
26509 return (0);
26512 switch (ptype->contentType) {
26513 case XML_SCHEMA_CONTENT_EMPTY:
26515 * SPEC (2.1) "If the {content type} is empty, then the
26516 * element information item has no character or element
26517 * information item [children]."
26519 ACTIVATE_PARENT_ELEM
26520 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1;
26521 VERROR(ret, NULL,
26522 "Element content is not allowed, "
26523 "because the content type is empty");
26524 ACTIVATE_ELEM
26525 goto unexpected_elem;
26526 break;
26528 case XML_SCHEMA_CONTENT_MIXED:
26529 case XML_SCHEMA_CONTENT_ELEMENTS: {
26530 xmlRegExecCtxtPtr regexCtxt;
26531 xmlChar *values[10];
26532 int terminal, nbval = 10, nbneg;
26534 /* VAL TODO: Optimized "anyType" validation.*/
26536 if (ptype->contModel == NULL) {
26537 VERROR_INT("xmlSchemaValidateChildElem",
26538 "type has elem content but no content model");
26539 return (-1);
26542 * Safety belf for evaluation if the cont. model was already
26543 * examined to be invalid.
26545 if (pielem->flags & XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT) {
26546 VERROR_INT("xmlSchemaValidateChildElem",
26547 "validating elem, but elem content is already invalid");
26548 return (-1);
26551 regexCtxt = pielem->regexCtxt;
26552 if (regexCtxt == NULL) {
26554 * Create the regex context.
26556 regexCtxt = xmlRegNewExecCtxt(ptype->contModel,
26557 (xmlRegExecCallbacks) xmlSchemaVContentModelCallback,
26558 vctxt);
26559 if (regexCtxt == NULL) {
26560 VERROR_INT("xmlSchemaValidateChildElem",
26561 "failed to create a regex context");
26562 return (-1);
26564 pielem->regexCtxt = regexCtxt;
26565 #ifdef DEBUG_AUTOMATA
26566 xmlGenericError(xmlGenericErrorContext, "AUTOMATA create on '%s'\n",
26567 pielem->localName);
26568 #endif
26572 * SPEC (2.4) "If the {content type} is element-only or mixed,
26573 * then the sequence of the element information item's
26574 * element information item [children], if any, taken in
26575 * order, is �valid� with respect to the {content type}'s
26576 * particle, as defined in Element Sequence Locally Valid
26577 * (Particle) (�3.9.4)."
26579 ret = xmlRegExecPushString2(regexCtxt,
26580 vctxt->inode->localName,
26581 vctxt->inode->nsName,
26582 vctxt->inode);
26583 #ifdef DEBUG_AUTOMATA
26584 if (ret < 0)
26585 xmlGenericError(xmlGenericErrorContext,
26586 "AUTOMATON push ERROR for '%s' on '%s'\n",
26587 vctxt->inode->localName, pielem->localName);
26588 else
26589 xmlGenericError(xmlGenericErrorContext,
26590 "AUTOMATON push OK for '%s' on '%s'\n",
26591 vctxt->inode->localName, pielem->localName);
26592 #endif
26593 if (vctxt->err == XML_SCHEMAV_INTERNAL) {
26594 VERROR_INT("xmlSchemaValidateChildElem",
26595 "calling xmlRegExecPushString2()");
26596 return (-1);
26598 if (ret < 0) {
26599 xmlRegExecErrInfo(regexCtxt, NULL, &nbval, &nbneg,
26600 &values[0], &terminal);
26601 xmlSchemaComplexTypeErr(ACTXT_CAST vctxt,
26602 XML_SCHEMAV_ELEMENT_CONTENT, NULL,NULL,
26603 "This element is not expected",
26604 nbval, nbneg, values);
26605 ret = vctxt->err;
26606 goto unexpected_elem;
26607 } else
26608 ret = 0;
26610 break;
26611 case XML_SCHEMA_CONTENT_SIMPLE:
26612 case XML_SCHEMA_CONTENT_BASIC:
26613 ACTIVATE_PARENT_ELEM
26614 if (WXS_IS_COMPLEX(ptype)) {
26616 * SPEC (cvc-complex-type) (2.2)
26617 * "If the {content type} is a simple type definition, then
26618 * the element information item has no element information
26619 * item [children], ..."
26621 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
26622 VERROR(ret, NULL, "Element content is not allowed, "
26623 "because the content type is a simple type definition");
26624 } else {
26626 * SPEC (cvc-type) (3.1.2) "The element information item must
26627 * have no element information item [children]."
26629 ret = XML_SCHEMAV_CVC_TYPE_3_1_2;
26630 VERROR(ret, NULL, "Element content is not allowed, "
26631 "because the type definition is simple");
26633 ACTIVATE_ELEM
26634 ret = vctxt->err;
26635 goto unexpected_elem;
26636 break;
26638 default:
26639 break;
26641 return (ret);
26642 unexpected_elem:
26644 * Pop this element and set the skipDepth to skip
26645 * all further content of the parent element.
26647 vctxt->skipDepth = vctxt->depth;
26648 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED;
26649 pielem->flags |= XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT;
26650 return (ret);
26653 #define XML_SCHEMA_PUSH_TEXT_PERSIST 1
26654 #define XML_SCHEMA_PUSH_TEXT_CREATED 2
26655 #define XML_SCHEMA_PUSH_TEXT_VOLATILE 3
26657 static int
26658 xmlSchemaVPushText(xmlSchemaValidCtxtPtr vctxt,
26659 int nodeType, const xmlChar *value, int len,
26660 int mode, int *consumed)
26663 * Unfortunately we have to duplicate the text sometimes.
26664 * OPTIMIZE: Maybe we could skip it, if:
26665 * 1. content type is simple
26666 * 2. whitespace is "collapse"
26667 * 3. it consists of whitespace only
26669 * Process character content.
26671 if (consumed != NULL)
26672 *consumed = 0;
26673 if (INODE_NILLED(vctxt->inode)) {
26675 * SPEC cvc-elt (3.3.4 - 3.2.1)
26676 * "The element information item must have no character or
26677 * element information item [children]."
26679 VERROR(XML_SCHEMAV_CVC_ELT_3_2_1, NULL,
26680 "Neither character nor element content is allowed "
26681 "because the element is 'nilled'");
26682 return (vctxt->err);
26685 * SPEC (2.1) "If the {content type} is empty, then the
26686 * element information item has no character or element
26687 * information item [children]."
26689 if (vctxt->inode->typeDef->contentType ==
26690 XML_SCHEMA_CONTENT_EMPTY) {
26691 VERROR(XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1, NULL,
26692 "Character content is not allowed, "
26693 "because the content type is empty");
26694 return (vctxt->err);
26697 if (vctxt->inode->typeDef->contentType ==
26698 XML_SCHEMA_CONTENT_ELEMENTS) {
26699 if ((nodeType != XML_TEXT_NODE) ||
26700 (! xmlSchemaIsBlank((xmlChar *) value, len))) {
26702 * SPEC cvc-complex-type (2.3)
26703 * "If the {content type} is element-only, then the
26704 * element information item has no character information
26705 * item [children] other than those whose [character
26706 * code] is defined as a white space in [XML 1.0 (Second
26707 * Edition)]."
26709 VERROR(XML_SCHEMAV_CVC_COMPLEX_TYPE_2_3, NULL,
26710 "Character content other than whitespace is not allowed "
26711 "because the content type is 'element-only'");
26712 return (vctxt->err);
26714 return (0);
26717 if ((value == NULL) || (value[0] == 0))
26718 return (0);
26720 * Save the value.
26721 * NOTE that even if the content type is *mixed*, we need the
26722 * *initial value* for default/fixed value constraints.
26724 if ((vctxt->inode->typeDef->contentType == XML_SCHEMA_CONTENT_MIXED) &&
26725 ((vctxt->inode->decl == NULL) ||
26726 (vctxt->inode->decl->value == NULL)))
26727 return (0);
26729 if (vctxt->inode->value == NULL) {
26731 * Set the value.
26733 switch (mode) {
26734 case XML_SCHEMA_PUSH_TEXT_PERSIST:
26736 * When working on a tree.
26738 vctxt->inode->value = value;
26739 break;
26740 case XML_SCHEMA_PUSH_TEXT_CREATED:
26742 * When working with the reader.
26743 * The value will be freed by the element info.
26745 vctxt->inode->value = value;
26746 if (consumed != NULL)
26747 *consumed = 1;
26748 vctxt->inode->flags |=
26749 XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
26750 break;
26751 case XML_SCHEMA_PUSH_TEXT_VOLATILE:
26753 * When working with SAX.
26754 * The value will be freed by the element info.
26756 if (len != -1)
26757 vctxt->inode->value = BAD_CAST xmlStrndup(value, len);
26758 else
26759 vctxt->inode->value = BAD_CAST xmlStrdup(value);
26760 vctxt->inode->flags |=
26761 XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
26762 break;
26763 default:
26764 break;
26766 } else {
26767 if (len < 0)
26768 len = xmlStrlen(value);
26770 * Concat the value.
26772 if (vctxt->inode->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
26773 vctxt->inode->value = BAD_CAST xmlStrncat(
26774 (xmlChar *) vctxt->inode->value, value, len);
26775 } else {
26776 vctxt->inode->value =
26777 BAD_CAST xmlStrncatNew(vctxt->inode->value, value, len);
26778 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
26782 return (0);
26785 static int
26786 xmlSchemaValidateElem(xmlSchemaValidCtxtPtr vctxt)
26788 int ret = 0;
26790 if ((vctxt->skipDepth != -1) &&
26791 (vctxt->depth >= vctxt->skipDepth)) {
26792 VERROR_INT("xmlSchemaValidateElem",
26793 "in skip-state");
26794 goto internal_error;
26796 if (vctxt->xsiAssemble) {
26798 * We will stop validation if there was an error during
26799 * dynamic schema construction.
26800 * Note that we simply set @skipDepth to 0, this could
26801 * mean that a streaming document via SAX would be
26802 * still read to the end but it won't be validated any more.
26803 * TODO: If we are sure how to stop the validation at once
26804 * for all input scenarios, then this should be changed to
26805 * instantly stop the validation.
26807 ret = xmlSchemaAssembleByXSI(vctxt);
26808 if (ret != 0) {
26809 if (ret == -1)
26810 goto internal_error;
26811 vctxt->skipDepth = 0;
26812 return(ret);
26815 if (vctxt->depth > 0) {
26817 * Validate this element against the content model
26818 * of the parent.
26820 ret = xmlSchemaValidateChildElem(vctxt);
26821 if (ret != 0) {
26822 if (ret < 0) {
26823 VERROR_INT("xmlSchemaValidateElem",
26824 "calling xmlSchemaStreamValidateChildElement()");
26825 goto internal_error;
26827 goto exit;
26829 if (vctxt->depth == vctxt->skipDepth)
26830 goto exit;
26831 if ((vctxt->inode->decl == NULL) &&
26832 (vctxt->inode->typeDef == NULL)) {
26833 VERROR_INT("xmlSchemaValidateElem",
26834 "the child element was valid but neither the "
26835 "declaration nor the type was set");
26836 goto internal_error;
26838 } else {
26840 * Get the declaration of the validation root.
26842 vctxt->inode->decl = xmlSchemaGetElem(vctxt->schema,
26843 vctxt->inode->localName,
26844 vctxt->inode->nsName);
26845 if (vctxt->inode->decl == NULL) {
26846 ret = XML_SCHEMAV_CVC_ELT_1;
26847 VERROR(ret, NULL,
26848 "No matching global declaration available "
26849 "for the validation root");
26850 goto exit;
26854 if (vctxt->inode->decl == NULL)
26855 goto type_validation;
26857 if (vctxt->inode->decl->type == XML_SCHEMA_TYPE_ANY) {
26858 int skip;
26860 * Wildcards.
26862 ret = xmlSchemaValidateElemWildcard(vctxt, &skip);
26863 if (ret != 0) {
26864 if (ret < 0) {
26865 VERROR_INT("xmlSchemaValidateElem",
26866 "calling xmlSchemaValidateElemWildcard()");
26867 goto internal_error;
26869 goto exit;
26871 if (skip) {
26872 vctxt->skipDepth = vctxt->depth;
26873 goto exit;
26876 * The declaration might be set by the wildcard validation,
26877 * when the processContents is "lax" or "strict".
26879 if (vctxt->inode->decl->type != XML_SCHEMA_TYPE_ELEMENT) {
26881 * Clear the "decl" field to not confuse further processing.
26883 vctxt->inode->decl = NULL;
26884 goto type_validation;
26888 * Validate against the declaration.
26890 ret = xmlSchemaValidateElemDecl(vctxt);
26891 if (ret != 0) {
26892 if (ret < 0) {
26893 VERROR_INT("xmlSchemaValidateElem",
26894 "calling xmlSchemaValidateElemDecl()");
26895 goto internal_error;
26897 goto exit;
26900 * Validate against the type definition.
26902 type_validation:
26904 if (vctxt->inode->typeDef == NULL) {
26905 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE;
26906 ret = XML_SCHEMAV_CVC_TYPE_1;
26907 VERROR(ret, NULL,
26908 "The type definition is absent");
26909 goto exit;
26911 if (vctxt->inode->typeDef->flags & XML_SCHEMAS_TYPE_ABSTRACT) {
26912 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE;
26913 ret = XML_SCHEMAV_CVC_TYPE_2;
26914 VERROR(ret, NULL,
26915 "The type definition is abstract");
26916 goto exit;
26919 * Evaluate IDCs. Do it here, since new IDC matchers are registered
26920 * during validation against the declaration. This must be done
26921 * _before_ attribute validation.
26923 if (vctxt->xpathStates != NULL) {
26924 ret = xmlSchemaXPathEvaluate(vctxt, XML_ELEMENT_NODE);
26925 vctxt->inode->appliedXPath = 1;
26926 if (ret == -1) {
26927 VERROR_INT("xmlSchemaValidateElem",
26928 "calling xmlSchemaXPathEvaluate()");
26929 goto internal_error;
26933 * Validate attributes.
26935 if (WXS_IS_COMPLEX(vctxt->inode->typeDef)) {
26936 if ((vctxt->nbAttrInfos != 0) ||
26937 (vctxt->inode->typeDef->attrUses != NULL)) {
26939 ret = xmlSchemaVAttributesComplex(vctxt);
26941 } else if (vctxt->nbAttrInfos != 0) {
26943 ret = xmlSchemaVAttributesSimple(vctxt);
26946 * Clear registered attributes.
26948 if (vctxt->nbAttrInfos != 0)
26949 xmlSchemaClearAttrInfos(vctxt);
26950 if (ret == -1) {
26951 VERROR_INT("xmlSchemaValidateElem",
26952 "calling attributes validation");
26953 goto internal_error;
26956 * Don't return an error if attributes are invalid on purpose.
26958 ret = 0;
26960 exit:
26961 if (ret != 0)
26962 vctxt->skipDepth = vctxt->depth;
26963 return (ret);
26964 internal_error:
26965 return (-1);
26968 #ifdef XML_SCHEMA_READER_ENABLED
26969 static int
26970 xmlSchemaVReaderWalk(xmlSchemaValidCtxtPtr vctxt)
26972 const int WHTSP = 13, SIGN_WHTSP = 14, END_ELEM = 15;
26973 int depth, nodeType, ret = 0, consumed;
26974 xmlSchemaNodeInfoPtr ielem;
26976 vctxt->depth = -1;
26977 ret = xmlTextReaderRead(vctxt->reader);
26979 * Move to the document element.
26981 while (ret == 1) {
26982 nodeType = xmlTextReaderNodeType(vctxt->reader);
26983 if (nodeType == XML_ELEMENT_NODE)
26984 goto root_found;
26985 ret = xmlTextReaderRead(vctxt->reader);
26987 goto exit;
26989 root_found:
26991 do {
26992 depth = xmlTextReaderDepth(vctxt->reader);
26993 nodeType = xmlTextReaderNodeType(vctxt->reader);
26995 if (nodeType == XML_ELEMENT_NODE) {
26997 vctxt->depth++;
26998 if (xmlSchemaValidatorPushElem(vctxt) == -1) {
26999 VERROR_INT("xmlSchemaVReaderWalk",
27000 "calling xmlSchemaValidatorPushElem()");
27001 goto internal_error;
27003 ielem = vctxt->inode;
27004 ielem->localName = xmlTextReaderLocalName(vctxt->reader);
27005 ielem->nsName = xmlTextReaderNamespaceUri(vctxt->reader);
27006 ielem->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES;
27008 * Is the element empty?
27010 ret = xmlTextReaderIsEmptyElement(vctxt->reader);
27011 if (ret == -1) {
27012 VERROR_INT("xmlSchemaVReaderWalk",
27013 "calling xmlTextReaderIsEmptyElement()");
27014 goto internal_error;
27016 if (ret) {
27017 ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
27020 * Register attributes.
27022 vctxt->nbAttrInfos = 0;
27023 ret = xmlTextReaderMoveToFirstAttribute(vctxt->reader);
27024 if (ret == -1) {
27025 VERROR_INT("xmlSchemaVReaderWalk",
27026 "calling xmlTextReaderMoveToFirstAttribute()");
27027 goto internal_error;
27029 if (ret == 1) {
27030 do {
27032 * VAL TODO: How do we know that the reader works on a
27033 * node tree, to be able to pass a node here?
27035 if (xmlSchemaValidatorPushAttribute(vctxt, NULL,
27036 (const xmlChar *) xmlTextReaderLocalName(vctxt->reader),
27037 xmlTextReaderNamespaceUri(vctxt->reader), 1,
27038 xmlTextReaderValue(vctxt->reader), 1) == -1) {
27040 VERROR_INT("xmlSchemaVReaderWalk",
27041 "calling xmlSchemaValidatorPushAttribute()");
27042 goto internal_error;
27044 ret = xmlTextReaderMoveToNextAttribute(vctxt->reader);
27045 if (ret == -1) {
27046 VERROR_INT("xmlSchemaVReaderWalk",
27047 "calling xmlTextReaderMoveToFirstAttribute()");
27048 goto internal_error;
27050 } while (ret == 1);
27052 * Back to element position.
27054 ret = xmlTextReaderMoveToElement(vctxt->reader);
27055 if (ret == -1) {
27056 VERROR_INT("xmlSchemaVReaderWalk",
27057 "calling xmlTextReaderMoveToElement()");
27058 goto internal_error;
27062 * Validate the element.
27064 ret= xmlSchemaValidateElem(vctxt);
27065 if (ret != 0) {
27066 if (ret == -1) {
27067 VERROR_INT("xmlSchemaVReaderWalk",
27068 "calling xmlSchemaValidateElem()");
27069 goto internal_error;
27071 goto exit;
27073 if (vctxt->depth == vctxt->skipDepth) {
27074 int curDepth;
27076 * Skip all content.
27078 if ((ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY) == 0) {
27079 ret = xmlTextReaderRead(vctxt->reader);
27080 curDepth = xmlTextReaderDepth(vctxt->reader);
27081 while ((ret == 1) && (curDepth != depth)) {
27082 ret = xmlTextReaderRead(vctxt->reader);
27083 curDepth = xmlTextReaderDepth(vctxt->reader);
27085 if (ret < 0) {
27087 * VAL TODO: A reader error occured; what to do here?
27089 ret = 1;
27090 goto exit;
27093 goto leave_elem;
27096 * READER VAL TODO: Is an END_ELEM really never called
27097 * if the elem is empty?
27099 if (ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
27100 goto leave_elem;
27101 } else if (nodeType == END_ELEM) {
27103 * Process END of element.
27105 leave_elem:
27106 ret = xmlSchemaValidatorPopElem(vctxt);
27107 if (ret != 0) {
27108 if (ret < 0) {
27109 VERROR_INT("xmlSchemaVReaderWalk",
27110 "calling xmlSchemaValidatorPopElem()");
27111 goto internal_error;
27113 goto exit;
27115 if (vctxt->depth >= 0)
27116 ielem = vctxt->inode;
27117 else
27118 ielem = NULL;
27119 } else if ((nodeType == XML_TEXT_NODE) ||
27120 (nodeType == XML_CDATA_SECTION_NODE) ||
27121 (nodeType == WHTSP) ||
27122 (nodeType == SIGN_WHTSP)) {
27124 * Process character content.
27126 xmlChar *value;
27128 if ((nodeType == WHTSP) || (nodeType == SIGN_WHTSP))
27129 nodeType = XML_TEXT_NODE;
27131 value = xmlTextReaderValue(vctxt->reader);
27132 ret = xmlSchemaVPushText(vctxt, nodeType, BAD_CAST value,
27133 -1, XML_SCHEMA_PUSH_TEXT_CREATED, &consumed);
27134 if (! consumed)
27135 xmlFree(value);
27136 if (ret == -1) {
27137 VERROR_INT("xmlSchemaVReaderWalk",
27138 "calling xmlSchemaVPushText()");
27139 goto internal_error;
27141 } else if ((nodeType == XML_ENTITY_NODE) ||
27142 (nodeType == XML_ENTITY_REF_NODE)) {
27144 * VAL TODO: What to do with entities?
27146 TODO
27149 * Read next node.
27151 ret = xmlTextReaderRead(vctxt->reader);
27152 } while (ret == 1);
27154 exit:
27155 return (ret);
27156 internal_error:
27157 return (-1);
27159 #endif
27161 /************************************************************************
27163 * SAX validation handlers *
27165 ************************************************************************/
27168 * Process text content.
27170 static void
27171 xmlSchemaSAXHandleText(void *ctx,
27172 const xmlChar * ch,
27173 int len)
27175 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27177 if (vctxt->depth < 0)
27178 return;
27179 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27180 return;
27181 if (vctxt->inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
27182 vctxt->inode->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
27183 if (xmlSchemaVPushText(vctxt, XML_TEXT_NODE, ch, len,
27184 XML_SCHEMA_PUSH_TEXT_VOLATILE, NULL) == -1) {
27185 VERROR_INT("xmlSchemaSAXHandleCDataSection",
27186 "calling xmlSchemaVPushText()");
27187 vctxt->err = -1;
27188 xmlStopParser(vctxt->parserCtxt);
27193 * Process CDATA content.
27195 static void
27196 xmlSchemaSAXHandleCDataSection(void *ctx,
27197 const xmlChar * ch,
27198 int len)
27200 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27202 if (vctxt->depth < 0)
27203 return;
27204 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27205 return;
27206 if (vctxt->inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
27207 vctxt->inode->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
27208 if (xmlSchemaVPushText(vctxt, XML_CDATA_SECTION_NODE, ch, len,
27209 XML_SCHEMA_PUSH_TEXT_VOLATILE, NULL) == -1) {
27210 VERROR_INT("xmlSchemaSAXHandleCDataSection",
27211 "calling xmlSchemaVPushText()");
27212 vctxt->err = -1;
27213 xmlStopParser(vctxt->parserCtxt);
27217 static void
27218 xmlSchemaSAXHandleReference(void *ctx ATTRIBUTE_UNUSED,
27219 const xmlChar * name ATTRIBUTE_UNUSED)
27221 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27223 if (vctxt->depth < 0)
27224 return;
27225 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27226 return;
27227 /* SAX VAL TODO: What to do here? */
27228 TODO
27231 static void
27232 xmlSchemaSAXHandleStartElementNs(void *ctx,
27233 const xmlChar * localname,
27234 const xmlChar * prefix ATTRIBUTE_UNUSED,
27235 const xmlChar * URI,
27236 int nb_namespaces,
27237 const xmlChar ** namespaces,
27238 int nb_attributes,
27239 int nb_defaulted ATTRIBUTE_UNUSED,
27240 const xmlChar ** attributes)
27242 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27243 int ret;
27244 xmlSchemaNodeInfoPtr ielem;
27245 int i, j;
27248 * SAX VAL TODO: What to do with nb_defaulted?
27251 * Skip elements if inside a "skip" wildcard or invalid.
27253 vctxt->depth++;
27254 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27255 return;
27257 * Push the element.
27259 if (xmlSchemaValidatorPushElem(vctxt) == -1) {
27260 VERROR_INT("xmlSchemaSAXHandleStartElementNs",
27261 "calling xmlSchemaValidatorPushElem()");
27262 goto internal_error;
27264 ielem = vctxt->inode;
27266 * TODO: Is this OK?
27268 ielem->nodeLine = xmlSAX2GetLineNumber(vctxt->parserCtxt);
27269 ielem->localName = localname;
27270 ielem->nsName = URI;
27271 ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
27273 * Register namespaces on the elem info.
27275 if (nb_namespaces != 0) {
27277 * Although the parser builds its own namespace list,
27278 * we have no access to it, so we'll use an own one.
27280 for (i = 0, j = 0; i < nb_namespaces; i++, j += 2) {
27282 * Store prefix and namespace name.
27284 if (ielem->nsBindings == NULL) {
27285 ielem->nsBindings =
27286 (const xmlChar **) xmlMalloc(10 *
27287 sizeof(const xmlChar *));
27288 if (ielem->nsBindings == NULL) {
27289 xmlSchemaVErrMemory(vctxt,
27290 "allocating namespace bindings for SAX validation",
27291 NULL);
27292 goto internal_error;
27294 ielem->nbNsBindings = 0;
27295 ielem->sizeNsBindings = 5;
27296 } else if (ielem->sizeNsBindings <= ielem->nbNsBindings) {
27297 ielem->sizeNsBindings *= 2;
27298 ielem->nsBindings =
27299 (const xmlChar **) xmlRealloc(
27300 (void *) ielem->nsBindings,
27301 ielem->sizeNsBindings * 2 * sizeof(const xmlChar *));
27302 if (ielem->nsBindings == NULL) {
27303 xmlSchemaVErrMemory(vctxt,
27304 "re-allocating namespace bindings for SAX validation",
27305 NULL);
27306 goto internal_error;
27310 ielem->nsBindings[ielem->nbNsBindings * 2] = namespaces[j];
27311 if (namespaces[j+1][0] == 0) {
27313 * Handle xmlns="".
27315 ielem->nsBindings[ielem->nbNsBindings * 2 + 1] = NULL;
27316 } else
27317 ielem->nsBindings[ielem->nbNsBindings * 2 + 1] =
27318 namespaces[j+1];
27319 ielem->nbNsBindings++;
27323 * Register attributes.
27324 * SAX VAL TODO: We are not adding namespace declaration
27325 * attributes yet.
27327 if (nb_attributes != 0) {
27328 xmlChar *value;
27330 for (j = 0, i = 0; i < nb_attributes; i++, j += 5) {
27332 * Duplicate the value.
27334 value = xmlStrndup(attributes[j+3],
27335 attributes[j+4] - attributes[j+3]);
27337 * TODO: Set the node line.
27339 ret = xmlSchemaValidatorPushAttribute(vctxt,
27340 NULL, ielem->nodeLine, attributes[j], attributes[j+2], 0,
27341 value, 1);
27342 if (ret == -1) {
27343 VERROR_INT("xmlSchemaSAXHandleStartElementNs",
27344 "calling xmlSchemaValidatorPushAttribute()");
27345 goto internal_error;
27350 * Validate the element.
27352 ret = xmlSchemaValidateElem(vctxt);
27353 if (ret != 0) {
27354 if (ret == -1) {
27355 VERROR_INT("xmlSchemaSAXHandleStartElementNs",
27356 "calling xmlSchemaValidateElem()");
27357 goto internal_error;
27359 goto exit;
27362 exit:
27363 return;
27364 internal_error:
27365 vctxt->err = -1;
27366 xmlStopParser(vctxt->parserCtxt);
27367 return;
27370 static void
27371 xmlSchemaSAXHandleEndElementNs(void *ctx,
27372 const xmlChar * localname ATTRIBUTE_UNUSED,
27373 const xmlChar * prefix ATTRIBUTE_UNUSED,
27374 const xmlChar * URI ATTRIBUTE_UNUSED)
27376 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27377 int res;
27380 * Skip elements if inside a "skip" wildcard or if invalid.
27382 if (vctxt->skipDepth != -1) {
27383 if (vctxt->depth > vctxt->skipDepth) {
27384 vctxt->depth--;
27385 return;
27386 } else
27387 vctxt->skipDepth = -1;
27390 * SAX VAL TODO: Just a temporary check.
27392 if ((!xmlStrEqual(vctxt->inode->localName, localname)) ||
27393 (!xmlStrEqual(vctxt->inode->nsName, URI))) {
27394 VERROR_INT("xmlSchemaSAXHandleEndElementNs",
27395 "elem pop mismatch");
27397 res = xmlSchemaValidatorPopElem(vctxt);
27398 if (res != 0) {
27399 if (res < 0) {
27400 VERROR_INT("xmlSchemaSAXHandleEndElementNs",
27401 "calling xmlSchemaValidatorPopElem()");
27402 goto internal_error;
27404 goto exit;
27406 exit:
27407 return;
27408 internal_error:
27409 vctxt->err = -1;
27410 xmlStopParser(vctxt->parserCtxt);
27411 return;
27414 /************************************************************************
27416 * Validation interfaces *
27418 ************************************************************************/
27421 * xmlSchemaNewValidCtxt:
27422 * @schema: a precompiled XML Schemas
27424 * Create an XML Schemas validation context based on the given schema.
27426 * Returns the validation context or NULL in case of error
27428 xmlSchemaValidCtxtPtr
27429 xmlSchemaNewValidCtxt(xmlSchemaPtr schema)
27431 xmlSchemaValidCtxtPtr ret;
27433 ret = (xmlSchemaValidCtxtPtr) xmlMalloc(sizeof(xmlSchemaValidCtxt));
27434 if (ret == NULL) {
27435 xmlSchemaVErrMemory(NULL, "allocating validation context", NULL);
27436 return (NULL);
27438 memset(ret, 0, sizeof(xmlSchemaValidCtxt));
27439 ret->type = XML_SCHEMA_CTXT_VALIDATOR;
27440 ret->dict = xmlDictCreate();
27441 ret->nodeQNames = xmlSchemaItemListCreate();
27442 ret->schema = schema;
27443 return (ret);
27447 * xmlSchemaClearValidCtxt:
27448 * @ctxt: the schema validation context
27450 * Free the resources associated to the schema validation context;
27451 * leaves some fields alive intended for reuse of the context.
27453 static void
27454 xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt)
27456 if (vctxt == NULL)
27457 return;
27460 * TODO: Should we clear the flags?
27461 * Might be problematic if one reuses the context
27462 * and assumes that the options remain the same.
27464 vctxt->flags = 0;
27465 vctxt->validationRoot = NULL;
27466 vctxt->doc = NULL;
27467 #ifdef LIBXML_READER_ENABLED
27468 vctxt->reader = NULL;
27469 #endif
27470 vctxt->hasKeyrefs = 0;
27472 if (vctxt->value != NULL) {
27473 xmlSchemaFreeValue(vctxt->value);
27474 vctxt->value = NULL;
27477 * Augmented IDC information.
27479 if (vctxt->aidcs != NULL) {
27480 xmlSchemaIDCAugPtr cur = vctxt->aidcs, next;
27481 do {
27482 next = cur->next;
27483 xmlFree(cur);
27484 cur = next;
27485 } while (cur != NULL);
27486 vctxt->aidcs = NULL;
27488 if (vctxt->idcMatcherCache != NULL) {
27489 xmlSchemaIDCMatcherPtr matcher = vctxt->idcMatcherCache, tmp;
27491 while (matcher) {
27492 tmp = matcher;
27493 matcher = matcher->nextCached;
27494 xmlSchemaIDCFreeMatcherList(tmp);
27496 vctxt->idcMatcherCache = NULL;
27500 if (vctxt->idcNodes != NULL) {
27501 int i;
27502 xmlSchemaPSVIIDCNodePtr item;
27504 for (i = 0; i < vctxt->nbIdcNodes; i++) {
27505 item = vctxt->idcNodes[i];
27506 xmlFree(item->keys);
27507 xmlFree(item);
27509 xmlFree(vctxt->idcNodes);
27510 vctxt->idcNodes = NULL;
27511 vctxt->nbIdcNodes = 0;
27512 vctxt->sizeIdcNodes = 0;
27515 * Note that we won't delete the XPath state pool here.
27517 if (vctxt->xpathStates != NULL) {
27518 xmlSchemaFreeIDCStateObjList(vctxt->xpathStates);
27519 vctxt->xpathStates = NULL;
27522 * Attribute info.
27524 if (vctxt->nbAttrInfos != 0) {
27525 xmlSchemaClearAttrInfos(vctxt);
27528 * Element info.
27530 if (vctxt->elemInfos != NULL) {
27531 int i;
27532 xmlSchemaNodeInfoPtr ei;
27534 for (i = 0; i < vctxt->sizeElemInfos; i++) {
27535 ei = vctxt->elemInfos[i];
27536 if (ei == NULL)
27537 break;
27538 xmlSchemaClearElemInfo(vctxt, ei);
27541 xmlSchemaItemListClear(vctxt->nodeQNames);
27542 /* Recreate the dict. */
27543 xmlDictFree(vctxt->dict);
27545 * TODO: Is is save to recreate it? Do we have a scenario
27546 * where the user provides the dict?
27548 vctxt->dict = xmlDictCreate();
27552 * xmlSchemaFreeValidCtxt:
27553 * @ctxt: the schema validation context
27555 * Free the resources associated to the schema validation context
27557 void
27558 xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt)
27560 if (ctxt == NULL)
27561 return;
27562 if (ctxt->value != NULL)
27563 xmlSchemaFreeValue(ctxt->value);
27564 if (ctxt->pctxt != NULL)
27565 xmlSchemaFreeParserCtxt(ctxt->pctxt);
27566 if (ctxt->idcNodes != NULL) {
27567 int i;
27568 xmlSchemaPSVIIDCNodePtr item;
27570 for (i = 0; i < ctxt->nbIdcNodes; i++) {
27571 item = ctxt->idcNodes[i];
27572 xmlFree(item->keys);
27573 xmlFree(item);
27575 xmlFree(ctxt->idcNodes);
27577 if (ctxt->idcKeys != NULL) {
27578 int i;
27579 for (i = 0; i < ctxt->nbIdcKeys; i++)
27580 xmlSchemaIDCFreeKey(ctxt->idcKeys[i]);
27581 xmlFree(ctxt->idcKeys);
27584 if (ctxt->xpathStates != NULL) {
27585 xmlSchemaFreeIDCStateObjList(ctxt->xpathStates);
27586 ctxt->xpathStates = NULL;
27588 if (ctxt->xpathStatePool != NULL) {
27589 xmlSchemaFreeIDCStateObjList(ctxt->xpathStatePool);
27590 ctxt->xpathStatePool = NULL;
27594 * Augmented IDC information.
27596 if (ctxt->aidcs != NULL) {
27597 xmlSchemaIDCAugPtr cur = ctxt->aidcs, next;
27598 do {
27599 next = cur->next;
27600 xmlFree(cur);
27601 cur = next;
27602 } while (cur != NULL);
27604 if (ctxt->attrInfos != NULL) {
27605 int i;
27606 xmlSchemaAttrInfoPtr attr;
27608 /* Just a paranoid call to the cleanup. */
27609 if (ctxt->nbAttrInfos != 0)
27610 xmlSchemaClearAttrInfos(ctxt);
27611 for (i = 0; i < ctxt->sizeAttrInfos; i++) {
27612 attr = ctxt->attrInfos[i];
27613 xmlFree(attr);
27615 xmlFree(ctxt->attrInfos);
27617 if (ctxt->elemInfos != NULL) {
27618 int i;
27619 xmlSchemaNodeInfoPtr ei;
27621 for (i = 0; i < ctxt->sizeElemInfos; i++) {
27622 ei = ctxt->elemInfos[i];
27623 if (ei == NULL)
27624 break;
27625 xmlSchemaClearElemInfo(ctxt, ei);
27626 xmlFree(ei);
27628 xmlFree(ctxt->elemInfos);
27630 if (ctxt->nodeQNames != NULL)
27631 xmlSchemaItemListFree(ctxt->nodeQNames);
27632 if (ctxt->dict != NULL)
27633 xmlDictFree(ctxt->dict);
27634 xmlFree(ctxt);
27638 * xmlSchemaIsValid:
27639 * @ctxt: the schema validation context
27641 * Check if any error was detected during validation.
27643 * Returns 1 if valid so far, 0 if errors were detected, and -1 in case
27644 * of internal error.
27647 xmlSchemaIsValid(xmlSchemaValidCtxtPtr ctxt)
27649 if (ctxt == NULL)
27650 return(-1);
27651 return(ctxt->err == 0);
27655 * xmlSchemaSetValidErrors:
27656 * @ctxt: a schema validation context
27657 * @err: the error function
27658 * @warn: the warning function
27659 * @ctx: the functions context
27661 * Set the error and warning callback informations
27663 void
27664 xmlSchemaSetValidErrors(xmlSchemaValidCtxtPtr ctxt,
27665 xmlSchemaValidityErrorFunc err,
27666 xmlSchemaValidityWarningFunc warn, void *ctx)
27668 if (ctxt == NULL)
27669 return;
27670 ctxt->error = err;
27671 ctxt->warning = warn;
27672 ctxt->errCtxt = ctx;
27673 if (ctxt->pctxt != NULL)
27674 xmlSchemaSetParserErrors(ctxt->pctxt, err, warn, ctx);
27678 * xmlSchemaSetValidStructuredErrors:
27679 * @ctxt: a schema validation context
27680 * @serror: the structured error function
27681 * @ctx: the functions context
27683 * Set the structured error callback
27685 void
27686 xmlSchemaSetValidStructuredErrors(xmlSchemaValidCtxtPtr ctxt,
27687 xmlStructuredErrorFunc serror, void *ctx)
27689 if (ctxt == NULL)
27690 return;
27691 ctxt->serror = serror;
27692 ctxt->error = NULL;
27693 ctxt->warning = NULL;
27694 ctxt->errCtxt = ctx;
27695 if (ctxt->pctxt != NULL)
27696 xmlSchemaSetParserStructuredErrors(ctxt->pctxt, serror, ctx);
27700 * xmlSchemaGetValidErrors:
27701 * @ctxt: a XML-Schema validation context
27702 * @err: the error function result
27703 * @warn: the warning function result
27704 * @ctx: the functions context result
27706 * Get the error and warning callback informations
27708 * Returns -1 in case of error and 0 otherwise
27711 xmlSchemaGetValidErrors(xmlSchemaValidCtxtPtr ctxt,
27712 xmlSchemaValidityErrorFunc * err,
27713 xmlSchemaValidityWarningFunc * warn, void **ctx)
27715 if (ctxt == NULL)
27716 return (-1);
27717 if (err != NULL)
27718 *err = ctxt->error;
27719 if (warn != NULL)
27720 *warn = ctxt->warning;
27721 if (ctx != NULL)
27722 *ctx = ctxt->errCtxt;
27723 return (0);
27728 * xmlSchemaSetValidOptions:
27729 * @ctxt: a schema validation context
27730 * @options: a combination of xmlSchemaValidOption
27732 * Sets the options to be used during the validation.
27734 * Returns 0 in case of success, -1 in case of an
27735 * API error.
27738 xmlSchemaSetValidOptions(xmlSchemaValidCtxtPtr ctxt,
27739 int options)
27742 int i;
27744 if (ctxt == NULL)
27745 return (-1);
27747 * WARNING: Change the start value if adding to the
27748 * xmlSchemaValidOption.
27749 * TODO: Is there an other, more easy to maintain,
27750 * way?
27752 for (i = 1; i < (int) sizeof(int) * 8; i++) {
27753 if (options & 1<<i)
27754 return (-1);
27756 ctxt->options = options;
27757 return (0);
27761 * xmlSchemaValidCtxtGetOptions:
27762 * @ctxt: a schema validation context
27764 * Get the validation context options.
27766 * Returns the option combination or -1 on error.
27769 xmlSchemaValidCtxtGetOptions(xmlSchemaValidCtxtPtr ctxt)
27772 if (ctxt == NULL)
27773 return (-1);
27774 else
27775 return (ctxt->options);
27778 static int
27779 xmlSchemaVDocWalk(xmlSchemaValidCtxtPtr vctxt)
27781 xmlAttrPtr attr;
27782 int ret = 0;
27783 xmlSchemaNodeInfoPtr ielem = NULL;
27784 xmlNodePtr node, valRoot;
27785 const xmlChar *nsName;
27787 /* DOC VAL TODO: Move this to the start function. */
27788 valRoot = xmlDocGetRootElement(vctxt->doc);
27789 if (valRoot == NULL) {
27790 /* VAL TODO: Error code? */
27791 VERROR(1, NULL, "The document has no document element");
27792 return (1);
27794 vctxt->depth = -1;
27795 vctxt->validationRoot = valRoot;
27796 node = valRoot;
27797 while (node != NULL) {
27798 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27799 goto next_sibling;
27800 if (node->type == XML_ELEMENT_NODE) {
27803 * Init the node-info.
27805 vctxt->depth++;
27806 if (xmlSchemaValidatorPushElem(vctxt) == -1)
27807 goto internal_error;
27808 ielem = vctxt->inode;
27809 ielem->node = node;
27810 ielem->nodeLine = node->line;
27811 ielem->localName = node->name;
27812 if (node->ns != NULL)
27813 ielem->nsName = node->ns->href;
27814 ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
27816 * Register attributes.
27817 * DOC VAL TODO: We do not register namespace declaration
27818 * attributes yet.
27820 vctxt->nbAttrInfos = 0;
27821 if (node->properties != NULL) {
27822 attr = node->properties;
27823 do {
27824 if (attr->ns != NULL)
27825 nsName = attr->ns->href;
27826 else
27827 nsName = NULL;
27828 ret = xmlSchemaValidatorPushAttribute(vctxt,
27829 (xmlNodePtr) attr,
27831 * Note that we give it the line number of the
27832 * parent element.
27834 ielem->nodeLine,
27835 attr->name, nsName, 0,
27836 xmlNodeListGetString(attr->doc, attr->children, 1), 1);
27837 if (ret == -1) {
27838 VERROR_INT("xmlSchemaDocWalk",
27839 "calling xmlSchemaValidatorPushAttribute()");
27840 goto internal_error;
27842 attr = attr->next;
27843 } while (attr);
27846 * Validate the element.
27848 ret = xmlSchemaValidateElem(vctxt);
27849 if (ret != 0) {
27850 if (ret == -1) {
27851 VERROR_INT("xmlSchemaDocWalk",
27852 "calling xmlSchemaValidateElem()");
27853 goto internal_error;
27856 * Don't stop validation; just skip the content
27857 * of this element.
27859 goto leave_node;
27861 if ((vctxt->skipDepth != -1) &&
27862 (vctxt->depth >= vctxt->skipDepth))
27863 goto leave_node;
27864 } else if ((node->type == XML_TEXT_NODE) ||
27865 (node->type == XML_CDATA_SECTION_NODE)) {
27867 * Process character content.
27869 if ((ielem != NULL) && (ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY))
27870 ielem->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
27871 ret = xmlSchemaVPushText(vctxt, node->type, node->content,
27872 -1, XML_SCHEMA_PUSH_TEXT_PERSIST, NULL);
27873 if (ret < 0) {
27874 VERROR_INT("xmlSchemaVDocWalk",
27875 "calling xmlSchemaVPushText()");
27876 goto internal_error;
27879 * DOC VAL TODO: Should we skip further validation of the
27880 * element content here?
27882 } else if ((node->type == XML_ENTITY_NODE) ||
27883 (node->type == XML_ENTITY_REF_NODE)) {
27885 * DOC VAL TODO: What to do with entities?
27887 VERROR_INT("xmlSchemaVDocWalk",
27888 "there is at least one entity reference in the node-tree "
27889 "currently being validated. Processing of entities with "
27890 "this XML Schema processor is not supported (yet). Please "
27891 "substitute entities before validation.");
27892 goto internal_error;
27893 } else {
27894 goto leave_node;
27896 * DOC VAL TODO: XInclude nodes, etc.
27900 * Walk the doc.
27902 if (node->children != NULL) {
27903 node = node->children;
27904 continue;
27906 leave_node:
27907 if (node->type == XML_ELEMENT_NODE) {
27909 * Leaving the scope of an element.
27911 if (node != vctxt->inode->node) {
27912 VERROR_INT("xmlSchemaVDocWalk",
27913 "element position mismatch");
27914 goto internal_error;
27916 ret = xmlSchemaValidatorPopElem(vctxt);
27917 if (ret != 0) {
27918 if (ret < 0) {
27919 VERROR_INT("xmlSchemaVDocWalk",
27920 "calling xmlSchemaValidatorPopElem()");
27921 goto internal_error;
27924 if (node == valRoot)
27925 goto exit;
27927 next_sibling:
27928 if (node->next != NULL)
27929 node = node->next;
27930 else {
27931 node = node->parent;
27932 goto leave_node;
27936 exit:
27937 return (ret);
27938 internal_error:
27939 return (-1);
27942 static int
27943 xmlSchemaPreRun(xmlSchemaValidCtxtPtr vctxt) {
27945 * Some initialization.
27947 vctxt->err = 0;
27948 vctxt->nberrors = 0;
27949 vctxt->depth = -1;
27950 vctxt->skipDepth = -1;
27951 vctxt->xsiAssemble = 0;
27952 vctxt->hasKeyrefs = 0;
27953 #ifdef ENABLE_IDC_NODE_TABLES_TEST
27954 vctxt->createIDCNodeTables = 1;
27955 #else
27956 vctxt->createIDCNodeTables = 0;
27957 #endif
27959 * Create a schema + parser if necessary.
27961 if (vctxt->schema == NULL) {
27962 xmlSchemaParserCtxtPtr pctxt;
27964 vctxt->xsiAssemble = 1;
27966 * If not schema was given then we will create a schema
27967 * dynamically using XSI schema locations.
27969 * Create the schema parser context.
27971 if ((vctxt->pctxt == NULL) &&
27972 (xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1))
27973 return (-1);
27974 pctxt = vctxt->pctxt;
27975 pctxt->xsiAssemble = 1;
27977 * Create the schema.
27979 vctxt->schema = xmlSchemaNewSchema(pctxt);
27980 if (vctxt->schema == NULL)
27981 return (-1);
27983 * Create the schema construction context.
27985 pctxt->constructor = xmlSchemaConstructionCtxtCreate(pctxt->dict);
27986 if (pctxt->constructor == NULL)
27987 return(-1);
27988 pctxt->constructor->mainSchema = vctxt->schema;
27990 * Take ownership of the constructor to be able to free it.
27992 pctxt->ownsConstructor = 1;
27995 * Augment the IDC definitions for the main schema and all imported ones
27996 * NOTE: main schema if the first in the imported list
27998 xmlHashScan(vctxt->schema->schemasImports,(xmlHashScanner)xmlSchemaAugmentImportedIDC, vctxt);
28000 return(0);
28003 static void
28004 xmlSchemaPostRun(xmlSchemaValidCtxtPtr vctxt) {
28005 if (vctxt->xsiAssemble) {
28006 if (vctxt->schema != NULL) {
28007 xmlSchemaFree(vctxt->schema);
28008 vctxt->schema = NULL;
28011 xmlSchemaClearValidCtxt(vctxt);
28014 static int
28015 xmlSchemaVStart(xmlSchemaValidCtxtPtr vctxt)
28017 int ret = 0;
28019 if (xmlSchemaPreRun(vctxt) < 0)
28020 return(-1);
28022 if (vctxt->doc != NULL) {
28024 * Tree validation.
28026 ret = xmlSchemaVDocWalk(vctxt);
28027 #ifdef LIBXML_READER_ENABLED
28028 } else if (vctxt->reader != NULL) {
28030 * XML Reader validation.
28032 #ifdef XML_SCHEMA_READER_ENABLED
28033 ret = xmlSchemaVReaderWalk(vctxt);
28034 #endif
28035 #endif
28036 } else if ((vctxt->sax != NULL) && (vctxt->parserCtxt != NULL)) {
28038 * SAX validation.
28040 ret = xmlParseDocument(vctxt->parserCtxt);
28041 } else {
28042 VERROR_INT("xmlSchemaVStart",
28043 "no instance to validate");
28044 ret = -1;
28047 xmlSchemaPostRun(vctxt);
28048 if (ret == 0)
28049 ret = vctxt->err;
28050 return (ret);
28054 * xmlSchemaValidateOneElement:
28055 * @ctxt: a schema validation context
28056 * @elem: an element node
28058 * Validate a branch of a tree, starting with the given @elem.
28060 * Returns 0 if the element and its subtree is valid, a positive error
28061 * code number otherwise and -1 in case of an internal or API error.
28064 xmlSchemaValidateOneElement(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem)
28066 if ((ctxt == NULL) || (elem == NULL) || (elem->type != XML_ELEMENT_NODE))
28067 return (-1);
28069 if (ctxt->schema == NULL)
28070 return (-1);
28072 ctxt->doc = elem->doc;
28073 ctxt->node = elem;
28074 ctxt->validationRoot = elem;
28075 return(xmlSchemaVStart(ctxt));
28079 * xmlSchemaValidateDoc:
28080 * @ctxt: a schema validation context
28081 * @doc: a parsed document tree
28083 * Validate a document tree in memory.
28085 * Returns 0 if the document is schemas valid, a positive error code
28086 * number otherwise and -1 in case of internal or API error.
28089 xmlSchemaValidateDoc(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
28091 if ((ctxt == NULL) || (doc == NULL))
28092 return (-1);
28094 ctxt->doc = doc;
28095 ctxt->node = xmlDocGetRootElement(doc);
28096 if (ctxt->node == NULL) {
28097 xmlSchemaCustomErr(ACTXT_CAST ctxt,
28098 XML_SCHEMAV_DOCUMENT_ELEMENT_MISSING,
28099 (xmlNodePtr) doc, NULL,
28100 "The document has no document element", NULL, NULL);
28101 return (ctxt->err);
28103 ctxt->validationRoot = ctxt->node;
28104 return (xmlSchemaVStart(ctxt));
28108 /************************************************************************
28110 * Function and data for SAX streaming API *
28112 ************************************************************************/
28113 typedef struct _xmlSchemaSplitSAXData xmlSchemaSplitSAXData;
28114 typedef xmlSchemaSplitSAXData *xmlSchemaSplitSAXDataPtr;
28116 struct _xmlSchemaSplitSAXData {
28117 xmlSAXHandlerPtr user_sax;
28118 void *user_data;
28119 xmlSchemaValidCtxtPtr ctxt;
28120 xmlSAXHandlerPtr schemas_sax;
28123 #define XML_SAX_PLUG_MAGIC 0xdc43ba21
28125 struct _xmlSchemaSAXPlug {
28126 unsigned int magic;
28128 /* the original callbacks informations */
28129 xmlSAXHandlerPtr *user_sax_ptr;
28130 xmlSAXHandlerPtr user_sax;
28131 void **user_data_ptr;
28132 void *user_data;
28134 /* the block plugged back and validation informations */
28135 xmlSAXHandler schemas_sax;
28136 xmlSchemaValidCtxtPtr ctxt;
28139 /* All those functions just bounces to the user provided SAX handlers */
28140 static void
28141 internalSubsetSplit(void *ctx, const xmlChar *name,
28142 const xmlChar *ExternalID, const xmlChar *SystemID)
28144 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28145 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28146 (ctxt->user_sax->internalSubset != NULL))
28147 ctxt->user_sax->internalSubset(ctxt->user_data, name, ExternalID,
28148 SystemID);
28151 static int
28152 isStandaloneSplit(void *ctx)
28154 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28155 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28156 (ctxt->user_sax->isStandalone != NULL))
28157 return(ctxt->user_sax->isStandalone(ctxt->user_data));
28158 return(0);
28161 static int
28162 hasInternalSubsetSplit(void *ctx)
28164 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28165 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28166 (ctxt->user_sax->hasInternalSubset != NULL))
28167 return(ctxt->user_sax->hasInternalSubset(ctxt->user_data));
28168 return(0);
28171 static int
28172 hasExternalSubsetSplit(void *ctx)
28174 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28175 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28176 (ctxt->user_sax->hasExternalSubset != NULL))
28177 return(ctxt->user_sax->hasExternalSubset(ctxt->user_data));
28178 return(0);
28181 static void
28182 externalSubsetSplit(void *ctx, const xmlChar *name,
28183 const xmlChar *ExternalID, const xmlChar *SystemID)
28185 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28186 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28187 (ctxt->user_sax->externalSubset != NULL))
28188 ctxt->user_sax->externalSubset(ctxt->user_data, name, ExternalID,
28189 SystemID);
28192 static xmlParserInputPtr
28193 resolveEntitySplit(void *ctx, const xmlChar *publicId, const xmlChar *systemId)
28195 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28196 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28197 (ctxt->user_sax->resolveEntity != NULL))
28198 return(ctxt->user_sax->resolveEntity(ctxt->user_data, publicId,
28199 systemId));
28200 return(NULL);
28203 static xmlEntityPtr
28204 getEntitySplit(void *ctx, const xmlChar *name)
28206 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28207 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28208 (ctxt->user_sax->getEntity != NULL))
28209 return(ctxt->user_sax->getEntity(ctxt->user_data, name));
28210 return(NULL);
28213 static xmlEntityPtr
28214 getParameterEntitySplit(void *ctx, const xmlChar *name)
28216 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28217 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28218 (ctxt->user_sax->getParameterEntity != NULL))
28219 return(ctxt->user_sax->getParameterEntity(ctxt->user_data, name));
28220 return(NULL);
28224 static void
28225 entityDeclSplit(void *ctx, const xmlChar *name, int type,
28226 const xmlChar *publicId, const xmlChar *systemId, xmlChar *content)
28228 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28229 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28230 (ctxt->user_sax->entityDecl != NULL))
28231 ctxt->user_sax->entityDecl(ctxt->user_data, name, type, publicId,
28232 systemId, content);
28235 static void
28236 attributeDeclSplit(void *ctx, const xmlChar * elem,
28237 const xmlChar * name, int type, int def,
28238 const xmlChar * defaultValue, xmlEnumerationPtr tree)
28240 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28241 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28242 (ctxt->user_sax->attributeDecl != NULL)) {
28243 ctxt->user_sax->attributeDecl(ctxt->user_data, elem, name, type,
28244 def, defaultValue, tree);
28245 } else {
28246 xmlFreeEnumeration(tree);
28250 static void
28251 elementDeclSplit(void *ctx, const xmlChar *name, int type,
28252 xmlElementContentPtr content)
28254 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28255 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28256 (ctxt->user_sax->elementDecl != NULL))
28257 ctxt->user_sax->elementDecl(ctxt->user_data, name, type, content);
28260 static void
28261 notationDeclSplit(void *ctx, const xmlChar *name,
28262 const xmlChar *publicId, const xmlChar *systemId)
28264 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28265 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28266 (ctxt->user_sax->notationDecl != NULL))
28267 ctxt->user_sax->notationDecl(ctxt->user_data, name, publicId,
28268 systemId);
28271 static void
28272 unparsedEntityDeclSplit(void *ctx, const xmlChar *name,
28273 const xmlChar *publicId, const xmlChar *systemId,
28274 const xmlChar *notationName)
28276 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28277 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28278 (ctxt->user_sax->unparsedEntityDecl != NULL))
28279 ctxt->user_sax->unparsedEntityDecl(ctxt->user_data, name, publicId,
28280 systemId, notationName);
28283 static void
28284 setDocumentLocatorSplit(void *ctx, xmlSAXLocatorPtr loc)
28286 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28287 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28288 (ctxt->user_sax->setDocumentLocator != NULL))
28289 ctxt->user_sax->setDocumentLocator(ctxt->user_data, loc);
28292 static void
28293 startDocumentSplit(void *ctx)
28295 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28296 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28297 (ctxt->user_sax->startDocument != NULL))
28298 ctxt->user_sax->startDocument(ctxt->user_data);
28301 static void
28302 endDocumentSplit(void *ctx)
28304 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28305 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28306 (ctxt->user_sax->endDocument != NULL))
28307 ctxt->user_sax->endDocument(ctxt->user_data);
28310 static void
28311 processingInstructionSplit(void *ctx, const xmlChar *target,
28312 const xmlChar *data)
28314 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28315 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28316 (ctxt->user_sax->processingInstruction != NULL))
28317 ctxt->user_sax->processingInstruction(ctxt->user_data, target, data);
28320 static void
28321 commentSplit(void *ctx, const xmlChar *value)
28323 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28324 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28325 (ctxt->user_sax->comment != NULL))
28326 ctxt->user_sax->comment(ctxt->user_data, value);
28330 * Varargs error callbacks to the user application, harder ...
28333 static void XMLCDECL
28334 warningSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
28335 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28336 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28337 (ctxt->user_sax->warning != NULL)) {
28338 TODO
28341 static void XMLCDECL
28342 errorSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
28343 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28344 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28345 (ctxt->user_sax->error != NULL)) {
28346 TODO
28349 static void XMLCDECL
28350 fatalErrorSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
28351 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28352 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28353 (ctxt->user_sax->fatalError != NULL)) {
28354 TODO
28359 * Those are function where both the user handler and the schemas handler
28360 * need to be called.
28362 static void
28363 charactersSplit(void *ctx, const xmlChar *ch, int len)
28365 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28366 if (ctxt == NULL)
28367 return;
28368 if ((ctxt->user_sax != NULL) && (ctxt->user_sax->characters != NULL))
28369 ctxt->user_sax->characters(ctxt->user_data, ch, len);
28370 if (ctxt->ctxt != NULL)
28371 xmlSchemaSAXHandleText(ctxt->ctxt, ch, len);
28374 static void
28375 ignorableWhitespaceSplit(void *ctx, const xmlChar *ch, int len)
28377 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28378 if (ctxt == NULL)
28379 return;
28380 if ((ctxt->user_sax != NULL) &&
28381 (ctxt->user_sax->ignorableWhitespace != NULL))
28382 ctxt->user_sax->ignorableWhitespace(ctxt->user_data, ch, len);
28383 if (ctxt->ctxt != NULL)
28384 xmlSchemaSAXHandleText(ctxt->ctxt, ch, len);
28387 static void
28388 cdataBlockSplit(void *ctx, const xmlChar *value, int len)
28390 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28391 if (ctxt == NULL)
28392 return;
28393 if ((ctxt->user_sax != NULL) &&
28394 (ctxt->user_sax->cdataBlock != NULL))
28395 ctxt->user_sax->cdataBlock(ctxt->user_data, value, len);
28396 if (ctxt->ctxt != NULL)
28397 xmlSchemaSAXHandleCDataSection(ctxt->ctxt, value, len);
28400 static void
28401 referenceSplit(void *ctx, const xmlChar *name)
28403 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28404 if (ctxt == NULL)
28405 return;
28406 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28407 (ctxt->user_sax->reference != NULL))
28408 ctxt->user_sax->reference(ctxt->user_data, name);
28409 if (ctxt->ctxt != NULL)
28410 xmlSchemaSAXHandleReference(ctxt->user_data, name);
28413 static void
28414 startElementNsSplit(void *ctx, const xmlChar * localname,
28415 const xmlChar * prefix, const xmlChar * URI,
28416 int nb_namespaces, const xmlChar ** namespaces,
28417 int nb_attributes, int nb_defaulted,
28418 const xmlChar ** attributes) {
28419 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28420 if (ctxt == NULL)
28421 return;
28422 if ((ctxt->user_sax != NULL) &&
28423 (ctxt->user_sax->startElementNs != NULL))
28424 ctxt->user_sax->startElementNs(ctxt->user_data, localname, prefix,
28425 URI, nb_namespaces, namespaces,
28426 nb_attributes, nb_defaulted,
28427 attributes);
28428 if (ctxt->ctxt != NULL)
28429 xmlSchemaSAXHandleStartElementNs(ctxt->ctxt, localname, prefix,
28430 URI, nb_namespaces, namespaces,
28431 nb_attributes, nb_defaulted,
28432 attributes);
28435 static void
28436 endElementNsSplit(void *ctx, const xmlChar * localname,
28437 const xmlChar * prefix, const xmlChar * URI) {
28438 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28439 if (ctxt == NULL)
28440 return;
28441 if ((ctxt->user_sax != NULL) &&
28442 (ctxt->user_sax->endElementNs != NULL))
28443 ctxt->user_sax->endElementNs(ctxt->user_data, localname, prefix, URI);
28444 if (ctxt->ctxt != NULL)
28445 xmlSchemaSAXHandleEndElementNs(ctxt->ctxt, localname, prefix, URI);
28449 * xmlSchemaSAXPlug:
28450 * @ctxt: a schema validation context
28451 * @sax: a pointer to the original xmlSAXHandlerPtr
28452 * @user_data: a pointer to the original SAX user data pointer
28454 * Plug a SAX based validation layer in a SAX parsing event flow.
28455 * The original @saxptr and @dataptr data are replaced by new pointers
28456 * but the calls to the original will be maintained.
28458 * Returns a pointer to a data structure needed to unplug the validation layer
28459 * or NULL in case of errors.
28461 xmlSchemaSAXPlugPtr
28462 xmlSchemaSAXPlug(xmlSchemaValidCtxtPtr ctxt,
28463 xmlSAXHandlerPtr *sax, void **user_data)
28465 xmlSchemaSAXPlugPtr ret;
28466 xmlSAXHandlerPtr old_sax;
28468 if ((ctxt == NULL) || (sax == NULL) || (user_data == NULL))
28469 return(NULL);
28472 * We only allow to plug into SAX2 event streams
28474 old_sax = *sax;
28475 if ((old_sax != NULL) && (old_sax->initialized != XML_SAX2_MAGIC))
28476 return(NULL);
28477 if ((old_sax != NULL) &&
28478 (old_sax->startElementNs == NULL) && (old_sax->endElementNs == NULL) &&
28479 ((old_sax->startElement != NULL) || (old_sax->endElement != NULL)))
28480 return(NULL);
28483 * everything seems right allocate the local data needed for that layer
28485 ret = (xmlSchemaSAXPlugPtr) xmlMalloc(sizeof(xmlSchemaSAXPlugStruct));
28486 if (ret == NULL) {
28487 return(NULL);
28489 memset(ret, 0, sizeof(xmlSchemaSAXPlugStruct));
28490 ret->magic = XML_SAX_PLUG_MAGIC;
28491 ret->schemas_sax.initialized = XML_SAX2_MAGIC;
28492 ret->ctxt = ctxt;
28493 ret->user_sax_ptr = sax;
28494 ret->user_sax = old_sax;
28495 if (old_sax == NULL) {
28497 * go direct, no need for the split block and functions.
28499 ret->schemas_sax.startElementNs = xmlSchemaSAXHandleStartElementNs;
28500 ret->schemas_sax.endElementNs = xmlSchemaSAXHandleEndElementNs;
28502 * Note that we use the same text-function for both, to prevent
28503 * the parser from testing for ignorable whitespace.
28505 ret->schemas_sax.ignorableWhitespace = xmlSchemaSAXHandleText;
28506 ret->schemas_sax.characters = xmlSchemaSAXHandleText;
28508 ret->schemas_sax.cdataBlock = xmlSchemaSAXHandleCDataSection;
28509 ret->schemas_sax.reference = xmlSchemaSAXHandleReference;
28511 ret->user_data = ctxt;
28512 *user_data = ctxt;
28513 } else {
28515 * for each callback unused by Schemas initialize it to the Split
28516 * routine only if non NULL in the user block, this can speed up
28517 * things at the SAX level.
28519 if (old_sax->internalSubset != NULL)
28520 ret->schemas_sax.internalSubset = internalSubsetSplit;
28521 if (old_sax->isStandalone != NULL)
28522 ret->schemas_sax.isStandalone = isStandaloneSplit;
28523 if (old_sax->hasInternalSubset != NULL)
28524 ret->schemas_sax.hasInternalSubset = hasInternalSubsetSplit;
28525 if (old_sax->hasExternalSubset != NULL)
28526 ret->schemas_sax.hasExternalSubset = hasExternalSubsetSplit;
28527 if (old_sax->resolveEntity != NULL)
28528 ret->schemas_sax.resolveEntity = resolveEntitySplit;
28529 if (old_sax->getEntity != NULL)
28530 ret->schemas_sax.getEntity = getEntitySplit;
28531 if (old_sax->entityDecl != NULL)
28532 ret->schemas_sax.entityDecl = entityDeclSplit;
28533 if (old_sax->notationDecl != NULL)
28534 ret->schemas_sax.notationDecl = notationDeclSplit;
28535 if (old_sax->attributeDecl != NULL)
28536 ret->schemas_sax.attributeDecl = attributeDeclSplit;
28537 if (old_sax->elementDecl != NULL)
28538 ret->schemas_sax.elementDecl = elementDeclSplit;
28539 if (old_sax->unparsedEntityDecl != NULL)
28540 ret->schemas_sax.unparsedEntityDecl = unparsedEntityDeclSplit;
28541 if (old_sax->setDocumentLocator != NULL)
28542 ret->schemas_sax.setDocumentLocator = setDocumentLocatorSplit;
28543 if (old_sax->startDocument != NULL)
28544 ret->schemas_sax.startDocument = startDocumentSplit;
28545 if (old_sax->endDocument != NULL)
28546 ret->schemas_sax.endDocument = endDocumentSplit;
28547 if (old_sax->processingInstruction != NULL)
28548 ret->schemas_sax.processingInstruction = processingInstructionSplit;
28549 if (old_sax->comment != NULL)
28550 ret->schemas_sax.comment = commentSplit;
28551 if (old_sax->warning != NULL)
28552 ret->schemas_sax.warning = warningSplit;
28553 if (old_sax->error != NULL)
28554 ret->schemas_sax.error = errorSplit;
28555 if (old_sax->fatalError != NULL)
28556 ret->schemas_sax.fatalError = fatalErrorSplit;
28557 if (old_sax->getParameterEntity != NULL)
28558 ret->schemas_sax.getParameterEntity = getParameterEntitySplit;
28559 if (old_sax->externalSubset != NULL)
28560 ret->schemas_sax.externalSubset = externalSubsetSplit;
28563 * the 6 schemas callback have to go to the splitter functions
28564 * Note that we use the same text-function for ignorableWhitespace
28565 * if possible, to prevent the parser from testing for ignorable
28566 * whitespace.
28568 ret->schemas_sax.characters = charactersSplit;
28569 if ((old_sax->ignorableWhitespace != NULL) &&
28570 (old_sax->ignorableWhitespace != old_sax->characters))
28571 ret->schemas_sax.ignorableWhitespace = ignorableWhitespaceSplit;
28572 else
28573 ret->schemas_sax.ignorableWhitespace = charactersSplit;
28574 ret->schemas_sax.cdataBlock = cdataBlockSplit;
28575 ret->schemas_sax.reference = referenceSplit;
28576 ret->schemas_sax.startElementNs = startElementNsSplit;
28577 ret->schemas_sax.endElementNs = endElementNsSplit;
28579 ret->user_data_ptr = user_data;
28580 ret->user_data = *user_data;
28581 *user_data = ret;
28585 * plug the pointers back.
28587 *sax = &(ret->schemas_sax);
28588 ctxt->sax = *sax;
28589 ctxt->flags |= XML_SCHEMA_VALID_CTXT_FLAG_STREAM;
28590 xmlSchemaPreRun(ctxt);
28591 return(ret);
28595 * xmlSchemaSAXUnplug:
28596 * @plug: a data structure returned by xmlSchemaSAXPlug
28598 * Unplug a SAX based validation layer in a SAX parsing event flow.
28599 * The original pointers used in the call are restored.
28601 * Returns 0 in case of success and -1 in case of failure.
28604 xmlSchemaSAXUnplug(xmlSchemaSAXPlugPtr plug)
28606 xmlSAXHandlerPtr *sax;
28607 void **user_data;
28609 if ((plug == NULL) || (plug->magic != XML_SAX_PLUG_MAGIC))
28610 return(-1);
28611 plug->magic = 0;
28613 xmlSchemaPostRun(plug->ctxt);
28614 /* restore the data */
28615 sax = plug->user_sax_ptr;
28616 *sax = plug->user_sax;
28617 if (plug->user_sax != NULL) {
28618 user_data = plug->user_data_ptr;
28619 *user_data = plug->user_data;
28622 /* free and return */
28623 xmlFree(plug);
28624 return(0);
28628 * xmlSchemaValidateStream:
28629 * @ctxt: a schema validation context
28630 * @input: the input to use for reading the data
28631 * @enc: an optional encoding information
28632 * @sax: a SAX handler for the resulting events
28633 * @user_data: the context to provide to the SAX handler.
28635 * Validate an input based on a flow of SAX event from the parser
28636 * and forward the events to the @sax handler with the provided @user_data
28637 * the user provided @sax handler must be a SAX2 one.
28639 * Returns 0 if the document is schemas valid, a positive error code
28640 * number otherwise and -1 in case of internal or API error.
28643 xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt,
28644 xmlParserInputBufferPtr input, xmlCharEncoding enc,
28645 xmlSAXHandlerPtr sax, void *user_data)
28647 xmlSchemaSAXPlugPtr plug = NULL;
28648 xmlSAXHandlerPtr old_sax = NULL;
28649 xmlParserCtxtPtr pctxt = NULL;
28650 xmlParserInputPtr inputStream = NULL;
28651 int ret;
28653 if ((ctxt == NULL) || (input == NULL))
28654 return (-1);
28657 * prepare the parser
28659 pctxt = xmlNewParserCtxt();
28660 if (pctxt == NULL)
28661 return (-1);
28662 old_sax = pctxt->sax;
28663 pctxt->sax = sax;
28664 pctxt->userData = user_data;
28665 #if 0
28666 if (options)
28667 xmlCtxtUseOptions(pctxt, options);
28668 #endif
28669 pctxt->linenumbers = 1;
28671 inputStream = xmlNewIOInputStream(pctxt, input, enc);;
28672 if (inputStream == NULL) {
28673 ret = -1;
28674 goto done;
28676 inputPush(pctxt, inputStream);
28677 ctxt->parserCtxt = pctxt;
28678 ctxt->input = input;
28681 * Plug the validation and launch the parsing
28683 plug = xmlSchemaSAXPlug(ctxt, &(pctxt->sax), &(pctxt->userData));
28684 if (plug == NULL) {
28685 ret = -1;
28686 goto done;
28688 ctxt->input = input;
28689 ctxt->enc = enc;
28690 ctxt->sax = pctxt->sax;
28691 ctxt->flags |= XML_SCHEMA_VALID_CTXT_FLAG_STREAM;
28692 ret = xmlSchemaVStart(ctxt);
28694 if ((ret == 0) && (! ctxt->parserCtxt->wellFormed)) {
28695 ret = ctxt->parserCtxt->errNo;
28696 if (ret == 0)
28697 ret = 1;
28700 done:
28701 ctxt->parserCtxt = NULL;
28702 ctxt->sax = NULL;
28703 ctxt->input = NULL;
28704 if (plug != NULL) {
28705 xmlSchemaSAXUnplug(plug);
28707 /* cleanup */
28708 if (pctxt != NULL) {
28709 pctxt->sax = old_sax;
28710 xmlFreeParserCtxt(pctxt);
28712 return (ret);
28716 * xmlSchemaValidateFile:
28717 * @ctxt: a schema validation context
28718 * @filename: the URI of the instance
28719 * @options: a future set of options, currently unused
28721 * Do a schemas validation of the given resource, it will use the
28722 * SAX streamable validation internally.
28724 * Returns 0 if the document is valid, a positive error code
28725 * number otherwise and -1 in case of an internal or API error.
28728 xmlSchemaValidateFile(xmlSchemaValidCtxtPtr ctxt,
28729 const char * filename,
28730 int options ATTRIBUTE_UNUSED)
28732 int ret;
28733 xmlParserInputBufferPtr input;
28735 if ((ctxt == NULL) || (filename == NULL))
28736 return (-1);
28738 input = xmlParserInputBufferCreateFilename(filename,
28739 XML_CHAR_ENCODING_NONE);
28740 if (input == NULL)
28741 return (-1);
28742 ret = xmlSchemaValidateStream(ctxt, input, XML_CHAR_ENCODING_NONE,
28743 NULL, NULL);
28744 return (ret);
28748 * xmlSchemaValidCtxtGetParserCtxt:
28749 * @ctxt: a schema validation context
28751 * allow access to the parser context of the schema validation context
28753 * Returns the parser context of the schema validation context or NULL
28754 * in case of error.
28756 xmlParserCtxtPtr
28757 xmlSchemaValidCtxtGetParserCtxt(xmlSchemaValidCtxtPtr ctxt)
28759 if (ctxt == NULL)
28760 return(NULL);
28761 return (ctxt->parserCtxt);
28764 #define bottom_xmlschemas
28765 #include "elfgcchack.h"
28766 #endif /* LIBXML_SCHEMAS_ENABLED */