ws2_32/tests: Execute test_iocp() near the end.
[wine.git] / libs / xml2 / xmlschemas.c
blob53239110985babc6a3c1be613f32ba7a319d7b55
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 * - Eliminated 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.
48 /* To avoid EBCDIC trouble when parsing on zOS */
49 #if defined(__MVS__)
50 #pragma convert("ISO8859-1")
51 #endif
53 #define IN_LIBXML
54 #include "libxml.h"
56 #ifdef LIBXML_SCHEMAS_ENABLED
58 #include <string.h>
59 #include <libxml/xmlmemory.h>
60 #include <libxml/parser.h>
61 #include <libxml/parserInternals.h>
62 #include <libxml/hash.h>
63 #include <libxml/uri.h>
64 #include <libxml/xmlschemas.h>
65 #include <libxml/schemasInternals.h>
66 #include <libxml/xmlschemastypes.h>
67 #include <libxml/xmlautomata.h>
68 #include <libxml/xmlregexp.h>
69 #include <libxml/dict.h>
70 #include <libxml/encoding.h>
71 #include <libxml/xmlIO.h>
72 #ifdef LIBXML_PATTERN_ENABLED
73 #include <libxml/pattern.h>
74 #endif
75 #ifdef LIBXML_READER_ENABLED
76 #include <libxml/xmlreader.h>
77 #endif
79 #include "private/error.h"
80 #include "private/string.h"
82 /* #define DEBUG 1 */
84 /* #define DEBUG_CONTENT 1 */
86 /* #define DEBUG_TYPE 1 */
88 /* #define DEBUG_CONTENT_REGEXP 1 */
90 /* #define DEBUG_AUTOMATA 1 */
92 /* #define DEBUG_IDC */
94 /* #define DEBUG_IDC_NODE_TABLE */
96 /* #define WXS_ELEM_DECL_CONS_ENABLED */
98 #ifdef DEBUG_IDC
99 #ifndef DEBUG_IDC_NODE_TABLE
100 #define DEBUG_IDC_NODE_TABLE
101 #endif
102 #endif
104 /* #define ENABLE_PARTICLE_RESTRICTION 1 */
106 #define ENABLE_REDEFINE
108 /* #define ENABLE_NAMED_LOCALS */
110 /* #define ENABLE_IDC_NODE_TABLES_TEST */
112 #define DUMP_CONTENT_MODEL
114 #ifdef LIBXML_READER_ENABLED
115 /* #define XML_SCHEMA_READER_ENABLED */
116 #endif
118 #define UNBOUNDED (1 << 30)
119 #define TODO \
120 xmlGenericError(xmlGenericErrorContext, \
121 "Unimplemented block at %s:%d\n", \
122 __FILE__, __LINE__);
124 #define XML_SCHEMAS_NO_NAMESPACE (const xmlChar *) "##"
127 * The XML Schemas namespaces
129 static const xmlChar *xmlSchemaNs = (const xmlChar *)
130 "http://www.w3.org/2001/XMLSchema";
132 static const xmlChar *xmlSchemaInstanceNs = (const xmlChar *)
133 "http://www.w3.org/2001/XMLSchema-instance";
135 static const xmlChar *xmlNamespaceNs = (const xmlChar *)
136 "http://www.w3.org/2000/xmlns/";
139 * Come casting macros.
141 #define ACTXT_CAST (xmlSchemaAbstractCtxtPtr)
142 #define PCTXT_CAST (xmlSchemaParserCtxtPtr)
143 #define VCTXT_CAST (xmlSchemaValidCtxtPtr)
144 #define WXS_BASIC_CAST (xmlSchemaBasicItemPtr)
145 #define WXS_TREE_CAST (xmlSchemaTreeItemPtr)
146 #define WXS_PTC_CAST (xmlSchemaParticlePtr)
147 #define WXS_TYPE_CAST (xmlSchemaTypePtr)
148 #define WXS_ELEM_CAST (xmlSchemaElementPtr)
149 #define WXS_ATTR_GROUP_CAST (xmlSchemaAttributeGroupPtr)
150 #define WXS_ATTR_CAST (xmlSchemaAttributePtr)
151 #define WXS_ATTR_USE_CAST (xmlSchemaAttributeUsePtr)
152 #define WXS_ATTR_PROHIB_CAST (xmlSchemaAttributeUseProhibPtr)
153 #define WXS_MODEL_GROUPDEF_CAST (xmlSchemaModelGroupDefPtr)
154 #define WXS_MODEL_GROUP_CAST (xmlSchemaModelGroupPtr)
155 #define WXS_IDC_CAST (xmlSchemaIDCPtr)
156 #define WXS_QNAME_CAST (xmlSchemaQNameRefPtr)
157 #define WXS_LIST_CAST (xmlSchemaItemListPtr)
160 * Macros to query common properties of components.
162 #define WXS_ITEM_NODE(i) xmlSchemaGetComponentNode(WXS_BASIC_CAST (i))
164 #define WXS_ITEM_TYPE_NAME(i) xmlSchemaGetComponentTypeStr(WXS_BASIC_CAST (i))
166 * Macros for element declarations.
168 #define WXS_ELEM_TYPEDEF(e) (e)->subtypes
170 #define WXS_SUBST_HEAD(item) (item)->refDecl
172 * Macros for attribute declarations.
174 #define WXS_ATTR_TYPEDEF(a) (a)->subtypes
176 * Macros for attribute uses.
178 #define WXS_ATTRUSE_DECL(au) (WXS_ATTR_USE_CAST (au))->attrDecl
180 #define WXS_ATTRUSE_TYPEDEF(au) WXS_ATTR_TYPEDEF(WXS_ATTRUSE_DECL( WXS_ATTR_USE_CAST au))
182 #define WXS_ATTRUSE_DECL_NAME(au) (WXS_ATTRUSE_DECL(au))->name
184 #define WXS_ATTRUSE_DECL_TNS(au) (WXS_ATTRUSE_DECL(au))->targetNamespace
186 * Macros for attribute groups.
188 #define WXS_ATTR_GROUP_HAS_REFS(ag) ((WXS_ATTR_GROUP_CAST (ag))->flags & XML_SCHEMAS_ATTRGROUP_HAS_REFS)
189 #define WXS_ATTR_GROUP_EXPANDED(ag) ((WXS_ATTR_GROUP_CAST (ag))->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED)
191 * Macros for particles.
193 #define WXS_PARTICLE(p) WXS_PTC_CAST (p)
195 #define WXS_PARTICLE_TERM(p) (WXS_PARTICLE(p))->children
197 #define WXS_PARTICLE_TERM_AS_ELEM(p) (WXS_ELEM_CAST WXS_PARTICLE_TERM(p))
199 #define WXS_PARTICLE_MODEL(p) WXS_MODEL_GROUP_CAST WXS_PARTICLE(p)->children
201 * Macros for model groups definitions.
203 #define WXS_MODELGROUPDEF_MODEL(mgd) (WXS_MODEL_GROUP_CAST (mgd))->children
205 * Macros for model groups.
207 #define WXS_IS_MODEL_GROUP(i) \
208 (((i)->type == XML_SCHEMA_TYPE_SEQUENCE) || \
209 ((i)->type == XML_SCHEMA_TYPE_CHOICE) || \
210 ((i)->type == XML_SCHEMA_TYPE_ALL))
212 #define WXS_MODELGROUP_PARTICLE(mg) WXS_PTC_CAST (mg)->children
214 * Macros for schema buckets.
216 #define WXS_IS_BUCKET_INCREDEF(t) (((t) == XML_SCHEMA_SCHEMA_INCLUDE) || \
217 ((t) == XML_SCHEMA_SCHEMA_REDEFINE))
219 #define WXS_IS_BUCKET_IMPMAIN(t) (((t) == XML_SCHEMA_SCHEMA_MAIN) || \
220 ((t) == XML_SCHEMA_SCHEMA_IMPORT))
222 #define WXS_IMPBUCKET(b) ((xmlSchemaImportPtr) (b))
224 #define WXS_INCBUCKET(b) ((xmlSchemaIncludePtr) (b))
226 * Macros for complex/simple types.
228 #define WXS_IS_ANYTYPE(i) \
229 (( (i)->type == XML_SCHEMA_TYPE_BASIC) && \
230 ( (WXS_TYPE_CAST (i))->builtInType == XML_SCHEMAS_ANYTYPE))
232 #define WXS_IS_COMPLEX(i) \
233 (((i)->type == XML_SCHEMA_TYPE_COMPLEX) || \
234 ((i)->builtInType == XML_SCHEMAS_ANYTYPE))
236 #define WXS_IS_SIMPLE(item) \
237 ((item->type == XML_SCHEMA_TYPE_SIMPLE) || \
238 ((item->type == XML_SCHEMA_TYPE_BASIC) && \
239 (item->builtInType != XML_SCHEMAS_ANYTYPE)))
241 #define WXS_IS_ANY_SIMPLE_TYPE(i) \
242 (((i)->type == XML_SCHEMA_TYPE_BASIC) && \
243 ((i)->builtInType == XML_SCHEMAS_ANYSIMPLETYPE))
245 #define WXS_IS_RESTRICTION(t) \
246 ((t)->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION)
248 #define WXS_IS_EXTENSION(t) \
249 ((t)->flags & XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION)
251 #define WXS_IS_TYPE_NOT_FIXED(i) \
252 (((i)->type != XML_SCHEMA_TYPE_BASIC) && \
253 (((i)->flags & XML_SCHEMAS_TYPE_INTERNAL_RESOLVED) == 0))
255 #define WXS_IS_TYPE_NOT_FIXED_1(item) \
256 (((item)->type != XML_SCHEMA_TYPE_BASIC) && \
257 (((item)->flags & XML_SCHEMAS_TYPE_FIXUP_1) == 0))
259 #define WXS_TYPE_IS_GLOBAL(t) ((t)->flags & XML_SCHEMAS_TYPE_GLOBAL)
261 #define WXS_TYPE_IS_LOCAL(t) (((t)->flags & XML_SCHEMAS_TYPE_GLOBAL) == 0)
263 * Macros for exclusively for complex types.
265 #define WXS_HAS_COMPLEX_CONTENT(item) \
266 ((item->contentType == XML_SCHEMA_CONTENT_MIXED) || \
267 (item->contentType == XML_SCHEMA_CONTENT_EMPTY) || \
268 (item->contentType == XML_SCHEMA_CONTENT_ELEMENTS))
270 #define WXS_HAS_SIMPLE_CONTENT(item) \
271 ((item->contentType == XML_SCHEMA_CONTENT_SIMPLE) || \
272 (item->contentType == XML_SCHEMA_CONTENT_BASIC))
274 #define WXS_HAS_MIXED_CONTENT(item) \
275 (item->contentType == XML_SCHEMA_CONTENT_MIXED)
277 #define WXS_EMPTIABLE(t) \
278 (xmlSchemaIsParticleEmptiable(WXS_PTC_CAST (t)->subtypes))
280 #define WXS_TYPE_CONTENTTYPE(t) (t)->subtypes
282 #define WXS_TYPE_PARTICLE(t) WXS_PTC_CAST (t)->subtypes
284 #define WXS_TYPE_PARTICLE_TERM(t) WXS_PARTICLE_TERM(WXS_TYPE_PARTICLE(t))
286 * Macros for exclusively for simple types.
288 #define WXS_LIST_ITEMTYPE(t) (t)->subtypes
290 #define WXS_IS_ATOMIC(t) (t->flags & XML_SCHEMAS_TYPE_VARIETY_ATOMIC)
292 #define WXS_IS_LIST(t) (t->flags & XML_SCHEMAS_TYPE_VARIETY_LIST)
294 #define WXS_IS_UNION(t) (t->flags & XML_SCHEMAS_TYPE_VARIETY_UNION)
296 * Misc parser context macros.
298 #define WXS_CONSTRUCTOR(ctx) (ctx)->constructor
300 #define WXS_HAS_BUCKETS(ctx) \
301 ( (WXS_CONSTRUCTOR((ctx))->buckets != NULL) && \
302 (WXS_CONSTRUCTOR((ctx))->buckets->nbItems > 0) )
304 #define WXS_SUBST_GROUPS(ctx) WXS_CONSTRUCTOR((ctx))->substGroups
306 #define WXS_BUCKET(ctx) WXS_CONSTRUCTOR((ctx))->bucket
308 #define WXS_SCHEMA(ctx) (ctx)->schema
310 #define WXS_ADD_LOCAL(ctx, item) \
311 do { \
312 if (xmlSchemaAddItemSize(&(WXS_BUCKET(ctx)->locals), 10, item) < 0) { \
313 xmlFree(item); \
314 item = NULL; \
316 } while (0)
318 #define WXS_ADD_GLOBAL(ctx, item) \
319 do { \
320 if (xmlSchemaAddItemSize(&(WXS_BUCKET(ctx)->globals), 5, item) < 0) { \
321 xmlFree(item); \
322 item = NULL; \
324 } while (0)
326 #define WXS_ADD_PENDING(ctx, item) \
327 xmlSchemaAddItemSize(&((ctx)->constructor->pending), 10, item)
329 * xmlSchemaItemList macros.
331 #define WXS_ILIST_IS_EMPTY(l) ((l == NULL) || ((l)->nbItems == 0))
333 * Misc macros.
335 #define IS_SCHEMA(node, type) \
336 ((node != NULL) && (node->ns != NULL) && \
337 (xmlStrEqual(node->name, (const xmlChar *) type)) && \
338 (xmlStrEqual(node->ns->href, xmlSchemaNs)))
340 #define FREE_AND_NULL(str) if ((str) != NULL) { xmlFree((xmlChar *) (str)); str = NULL; }
343 * Since we put the default/fixed values into the dict, we can
344 * use pointer comparison for those values.
345 * REMOVED: (xmlStrEqual((v1), (v2)))
347 #define WXS_ARE_DEFAULT_STR_EQUAL(v1, v2) ((v1) == (v2))
349 #define INODE_NILLED(item) (item->flags & XML_SCHEMA_ELEM_INFO_NILLED)
351 #define CAN_PARSE_SCHEMA(b) (((b)->doc != NULL) && ((b)->parsed == 0))
353 #define HFAILURE if (res == -1) goto exit_failure;
355 #define HERROR if (res != 0) goto exit_error;
357 #define HSTOP(ctx) if ((ctx)->stop) goto exit;
359 * Some flags used for various schema constraints.
361 #define SUBSET_RESTRICTION 1<<0
362 #define SUBSET_EXTENSION 1<<1
363 #define SUBSET_SUBSTITUTION 1<<2
364 #define SUBSET_LIST 1<<3
365 #define SUBSET_UNION 1<<4
367 typedef struct _xmlSchemaNodeInfo xmlSchemaNodeInfo;
368 typedef xmlSchemaNodeInfo *xmlSchemaNodeInfoPtr;
370 typedef struct _xmlSchemaItemList xmlSchemaItemList;
371 typedef xmlSchemaItemList *xmlSchemaItemListPtr;
372 struct _xmlSchemaItemList {
373 void **items; /* used for dynamic addition of schemata */
374 int nbItems; /* used for dynamic addition of schemata */
375 int sizeItems; /* used for dynamic addition of schemata */
378 #define XML_SCHEMA_CTXT_PARSER 1
379 #define XML_SCHEMA_CTXT_VALIDATOR 2
381 typedef struct _xmlSchemaAbstractCtxt xmlSchemaAbstractCtxt;
382 typedef xmlSchemaAbstractCtxt *xmlSchemaAbstractCtxtPtr;
383 struct _xmlSchemaAbstractCtxt {
384 int type; /* E.g. XML_SCHEMA_CTXT_VALIDATOR */
385 void *dummy; /* Fix alignment issues */
388 typedef struct _xmlSchemaBucket xmlSchemaBucket;
389 typedef xmlSchemaBucket *xmlSchemaBucketPtr;
391 #define XML_SCHEMA_SCHEMA_MAIN 0
392 #define XML_SCHEMA_SCHEMA_IMPORT 1
393 #define XML_SCHEMA_SCHEMA_INCLUDE 2
394 #define XML_SCHEMA_SCHEMA_REDEFINE 3
397 * xmlSchemaSchemaRelation:
399 * Used to create a graph of schema relationships.
401 typedef struct _xmlSchemaSchemaRelation xmlSchemaSchemaRelation;
402 typedef xmlSchemaSchemaRelation *xmlSchemaSchemaRelationPtr;
403 struct _xmlSchemaSchemaRelation {
404 xmlSchemaSchemaRelationPtr next;
405 int type; /* E.g. XML_SCHEMA_SCHEMA_IMPORT */
406 const xmlChar *importNamespace;
407 xmlSchemaBucketPtr bucket;
410 #define XML_SCHEMA_BUCKET_MARKED 1<<0
411 #define XML_SCHEMA_BUCKET_COMPS_ADDED 1<<1
413 struct _xmlSchemaBucket {
414 int type;
415 int flags;
416 const xmlChar *schemaLocation;
417 const xmlChar *origTargetNamespace;
418 const xmlChar *targetNamespace;
419 xmlDocPtr doc;
420 xmlSchemaSchemaRelationPtr relations;
421 int located;
422 int parsed;
423 int imported;
424 int preserveDoc;
425 xmlSchemaItemListPtr globals; /* Global components. */
426 xmlSchemaItemListPtr locals; /* Local components. */
430 * xmlSchemaImport:
431 * (extends xmlSchemaBucket)
433 * Reflects a schema. Holds some information
434 * about the schema and its toplevel components. Duplicate
435 * toplevel components are not checked at this level.
437 typedef struct _xmlSchemaImport xmlSchemaImport;
438 typedef xmlSchemaImport *xmlSchemaImportPtr;
439 struct _xmlSchemaImport {
440 int type; /* Main OR import OR include. */
441 int flags;
442 const xmlChar *schemaLocation; /* The URI of the schema document. */
443 /* For chameleon includes, @origTargetNamespace will be NULL */
444 const xmlChar *origTargetNamespace;
446 * For chameleon includes, @targetNamespace will be the
447 * targetNamespace of the including schema.
449 const xmlChar *targetNamespace;
450 xmlDocPtr doc; /* The schema node-tree. */
451 /* @relations will hold any included/imported/redefined schemas. */
452 xmlSchemaSchemaRelationPtr relations;
453 int located;
454 int parsed;
455 int imported;
456 int preserveDoc;
457 xmlSchemaItemListPtr globals;
458 xmlSchemaItemListPtr locals;
459 /* The imported schema. */
460 xmlSchemaPtr schema;
464 * (extends xmlSchemaBucket)
466 typedef struct _xmlSchemaInclude xmlSchemaInclude;
467 typedef xmlSchemaInclude *xmlSchemaIncludePtr;
468 struct _xmlSchemaInclude {
469 int type;
470 int flags;
471 const xmlChar *schemaLocation;
472 const xmlChar *origTargetNamespace;
473 const xmlChar *targetNamespace;
474 xmlDocPtr doc;
475 xmlSchemaSchemaRelationPtr relations;
476 int located;
477 int parsed;
478 int imported;
479 int preserveDoc;
480 xmlSchemaItemListPtr globals; /* Global components. */
481 xmlSchemaItemListPtr locals; /* Local components. */
483 /* The owning main or import schema bucket. */
484 xmlSchemaImportPtr ownerImport;
488 * xmlSchemaBasicItem:
490 * The abstract base type for schema components.
492 typedef struct _xmlSchemaBasicItem xmlSchemaBasicItem;
493 typedef xmlSchemaBasicItem *xmlSchemaBasicItemPtr;
494 struct _xmlSchemaBasicItem {
495 xmlSchemaTypeType type;
496 void *dummy; /* Fix alignment issues */
500 * xmlSchemaAnnotItem:
502 * The abstract base type for annotated schema components.
503 * (Extends xmlSchemaBasicItem)
505 typedef struct _xmlSchemaAnnotItem xmlSchemaAnnotItem;
506 typedef xmlSchemaAnnotItem *xmlSchemaAnnotItemPtr;
507 struct _xmlSchemaAnnotItem {
508 xmlSchemaTypeType type;
509 xmlSchemaAnnotPtr annot;
513 * xmlSchemaTreeItem:
515 * The abstract base type for tree-like structured schema components.
516 * (Extends xmlSchemaAnnotItem)
518 typedef struct _xmlSchemaTreeItem xmlSchemaTreeItem;
519 typedef xmlSchemaTreeItem *xmlSchemaTreeItemPtr;
520 struct _xmlSchemaTreeItem {
521 xmlSchemaTypeType type;
522 xmlSchemaAnnotPtr annot;
523 xmlSchemaTreeItemPtr next;
524 xmlSchemaTreeItemPtr children;
528 #define XML_SCHEMA_ATTR_USE_FIXED 1<<0
530 * xmlSchemaAttributeUsePtr:
532 * The abstract base type for tree-like structured schema components.
533 * (Extends xmlSchemaTreeItem)
535 typedef struct _xmlSchemaAttributeUse xmlSchemaAttributeUse;
536 typedef xmlSchemaAttributeUse *xmlSchemaAttributeUsePtr;
537 struct _xmlSchemaAttributeUse {
538 xmlSchemaTypeType type;
539 xmlSchemaAnnotPtr annot;
540 xmlSchemaAttributeUsePtr next; /* The next attr. use. */
542 * The attr. decl. OR a QName-ref. to an attr. decl. OR
543 * a QName-ref. to an attribute group definition.
545 xmlSchemaAttributePtr attrDecl;
547 int flags;
548 xmlNodePtr node;
549 int occurs; /* required, optional */
550 const xmlChar * defValue;
551 xmlSchemaValPtr defVal;
555 * xmlSchemaAttributeUseProhibPtr:
557 * A helper component to reflect attribute prohibitions.
558 * (Extends xmlSchemaBasicItem)
560 typedef struct _xmlSchemaAttributeUseProhib xmlSchemaAttributeUseProhib;
561 typedef xmlSchemaAttributeUseProhib *xmlSchemaAttributeUseProhibPtr;
562 struct _xmlSchemaAttributeUseProhib {
563 xmlSchemaTypeType type; /* == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB */
564 xmlNodePtr node;
565 const xmlChar *name;
566 const xmlChar *targetNamespace;
567 int isRef;
571 * xmlSchemaRedef:
573 typedef struct _xmlSchemaRedef xmlSchemaRedef;
574 typedef xmlSchemaRedef *xmlSchemaRedefPtr;
575 struct _xmlSchemaRedef {
576 xmlSchemaRedefPtr next;
577 xmlSchemaBasicItemPtr item; /* The redefining component. */
578 xmlSchemaBasicItemPtr reference; /* The referencing component. */
579 xmlSchemaBasicItemPtr target; /* The to-be-redefined component. */
580 const xmlChar *refName; /* The name of the to-be-redefined component. */
581 const xmlChar *refTargetNs; /* The target namespace of the
582 to-be-redefined comp. */
583 xmlSchemaBucketPtr targetBucket; /* The redefined schema. */
587 * xmlSchemaConstructionCtxt:
589 typedef struct _xmlSchemaConstructionCtxt xmlSchemaConstructionCtxt;
590 typedef xmlSchemaConstructionCtxt *xmlSchemaConstructionCtxtPtr;
591 struct _xmlSchemaConstructionCtxt {
592 xmlSchemaPtr mainSchema; /* The main schema. */
593 xmlSchemaBucketPtr mainBucket; /* The main schema bucket */
594 xmlDictPtr dict;
595 xmlSchemaItemListPtr buckets; /* List of schema buckets. */
596 /* xmlSchemaItemListPtr relations; */ /* List of schema relations. */
597 xmlSchemaBucketPtr bucket; /* The current schema bucket */
598 xmlSchemaItemListPtr pending; /* All Components of all schemas that
599 need to be fixed. */
600 xmlHashTablePtr substGroups;
601 xmlSchemaRedefPtr redefs;
602 xmlSchemaRedefPtr lastRedef;
605 #define XML_SCHEMAS_PARSE_ERROR 1
606 #define SCHEMAS_PARSE_OPTIONS XML_PARSE_NOENT
608 struct _xmlSchemaParserCtxt {
609 int type;
610 void *errCtxt; /* user specific error context */
611 xmlSchemaValidityErrorFunc error; /* the callback in case of errors */
612 xmlSchemaValidityWarningFunc warning; /* the callback in case of warning */
613 int err;
614 int nberrors;
615 xmlStructuredErrorFunc serror;
617 xmlSchemaConstructionCtxtPtr constructor;
618 int ownsConstructor; /* TODO: Move this to parser *flags*. */
620 /* xmlSchemaPtr topschema; */
621 /* xmlHashTablePtr namespaces; */
623 xmlSchemaPtr schema; /* The main schema in use */
624 int counter;
626 const xmlChar *URL;
627 xmlDocPtr doc;
628 int preserve; /* Whether the doc should be freed */
630 const char *buffer;
631 int size;
634 * Used to build complex element content models
636 xmlAutomataPtr am;
637 xmlAutomataStatePtr start;
638 xmlAutomataStatePtr end;
639 xmlAutomataStatePtr state;
641 xmlDictPtr dict; /* dictionary for interned string names */
642 xmlSchemaTypePtr ctxtType; /* The current context simple/complex type */
643 int options;
644 xmlSchemaValidCtxtPtr vctxt;
645 int isS4S;
646 int isRedefine;
647 int xsiAssemble;
648 int stop; /* If the parser should stop; i.e. a critical error. */
649 const xmlChar *targetNamespace;
650 xmlSchemaBucketPtr redefined; /* The schema to be redefined. */
652 xmlSchemaRedefPtr redef; /* Used for redefinitions. */
653 int redefCounter; /* Used for redefinitions. */
654 xmlSchemaItemListPtr attrProhibs;
658 * xmlSchemaQNameRef:
660 * A component reference item (not a schema component)
661 * (Extends xmlSchemaBasicItem)
663 typedef struct _xmlSchemaQNameRef xmlSchemaQNameRef;
664 typedef xmlSchemaQNameRef *xmlSchemaQNameRefPtr;
665 struct _xmlSchemaQNameRef {
666 xmlSchemaTypeType type;
667 xmlSchemaBasicItemPtr item; /* The resolved referenced item. */
668 xmlSchemaTypeType itemType;
669 const xmlChar *name;
670 const xmlChar *targetNamespace;
671 xmlNodePtr node;
675 * xmlSchemaParticle:
677 * A particle component.
678 * (Extends xmlSchemaTreeItem)
680 typedef struct _xmlSchemaParticle xmlSchemaParticle;
681 typedef xmlSchemaParticle *xmlSchemaParticlePtr;
682 struct _xmlSchemaParticle {
683 xmlSchemaTypeType type;
684 xmlSchemaAnnotPtr annot;
685 xmlSchemaTreeItemPtr next; /* next particle */
686 xmlSchemaTreeItemPtr children; /* the "term" (e.g. a model group,
687 a group definition, a XML_SCHEMA_EXTRA_QNAMEREF (if a reference),
688 etc.) */
689 int minOccurs;
690 int maxOccurs;
691 xmlNodePtr node;
695 * xmlSchemaModelGroup:
697 * A model group component.
698 * (Extends xmlSchemaTreeItem)
700 typedef struct _xmlSchemaModelGroup xmlSchemaModelGroup;
701 typedef xmlSchemaModelGroup *xmlSchemaModelGroupPtr;
702 struct _xmlSchemaModelGroup {
703 xmlSchemaTypeType type; /* XML_SCHEMA_TYPE_SEQUENCE, XML_SCHEMA_TYPE_CHOICE, XML_SCHEMA_TYPE_ALL */
704 xmlSchemaAnnotPtr annot;
705 xmlSchemaTreeItemPtr next; /* not used */
706 xmlSchemaTreeItemPtr children; /* first particle (OR "element decl" OR "wildcard") */
707 xmlNodePtr node;
710 #define XML_SCHEMA_MODEL_GROUP_DEF_MARKED 1<<0
711 #define XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED 1<<1
713 * xmlSchemaModelGroupDef:
715 * A model group definition component.
716 * (Extends xmlSchemaTreeItem)
718 typedef struct _xmlSchemaModelGroupDef xmlSchemaModelGroupDef;
719 typedef xmlSchemaModelGroupDef *xmlSchemaModelGroupDefPtr;
720 struct _xmlSchemaModelGroupDef {
721 xmlSchemaTypeType type; /* XML_SCHEMA_TYPE_GROUP */
722 xmlSchemaAnnotPtr annot;
723 xmlSchemaTreeItemPtr next; /* not used */
724 xmlSchemaTreeItemPtr children; /* the "model group" */
725 const xmlChar *name;
726 const xmlChar *targetNamespace;
727 xmlNodePtr node;
728 int flags;
731 typedef struct _xmlSchemaIDC xmlSchemaIDC;
732 typedef xmlSchemaIDC *xmlSchemaIDCPtr;
735 * xmlSchemaIDCSelect:
737 * The identity-constraint "field" and "selector" item, holding the
738 * XPath expression.
740 typedef struct _xmlSchemaIDCSelect xmlSchemaIDCSelect;
741 typedef xmlSchemaIDCSelect *xmlSchemaIDCSelectPtr;
742 struct _xmlSchemaIDCSelect {
743 xmlSchemaIDCSelectPtr next;
744 xmlSchemaIDCPtr idc;
745 int index; /* an index position if significant for IDC key-sequences */
746 const xmlChar *xpath; /* the XPath expression */
747 void *xpathComp; /* the compiled XPath expression */
751 * xmlSchemaIDC:
753 * The identity-constraint definition component.
754 * (Extends xmlSchemaAnnotItem)
757 struct _xmlSchemaIDC {
758 xmlSchemaTypeType type;
759 xmlSchemaAnnotPtr annot;
760 xmlSchemaIDCPtr next;
761 xmlNodePtr node;
762 const xmlChar *name;
763 const xmlChar *targetNamespace;
764 xmlSchemaIDCSelectPtr selector;
765 xmlSchemaIDCSelectPtr fields;
766 int nbFields;
767 xmlSchemaQNameRefPtr ref;
771 * xmlSchemaIDCAug:
773 * The augmented IDC information used for validation.
775 typedef struct _xmlSchemaIDCAug xmlSchemaIDCAug;
776 typedef xmlSchemaIDCAug *xmlSchemaIDCAugPtr;
777 struct _xmlSchemaIDCAug {
778 xmlSchemaIDCAugPtr next; /* next in a list */
779 xmlSchemaIDCPtr def; /* the IDC definition */
780 int keyrefDepth; /* the lowest tree level to which IDC
781 tables need to be bubbled upwards */
785 * xmlSchemaPSVIIDCKeySequence:
787 * The key sequence of a node table item.
789 typedef struct _xmlSchemaPSVIIDCKey xmlSchemaPSVIIDCKey;
790 typedef xmlSchemaPSVIIDCKey *xmlSchemaPSVIIDCKeyPtr;
791 struct _xmlSchemaPSVIIDCKey {
792 xmlSchemaTypePtr type;
793 xmlSchemaValPtr val;
797 * xmlSchemaPSVIIDCNode:
799 * The node table item of a node table.
801 typedef struct _xmlSchemaPSVIIDCNode xmlSchemaPSVIIDCNode;
802 typedef xmlSchemaPSVIIDCNode *xmlSchemaPSVIIDCNodePtr;
803 struct _xmlSchemaPSVIIDCNode {
804 xmlNodePtr node;
805 xmlSchemaPSVIIDCKeyPtr *keys;
806 int nodeLine;
807 int nodeQNameID;
812 * xmlSchemaPSVIIDCBinding:
814 * The identity-constraint binding item of the [identity-constraint table].
816 typedef struct _xmlSchemaPSVIIDCBinding xmlSchemaPSVIIDCBinding;
817 typedef xmlSchemaPSVIIDCBinding *xmlSchemaPSVIIDCBindingPtr;
818 struct _xmlSchemaPSVIIDCBinding {
819 xmlSchemaPSVIIDCBindingPtr next; /* next binding of a specific node */
820 xmlSchemaIDCPtr definition; /* the IDC definition */
821 xmlSchemaPSVIIDCNodePtr *nodeTable; /* array of key-sequences */
822 int nbNodes; /* number of entries in the node table */
823 int sizeNodes; /* size of the node table */
824 xmlSchemaItemListPtr dupls;
828 #define XPATH_STATE_OBJ_TYPE_IDC_SELECTOR 1
829 #define XPATH_STATE_OBJ_TYPE_IDC_FIELD 2
831 #define XPATH_STATE_OBJ_MATCHES -2
832 #define XPATH_STATE_OBJ_BLOCKED -3
834 typedef struct _xmlSchemaIDCMatcher xmlSchemaIDCMatcher;
835 typedef xmlSchemaIDCMatcher *xmlSchemaIDCMatcherPtr;
838 * xmlSchemaIDCStateObj:
840 * The state object used to evaluate XPath expressions.
842 typedef struct _xmlSchemaIDCStateObj xmlSchemaIDCStateObj;
843 typedef xmlSchemaIDCStateObj *xmlSchemaIDCStateObjPtr;
844 struct _xmlSchemaIDCStateObj {
845 int type;
846 xmlSchemaIDCStateObjPtr next; /* next if in a list */
847 int depth; /* depth of creation */
848 int *history; /* list of (depth, state-id) tuples */
849 int nbHistory;
850 int sizeHistory;
851 xmlSchemaIDCMatcherPtr matcher; /* the correspondent field/selector
852 matcher */
853 xmlSchemaIDCSelectPtr sel;
854 void *xpathCtxt;
857 #define IDC_MATCHER 0
860 * xmlSchemaIDCMatcher:
862 * Used to evaluate IDC selectors (and fields).
864 struct _xmlSchemaIDCMatcher {
865 int type;
866 int depth; /* the tree depth at creation time */
867 xmlSchemaIDCMatcherPtr next; /* next in the list */
868 xmlSchemaIDCMatcherPtr nextCached; /* next in the cache list */
869 xmlSchemaIDCAugPtr aidc; /* the augmented IDC item */
870 int idcType;
871 xmlSchemaPSVIIDCKeyPtr **keySeqs; /* the key-sequences of the target
872 elements */
873 int sizeKeySeqs;
874 xmlSchemaItemListPtr targets; /* list of target-node
875 (xmlSchemaPSVIIDCNodePtr) entries */
876 xmlHashTablePtr htab;
880 * Element info flags.
882 #define XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES 1<<0
883 #define XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES 1<<1
884 #define XML_SCHEMA_ELEM_INFO_NILLED 1<<2
885 #define XML_SCHEMA_ELEM_INFO_LOCAL_TYPE 1<<3
887 #define XML_SCHEMA_NODE_INFO_VALUE_NEEDED 1<<4
888 #define XML_SCHEMA_ELEM_INFO_EMPTY 1<<5
889 #define XML_SCHEMA_ELEM_INFO_HAS_CONTENT 1<<6
891 #define XML_SCHEMA_ELEM_INFO_HAS_ELEM_CONTENT 1<<7
892 #define XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT 1<<8
893 #define XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED 1<<9
894 #define XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE 1<<10
897 * xmlSchemaNodeInfo:
899 * Holds information of an element node.
901 struct _xmlSchemaNodeInfo {
902 int nodeType;
903 xmlNodePtr node;
904 int nodeLine;
905 const xmlChar *localName;
906 const xmlChar *nsName;
907 const xmlChar *value;
908 xmlSchemaValPtr val; /* the pre-computed value if any */
909 xmlSchemaTypePtr typeDef; /* the complex/simple type definition if any */
911 int flags; /* combination of node info flags */
913 int valNeeded;
914 int normVal;
916 xmlSchemaElementPtr decl; /* the element/attribute declaration */
917 int depth;
918 xmlSchemaPSVIIDCBindingPtr idcTable; /* the table of PSVI IDC bindings
919 for the scope element*/
920 xmlSchemaIDCMatcherPtr idcMatchers; /* the IDC matchers for the scope
921 element */
922 xmlRegExecCtxtPtr regexCtxt;
924 const xmlChar **nsBindings; /* Namespace bindings on this element */
925 int nbNsBindings;
926 int sizeNsBindings;
928 int hasKeyrefs;
929 int appliedXPath; /* Indicates that an XPath has been applied. */
932 #define XML_SCHEMAS_ATTR_UNKNOWN 1
933 #define XML_SCHEMAS_ATTR_ASSESSED 2
934 #define XML_SCHEMAS_ATTR_PROHIBITED 3
935 #define XML_SCHEMAS_ATTR_ERR_MISSING 4
936 #define XML_SCHEMAS_ATTR_INVALID_VALUE 5
937 #define XML_SCHEMAS_ATTR_ERR_NO_TYPE 6
938 #define XML_SCHEMAS_ATTR_ERR_FIXED_VALUE 7
939 #define XML_SCHEMAS_ATTR_DEFAULT 8
940 #define XML_SCHEMAS_ATTR_VALIDATE_VALUE 9
941 #define XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL 10
942 #define XML_SCHEMAS_ATTR_HAS_ATTR_USE 11
943 #define XML_SCHEMAS_ATTR_HAS_ATTR_DECL 12
944 #define XML_SCHEMAS_ATTR_WILD_SKIP 13
945 #define XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL 14
946 #define XML_SCHEMAS_ATTR_ERR_WILD_DUPLICATE_ID 15
947 #define XML_SCHEMAS_ATTR_ERR_WILD_AND_USE_ID 16
948 #define XML_SCHEMAS_ATTR_META 17
950 * @metaType values of xmlSchemaAttrInfo.
952 #define XML_SCHEMA_ATTR_INFO_META_XSI_TYPE 1
953 #define XML_SCHEMA_ATTR_INFO_META_XSI_NIL 2
954 #define XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC 3
955 #define XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC 4
956 #define XML_SCHEMA_ATTR_INFO_META_XMLNS 5
958 typedef struct _xmlSchemaAttrInfo xmlSchemaAttrInfo;
959 typedef xmlSchemaAttrInfo *xmlSchemaAttrInfoPtr;
960 struct _xmlSchemaAttrInfo {
961 int nodeType;
962 xmlNodePtr node;
963 int nodeLine;
964 const xmlChar *localName;
965 const xmlChar *nsName;
966 const xmlChar *value;
967 xmlSchemaValPtr val; /* the pre-computed value if any */
968 xmlSchemaTypePtr typeDef; /* the complex/simple type definition if any */
969 int flags; /* combination of node info flags */
971 xmlSchemaAttributePtr decl; /* the attribute declaration */
972 xmlSchemaAttributeUsePtr use; /* the attribute use */
973 int state;
974 int metaType;
975 const xmlChar *vcValue; /* the value constraint value */
976 xmlSchemaNodeInfoPtr parent;
980 #define XML_SCHEMA_VALID_CTXT_FLAG_STREAM 1
982 * xmlSchemaValidCtxt:
984 * A Schemas validation context
986 struct _xmlSchemaValidCtxt {
987 int type;
988 void *errCtxt; /* user specific data block */
989 xmlSchemaValidityErrorFunc error; /* the callback in case of errors */
990 xmlSchemaValidityWarningFunc warning; /* the callback in case of warning */
991 xmlStructuredErrorFunc serror;
993 xmlSchemaPtr schema; /* The schema in use */
994 xmlDocPtr doc;
995 xmlParserInputBufferPtr input;
996 xmlCharEncoding enc;
997 xmlSAXHandlerPtr sax;
998 xmlParserCtxtPtr parserCtxt;
999 void *user_data; /* TODO: What is this for? */
1000 char *filename;
1002 int err;
1003 int nberrors;
1005 xmlNodePtr node;
1006 xmlNodePtr cur;
1007 /* xmlSchemaTypePtr type; */
1009 xmlRegExecCtxtPtr regexp;
1010 xmlSchemaValPtr value;
1012 int valueWS;
1013 int options;
1014 xmlNodePtr validationRoot;
1015 xmlSchemaParserCtxtPtr pctxt;
1016 int xsiAssemble;
1018 int depth;
1019 xmlSchemaNodeInfoPtr *elemInfos; /* array of element information */
1020 int sizeElemInfos;
1021 xmlSchemaNodeInfoPtr inode; /* the current element information */
1023 xmlSchemaIDCAugPtr aidcs; /* a list of augmented IDC information */
1025 xmlSchemaIDCStateObjPtr xpathStates; /* first active state object. */
1026 xmlSchemaIDCStateObjPtr xpathStatePool; /* first stored state object. */
1027 xmlSchemaIDCMatcherPtr idcMatcherCache; /* Cache for IDC matcher objects. */
1029 xmlSchemaPSVIIDCNodePtr *idcNodes; /* list of all IDC node-table entries*/
1030 int nbIdcNodes;
1031 int sizeIdcNodes;
1033 xmlSchemaPSVIIDCKeyPtr *idcKeys; /* list of all IDC node-table entries */
1034 int nbIdcKeys;
1035 int sizeIdcKeys;
1037 int flags;
1039 xmlDictPtr dict;
1041 #ifdef LIBXML_READER_ENABLED
1042 xmlTextReaderPtr reader;
1043 #endif
1045 xmlSchemaAttrInfoPtr *attrInfos;
1046 int nbAttrInfos;
1047 int sizeAttrInfos;
1049 int skipDepth;
1050 xmlSchemaItemListPtr nodeQNames;
1051 int hasKeyrefs;
1052 int createIDCNodeTables;
1053 int psviExposeIDCNodeTables;
1055 /* Locator for error reporting in streaming mode */
1056 xmlSchemaValidityLocatorFunc locFunc;
1057 void *locCtxt;
1061 * xmlSchemaSubstGroup:
1065 typedef struct _xmlSchemaSubstGroup xmlSchemaSubstGroup;
1066 typedef xmlSchemaSubstGroup *xmlSchemaSubstGroupPtr;
1067 struct _xmlSchemaSubstGroup {
1068 xmlSchemaElementPtr head;
1069 xmlSchemaItemListPtr members;
1073 * xmlIDCHashEntry:
1075 * an entry in hash tables to quickly look up keys/uniques
1077 typedef struct _xmlIDCHashEntry xmlIDCHashEntry;
1078 typedef xmlIDCHashEntry *xmlIDCHashEntryPtr;
1079 struct _xmlIDCHashEntry {
1080 xmlIDCHashEntryPtr next; /* next item with same hash */
1081 int index; /* index into associated item list */
1084 /************************************************************************
1086 * Some predeclarations *
1088 ************************************************************************/
1090 static int xmlSchemaParseInclude(xmlSchemaParserCtxtPtr ctxt,
1091 xmlSchemaPtr schema,
1092 xmlNodePtr node);
1093 static int xmlSchemaParseRedefine(xmlSchemaParserCtxtPtr ctxt,
1094 xmlSchemaPtr schema,
1095 xmlNodePtr node);
1096 static int
1097 xmlSchemaTypeFixup(xmlSchemaTypePtr type,
1098 xmlSchemaAbstractCtxtPtr ctxt);
1099 static const xmlChar *
1100 xmlSchemaFacetTypeToString(xmlSchemaTypeType type);
1101 static int
1102 xmlSchemaParseImport(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1103 xmlNodePtr node);
1104 static int
1105 xmlSchemaCheckFacetValues(xmlSchemaTypePtr typeDecl,
1106 xmlSchemaParserCtxtPtr ctxt);
1107 static void
1108 xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt);
1109 static xmlSchemaWhitespaceValueType
1110 xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type);
1111 static xmlSchemaTreeItemPtr
1112 xmlSchemaParseModelGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
1113 xmlNodePtr node, xmlSchemaTypeType type,
1114 int withParticle);
1115 static const xmlChar *
1116 xmlSchemaGetComponentTypeStr(xmlSchemaBasicItemPtr item);
1117 static xmlSchemaTypeLinkPtr
1118 xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type);
1119 static void
1120 xmlSchemaInternalErr(xmlSchemaAbstractCtxtPtr actxt,
1121 const char *funcName,
1122 const char *message) LIBXML_ATTR_FORMAT(3,0);
1123 static int
1124 xmlSchemaCheckCOSSTDerivedOK(xmlSchemaAbstractCtxtPtr ctxt,
1125 xmlSchemaTypePtr type,
1126 xmlSchemaTypePtr baseType,
1127 int subset);
1128 static void
1129 xmlSchemaCheckElementDeclComponent(xmlSchemaElementPtr elemDecl,
1130 xmlSchemaParserCtxtPtr ctxt);
1131 static void
1132 xmlSchemaComponentListFree(xmlSchemaItemListPtr list);
1133 static xmlSchemaQNameRefPtr
1134 xmlSchemaParseAttributeGroupRef(xmlSchemaParserCtxtPtr pctxt,
1135 xmlSchemaPtr schema,
1136 xmlNodePtr node);
1138 /************************************************************************
1140 * Helper functions *
1142 ************************************************************************/
1145 * xmlSchemaItemTypeToStr:
1146 * @type: the type of the schema item
1148 * Returns the component name of a schema item.
1150 static const xmlChar *
1151 xmlSchemaItemTypeToStr(xmlSchemaTypeType type)
1153 switch (type) {
1154 case XML_SCHEMA_TYPE_BASIC:
1155 return(BAD_CAST "simple type definition");
1156 case XML_SCHEMA_TYPE_SIMPLE:
1157 return(BAD_CAST "simple type definition");
1158 case XML_SCHEMA_TYPE_COMPLEX:
1159 return(BAD_CAST "complex type definition");
1160 case XML_SCHEMA_TYPE_ELEMENT:
1161 return(BAD_CAST "element declaration");
1162 case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
1163 return(BAD_CAST "attribute use");
1164 case XML_SCHEMA_TYPE_ATTRIBUTE:
1165 return(BAD_CAST "attribute declaration");
1166 case XML_SCHEMA_TYPE_GROUP:
1167 return(BAD_CAST "model group definition");
1168 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1169 return(BAD_CAST "attribute group definition");
1170 case XML_SCHEMA_TYPE_NOTATION:
1171 return(BAD_CAST "notation declaration");
1172 case XML_SCHEMA_TYPE_SEQUENCE:
1173 return(BAD_CAST "model group (sequence)");
1174 case XML_SCHEMA_TYPE_CHOICE:
1175 return(BAD_CAST "model group (choice)");
1176 case XML_SCHEMA_TYPE_ALL:
1177 return(BAD_CAST "model group (all)");
1178 case XML_SCHEMA_TYPE_PARTICLE:
1179 return(BAD_CAST "particle");
1180 case XML_SCHEMA_TYPE_IDC_UNIQUE:
1181 return(BAD_CAST "unique identity-constraint");
1182 /* return(BAD_CAST "IDC (unique)"); */
1183 case XML_SCHEMA_TYPE_IDC_KEY:
1184 return(BAD_CAST "key identity-constraint");
1185 /* return(BAD_CAST "IDC (key)"); */
1186 case XML_SCHEMA_TYPE_IDC_KEYREF:
1187 return(BAD_CAST "keyref identity-constraint");
1188 /* return(BAD_CAST "IDC (keyref)"); */
1189 case XML_SCHEMA_TYPE_ANY:
1190 return(BAD_CAST "wildcard (any)");
1191 case XML_SCHEMA_EXTRA_QNAMEREF:
1192 return(BAD_CAST "[helper component] QName reference");
1193 case XML_SCHEMA_EXTRA_ATTR_USE_PROHIB:
1194 return(BAD_CAST "[helper component] attribute use prohibition");
1195 default:
1196 return(BAD_CAST "Not a schema component");
1201 * xmlSchemaGetComponentTypeStr:
1202 * @type: the type of the schema item
1204 * Returns the component name of a schema item.
1206 static const xmlChar *
1207 xmlSchemaGetComponentTypeStr(xmlSchemaBasicItemPtr item)
1209 switch (item->type) {
1210 case XML_SCHEMA_TYPE_BASIC:
1211 if (WXS_IS_COMPLEX(WXS_TYPE_CAST item))
1212 return(BAD_CAST "complex type definition");
1213 else
1214 return(BAD_CAST "simple type definition");
1215 default:
1216 return(xmlSchemaItemTypeToStr(item->type));
1221 * xmlSchemaGetComponentNode:
1222 * @item: a schema component
1224 * Returns node associated with the schema component.
1225 * NOTE that such a node need not be available; plus, a component's
1226 * node need not to reflect the component directly, since there is no
1227 * one-to-one relationship between the XML Schema representation and
1228 * the component representation.
1230 static xmlNodePtr
1231 xmlSchemaGetComponentNode(xmlSchemaBasicItemPtr item)
1233 switch (item->type) {
1234 case XML_SCHEMA_TYPE_ELEMENT:
1235 return (((xmlSchemaElementPtr) item)->node);
1236 case XML_SCHEMA_TYPE_ATTRIBUTE:
1237 return (((xmlSchemaAttributePtr) item)->node);
1238 case XML_SCHEMA_TYPE_COMPLEX:
1239 case XML_SCHEMA_TYPE_SIMPLE:
1240 return (((xmlSchemaTypePtr) item)->node);
1241 case XML_SCHEMA_TYPE_ANY:
1242 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
1243 return (((xmlSchemaWildcardPtr) item)->node);
1244 case XML_SCHEMA_TYPE_PARTICLE:
1245 return (((xmlSchemaParticlePtr) item)->node);
1246 case XML_SCHEMA_TYPE_SEQUENCE:
1247 case XML_SCHEMA_TYPE_CHOICE:
1248 case XML_SCHEMA_TYPE_ALL:
1249 return (((xmlSchemaModelGroupPtr) item)->node);
1250 case XML_SCHEMA_TYPE_GROUP:
1251 return (((xmlSchemaModelGroupDefPtr) item)->node);
1252 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1253 return (((xmlSchemaAttributeGroupPtr) item)->node);
1254 case XML_SCHEMA_TYPE_IDC_UNIQUE:
1255 case XML_SCHEMA_TYPE_IDC_KEY:
1256 case XML_SCHEMA_TYPE_IDC_KEYREF:
1257 return (((xmlSchemaIDCPtr) item)->node);
1258 case XML_SCHEMA_EXTRA_QNAMEREF:
1259 return(((xmlSchemaQNameRefPtr) item)->node);
1260 /* TODO: What to do with NOTATIONs?
1261 case XML_SCHEMA_TYPE_NOTATION:
1262 return (((xmlSchemaNotationPtr) item)->node);
1264 case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
1265 return (((xmlSchemaAttributeUsePtr) item)->node);
1266 default:
1267 return (NULL);
1271 #if 0
1273 * xmlSchemaGetNextComponent:
1274 * @item: a schema component
1276 * Returns the next sibling of the schema component.
1278 static xmlSchemaBasicItemPtr
1279 xmlSchemaGetNextComponent(xmlSchemaBasicItemPtr item)
1281 switch (item->type) {
1282 case XML_SCHEMA_TYPE_ELEMENT:
1283 return ((xmlSchemaBasicItemPtr) ((xmlSchemaElementPtr) item)->next);
1284 case XML_SCHEMA_TYPE_ATTRIBUTE:
1285 return ((xmlSchemaBasicItemPtr) ((xmlSchemaAttributePtr) item)->next);
1286 case XML_SCHEMA_TYPE_COMPLEX:
1287 case XML_SCHEMA_TYPE_SIMPLE:
1288 return ((xmlSchemaBasicItemPtr) ((xmlSchemaTypePtr) item)->next);
1289 case XML_SCHEMA_TYPE_ANY:
1290 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
1291 return (NULL);
1292 case XML_SCHEMA_TYPE_PARTICLE:
1293 return ((xmlSchemaBasicItemPtr) ((xmlSchemaParticlePtr) item)->next);
1294 case XML_SCHEMA_TYPE_SEQUENCE:
1295 case XML_SCHEMA_TYPE_CHOICE:
1296 case XML_SCHEMA_TYPE_ALL:
1297 return (NULL);
1298 case XML_SCHEMA_TYPE_GROUP:
1299 return (NULL);
1300 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1301 return ((xmlSchemaBasicItemPtr) ((xmlSchemaAttributeGroupPtr) item)->next);
1302 case XML_SCHEMA_TYPE_IDC_UNIQUE:
1303 case XML_SCHEMA_TYPE_IDC_KEY:
1304 case XML_SCHEMA_TYPE_IDC_KEYREF:
1305 return ((xmlSchemaBasicItemPtr) ((xmlSchemaIDCPtr) item)->next);
1306 default:
1307 return (NULL);
1310 #endif
1314 * xmlSchemaFormatQName:
1315 * @buf: the string buffer
1316 * @namespaceName: the namespace name
1317 * @localName: the local name
1319 * Returns the given QName in the format "{namespaceName}localName" or
1320 * just "localName" if @namespaceName is NULL.
1322 * Returns the localName if @namespaceName is NULL, a formatted
1323 * string otherwise.
1325 static const xmlChar*
1326 xmlSchemaFormatQName(xmlChar **buf,
1327 const xmlChar *namespaceName,
1328 const xmlChar *localName)
1330 FREE_AND_NULL(*buf)
1331 if (namespaceName != NULL) {
1332 *buf = xmlStrdup(BAD_CAST "{");
1333 *buf = xmlStrcat(*buf, namespaceName);
1334 *buf = xmlStrcat(*buf, BAD_CAST "}");
1336 if (localName != NULL) {
1337 if (namespaceName == NULL)
1338 return(localName);
1339 *buf = xmlStrcat(*buf, localName);
1340 } else {
1341 *buf = xmlStrcat(*buf, BAD_CAST "(NULL)");
1343 return ((const xmlChar *) *buf);
1346 static const xmlChar*
1347 xmlSchemaFormatQNameNs(xmlChar **buf, xmlNsPtr ns, const xmlChar *localName)
1349 if (ns != NULL)
1350 return (xmlSchemaFormatQName(buf, ns->href, localName));
1351 else
1352 return (xmlSchemaFormatQName(buf, NULL, localName));
1355 static const xmlChar *
1356 xmlSchemaGetComponentName(xmlSchemaBasicItemPtr item)
1358 if (item == NULL) {
1359 return (NULL);
1361 switch (item->type) {
1362 case XML_SCHEMA_TYPE_ELEMENT:
1363 return (((xmlSchemaElementPtr) item)->name);
1364 case XML_SCHEMA_TYPE_ATTRIBUTE:
1365 return (((xmlSchemaAttributePtr) item)->name);
1366 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1367 return (((xmlSchemaAttributeGroupPtr) item)->name);
1368 case XML_SCHEMA_TYPE_BASIC:
1369 case XML_SCHEMA_TYPE_SIMPLE:
1370 case XML_SCHEMA_TYPE_COMPLEX:
1371 return (((xmlSchemaTypePtr) item)->name);
1372 case XML_SCHEMA_TYPE_GROUP:
1373 return (((xmlSchemaModelGroupDefPtr) item)->name);
1374 case XML_SCHEMA_TYPE_IDC_KEY:
1375 case XML_SCHEMA_TYPE_IDC_UNIQUE:
1376 case XML_SCHEMA_TYPE_IDC_KEYREF:
1377 return (((xmlSchemaIDCPtr) item)->name);
1378 case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
1379 if (WXS_ATTRUSE_DECL(item) != NULL) {
1380 return(xmlSchemaGetComponentName(
1381 WXS_BASIC_CAST WXS_ATTRUSE_DECL(item)));
1382 } else
1383 return(NULL);
1384 case XML_SCHEMA_EXTRA_QNAMEREF:
1385 return (((xmlSchemaQNameRefPtr) item)->name);
1386 case XML_SCHEMA_TYPE_NOTATION:
1387 return (((xmlSchemaNotationPtr) item)->name);
1388 default:
1390 * Other components cannot have names.
1392 break;
1394 return (NULL);
1397 #define xmlSchemaGetQNameRefName(r) (WXS_QNAME_CAST (r))->name
1398 #define xmlSchemaGetQNameRefTargetNs(r) (WXS_QNAME_CAST (r))->targetNamespace
1400 static const xmlChar *
1401 xmlSchemaGetQNameRefName(void *ref)
1403 return(((xmlSchemaQNameRefPtr) ref)->name);
1406 static const xmlChar *
1407 xmlSchemaGetQNameRefTargetNs(void *ref)
1409 return(((xmlSchemaQNameRefPtr) ref)->targetNamespace);
1413 static const xmlChar *
1414 xmlSchemaGetComponentTargetNs(xmlSchemaBasicItemPtr item)
1416 if (item == NULL) {
1417 return (NULL);
1419 switch (item->type) {
1420 case XML_SCHEMA_TYPE_ELEMENT:
1421 return (((xmlSchemaElementPtr) item)->targetNamespace);
1422 case XML_SCHEMA_TYPE_ATTRIBUTE:
1423 return (((xmlSchemaAttributePtr) item)->targetNamespace);
1424 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1425 return (((xmlSchemaAttributeGroupPtr) item)->targetNamespace);
1426 case XML_SCHEMA_TYPE_BASIC:
1427 return (BAD_CAST "http://www.w3.org/2001/XMLSchema");
1428 case XML_SCHEMA_TYPE_SIMPLE:
1429 case XML_SCHEMA_TYPE_COMPLEX:
1430 return (((xmlSchemaTypePtr) item)->targetNamespace);
1431 case XML_SCHEMA_TYPE_GROUP:
1432 return (((xmlSchemaModelGroupDefPtr) item)->targetNamespace);
1433 case XML_SCHEMA_TYPE_IDC_KEY:
1434 case XML_SCHEMA_TYPE_IDC_UNIQUE:
1435 case XML_SCHEMA_TYPE_IDC_KEYREF:
1436 return (((xmlSchemaIDCPtr) item)->targetNamespace);
1437 case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
1438 if (WXS_ATTRUSE_DECL(item) != NULL) {
1439 return(xmlSchemaGetComponentTargetNs(
1440 WXS_BASIC_CAST WXS_ATTRUSE_DECL(item)));
1442 /* TODO: Will returning NULL break something? */
1443 break;
1444 case XML_SCHEMA_EXTRA_QNAMEREF:
1445 return (((xmlSchemaQNameRefPtr) item)->targetNamespace);
1446 case XML_SCHEMA_TYPE_NOTATION:
1447 return (((xmlSchemaNotationPtr) item)->targetNamespace);
1448 default:
1450 * Other components cannot have names.
1452 break;
1454 return (NULL);
1457 static const xmlChar*
1458 xmlSchemaGetComponentQName(xmlChar **buf,
1459 void *item)
1461 return (xmlSchemaFormatQName(buf,
1462 xmlSchemaGetComponentTargetNs((xmlSchemaBasicItemPtr) item),
1463 xmlSchemaGetComponentName((xmlSchemaBasicItemPtr) item)));
1466 static const xmlChar*
1467 xmlSchemaGetComponentDesignation(xmlChar **buf, void *item)
1469 xmlChar *str = NULL;
1471 *buf = xmlStrcat(*buf, WXS_ITEM_TYPE_NAME(item));
1472 *buf = xmlStrcat(*buf, BAD_CAST " '");
1473 *buf = xmlStrcat(*buf, xmlSchemaGetComponentQName(&str,
1474 (xmlSchemaBasicItemPtr) item));
1475 *buf = xmlStrcat(*buf, BAD_CAST "'");
1476 FREE_AND_NULL(str);
1477 return(*buf);
1480 static const xmlChar*
1481 xmlSchemaGetIDCDesignation(xmlChar **buf, xmlSchemaIDCPtr idc)
1483 return(xmlSchemaGetComponentDesignation(buf, idc));
1487 * xmlSchemaWildcardPCToString:
1488 * @pc: the type of processContents
1490 * Returns a string representation of the type of
1491 * processContents.
1493 static const xmlChar *
1494 xmlSchemaWildcardPCToString(int pc)
1496 switch (pc) {
1497 case XML_SCHEMAS_ANY_SKIP:
1498 return (BAD_CAST "skip");
1499 case XML_SCHEMAS_ANY_LAX:
1500 return (BAD_CAST "lax");
1501 case XML_SCHEMAS_ANY_STRICT:
1502 return (BAD_CAST "strict");
1503 default:
1504 return (BAD_CAST "invalid process contents");
1509 * xmlSchemaGetCanonValueWhtspExt:
1510 * @val: the precomputed value
1511 * @retValue: the returned value
1512 * @ws: the whitespace type of the value
1513 * @for_hash: non-zero if this is supposed to generate a string for hashing
1515 * Get a the canonical representation of the value.
1516 * The caller has to free the returned retValue.
1518 * Returns 0 if the value could be built and -1 in case of
1519 * API errors or if the value type is not supported yet.
1521 static int
1522 xmlSchemaGetCanonValueWhtspExt_1(xmlSchemaValPtr val,
1523 xmlSchemaWhitespaceValueType ws,
1524 xmlChar **retValue,
1525 int for_hash)
1527 int list;
1528 xmlSchemaValType valType;
1529 const xmlChar *value, *value2 = NULL;
1532 if ((retValue == NULL) || (val == NULL))
1533 return (-1);
1534 list = xmlSchemaValueGetNext(val) ? 1 : 0;
1535 *retValue = NULL;
1536 do {
1537 value = NULL;
1538 valType = xmlSchemaGetValType(val);
1539 switch (valType) {
1540 case XML_SCHEMAS_STRING:
1541 case XML_SCHEMAS_NORMSTRING:
1542 case XML_SCHEMAS_ANYSIMPLETYPE:
1543 value = xmlSchemaValueGetAsString(val);
1544 if (value != NULL) {
1545 if (ws == XML_SCHEMA_WHITESPACE_COLLAPSE)
1546 value2 = xmlSchemaCollapseString(value);
1547 else if (ws == XML_SCHEMA_WHITESPACE_REPLACE)
1548 value2 = xmlSchemaWhiteSpaceReplace(value);
1549 if (value2 != NULL)
1550 value = value2;
1552 break;
1553 default:
1554 if (xmlSchemaGetCanonValue(val, &value2) == -1) {
1555 if (value2 != NULL)
1556 xmlFree((xmlChar *) value2);
1557 goto internal_error;
1559 if (for_hash && valType == XML_SCHEMAS_DECIMAL) {
1560 /* We can mostly use the canonical value for hashing,
1561 except in the case of decimal. There the canonical
1562 representation requires a trailing '.0' even for
1563 non-fractional numbers, but for the derived integer
1564 types it forbids any decimal point. Nevertheless they
1565 compare equal if the value is equal. We need to generate
1566 the same hash value for this to work, and it's easiest
1567 to just cut off the useless '.0' suffix for the
1568 decimal type. */
1569 int len = xmlStrlen(value2);
1570 if (len > 2 && value2[len-1] == '0' && value2[len-2] == '.')
1571 ((xmlChar*)value2)[len-2] = 0;
1573 value = value2;
1575 if (*retValue == NULL)
1576 if (value == NULL) {
1577 if (! list)
1578 *retValue = xmlStrdup(BAD_CAST "");
1579 } else
1580 *retValue = xmlStrdup(value);
1581 else if (value != NULL) {
1582 /* List. */
1583 *retValue = xmlStrcat((xmlChar *) *retValue, BAD_CAST " ");
1584 *retValue = xmlStrcat((xmlChar *) *retValue, value);
1586 FREE_AND_NULL(value2)
1587 val = xmlSchemaValueGetNext(val);
1588 } while (val != NULL);
1590 return (0);
1591 internal_error:
1592 if (*retValue != NULL)
1593 xmlFree((xmlChar *) (*retValue));
1594 if (value2 != NULL)
1595 xmlFree((xmlChar *) value2);
1596 return (-1);
1599 static int
1600 xmlSchemaGetCanonValueWhtspExt(xmlSchemaValPtr val,
1601 xmlSchemaWhitespaceValueType ws,
1602 xmlChar **retValue)
1604 return xmlSchemaGetCanonValueWhtspExt_1(val, ws, retValue, 0);
1607 static int
1608 xmlSchemaGetCanonValueHash(xmlSchemaValPtr val,
1609 xmlChar **retValue)
1611 return xmlSchemaGetCanonValueWhtspExt_1(val, XML_SCHEMA_WHITESPACE_COLLAPSE,
1612 retValue, 1);
1616 * xmlSchemaFormatItemForReport:
1617 * @buf: the string buffer
1618 * @itemDes: the designation of the item
1619 * @itemName: the name of the item
1620 * @item: the item as an object
1621 * @itemNode: the node of the item
1622 * @local: the local name
1623 * @parsing: if the function is used during the parse
1625 * Returns a representation of the given item used
1626 * for error reports.
1628 * The following order is used to build the resulting
1629 * designation if the arguments are not NULL:
1630 * 1a. If itemDes not NULL -> itemDes
1631 * 1b. If (itemDes not NULL) and (itemName not NULL)
1632 * -> itemDes + itemName
1633 * 2. If the preceding was NULL and (item not NULL) -> item
1634 * 3. If the preceding was NULL and (itemNode not NULL) -> itemNode
1636 * If the itemNode is an attribute node, the name of the attribute
1637 * will be appended to the result.
1639 * Returns the formatted string and sets @buf to the resulting value.
1641 static xmlChar*
1642 xmlSchemaFormatItemForReport(xmlChar **buf,
1643 const xmlChar *itemDes,
1644 xmlSchemaBasicItemPtr item,
1645 xmlNodePtr itemNode)
1647 xmlChar *str = NULL;
1648 int named = 1;
1650 if (*buf != NULL) {
1651 xmlFree(*buf);
1652 *buf = NULL;
1655 if (itemDes != NULL) {
1656 *buf = xmlStrdup(itemDes);
1657 } else if (item != NULL) {
1658 switch (item->type) {
1659 case XML_SCHEMA_TYPE_BASIC: {
1660 xmlSchemaTypePtr type = WXS_TYPE_CAST item;
1662 if (WXS_IS_ATOMIC(type))
1663 *buf = xmlStrdup(BAD_CAST "atomic type 'xs:");
1664 else if (WXS_IS_LIST(type))
1665 *buf = xmlStrdup(BAD_CAST "list type 'xs:");
1666 else if (WXS_IS_UNION(type))
1667 *buf = xmlStrdup(BAD_CAST "union type 'xs:");
1668 else
1669 *buf = xmlStrdup(BAD_CAST "simple type 'xs:");
1670 *buf = xmlStrcat(*buf, type->name);
1671 *buf = xmlStrcat(*buf, BAD_CAST "'");
1673 break;
1674 case XML_SCHEMA_TYPE_SIMPLE: {
1675 xmlSchemaTypePtr type = WXS_TYPE_CAST item;
1677 if (type->flags & XML_SCHEMAS_TYPE_GLOBAL) {
1678 *buf = xmlStrdup(BAD_CAST"");
1679 } else {
1680 *buf = xmlStrdup(BAD_CAST "local ");
1682 if (WXS_IS_ATOMIC(type))
1683 *buf = xmlStrcat(*buf, BAD_CAST "atomic type");
1684 else if (WXS_IS_LIST(type))
1685 *buf = xmlStrcat(*buf, BAD_CAST "list type");
1686 else if (WXS_IS_UNION(type))
1687 *buf = xmlStrcat(*buf, BAD_CAST "union type");
1688 else
1689 *buf = xmlStrcat(*buf, BAD_CAST "simple type");
1690 if (type->flags & XML_SCHEMAS_TYPE_GLOBAL) {
1691 *buf = xmlStrcat(*buf, BAD_CAST " '");
1692 *buf = xmlStrcat(*buf, type->name);
1693 *buf = xmlStrcat(*buf, BAD_CAST "'");
1696 break;
1697 case XML_SCHEMA_TYPE_COMPLEX: {
1698 xmlSchemaTypePtr type = WXS_TYPE_CAST item;
1700 if (type->flags & XML_SCHEMAS_TYPE_GLOBAL)
1701 *buf = xmlStrdup(BAD_CAST "");
1702 else
1703 *buf = xmlStrdup(BAD_CAST "local ");
1704 *buf = xmlStrcat(*buf, BAD_CAST "complex type");
1705 if (type->flags & XML_SCHEMAS_TYPE_GLOBAL) {
1706 *buf = xmlStrcat(*buf, BAD_CAST " '");
1707 *buf = xmlStrcat(*buf, type->name);
1708 *buf = xmlStrcat(*buf, BAD_CAST "'");
1711 break;
1712 case XML_SCHEMA_TYPE_ATTRIBUTE_USE: {
1713 xmlSchemaAttributeUsePtr ause;
1715 ause = WXS_ATTR_USE_CAST item;
1716 *buf = xmlStrdup(BAD_CAST "attribute use ");
1717 if (WXS_ATTRUSE_DECL(ause) != NULL) {
1718 *buf = xmlStrcat(*buf, BAD_CAST "'");
1719 *buf = xmlStrcat(*buf,
1720 xmlSchemaGetComponentQName(&str, WXS_ATTRUSE_DECL(ause)));
1721 FREE_AND_NULL(str)
1722 *buf = xmlStrcat(*buf, BAD_CAST "'");
1723 } else {
1724 *buf = xmlStrcat(*buf, BAD_CAST "(unknown)");
1727 break;
1728 case XML_SCHEMA_TYPE_ATTRIBUTE: {
1729 xmlSchemaAttributePtr attr;
1731 attr = (xmlSchemaAttributePtr) item;
1732 *buf = xmlStrdup(BAD_CAST "attribute decl.");
1733 *buf = xmlStrcat(*buf, BAD_CAST " '");
1734 *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1735 attr->targetNamespace, attr->name));
1736 FREE_AND_NULL(str)
1737 *buf = xmlStrcat(*buf, BAD_CAST "'");
1739 break;
1740 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
1741 xmlSchemaGetComponentDesignation(buf, item);
1742 break;
1743 case XML_SCHEMA_TYPE_ELEMENT: {
1744 xmlSchemaElementPtr elem;
1746 elem = (xmlSchemaElementPtr) item;
1747 *buf = xmlStrdup(BAD_CAST "element decl.");
1748 *buf = xmlStrcat(*buf, BAD_CAST " '");
1749 *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1750 elem->targetNamespace, elem->name));
1751 *buf = xmlStrcat(*buf, BAD_CAST "'");
1753 break;
1754 case XML_SCHEMA_TYPE_IDC_UNIQUE:
1755 case XML_SCHEMA_TYPE_IDC_KEY:
1756 case XML_SCHEMA_TYPE_IDC_KEYREF:
1757 if (item->type == XML_SCHEMA_TYPE_IDC_UNIQUE)
1758 *buf = xmlStrdup(BAD_CAST "unique '");
1759 else if (item->type == XML_SCHEMA_TYPE_IDC_KEY)
1760 *buf = xmlStrdup(BAD_CAST "key '");
1761 else
1762 *buf = xmlStrdup(BAD_CAST "keyRef '");
1763 *buf = xmlStrcat(*buf, ((xmlSchemaIDCPtr) item)->name);
1764 *buf = xmlStrcat(*buf, BAD_CAST "'");
1765 break;
1766 case XML_SCHEMA_TYPE_ANY:
1767 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
1768 *buf = xmlStrdup(xmlSchemaWildcardPCToString(
1769 ((xmlSchemaWildcardPtr) item)->processContents));
1770 *buf = xmlStrcat(*buf, BAD_CAST " wildcard");
1771 break;
1772 case XML_SCHEMA_FACET_MININCLUSIVE:
1773 case XML_SCHEMA_FACET_MINEXCLUSIVE:
1774 case XML_SCHEMA_FACET_MAXINCLUSIVE:
1775 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
1776 case XML_SCHEMA_FACET_TOTALDIGITS:
1777 case XML_SCHEMA_FACET_FRACTIONDIGITS:
1778 case XML_SCHEMA_FACET_PATTERN:
1779 case XML_SCHEMA_FACET_ENUMERATION:
1780 case XML_SCHEMA_FACET_WHITESPACE:
1781 case XML_SCHEMA_FACET_LENGTH:
1782 case XML_SCHEMA_FACET_MAXLENGTH:
1783 case XML_SCHEMA_FACET_MINLENGTH:
1784 *buf = xmlStrdup(BAD_CAST "facet '");
1785 *buf = xmlStrcat(*buf, xmlSchemaFacetTypeToString(item->type));
1786 *buf = xmlStrcat(*buf, BAD_CAST "'");
1787 break;
1788 case XML_SCHEMA_TYPE_GROUP: {
1789 *buf = xmlStrdup(BAD_CAST "model group def.");
1790 *buf = xmlStrcat(*buf, BAD_CAST " '");
1791 *buf = xmlStrcat(*buf, xmlSchemaGetComponentQName(&str, item));
1792 *buf = xmlStrcat(*buf, BAD_CAST "'");
1793 FREE_AND_NULL(str)
1795 break;
1796 case XML_SCHEMA_TYPE_SEQUENCE:
1797 case XML_SCHEMA_TYPE_CHOICE:
1798 case XML_SCHEMA_TYPE_ALL:
1799 case XML_SCHEMA_TYPE_PARTICLE:
1800 *buf = xmlStrdup(WXS_ITEM_TYPE_NAME(item));
1801 break;
1802 case XML_SCHEMA_TYPE_NOTATION: {
1803 *buf = xmlStrdup(WXS_ITEM_TYPE_NAME(item));
1804 *buf = xmlStrcat(*buf, BAD_CAST " '");
1805 *buf = xmlStrcat(*buf, xmlSchemaGetComponentQName(&str, item));
1806 *buf = xmlStrcat(*buf, BAD_CAST "'");
1807 FREE_AND_NULL(str);
1809 /* Falls through. */
1810 default:
1811 named = 0;
1813 } else
1814 named = 0;
1816 if ((named == 0) && (itemNode != NULL)) {
1817 xmlNodePtr elem;
1819 if (itemNode->type == XML_ATTRIBUTE_NODE)
1820 elem = itemNode->parent;
1821 else
1822 elem = itemNode;
1823 *buf = xmlStrdup(BAD_CAST "Element '");
1824 if (elem->ns != NULL) {
1825 *buf = xmlStrcat(*buf,
1826 xmlSchemaFormatQName(&str, elem->ns->href, elem->name));
1827 FREE_AND_NULL(str)
1828 } else
1829 *buf = xmlStrcat(*buf, elem->name);
1830 *buf = xmlStrcat(*buf, BAD_CAST "'");
1833 if ((itemNode != NULL) && (itemNode->type == XML_ATTRIBUTE_NODE)) {
1834 *buf = xmlStrcat(*buf, BAD_CAST ", attribute '");
1835 if (itemNode->ns != NULL) {
1836 *buf = xmlStrcat(*buf, xmlSchemaFormatQName(&str,
1837 itemNode->ns->href, itemNode->name));
1838 FREE_AND_NULL(str)
1839 } else
1840 *buf = xmlStrcat(*buf, itemNode->name);
1841 *buf = xmlStrcat(*buf, BAD_CAST "'");
1843 FREE_AND_NULL(str)
1845 return (xmlEscapeFormatString(buf));
1849 * xmlSchemaFormatFacetEnumSet:
1850 * @buf: the string buffer
1851 * @type: the type holding the enumeration facets
1853 * Builds a string consisting of all enumeration elements.
1855 * Returns a string of all enumeration elements.
1857 static const xmlChar *
1858 xmlSchemaFormatFacetEnumSet(xmlSchemaAbstractCtxtPtr actxt,
1859 xmlChar **buf, xmlSchemaTypePtr type)
1861 xmlSchemaFacetPtr facet;
1862 xmlSchemaWhitespaceValueType ws;
1863 xmlChar *value = NULL;
1864 int res, found = 0;
1866 if (*buf != NULL)
1867 xmlFree(*buf);
1868 *buf = NULL;
1870 do {
1872 * Use the whitespace type of the base type.
1874 ws = xmlSchemaGetWhiteSpaceFacetValue(type->baseType);
1875 for (facet = type->facets; facet != NULL; facet = facet->next) {
1876 if (facet->type != XML_SCHEMA_FACET_ENUMERATION)
1877 continue;
1878 found = 1;
1879 res = xmlSchemaGetCanonValueWhtspExt(facet->val,
1880 ws, &value);
1881 if (res == -1) {
1882 xmlSchemaInternalErr(actxt,
1883 "xmlSchemaFormatFacetEnumSet",
1884 "compute the canonical lexical representation");
1885 if (*buf != NULL)
1886 xmlFree(*buf);
1887 *buf = NULL;
1888 return (NULL);
1890 if (*buf == NULL)
1891 *buf = xmlStrdup(BAD_CAST "'");
1892 else
1893 *buf = xmlStrcat(*buf, BAD_CAST ", '");
1894 *buf = xmlStrcat(*buf, BAD_CAST value);
1895 *buf = xmlStrcat(*buf, BAD_CAST "'");
1896 if (value != NULL) {
1897 xmlFree((xmlChar *)value);
1898 value = NULL;
1902 * The enumeration facet of a type restricts the enumeration
1903 * facet of the ancestor type; i.e., such restricted enumerations
1904 * do not belong to the set of the given type. Thus we break
1905 * on the first found enumeration.
1907 if (found)
1908 break;
1909 type = type->baseType;
1910 } while ((type != NULL) && (type->type != XML_SCHEMA_TYPE_BASIC));
1912 return ((const xmlChar *) *buf);
1915 /************************************************************************
1917 * Error functions *
1919 ************************************************************************/
1921 #if 0
1922 static void
1923 xmlSchemaErrMemory(const char *msg)
1925 __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, NULL, NULL,
1926 msg);
1928 #endif
1930 static void
1931 xmlSchemaPSimpleErr(const char *msg)
1933 __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, NULL, NULL,
1934 msg);
1938 * xmlSchemaPErrMemory:
1939 * @node: a context node
1940 * @extra: extra information
1942 * Handle an out of memory condition
1944 static void
1945 xmlSchemaPErrMemory(xmlSchemaParserCtxtPtr ctxt,
1946 const char *extra, xmlNodePtr node)
1948 if (ctxt != NULL)
1949 ctxt->nberrors++;
1950 __xmlSimpleError(XML_FROM_SCHEMASP, XML_ERR_NO_MEMORY, node, NULL,
1951 extra);
1955 * xmlSchemaPErr:
1956 * @ctxt: the parsing context
1957 * @node: the context node
1958 * @error: the error code
1959 * @msg: the error message
1960 * @str1: extra data
1961 * @str2: extra data
1963 * Handle a parser error
1965 static void LIBXML_ATTR_FORMAT(4,0)
1966 xmlSchemaPErr(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
1967 const char *msg, const xmlChar * str1, const xmlChar * str2)
1969 xmlGenericErrorFunc channel = NULL;
1970 xmlStructuredErrorFunc schannel = NULL;
1971 void *data = NULL;
1973 if (ctxt != NULL) {
1974 ctxt->nberrors++;
1975 ctxt->err = error;
1976 channel = ctxt->error;
1977 data = ctxt->errCtxt;
1978 schannel = ctxt->serror;
1980 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
1981 error, XML_ERR_ERROR, NULL, 0,
1982 (const char *) str1, (const char *) str2, NULL, 0, 0,
1983 msg, str1, str2);
1987 * xmlSchemaPErr2:
1988 * @ctxt: the parsing context
1989 * @node: the context node
1990 * @node: the current child
1991 * @error: the error code
1992 * @msg: the error message
1993 * @str1: extra data
1994 * @str2: extra data
1996 * Handle a parser error
1998 static void LIBXML_ATTR_FORMAT(5,0)
1999 xmlSchemaPErr2(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
2000 xmlNodePtr child, int error,
2001 const char *msg, const xmlChar * str1, const xmlChar * str2)
2003 if (child != NULL)
2004 xmlSchemaPErr(ctxt, child, error, msg, str1, str2);
2005 else
2006 xmlSchemaPErr(ctxt, node, error, msg, str1, str2);
2011 * xmlSchemaPErrExt:
2012 * @ctxt: the parsing context
2013 * @node: the context node
2014 * @error: the error code
2015 * @strData1: extra data
2016 * @strData2: extra data
2017 * @strData3: extra data
2018 * @msg: the message
2019 * @str1: extra parameter for the message display
2020 * @str2: extra parameter for the message display
2021 * @str3: extra parameter for the message display
2022 * @str4: extra parameter for the message display
2023 * @str5: extra parameter for the message display
2025 * Handle a parser error
2027 static void LIBXML_ATTR_FORMAT(7,0)
2028 xmlSchemaPErrExt(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int error,
2029 const xmlChar * strData1, const xmlChar * strData2,
2030 const xmlChar * strData3, const char *msg, const xmlChar * str1,
2031 const xmlChar * str2, const xmlChar * str3, const xmlChar * str4,
2032 const xmlChar * str5)
2035 xmlGenericErrorFunc channel = NULL;
2036 xmlStructuredErrorFunc schannel = NULL;
2037 void *data = NULL;
2039 if (ctxt != NULL) {
2040 ctxt->nberrors++;
2041 ctxt->err = error;
2042 channel = ctxt->error;
2043 data = ctxt->errCtxt;
2044 schannel = ctxt->serror;
2046 __xmlRaiseError(schannel, channel, data, ctxt, node, XML_FROM_SCHEMASP,
2047 error, XML_ERR_ERROR, NULL, 0,
2048 (const char *) strData1, (const char *) strData2,
2049 (const char *) strData3, 0, 0, msg, str1, str2,
2050 str3, str4, str5);
2053 /************************************************************************
2055 * Allround error functions *
2057 ************************************************************************/
2060 * xmlSchemaVTypeErrMemory:
2061 * @node: a context node
2062 * @extra: extra information
2064 * Handle an out of memory condition
2066 static void
2067 xmlSchemaVErrMemory(xmlSchemaValidCtxtPtr ctxt,
2068 const char *extra, xmlNodePtr node)
2070 if (ctxt != NULL) {
2071 ctxt->nberrors++;
2072 ctxt->err = XML_SCHEMAV_INTERNAL;
2074 __xmlSimpleError(XML_FROM_SCHEMASV, XML_ERR_NO_MEMORY, node, NULL,
2075 extra);
2078 static void LIBXML_ATTR_FORMAT(2,0)
2079 xmlSchemaPSimpleInternalErr(xmlNodePtr node,
2080 const char *msg, const xmlChar *str)
2082 __xmlSimpleError(XML_FROM_SCHEMASP, XML_SCHEMAP_INTERNAL, node,
2083 msg, (const char *) str);
2086 #define WXS_ERROR_TYPE_ERROR 1
2087 #define WXS_ERROR_TYPE_WARNING 2
2089 * xmlSchemaErr4Line:
2090 * @ctxt: the validation context
2091 * @errorLevel: the error level
2092 * @error: the error code
2093 * @node: the context node
2094 * @line: the line number
2095 * @msg: the error message
2096 * @str1: extra data
2097 * @str2: extra data
2098 * @str3: extra data
2099 * @str4: extra data
2101 * Handle a validation error
2103 static void LIBXML_ATTR_FORMAT(6,0)
2104 xmlSchemaErr4Line(xmlSchemaAbstractCtxtPtr ctxt,
2105 xmlErrorLevel errorLevel,
2106 int error, xmlNodePtr node, int line, const char *msg,
2107 const xmlChar *str1, const xmlChar *str2,
2108 const xmlChar *str3, const xmlChar *str4)
2110 xmlStructuredErrorFunc schannel = NULL;
2111 xmlGenericErrorFunc channel = NULL;
2112 void *data = NULL;
2114 if (ctxt != NULL) {
2115 if (ctxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
2116 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctxt;
2117 const char *file = NULL;
2118 int col = 0;
2119 if (errorLevel != XML_ERR_WARNING) {
2120 vctxt->nberrors++;
2121 vctxt->err = error;
2122 channel = vctxt->error;
2123 } else {
2124 channel = vctxt->warning;
2126 schannel = vctxt->serror;
2127 data = vctxt->errCtxt;
2130 * Error node. If we specify a line number, then
2131 * do not channel any node to the error function.
2133 if (line == 0) {
2134 if ((node == NULL) &&
2135 (vctxt->depth >= 0) &&
2136 (vctxt->inode != NULL)) {
2137 node = vctxt->inode->node;
2140 * Get filename and line if no node-tree.
2142 if ((node == NULL) &&
2143 (vctxt->parserCtxt != NULL) &&
2144 (vctxt->parserCtxt->input != NULL)) {
2145 file = vctxt->parserCtxt->input->filename;
2146 line = vctxt->parserCtxt->input->line;
2147 col = vctxt->parserCtxt->input->col;
2149 } else {
2151 * Override the given node's (if any) position
2152 * and channel only the given line number.
2154 node = NULL;
2156 * Get filename.
2158 if (vctxt->doc != NULL)
2159 file = (const char *) vctxt->doc->URL;
2160 else if ((vctxt->parserCtxt != NULL) &&
2161 (vctxt->parserCtxt->input != NULL))
2162 file = vctxt->parserCtxt->input->filename;
2164 if (vctxt->locFunc != NULL) {
2165 if ((file == NULL) || (line == 0)) {
2166 unsigned long l;
2167 const char *f;
2168 vctxt->locFunc(vctxt->locCtxt, &f, &l);
2169 if (file == NULL)
2170 file = f;
2171 if (line == 0)
2172 line = (int) l;
2175 if ((file == NULL) && (vctxt->filename != NULL))
2176 file = vctxt->filename;
2178 __xmlRaiseError(schannel, channel, data, ctxt,
2179 node, XML_FROM_SCHEMASV,
2180 error, errorLevel, file, line,
2181 (const char *) str1, (const char *) str2,
2182 (const char *) str3, 0, col, msg, str1, str2, str3, str4);
2184 } else if (ctxt->type == XML_SCHEMA_CTXT_PARSER) {
2185 xmlSchemaParserCtxtPtr pctxt = (xmlSchemaParserCtxtPtr) ctxt;
2186 if (errorLevel != XML_ERR_WARNING) {
2187 pctxt->nberrors++;
2188 pctxt->err = error;
2189 channel = pctxt->error;
2190 } else {
2191 channel = pctxt->warning;
2193 schannel = pctxt->serror;
2194 data = pctxt->errCtxt;
2195 __xmlRaiseError(schannel, channel, data, ctxt,
2196 node, XML_FROM_SCHEMASP, error,
2197 errorLevel, NULL, 0,
2198 (const char *) str1, (const char *) str2,
2199 (const char *) str3, 0, 0, msg, str1, str2, str3, str4);
2200 } else {
2201 TODO
2207 * xmlSchemaErr3:
2208 * @ctxt: the validation context
2209 * @node: the context node
2210 * @error: the error code
2211 * @msg: the error message
2212 * @str1: extra data
2213 * @str2: extra data
2214 * @str3: extra data
2216 * Handle a validation error
2218 static void LIBXML_ATTR_FORMAT(4,0)
2219 xmlSchemaErr3(xmlSchemaAbstractCtxtPtr actxt,
2220 int error, xmlNodePtr node, const char *msg,
2221 const xmlChar *str1, const xmlChar *str2, const xmlChar *str3)
2223 xmlSchemaErr4Line(actxt, XML_ERR_ERROR, error, node, 0,
2224 msg, str1, str2, str3, NULL);
2227 static void LIBXML_ATTR_FORMAT(4,0)
2228 xmlSchemaErr4(xmlSchemaAbstractCtxtPtr actxt,
2229 int error, xmlNodePtr node, const char *msg,
2230 const xmlChar *str1, const xmlChar *str2,
2231 const xmlChar *str3, const xmlChar *str4)
2233 xmlSchemaErr4Line(actxt, XML_ERR_ERROR, error, node, 0,
2234 msg, str1, str2, str3, str4);
2237 static void LIBXML_ATTR_FORMAT(4,0)
2238 xmlSchemaErr(xmlSchemaAbstractCtxtPtr actxt,
2239 int error, xmlNodePtr node, const char *msg,
2240 const xmlChar *str1, const xmlChar *str2)
2242 xmlSchemaErr4(actxt, error, node, msg, str1, str2, NULL, NULL);
2245 static xmlChar *
2246 xmlSchemaFormatNodeForError(xmlChar ** msg,
2247 xmlSchemaAbstractCtxtPtr actxt,
2248 xmlNodePtr node)
2250 xmlChar *str = NULL;
2252 *msg = NULL;
2253 if ((node != NULL) &&
2254 (node->type != XML_ELEMENT_NODE) &&
2255 (node->type != XML_ATTRIBUTE_NODE))
2258 * Don't try to format other nodes than element and
2259 * attribute nodes.
2260 * Play safe and return an empty string.
2262 *msg = xmlStrdup(BAD_CAST "");
2263 return(*msg);
2265 if (node != NULL) {
2267 * Work on tree nodes.
2269 if (node->type == XML_ATTRIBUTE_NODE) {
2270 xmlNodePtr elem = node->parent;
2272 *msg = xmlStrdup(BAD_CAST "Element '");
2273 if (elem->ns != NULL)
2274 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2275 elem->ns->href, elem->name));
2276 else
2277 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2278 NULL, elem->name));
2279 FREE_AND_NULL(str);
2280 *msg = xmlStrcat(*msg, BAD_CAST "', ");
2281 *msg = xmlStrcat(*msg, BAD_CAST "attribute '");
2282 } else {
2283 *msg = xmlStrdup(BAD_CAST "Element '");
2285 if (node->ns != NULL)
2286 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2287 node->ns->href, node->name));
2288 else
2289 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2290 NULL, node->name));
2291 FREE_AND_NULL(str);
2292 *msg = xmlStrcat(*msg, BAD_CAST "': ");
2293 } else if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
2294 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) actxt;
2296 * Work on node infos.
2298 if (vctxt->inode->nodeType == XML_ATTRIBUTE_NODE) {
2299 xmlSchemaNodeInfoPtr ielem =
2300 vctxt->elemInfos[vctxt->depth];
2302 *msg = xmlStrdup(BAD_CAST "Element '");
2303 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2304 ielem->nsName, ielem->localName));
2305 FREE_AND_NULL(str);
2306 *msg = xmlStrcat(*msg, BAD_CAST "', ");
2307 *msg = xmlStrcat(*msg, BAD_CAST "attribute '");
2308 } else {
2309 *msg = xmlStrdup(BAD_CAST "Element '");
2311 *msg = xmlStrcat(*msg, xmlSchemaFormatQName(&str,
2312 vctxt->inode->nsName, vctxt->inode->localName));
2313 FREE_AND_NULL(str);
2314 *msg = xmlStrcat(*msg, BAD_CAST "': ");
2315 } else if (actxt->type == XML_SCHEMA_CTXT_PARSER) {
2317 * Hmm, no node while parsing?
2318 * Return an empty string, in case NULL will break something.
2320 *msg = xmlStrdup(BAD_CAST "");
2321 } else {
2322 TODO
2323 return (NULL);
2327 * xmlSchemaFormatItemForReport() also returns an escaped format
2328 * string, so do this before calling it below (in the future).
2330 xmlEscapeFormatString(msg);
2333 * VAL TODO: The output of the given schema component is currently
2334 * disabled.
2336 #if 0
2337 if ((type != NULL) && (xmlSchemaIsGlobalItem(type))) {
2338 *msg = xmlStrcat(*msg, BAD_CAST " [");
2339 *msg = xmlStrcat(*msg, xmlSchemaFormatItemForReport(&str,
2340 NULL, type, NULL, 0));
2341 FREE_AND_NULL(str)
2342 *msg = xmlStrcat(*msg, BAD_CAST "]");
2344 #endif
2345 return (*msg);
2348 static void LIBXML_ATTR_FORMAT(3,0)
2349 xmlSchemaInternalErr2(xmlSchemaAbstractCtxtPtr actxt,
2350 const char *funcName,
2351 const char *message,
2352 const xmlChar *str1,
2353 const xmlChar *str2)
2355 xmlChar *msg = NULL;
2357 if (actxt == NULL)
2358 return;
2359 msg = xmlStrdup(BAD_CAST "Internal error: %s, ");
2360 msg = xmlStrcat(msg, BAD_CAST message);
2361 msg = xmlStrcat(msg, BAD_CAST ".\n");
2363 if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR)
2364 xmlSchemaErr3(actxt, XML_SCHEMAV_INTERNAL, NULL,
2365 (const char *) msg, (const xmlChar *) funcName, str1, str2);
2366 else if (actxt->type == XML_SCHEMA_CTXT_PARSER)
2367 xmlSchemaErr3(actxt, XML_SCHEMAP_INTERNAL, NULL,
2368 (const char *) msg, (const xmlChar *) funcName, str1, str2);
2370 FREE_AND_NULL(msg)
2373 static void LIBXML_ATTR_FORMAT(3,0)
2374 xmlSchemaInternalErr(xmlSchemaAbstractCtxtPtr actxt,
2375 const char *funcName,
2376 const char *message)
2378 xmlSchemaInternalErr2(actxt, funcName, message, NULL, NULL);
2381 #if 0
2382 static void LIBXML_ATTR_FORMAT(3,0)
2383 xmlSchemaPInternalErr(xmlSchemaParserCtxtPtr pctxt,
2384 const char *funcName,
2385 const char *message,
2386 const xmlChar *str1,
2387 const xmlChar *str2)
2389 xmlSchemaInternalErr2(ACTXT_CAST pctxt, funcName, message,
2390 str1, str2);
2392 #endif
2394 static void LIBXML_ATTR_FORMAT(5,0)
2395 xmlSchemaCustomErr4(xmlSchemaAbstractCtxtPtr actxt,
2396 xmlParserErrors error,
2397 xmlNodePtr node,
2398 xmlSchemaBasicItemPtr item,
2399 const char *message,
2400 const xmlChar *str1, const xmlChar *str2,
2401 const xmlChar *str3, const xmlChar *str4)
2403 xmlChar *msg = NULL;
2405 if ((node == NULL) && (item != NULL) &&
2406 (actxt->type == XML_SCHEMA_CTXT_PARSER)) {
2407 node = WXS_ITEM_NODE(item);
2408 xmlSchemaFormatItemForReport(&msg, NULL, item, NULL);
2409 msg = xmlStrcat(msg, BAD_CAST ": ");
2410 } else
2411 xmlSchemaFormatNodeForError(&msg, actxt, node);
2412 msg = xmlStrcat(msg, (const xmlChar *) message);
2413 msg = xmlStrcat(msg, BAD_CAST ".\n");
2414 xmlSchemaErr4(actxt, error, node,
2415 (const char *) msg, str1, str2, str3, str4);
2416 FREE_AND_NULL(msg)
2419 static void LIBXML_ATTR_FORMAT(5,0)
2420 xmlSchemaCustomErr(xmlSchemaAbstractCtxtPtr actxt,
2421 xmlParserErrors error,
2422 xmlNodePtr node,
2423 xmlSchemaBasicItemPtr item,
2424 const char *message,
2425 const xmlChar *str1,
2426 const xmlChar *str2)
2428 xmlSchemaCustomErr4(actxt, error, node, item,
2429 message, str1, str2, NULL, NULL);
2434 static void LIBXML_ATTR_FORMAT(5,0)
2435 xmlSchemaCustomWarning(xmlSchemaAbstractCtxtPtr actxt,
2436 xmlParserErrors error,
2437 xmlNodePtr node,
2438 xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
2439 const char *message,
2440 const xmlChar *str1,
2441 const xmlChar *str2,
2442 const xmlChar *str3)
2444 xmlChar *msg = NULL;
2446 xmlSchemaFormatNodeForError(&msg, actxt, node);
2447 msg = xmlStrcat(msg, (const xmlChar *) message);
2448 msg = xmlStrcat(msg, BAD_CAST ".\n");
2450 /* URGENT TODO: Set the error code to something sane. */
2451 xmlSchemaErr4Line(actxt, XML_ERR_WARNING, error, node, 0,
2452 (const char *) msg, str1, str2, str3, NULL);
2454 FREE_AND_NULL(msg)
2459 static void LIBXML_ATTR_FORMAT(5,0)
2460 xmlSchemaKeyrefErr(xmlSchemaValidCtxtPtr vctxt,
2461 xmlParserErrors error,
2462 xmlSchemaPSVIIDCNodePtr idcNode,
2463 xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
2464 const char *message,
2465 const xmlChar *str1,
2466 const xmlChar *str2)
2468 xmlChar *msg = NULL, *qname = NULL;
2470 msg = xmlStrdup(BAD_CAST "Element '%s': ");
2471 msg = xmlStrcat(msg, (const xmlChar *) message);
2472 msg = xmlStrcat(msg, BAD_CAST ".\n");
2473 xmlSchemaErr4Line(ACTXT_CAST vctxt, XML_ERR_ERROR,
2474 error, NULL, idcNode->nodeLine, (const char *) msg,
2475 xmlSchemaFormatQName(&qname,
2476 vctxt->nodeQNames->items[idcNode->nodeQNameID +1],
2477 vctxt->nodeQNames->items[idcNode->nodeQNameID]),
2478 str1, str2, NULL);
2479 FREE_AND_NULL(qname);
2480 FREE_AND_NULL(msg);
2483 static int
2484 xmlSchemaEvalErrorNodeType(xmlSchemaAbstractCtxtPtr actxt,
2485 xmlNodePtr node)
2487 if (node != NULL)
2488 return (node->type);
2489 if ((actxt->type == XML_SCHEMA_CTXT_VALIDATOR) &&
2490 (((xmlSchemaValidCtxtPtr) actxt)->inode != NULL))
2491 return ( ((xmlSchemaValidCtxtPtr) actxt)->inode->nodeType);
2492 return (-1);
2495 static int
2496 xmlSchemaIsGlobalItem(xmlSchemaTypePtr item)
2498 switch (item->type) {
2499 case XML_SCHEMA_TYPE_COMPLEX:
2500 case XML_SCHEMA_TYPE_SIMPLE:
2501 if (item->flags & XML_SCHEMAS_TYPE_GLOBAL)
2502 return(1);
2503 break;
2504 case XML_SCHEMA_TYPE_GROUP:
2505 return (1);
2506 case XML_SCHEMA_TYPE_ELEMENT:
2507 if ( ((xmlSchemaElementPtr) item)->flags &
2508 XML_SCHEMAS_ELEM_GLOBAL)
2509 return(1);
2510 break;
2511 case XML_SCHEMA_TYPE_ATTRIBUTE:
2512 if ( ((xmlSchemaAttributePtr) item)->flags &
2513 XML_SCHEMAS_ATTR_GLOBAL)
2514 return(1);
2515 break;
2516 /* Note that attribute groups are always global. */
2517 default:
2518 return(1);
2520 return (0);
2523 static void
2524 xmlSchemaSimpleTypeErr(xmlSchemaAbstractCtxtPtr actxt,
2525 xmlParserErrors error,
2526 xmlNodePtr node,
2527 const xmlChar *value,
2528 xmlSchemaTypePtr type,
2529 int displayValue)
2531 xmlChar *msg = NULL;
2533 xmlSchemaFormatNodeForError(&msg, actxt, node);
2535 if (displayValue || (xmlSchemaEvalErrorNodeType(actxt, node) ==
2536 XML_ATTRIBUTE_NODE))
2537 msg = xmlStrcat(msg, BAD_CAST "'%s' is not a valid value of ");
2538 else
2539 msg = xmlStrcat(msg, BAD_CAST "The character content is not a valid "
2540 "value of ");
2542 if (! xmlSchemaIsGlobalItem(type))
2543 msg = xmlStrcat(msg, BAD_CAST "the local ");
2544 else
2545 msg = xmlStrcat(msg, BAD_CAST "the ");
2547 if (WXS_IS_ATOMIC(type))
2548 msg = xmlStrcat(msg, BAD_CAST "atomic type");
2549 else if (WXS_IS_LIST(type))
2550 msg = xmlStrcat(msg, BAD_CAST "list type");
2551 else if (WXS_IS_UNION(type))
2552 msg = xmlStrcat(msg, BAD_CAST "union type");
2554 if (xmlSchemaIsGlobalItem(type)) {
2555 xmlChar *str = NULL;
2556 msg = xmlStrcat(msg, BAD_CAST " '");
2557 if (type->builtInType != 0) {
2558 msg = xmlStrcat(msg, BAD_CAST "xs:");
2559 str = xmlStrdup(type->name);
2560 } else {
2561 const xmlChar *qName = xmlSchemaFormatQName(&str, type->targetNamespace, type->name);
2562 if (!str)
2563 str = xmlStrdup(qName);
2565 msg = xmlStrcat(msg, xmlEscapeFormatString(&str));
2566 msg = xmlStrcat(msg, BAD_CAST "'");
2567 FREE_AND_NULL(str);
2569 msg = xmlStrcat(msg, BAD_CAST ".\n");
2570 if (displayValue || (xmlSchemaEvalErrorNodeType(actxt, node) ==
2571 XML_ATTRIBUTE_NODE))
2572 xmlSchemaErr(actxt, error, node, (const char *) msg, value, NULL);
2573 else
2574 xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
2575 FREE_AND_NULL(msg)
2578 static const xmlChar *
2579 xmlSchemaFormatErrorNodeQName(xmlChar ** str,
2580 xmlSchemaNodeInfoPtr ni,
2581 xmlNodePtr node)
2583 if (node != NULL) {
2584 if (node->ns != NULL)
2585 return (xmlSchemaFormatQName(str, node->ns->href, node->name));
2586 else
2587 return (xmlSchemaFormatQName(str, NULL, node->name));
2588 } else if (ni != NULL)
2589 return (xmlSchemaFormatQName(str, ni->nsName, ni->localName));
2590 return (NULL);
2593 static void
2594 xmlSchemaIllegalAttrErr(xmlSchemaAbstractCtxtPtr actxt,
2595 xmlParserErrors error,
2596 xmlSchemaAttrInfoPtr ni,
2597 xmlNodePtr node)
2599 xmlChar *msg = NULL, *str = NULL;
2601 xmlSchemaFormatNodeForError(&msg, actxt, node);
2602 msg = xmlStrcat(msg, BAD_CAST "The attribute '%s' is not allowed.\n");
2603 xmlSchemaErr(actxt, error, node, (const char *) msg,
2604 xmlSchemaFormatErrorNodeQName(&str, (xmlSchemaNodeInfoPtr) ni, node),
2605 NULL);
2606 FREE_AND_NULL(str)
2607 FREE_AND_NULL(msg)
2610 static void LIBXML_ATTR_FORMAT(5,0)
2611 xmlSchemaComplexTypeErr(xmlSchemaAbstractCtxtPtr actxt,
2612 xmlParserErrors error,
2613 xmlNodePtr node,
2614 xmlSchemaTypePtr type ATTRIBUTE_UNUSED,
2615 const char *message,
2616 int nbval,
2617 int nbneg,
2618 xmlChar **values)
2620 xmlChar *str = NULL, *msg = NULL;
2621 xmlChar *localName, *nsName;
2622 const xmlChar *cur, *end;
2623 int i;
2625 xmlSchemaFormatNodeForError(&msg, actxt, node);
2626 msg = xmlStrcat(msg, (const xmlChar *) message);
2627 msg = xmlStrcat(msg, BAD_CAST ".");
2629 * Note that is does not make sense to report that we have a
2630 * wildcard here, since the wildcard might be unfolded into
2631 * multiple transitions.
2633 if (nbval + nbneg > 0) {
2634 if (nbval + nbneg > 1) {
2635 str = xmlStrdup(BAD_CAST " Expected is one of ( ");
2636 } else
2637 str = xmlStrdup(BAD_CAST " Expected is ( ");
2638 nsName = NULL;
2640 for (i = 0; i < nbval + nbneg; i++) {
2641 cur = values[i];
2642 if (cur == NULL)
2643 continue;
2644 if ((cur[0] == 'n') && (cur[1] == 'o') && (cur[2] == 't') &&
2645 (cur[3] == ' ')) {
2646 cur += 4;
2647 str = xmlStrcat(str, BAD_CAST "##other");
2650 * Get the local name.
2652 localName = NULL;
2654 end = cur;
2655 if (*end == '*') {
2656 localName = xmlStrdup(BAD_CAST "*");
2657 end++;
2658 } else {
2659 while ((*end != 0) && (*end != '|'))
2660 end++;
2661 localName = xmlStrncat(localName, BAD_CAST cur, end - cur);
2663 if (*end != 0) {
2664 end++;
2666 * Skip "*|*" if they come with negated expressions, since
2667 * they represent the same negated wildcard.
2669 if ((nbneg == 0) || (*end != '*') || (*localName != '*')) {
2671 * Get the namespace name.
2673 cur = end;
2674 if (*end == '*') {
2675 nsName = xmlStrdup(BAD_CAST "{*}");
2676 } else {
2677 while (*end != 0)
2678 end++;
2680 if (i >= nbval)
2681 nsName = xmlStrdup(BAD_CAST "{##other:");
2682 else
2683 nsName = xmlStrdup(BAD_CAST "{");
2685 nsName = xmlStrncat(nsName, BAD_CAST cur, end - cur);
2686 nsName = xmlStrcat(nsName, BAD_CAST "}");
2688 str = xmlStrcat(str, BAD_CAST nsName);
2689 FREE_AND_NULL(nsName)
2690 } else {
2691 FREE_AND_NULL(localName);
2692 continue;
2695 str = xmlStrcat(str, BAD_CAST localName);
2696 FREE_AND_NULL(localName);
2698 if (i < nbval + nbneg -1)
2699 str = xmlStrcat(str, BAD_CAST ", ");
2701 str = xmlStrcat(str, BAD_CAST " ).\n");
2702 msg = xmlStrcat(msg, xmlEscapeFormatString(&str));
2703 FREE_AND_NULL(str)
2704 } else
2705 msg = xmlStrcat(msg, BAD_CAST "\n");
2706 xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
2707 xmlFree(msg);
2710 static void LIBXML_ATTR_FORMAT(8,0)
2711 xmlSchemaFacetErr(xmlSchemaAbstractCtxtPtr actxt,
2712 xmlParserErrors error,
2713 xmlNodePtr node,
2714 const xmlChar *value,
2715 unsigned long length,
2716 xmlSchemaTypePtr type,
2717 xmlSchemaFacetPtr facet,
2718 const char *message,
2719 const xmlChar *str1,
2720 const xmlChar *str2)
2722 xmlChar *str = NULL, *msg = NULL;
2723 xmlSchemaTypeType facetType;
2724 int nodeType = xmlSchemaEvalErrorNodeType(actxt, node);
2726 xmlSchemaFormatNodeForError(&msg, actxt, node);
2727 if (error == XML_SCHEMAV_CVC_ENUMERATION_VALID) {
2728 facetType = XML_SCHEMA_FACET_ENUMERATION;
2730 * If enumerations are validated, one must not expect the
2731 * facet to be given.
2733 } else
2734 facetType = facet->type;
2735 msg = xmlStrcat(msg, BAD_CAST "[");
2736 msg = xmlStrcat(msg, BAD_CAST "facet '");
2737 msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facetType));
2738 msg = xmlStrcat(msg, BAD_CAST "'] ");
2739 if (message == NULL) {
2741 * Use a default message.
2743 if ((facetType == XML_SCHEMA_FACET_LENGTH) ||
2744 (facetType == XML_SCHEMA_FACET_MINLENGTH) ||
2745 (facetType == XML_SCHEMA_FACET_MAXLENGTH)) {
2747 char len[25], actLen[25];
2749 /* FIXME, TODO: What is the max expected string length of the
2750 * this value?
2752 if (nodeType == XML_ATTRIBUTE_NODE)
2753 msg = xmlStrcat(msg, BAD_CAST "The value '%s' has a length of '%s'; ");
2754 else
2755 msg = xmlStrcat(msg, BAD_CAST "The value has a length of '%s'; ");
2757 snprintf(len, 24, "%lu", xmlSchemaGetFacetValueAsULong(facet));
2758 snprintf(actLen, 24, "%lu", length);
2760 if (facetType == XML_SCHEMA_FACET_LENGTH)
2761 msg = xmlStrcat(msg,
2762 BAD_CAST "this differs from the allowed length of '%s'.\n");
2763 else if (facetType == XML_SCHEMA_FACET_MAXLENGTH)
2764 msg = xmlStrcat(msg,
2765 BAD_CAST "this exceeds the allowed maximum length of '%s'.\n");
2766 else if (facetType == XML_SCHEMA_FACET_MINLENGTH)
2767 msg = xmlStrcat(msg,
2768 BAD_CAST "this underruns the allowed minimum length of '%s'.\n");
2770 if (nodeType == XML_ATTRIBUTE_NODE)
2771 xmlSchemaErr3(actxt, error, node, (const char *) msg,
2772 value, (const xmlChar *) actLen, (const xmlChar *) len);
2773 else
2774 xmlSchemaErr(actxt, error, node, (const char *) msg,
2775 (const xmlChar *) actLen, (const xmlChar *) len);
2777 } else if (facetType == XML_SCHEMA_FACET_ENUMERATION) {
2778 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not an element "
2779 "of the set {%s}.\n");
2780 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2781 xmlSchemaFormatFacetEnumSet(actxt, &str, type));
2782 } else if (facetType == XML_SCHEMA_FACET_PATTERN) {
2783 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not accepted "
2784 "by the pattern '%s'.\n");
2785 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2786 facet->value);
2787 } else if (facetType == XML_SCHEMA_FACET_MININCLUSIVE) {
2788 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is less than the "
2789 "minimum value allowed ('%s').\n");
2790 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2791 facet->value);
2792 } else if (facetType == XML_SCHEMA_FACET_MAXINCLUSIVE) {
2793 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is greater than the "
2794 "maximum value allowed ('%s').\n");
2795 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2796 facet->value);
2797 } else if (facetType == XML_SCHEMA_FACET_MINEXCLUSIVE) {
2798 msg = xmlStrcat(msg, BAD_CAST "The value '%s' must be greater than "
2799 "'%s'.\n");
2800 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2801 facet->value);
2802 } else if (facetType == XML_SCHEMA_FACET_MAXEXCLUSIVE) {
2803 msg = xmlStrcat(msg, BAD_CAST "The value '%s' must be less than "
2804 "'%s'.\n");
2805 xmlSchemaErr(actxt, error, node, (const char *) msg, value,
2806 facet->value);
2807 } else if (facetType == XML_SCHEMA_FACET_TOTALDIGITS) {
2808 msg = xmlStrcat(msg, BAD_CAST "The value '%s' has more "
2809 "digits than are allowed ('%s').\n");
2810 xmlSchemaErr(actxt, error, node, (const char*) msg, value,
2811 facet->value);
2812 } else if (facetType == XML_SCHEMA_FACET_FRACTIONDIGITS) {
2813 msg = xmlStrcat(msg, BAD_CAST "The value '%s' has more fractional "
2814 "digits than are allowed ('%s').\n");
2815 xmlSchemaErr(actxt, error, node, (const char*) msg, value,
2816 facet->value);
2817 } else if (nodeType == XML_ATTRIBUTE_NODE) {
2818 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not facet-valid.\n");
2819 xmlSchemaErr(actxt, error, node, (const char *) msg, value, NULL);
2820 } else {
2821 msg = xmlStrcat(msg, BAD_CAST "The value is not facet-valid.\n");
2822 xmlSchemaErr(actxt, error, node, (const char *) msg, NULL, NULL);
2824 } else {
2825 msg = xmlStrcat(msg, (const xmlChar *) message);
2826 msg = xmlStrcat(msg, BAD_CAST ".\n");
2827 xmlSchemaErr(actxt, error, node, (const char *) msg, str1, str2);
2829 FREE_AND_NULL(str)
2830 xmlFree(msg);
2833 #define VERROR(err, type, msg) \
2834 xmlSchemaCustomErr(ACTXT_CAST vctxt, err, NULL, type, msg, NULL, NULL);
2836 #define VERROR_INT(func, msg) xmlSchemaInternalErr(ACTXT_CAST vctxt, func, msg);
2838 #define PERROR_INT(func, msg) xmlSchemaInternalErr(ACTXT_CAST pctxt, func, msg);
2839 #define PERROR_INT2(func, msg) xmlSchemaInternalErr(ACTXT_CAST ctxt, func, msg);
2841 #define AERROR_INT(func, msg) xmlSchemaInternalErr(actxt, func, msg);
2845 * xmlSchemaPMissingAttrErr:
2846 * @ctxt: the schema validation context
2847 * @ownerItem: the owner as a schema object
2848 * @ownerElem: the owner as an element node
2849 * @node: the parent element node of the missing attribute node
2850 * @type: the corresponding type of the attribute node
2852 * Reports an illegal attribute.
2854 static void
2855 xmlSchemaPMissingAttrErr(xmlSchemaParserCtxtPtr ctxt,
2856 xmlParserErrors error,
2857 xmlSchemaBasicItemPtr ownerItem,
2858 xmlNodePtr ownerElem,
2859 const char *name,
2860 const char *message)
2862 xmlChar *des = NULL;
2864 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
2866 if (message != NULL)
2867 xmlSchemaPErr(ctxt, ownerElem, error, "%s: %s.\n", BAD_CAST des, BAD_CAST message);
2868 else
2869 xmlSchemaPErr(ctxt, ownerElem, error,
2870 "%s: The attribute '%s' is required but missing.\n",
2871 BAD_CAST des, BAD_CAST name);
2872 FREE_AND_NULL(des);
2877 * xmlSchemaPResCompAttrErr:
2878 * @ctxt: the schema validation context
2879 * @error: the error code
2880 * @ownerItem: the owner as a schema object
2881 * @ownerElem: the owner as an element node
2882 * @name: the name of the attribute holding the QName
2883 * @refName: the referenced local name
2884 * @refURI: the referenced namespace URI
2885 * @message: optional message
2887 * Used to report QName attribute values that failed to resolve
2888 * to schema components.
2890 static void
2891 xmlSchemaPResCompAttrErr(xmlSchemaParserCtxtPtr ctxt,
2892 xmlParserErrors error,
2893 xmlSchemaBasicItemPtr ownerItem,
2894 xmlNodePtr ownerElem,
2895 const char *name,
2896 const xmlChar *refName,
2897 const xmlChar *refURI,
2898 xmlSchemaTypeType refType,
2899 const char *refTypeStr)
2901 xmlChar *des = NULL, *strA = NULL;
2903 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
2904 if (refTypeStr == NULL)
2905 refTypeStr = (const char *) xmlSchemaItemTypeToStr(refType);
2906 xmlSchemaPErrExt(ctxt, ownerElem, error,
2907 NULL, NULL, NULL,
2908 "%s, attribute '%s': The QName value '%s' does not resolve to a(n) "
2909 "%s.\n", BAD_CAST des, BAD_CAST name,
2910 xmlSchemaFormatQName(&strA, refURI, refName),
2911 BAD_CAST refTypeStr, NULL);
2912 FREE_AND_NULL(des)
2913 FREE_AND_NULL(strA)
2917 * xmlSchemaPCustomAttrErr:
2918 * @ctxt: the schema parser context
2919 * @error: the error code
2920 * @ownerDes: the designation of the owner
2921 * @ownerItem: the owner as a schema object
2922 * @attr: the illegal attribute node
2924 * Reports an illegal attribute during the parse.
2926 static void
2927 xmlSchemaPCustomAttrErr(xmlSchemaParserCtxtPtr ctxt,
2928 xmlParserErrors error,
2929 xmlChar **ownerDes,
2930 xmlSchemaBasicItemPtr ownerItem,
2931 xmlAttrPtr attr,
2932 const char *msg)
2934 xmlChar *des = NULL;
2936 if (ownerDes == NULL)
2937 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, attr->parent);
2938 else if (*ownerDes == NULL) {
2939 xmlSchemaFormatItemForReport(ownerDes, NULL, ownerItem, attr->parent);
2940 des = *ownerDes;
2941 } else
2942 des = *ownerDes;
2943 if (attr == NULL) {
2944 xmlSchemaPErrExt(ctxt, NULL, error, NULL, NULL, NULL,
2945 "%s, attribute '%s': %s.\n",
2946 BAD_CAST des, (const xmlChar *) "Unknown",
2947 (const xmlChar *) msg, NULL, NULL);
2948 } else {
2949 xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
2950 "%s, attribute '%s': %s.\n",
2951 BAD_CAST des, attr->name, (const xmlChar *) msg, NULL, NULL);
2953 if (ownerDes == NULL)
2954 FREE_AND_NULL(des);
2958 * xmlSchemaPIllegalAttrErr:
2959 * @ctxt: the schema parser context
2960 * @error: the error code
2961 * @ownerItem: the attribute's owner item
2962 * @attr: the illegal attribute node
2964 * Reports an illegal attribute during the parse.
2966 static void
2967 xmlSchemaPIllegalAttrErr(xmlSchemaParserCtxtPtr ctxt,
2968 xmlParserErrors error,
2969 xmlSchemaBasicItemPtr ownerComp ATTRIBUTE_UNUSED,
2970 xmlAttrPtr attr)
2972 xmlChar *strA = NULL, *strB = NULL;
2974 xmlSchemaFormatNodeForError(&strA, ACTXT_CAST ctxt, attr->parent);
2975 xmlSchemaErr4(ACTXT_CAST ctxt, error, (xmlNodePtr) attr,
2976 "%sThe attribute '%s' is not allowed.\n", BAD_CAST strA,
2977 xmlSchemaFormatQNameNs(&strB, attr->ns, attr->name),
2978 NULL, NULL);
2979 FREE_AND_NULL(strA);
2980 FREE_AND_NULL(strB);
2984 * xmlSchemaPCustomErr:
2985 * @ctxt: the schema parser context
2986 * @error: the error code
2987 * @itemDes: the designation of the schema item
2988 * @item: the schema item
2989 * @itemElem: the node of the schema item
2990 * @message: the error message
2991 * @str1: an optional param for the error message
2992 * @str2: an optional param for the error message
2993 * @str3: an optional param for the error message
2995 * Reports an error during parsing.
2997 static void LIBXML_ATTR_FORMAT(5,0)
2998 xmlSchemaPCustomErrExt(xmlSchemaParserCtxtPtr ctxt,
2999 xmlParserErrors error,
3000 xmlSchemaBasicItemPtr item,
3001 xmlNodePtr itemElem,
3002 const char *message,
3003 const xmlChar *str1,
3004 const xmlChar *str2,
3005 const xmlChar *str3)
3007 xmlChar *des = NULL, *msg = NULL;
3009 xmlSchemaFormatItemForReport(&des, NULL, item, itemElem);
3010 msg = xmlStrdup(BAD_CAST "%s: ");
3011 msg = xmlStrcat(msg, (const xmlChar *) message);
3012 msg = xmlStrcat(msg, BAD_CAST ".\n");
3013 if ((itemElem == NULL) && (item != NULL))
3014 itemElem = WXS_ITEM_NODE(item);
3015 xmlSchemaPErrExt(ctxt, itemElem, error, NULL, NULL, NULL,
3016 (const char *) msg, BAD_CAST des, str1, str2, str3, NULL);
3017 FREE_AND_NULL(des);
3018 FREE_AND_NULL(msg);
3022 * xmlSchemaPCustomErr:
3023 * @ctxt: the schema parser context
3024 * @error: the error code
3025 * @itemDes: the designation of the schema item
3026 * @item: the schema item
3027 * @itemElem: the node of the schema item
3028 * @message: the error message
3029 * @str1: the optional param for the error message
3031 * Reports an error during parsing.
3033 static void LIBXML_ATTR_FORMAT(5,0)
3034 xmlSchemaPCustomErr(xmlSchemaParserCtxtPtr ctxt,
3035 xmlParserErrors error,
3036 xmlSchemaBasicItemPtr item,
3037 xmlNodePtr itemElem,
3038 const char *message,
3039 const xmlChar *str1)
3041 xmlSchemaPCustomErrExt(ctxt, error, item, itemElem, message,
3042 str1, NULL, NULL);
3046 * xmlSchemaPAttrUseErr:
3047 * @ctxt: the schema parser context
3048 * @error: the error code
3049 * @itemDes: the designation of the schema type
3050 * @item: the schema type
3051 * @itemElem: the node of the schema type
3052 * @attr: the invalid schema attribute
3053 * @message: the error message
3054 * @str1: the optional param for the error message
3056 * Reports an attribute use error during parsing.
3058 static void LIBXML_ATTR_FORMAT(6,0)
3059 xmlSchemaPAttrUseErr4(xmlSchemaParserCtxtPtr ctxt,
3060 xmlParserErrors error,
3061 xmlNodePtr node,
3062 xmlSchemaBasicItemPtr ownerItem,
3063 const xmlSchemaAttributeUsePtr attruse,
3064 const char *message,
3065 const xmlChar *str1, const xmlChar *str2,
3066 const xmlChar *str3,const xmlChar *str4)
3068 xmlChar *str = NULL, *msg = NULL;
3070 xmlSchemaFormatItemForReport(&msg, NULL, ownerItem, NULL);
3071 msg = xmlStrcat(msg, BAD_CAST ", ");
3072 msg = xmlStrcat(msg,
3073 BAD_CAST xmlSchemaFormatItemForReport(&str, NULL,
3074 WXS_BASIC_CAST attruse, NULL));
3075 FREE_AND_NULL(str);
3076 msg = xmlStrcat(msg, BAD_CAST ": ");
3077 msg = xmlStrcat(msg, (const xmlChar *) message);
3078 msg = xmlStrcat(msg, BAD_CAST ".\n");
3079 xmlSchemaErr4(ACTXT_CAST ctxt, error, node,
3080 (const char *) msg, str1, str2, str3, str4);
3081 xmlFree(msg);
3085 * xmlSchemaPIllegalFacetAtomicErr:
3086 * @ctxt: the schema parser context
3087 * @error: the error code
3088 * @type: the schema type
3089 * @baseType: the base type of type
3090 * @facet: the illegal facet
3092 * Reports an illegal facet for atomic simple types.
3094 static void
3095 xmlSchemaPIllegalFacetAtomicErr(xmlSchemaParserCtxtPtr ctxt,
3096 xmlParserErrors error,
3097 xmlSchemaTypePtr type,
3098 xmlSchemaTypePtr baseType,
3099 xmlSchemaFacetPtr facet)
3101 xmlChar *des = NULL, *strT = NULL;
3103 xmlSchemaFormatItemForReport(&des, NULL, WXS_BASIC_CAST type, type->node);
3104 xmlSchemaPErrExt(ctxt, type->node, error, NULL, NULL, NULL,
3105 "%s: The facet '%s' is not allowed on types derived from the "
3106 "type %s.\n",
3107 BAD_CAST des, xmlSchemaFacetTypeToString(facet->type),
3108 xmlSchemaFormatItemForReport(&strT, NULL, WXS_BASIC_CAST baseType, NULL),
3109 NULL, NULL);
3110 FREE_AND_NULL(des);
3111 FREE_AND_NULL(strT);
3115 * xmlSchemaPIllegalFacetListUnionErr:
3116 * @ctxt: the schema parser context
3117 * @error: the error code
3118 * @itemDes: the designation of the schema item involved
3119 * @item: the schema item involved
3120 * @facet: the illegal facet
3122 * Reports an illegal facet for <list> and <union>.
3124 static void
3125 xmlSchemaPIllegalFacetListUnionErr(xmlSchemaParserCtxtPtr ctxt,
3126 xmlParserErrors error,
3127 xmlSchemaTypePtr type,
3128 xmlSchemaFacetPtr facet)
3130 xmlChar *des = NULL;
3132 xmlSchemaFormatItemForReport(&des, NULL, WXS_BASIC_CAST type,
3133 type->node);
3134 xmlSchemaPErr(ctxt, type->node, error,
3135 "%s: The facet '%s' is not allowed.\n",
3136 BAD_CAST des, xmlSchemaFacetTypeToString(facet->type));
3137 FREE_AND_NULL(des);
3141 * xmlSchemaPMutualExclAttrErr:
3142 * @ctxt: the schema validation context
3143 * @error: the error code
3144 * @elemDes: the designation of the parent element node
3145 * @attr: the bad attribute node
3146 * @type: the corresponding type of the attribute node
3148 * Reports an illegal attribute.
3150 static void
3151 xmlSchemaPMutualExclAttrErr(xmlSchemaParserCtxtPtr ctxt,
3152 xmlParserErrors error,
3153 xmlSchemaBasicItemPtr ownerItem,
3154 xmlAttrPtr attr,
3155 const char *name1,
3156 const char *name2)
3158 xmlChar *des = NULL;
3160 xmlSchemaFormatItemForReport(&des, NULL, WXS_BASIC_CAST ownerItem, attr->parent);
3161 xmlSchemaPErrExt(ctxt, (xmlNodePtr) attr, error, NULL, NULL, NULL,
3162 "%s: The attributes '%s' and '%s' are mutually exclusive.\n",
3163 BAD_CAST des, BAD_CAST name1, BAD_CAST name2, NULL, NULL);
3164 FREE_AND_NULL(des);
3168 * xmlSchemaPSimpleTypeErr:
3169 * @ctxt: the schema validation context
3170 * @error: the error code
3171 * @type: the type specifier
3172 * @ownerItem: the schema object if existent
3173 * @node: the validated node
3174 * @value: the validated value
3176 * Reports a simple type validation error.
3177 * TODO: Should this report the value of an element as well?
3179 static void LIBXML_ATTR_FORMAT(8,0)
3180 xmlSchemaPSimpleTypeErr(xmlSchemaParserCtxtPtr ctxt,
3181 xmlParserErrors error,
3182 xmlSchemaBasicItemPtr ownerItem ATTRIBUTE_UNUSED,
3183 xmlNodePtr node,
3184 xmlSchemaTypePtr type,
3185 const char *expected,
3186 const xmlChar *value,
3187 const char *message,
3188 const xmlChar *str1,
3189 const xmlChar *str2)
3191 xmlChar *msg = NULL;
3193 xmlSchemaFormatNodeForError(&msg, ACTXT_CAST ctxt, node);
3194 if (message == NULL) {
3196 * Use default messages.
3198 if (type != NULL) {
3199 if (node->type == XML_ATTRIBUTE_NODE)
3200 msg = xmlStrcat(msg, BAD_CAST "'%s' is not a valid value of ");
3201 else
3202 msg = xmlStrcat(msg, BAD_CAST "The character content is not a "
3203 "valid value of ");
3204 if (! xmlSchemaIsGlobalItem(type))
3205 msg = xmlStrcat(msg, BAD_CAST "the local ");
3206 else
3207 msg = xmlStrcat(msg, BAD_CAST "the ");
3209 if (WXS_IS_ATOMIC(type))
3210 msg = xmlStrcat(msg, BAD_CAST "atomic type");
3211 else if (WXS_IS_LIST(type))
3212 msg = xmlStrcat(msg, BAD_CAST "list type");
3213 else if (WXS_IS_UNION(type))
3214 msg = xmlStrcat(msg, BAD_CAST "union type");
3216 if (xmlSchemaIsGlobalItem(type)) {
3217 xmlChar *str = NULL;
3218 msg = xmlStrcat(msg, BAD_CAST " '");
3219 if (type->builtInType != 0) {
3220 msg = xmlStrcat(msg, BAD_CAST "xs:");
3221 str = xmlStrdup(type->name);
3222 } else {
3223 const xmlChar *qName = xmlSchemaFormatQName(&str, type->targetNamespace, type->name);
3224 if (!str)
3225 str = xmlStrdup(qName);
3227 msg = xmlStrcat(msg, xmlEscapeFormatString(&str));
3228 msg = xmlStrcat(msg, BAD_CAST "'.");
3229 FREE_AND_NULL(str);
3231 } else {
3232 if (node->type == XML_ATTRIBUTE_NODE)
3233 msg = xmlStrcat(msg, BAD_CAST "The value '%s' is not valid.");
3234 else
3235 msg = xmlStrcat(msg, BAD_CAST "The character content is not "
3236 "valid.");
3238 if (expected) {
3239 xmlChar *expectedEscaped = xmlCharStrdup(expected);
3240 msg = xmlStrcat(msg, BAD_CAST " Expected is '");
3241 msg = xmlStrcat(msg, xmlEscapeFormatString(&expectedEscaped));
3242 FREE_AND_NULL(expectedEscaped);
3243 msg = xmlStrcat(msg, BAD_CAST "'.\n");
3244 } else
3245 msg = xmlStrcat(msg, BAD_CAST "\n");
3246 if (node->type == XML_ATTRIBUTE_NODE)
3247 xmlSchemaPErr(ctxt, node, error, (const char *) msg, value, NULL);
3248 else
3249 xmlSchemaPErr(ctxt, node, error, (const char *) msg, NULL, NULL);
3250 } else {
3251 msg = xmlStrcat(msg, BAD_CAST message);
3252 msg = xmlStrcat(msg, BAD_CAST ".\n");
3253 xmlSchemaPErrExt(ctxt, node, error, NULL, NULL, NULL,
3254 (const char*) msg, str1, str2, NULL, NULL, NULL);
3256 /* Cleanup. */
3257 FREE_AND_NULL(msg)
3261 * xmlSchemaPContentErr:
3262 * @ctxt: the schema parser context
3263 * @error: the error code
3264 * @ownerItem: the owner item of the holder of the content
3265 * @ownerElem: the node of the holder of the content
3266 * @child: the invalid child node
3267 * @message: the optional error message
3268 * @content: the optional string describing the correct content
3270 * Reports an error concerning the content of a schema element.
3272 static void
3273 xmlSchemaPContentErr(xmlSchemaParserCtxtPtr ctxt,
3274 xmlParserErrors error,
3275 xmlSchemaBasicItemPtr ownerItem,
3276 xmlNodePtr ownerElem,
3277 xmlNodePtr child,
3278 const char *message,
3279 const char *content)
3281 xmlChar *des = NULL;
3283 xmlSchemaFormatItemForReport(&des, NULL, ownerItem, ownerElem);
3284 if (message != NULL)
3285 xmlSchemaPErr2(ctxt, ownerElem, child, error,
3286 "%s: %s.\n",
3287 BAD_CAST des, BAD_CAST message);
3288 else {
3289 if (content != NULL) {
3290 xmlSchemaPErr2(ctxt, ownerElem, child, error,
3291 "%s: The content is not valid. Expected is %s.\n",
3292 BAD_CAST des, BAD_CAST content);
3293 } else {
3294 xmlSchemaPErr2(ctxt, ownerElem, child, error,
3295 "%s: The content is not valid.\n",
3296 BAD_CAST des, NULL);
3299 FREE_AND_NULL(des)
3302 /************************************************************************
3304 * Streamable error functions *
3306 ************************************************************************/
3311 /************************************************************************
3313 * Validation helper functions *
3315 ************************************************************************/
3318 /************************************************************************
3320 * Allocation functions *
3322 ************************************************************************/
3325 * xmlSchemaNewSchemaForParserCtxt:
3326 * @ctxt: a schema validation context
3328 * Allocate a new Schema structure.
3330 * Returns the newly allocated structure or NULL in case or error
3332 static xmlSchemaPtr
3333 xmlSchemaNewSchema(xmlSchemaParserCtxtPtr ctxt)
3335 xmlSchemaPtr ret;
3337 ret = (xmlSchemaPtr) xmlMalloc(sizeof(xmlSchema));
3338 if (ret == NULL) {
3339 xmlSchemaPErrMemory(ctxt, "allocating schema", NULL);
3340 return (NULL);
3342 memset(ret, 0, sizeof(xmlSchema));
3343 ret->dict = ctxt->dict;
3344 xmlDictReference(ret->dict);
3346 return (ret);
3350 * xmlSchemaNewFacet:
3352 * Allocate a new Facet structure.
3354 * Returns the newly allocated structure or NULL in case or error
3356 xmlSchemaFacetPtr
3357 xmlSchemaNewFacet(void)
3359 xmlSchemaFacetPtr ret;
3361 ret = (xmlSchemaFacetPtr) xmlMalloc(sizeof(xmlSchemaFacet));
3362 if (ret == NULL) {
3363 return (NULL);
3365 memset(ret, 0, sizeof(xmlSchemaFacet));
3367 return (ret);
3371 * xmlSchemaNewAnnot:
3372 * @ctxt: a schema validation context
3373 * @node: a node
3375 * Allocate a new annotation structure.
3377 * Returns the newly allocated structure or NULL in case or error
3379 static xmlSchemaAnnotPtr
3380 xmlSchemaNewAnnot(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
3382 xmlSchemaAnnotPtr ret;
3384 ret = (xmlSchemaAnnotPtr) xmlMalloc(sizeof(xmlSchemaAnnot));
3385 if (ret == NULL) {
3386 xmlSchemaPErrMemory(ctxt, "allocating annotation", node);
3387 return (NULL);
3389 memset(ret, 0, sizeof(xmlSchemaAnnot));
3390 ret->content = node;
3391 return (ret);
3394 static xmlSchemaItemListPtr
3395 xmlSchemaItemListCreate(void)
3397 xmlSchemaItemListPtr ret;
3399 ret = xmlMalloc(sizeof(xmlSchemaItemList));
3400 if (ret == NULL) {
3401 xmlSchemaPErrMemory(NULL,
3402 "allocating an item list structure", NULL);
3403 return (NULL);
3405 memset(ret, 0, sizeof(xmlSchemaItemList));
3406 return (ret);
3409 static void
3410 xmlSchemaItemListClear(xmlSchemaItemListPtr list)
3412 if (list->items != NULL) {
3413 xmlFree(list->items);
3414 list->items = NULL;
3416 list->nbItems = 0;
3417 list->sizeItems = 0;
3420 static int
3421 xmlSchemaItemListAdd(xmlSchemaItemListPtr list, void *item)
3423 if (list->sizeItems <= list->nbItems) {
3424 void **tmp;
3425 size_t newSize = list->sizeItems == 0 ? 20 : list->sizeItems * 2;
3427 tmp = (void **) xmlRealloc(list->items, newSize * sizeof(void *));
3428 if (tmp == NULL) {
3429 xmlSchemaPErrMemory(NULL, "growing item list", NULL);
3430 return(-1);
3432 list->items = tmp;
3433 list->sizeItems = newSize;
3435 list->items[list->nbItems++] = item;
3436 return(0);
3439 static int
3440 xmlSchemaItemListAddSize(xmlSchemaItemListPtr list,
3441 int initialSize,
3442 void *item)
3444 if (list->items == NULL) {
3445 if (initialSize <= 0)
3446 initialSize = 1;
3447 list->items = (void **) xmlMalloc(
3448 initialSize * sizeof(void *));
3449 if (list->items == NULL) {
3450 xmlSchemaPErrMemory(NULL, "allocating new item list", NULL);
3451 return(-1);
3453 list->sizeItems = initialSize;
3454 } else if (list->sizeItems <= list->nbItems) {
3455 void **tmp;
3457 list->sizeItems *= 2;
3458 tmp = (void **) xmlRealloc(list->items,
3459 list->sizeItems * sizeof(void *));
3460 if (tmp == NULL) {
3461 xmlSchemaPErrMemory(NULL, "growing item list", NULL);
3462 list->sizeItems /= 2;
3463 return(-1);
3465 list->items = tmp;
3467 list->items[list->nbItems++] = item;
3468 return(0);
3471 static int
3472 xmlSchemaItemListInsert(xmlSchemaItemListPtr list, void *item, int idx)
3474 if (list->sizeItems <= list->nbItems) {
3475 void **tmp;
3476 size_t newSize = list->sizeItems == 0 ? 20 : list->sizeItems * 2;
3478 tmp = (void **) xmlRealloc(list->items, newSize * sizeof(void *));
3479 if (tmp == NULL) {
3480 xmlSchemaPErrMemory(NULL, "growing item list", NULL);
3481 return(-1);
3483 list->items = tmp;
3484 list->sizeItems = newSize;
3487 * Just append if the index is greater/equal than the item count.
3489 if (idx >= list->nbItems) {
3490 list->items[list->nbItems++] = item;
3491 } else {
3492 int i;
3493 for (i = list->nbItems; i > idx; i--)
3494 list->items[i] = list->items[i-1];
3495 list->items[idx] = item;
3496 list->nbItems++;
3498 return(0);
3501 #if 0 /* enable if ever needed */
3502 static int
3503 xmlSchemaItemListInsertSize(xmlSchemaItemListPtr list,
3504 int initialSize,
3505 void *item,
3506 int idx)
3508 if (list->items == NULL) {
3509 if (initialSize <= 0)
3510 initialSize = 1;
3511 list->items = (void **) xmlMalloc(
3512 initialSize * sizeof(void *));
3513 if (list->items == NULL) {
3514 xmlSchemaPErrMemory(NULL, "allocating new item list", NULL);
3515 return(-1);
3517 list->sizeItems = initialSize;
3518 } else if (list->sizeItems <= list->nbItems) {
3519 list->sizeItems *= 2;
3520 list->items = (void **) xmlRealloc(list->items,
3521 list->sizeItems * sizeof(void *));
3522 if (list->items == NULL) {
3523 xmlSchemaPErrMemory(NULL, "growing item list", NULL);
3524 list->sizeItems = 0;
3525 return(-1);
3529 * Just append if the index is greater/equal than the item count.
3531 if (idx >= list->nbItems) {
3532 list->items[list->nbItems++] = item;
3533 } else {
3534 int i;
3535 for (i = list->nbItems; i > idx; i--)
3536 list->items[i] = list->items[i-1];
3537 list->items[idx] = item;
3538 list->nbItems++;
3540 return(0);
3542 #endif
3544 static int
3545 xmlSchemaItemListRemove(xmlSchemaItemListPtr list, int idx)
3547 int i;
3548 if ((list->items == NULL) || (idx >= list->nbItems)) {
3549 xmlSchemaPSimpleErr("Internal error: xmlSchemaItemListRemove, "
3550 "index error.\n");
3551 return(-1);
3554 if (list->nbItems == 1) {
3555 /* TODO: Really free the list? */
3556 xmlFree(list->items);
3557 list->items = NULL;
3558 list->nbItems = 0;
3559 list->sizeItems = 0;
3560 } else if (list->nbItems -1 == idx) {
3561 list->nbItems--;
3562 } else {
3563 for (i = idx; i < list->nbItems -1; i++)
3564 list->items[i] = list->items[i+1];
3565 list->nbItems--;
3567 return(0);
3571 * xmlSchemaItemListFree:
3572 * @annot: a schema type structure
3574 * Deallocate a annotation structure
3576 static void
3577 xmlSchemaItemListFree(xmlSchemaItemListPtr list)
3579 if (list == NULL)
3580 return;
3581 if (list->items != NULL)
3582 xmlFree(list->items);
3583 xmlFree(list);
3586 static void
3587 xmlSchemaBucketFree(xmlSchemaBucketPtr bucket)
3589 if (bucket == NULL)
3590 return;
3591 if (bucket->globals != NULL) {
3592 xmlSchemaComponentListFree(bucket->globals);
3593 xmlSchemaItemListFree(bucket->globals);
3595 if (bucket->locals != NULL) {
3596 xmlSchemaComponentListFree(bucket->locals);
3597 xmlSchemaItemListFree(bucket->locals);
3599 if (bucket->relations != NULL) {
3600 xmlSchemaSchemaRelationPtr prev, cur = bucket->relations;
3601 do {
3602 prev = cur;
3603 cur = cur->next;
3604 xmlFree(prev);
3605 } while (cur != NULL);
3607 if ((! bucket->preserveDoc) && (bucket->doc != NULL)) {
3608 xmlFreeDoc(bucket->doc);
3610 if (bucket->type == XML_SCHEMA_SCHEMA_IMPORT) {
3611 if (WXS_IMPBUCKET(bucket)->schema != NULL)
3612 xmlSchemaFree(WXS_IMPBUCKET(bucket)->schema);
3614 xmlFree(bucket);
3617 static void
3618 xmlSchemaBucketFreeEntry(void *bucket, const xmlChar *name ATTRIBUTE_UNUSED)
3620 xmlSchemaBucketFree((xmlSchemaBucketPtr) bucket);
3623 static xmlSchemaBucketPtr
3624 xmlSchemaBucketCreate(xmlSchemaParserCtxtPtr pctxt,
3625 int type, const xmlChar *targetNamespace)
3627 xmlSchemaBucketPtr ret;
3628 int size;
3629 xmlSchemaPtr mainSchema;
3631 if (WXS_CONSTRUCTOR(pctxt)->mainSchema == NULL) {
3632 PERROR_INT("xmlSchemaBucketCreate",
3633 "no main schema on constructor");
3634 return(NULL);
3636 mainSchema = WXS_CONSTRUCTOR(pctxt)->mainSchema;
3637 /* Create the schema bucket. */
3638 if (WXS_IS_BUCKET_INCREDEF(type))
3639 size = sizeof(xmlSchemaInclude);
3640 else
3641 size = sizeof(xmlSchemaImport);
3642 ret = (xmlSchemaBucketPtr) xmlMalloc(size);
3643 if (ret == NULL) {
3644 xmlSchemaPErrMemory(NULL, "allocating schema bucket", NULL);
3645 return(NULL);
3647 memset(ret, 0, size);
3648 ret->targetNamespace = targetNamespace;
3649 ret->type = type;
3650 ret->globals = xmlSchemaItemListCreate();
3651 if (ret->globals == NULL) {
3652 xmlSchemaBucketFree(ret);
3653 return(NULL);
3655 ret->locals = xmlSchemaItemListCreate();
3656 if (ret->locals == NULL) {
3657 xmlSchemaBucketFree(ret);
3658 return(NULL);
3661 * The following will assure that only the first bucket is marked as
3662 * XML_SCHEMA_SCHEMA_MAIN and it points to the *main* schema.
3663 * For each following import buckets an xmlSchema will be created.
3664 * An xmlSchema will be created for every distinct targetNamespace.
3665 * We assign the targetNamespace to the schemata here.
3667 if (! WXS_HAS_BUCKETS(pctxt)) {
3668 if (WXS_IS_BUCKET_INCREDEF(type)) {
3669 PERROR_INT("xmlSchemaBucketCreate",
3670 "first bucket but it's an include or redefine");
3671 xmlSchemaBucketFree(ret);
3672 return(NULL);
3674 /* Force the type to be XML_SCHEMA_SCHEMA_MAIN. */
3675 ret->type = XML_SCHEMA_SCHEMA_MAIN;
3676 /* Point to the *main* schema. */
3677 WXS_CONSTRUCTOR(pctxt)->mainBucket = ret;
3678 WXS_IMPBUCKET(ret)->schema = mainSchema;
3680 * Ensure that the main schema gets a targetNamespace.
3682 mainSchema->targetNamespace = targetNamespace;
3683 } else {
3684 if (type == XML_SCHEMA_SCHEMA_MAIN) {
3685 PERROR_INT("xmlSchemaBucketCreate",
3686 "main bucket but it's not the first one");
3687 xmlSchemaBucketFree(ret);
3688 return(NULL);
3689 } else if (type == XML_SCHEMA_SCHEMA_IMPORT) {
3691 * Create a schema for imports and assign the
3692 * targetNamespace.
3694 WXS_IMPBUCKET(ret)->schema = xmlSchemaNewSchema(pctxt);
3695 if (WXS_IMPBUCKET(ret)->schema == NULL) {
3696 xmlSchemaBucketFree(ret);
3697 return(NULL);
3699 WXS_IMPBUCKET(ret)->schema->targetNamespace = targetNamespace;
3702 if (WXS_IS_BUCKET_IMPMAIN(type)) {
3703 int res;
3705 * Imports go into the "schemasImports" slot of the main *schema*.
3706 * Note that we create an import entry for the main schema as well; i.e.,
3707 * even if there's only one schema, we'll get an import.
3709 if (mainSchema->schemasImports == NULL) {
3710 mainSchema->schemasImports = xmlHashCreateDict(5,
3711 WXS_CONSTRUCTOR(pctxt)->dict);
3712 if (mainSchema->schemasImports == NULL) {
3713 xmlSchemaBucketFree(ret);
3714 return(NULL);
3717 if (targetNamespace == NULL)
3718 res = xmlHashAddEntry(mainSchema->schemasImports,
3719 XML_SCHEMAS_NO_NAMESPACE, ret);
3720 else
3721 res = xmlHashAddEntry(mainSchema->schemasImports,
3722 targetNamespace, ret);
3723 if (res != 0) {
3724 PERROR_INT("xmlSchemaBucketCreate",
3725 "failed to add the schema bucket to the hash");
3726 xmlSchemaBucketFree(ret);
3727 return(NULL);
3729 } else {
3730 /* Set the @ownerImport of an include bucket. */
3731 if (WXS_IS_BUCKET_IMPMAIN(WXS_CONSTRUCTOR(pctxt)->bucket->type))
3732 WXS_INCBUCKET(ret)->ownerImport =
3733 WXS_IMPBUCKET(WXS_CONSTRUCTOR(pctxt)->bucket);
3734 else
3735 WXS_INCBUCKET(ret)->ownerImport =
3736 WXS_INCBUCKET(WXS_CONSTRUCTOR(pctxt)->bucket)->ownerImport;
3738 /* Includes got into the "includes" slot of the *main* schema. */
3739 if (mainSchema->includes == NULL) {
3740 mainSchema->includes = xmlSchemaItemListCreate();
3741 if (mainSchema->includes == NULL) {
3742 xmlSchemaBucketFree(ret);
3743 return(NULL);
3746 if (xmlSchemaItemListAdd(mainSchema->includes, ret) < 0) {
3747 xmlSchemaBucketFree(ret);
3748 return(NULL);
3752 * Add to list of all buckets; this is used for lookup
3753 * during schema construction time only.
3755 if (xmlSchemaItemListAdd(WXS_CONSTRUCTOR(pctxt)->buckets, ret) == -1)
3756 return(NULL);
3757 return(ret);
3760 static int
3761 xmlSchemaAddItemSize(xmlSchemaItemListPtr *list, int initialSize, void *item)
3763 if (*list == NULL) {
3764 *list = xmlSchemaItemListCreate();
3765 if (*list == NULL)
3766 return(-1);
3768 return(xmlSchemaItemListAddSize(*list, initialSize, item));
3772 * xmlSchemaFreeAnnot:
3773 * @annot: a schema type structure
3775 * Deallocate a annotation structure
3777 static void
3778 xmlSchemaFreeAnnot(xmlSchemaAnnotPtr annot)
3780 if (annot == NULL)
3781 return;
3782 if (annot->next == NULL) {
3783 xmlFree(annot);
3784 } else {
3785 xmlSchemaAnnotPtr prev;
3787 do {
3788 prev = annot;
3789 annot = annot->next;
3790 xmlFree(prev);
3791 } while (annot != NULL);
3796 * xmlSchemaFreeNotation:
3797 * @schema: a schema notation structure
3799 * Deallocate a Schema Notation structure.
3801 static void
3802 xmlSchemaFreeNotation(xmlSchemaNotationPtr nota)
3804 if (nota == NULL)
3805 return;
3806 xmlFree(nota);
3810 * xmlSchemaFreeAttribute:
3811 * @attr: an attribute declaration
3813 * Deallocates an attribute declaration structure.
3815 static void
3816 xmlSchemaFreeAttribute(xmlSchemaAttributePtr attr)
3818 if (attr == NULL)
3819 return;
3820 if (attr->annot != NULL)
3821 xmlSchemaFreeAnnot(attr->annot);
3822 if (attr->defVal != NULL)
3823 xmlSchemaFreeValue(attr->defVal);
3824 xmlFree(attr);
3828 * xmlSchemaFreeAttributeUse:
3829 * @use: an attribute use
3831 * Deallocates an attribute use structure.
3833 static void
3834 xmlSchemaFreeAttributeUse(xmlSchemaAttributeUsePtr use)
3836 if (use == NULL)
3837 return;
3838 if (use->annot != NULL)
3839 xmlSchemaFreeAnnot(use->annot);
3840 if (use->defVal != NULL)
3841 xmlSchemaFreeValue(use->defVal);
3842 xmlFree(use);
3846 * xmlSchemaFreeAttributeUseProhib:
3847 * @prohib: an attribute use prohibition
3849 * Deallocates an attribute use structure.
3851 static void
3852 xmlSchemaFreeAttributeUseProhib(xmlSchemaAttributeUseProhibPtr prohib)
3854 if (prohib == NULL)
3855 return;
3856 xmlFree(prohib);
3860 * xmlSchemaFreeWildcardNsSet:
3861 * set: a schema wildcard namespace
3863 * Deallocates a list of wildcard constraint structures.
3865 static void
3866 xmlSchemaFreeWildcardNsSet(xmlSchemaWildcardNsPtr set)
3868 xmlSchemaWildcardNsPtr next;
3870 while (set != NULL) {
3871 next = set->next;
3872 xmlFree(set);
3873 set = next;
3878 * xmlSchemaFreeWildcard:
3879 * @wildcard: a wildcard structure
3881 * Deallocates a wildcard structure.
3883 void
3884 xmlSchemaFreeWildcard(xmlSchemaWildcardPtr wildcard)
3886 if (wildcard == NULL)
3887 return;
3888 if (wildcard->annot != NULL)
3889 xmlSchemaFreeAnnot(wildcard->annot);
3890 if (wildcard->nsSet != NULL)
3891 xmlSchemaFreeWildcardNsSet(wildcard->nsSet);
3892 if (wildcard->negNsSet != NULL)
3893 xmlFree(wildcard->negNsSet);
3894 xmlFree(wildcard);
3898 * xmlSchemaFreeAttributeGroup:
3899 * @schema: a schema attribute group structure
3901 * Deallocate a Schema Attribute Group structure.
3903 static void
3904 xmlSchemaFreeAttributeGroup(xmlSchemaAttributeGroupPtr attrGr)
3906 if (attrGr == NULL)
3907 return;
3908 if (attrGr->annot != NULL)
3909 xmlSchemaFreeAnnot(attrGr->annot);
3910 if (attrGr->attrUses != NULL)
3911 xmlSchemaItemListFree(WXS_LIST_CAST attrGr->attrUses);
3912 xmlFree(attrGr);
3916 * xmlSchemaFreeQNameRef:
3917 * @item: a QName reference structure
3919 * Deallocatea a QName reference structure.
3921 static void
3922 xmlSchemaFreeQNameRef(xmlSchemaQNameRefPtr item)
3924 xmlFree(item);
3928 * xmlSchemaFreeTypeLinkList:
3929 * @alink: a type link
3931 * Deallocate a list of types.
3933 static void
3934 xmlSchemaFreeTypeLinkList(xmlSchemaTypeLinkPtr link)
3936 xmlSchemaTypeLinkPtr next;
3938 while (link != NULL) {
3939 next = link->next;
3940 xmlFree(link);
3941 link = next;
3945 static void
3946 xmlSchemaFreeIDCStateObjList(xmlSchemaIDCStateObjPtr sto)
3948 xmlSchemaIDCStateObjPtr next;
3949 while (sto != NULL) {
3950 next = sto->next;
3951 if (sto->history != NULL)
3952 xmlFree(sto->history);
3953 if (sto->xpathCtxt != NULL)
3954 xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
3955 xmlFree(sto);
3956 sto = next;
3961 * xmlSchemaFreeIDC:
3962 * @idc: a identity-constraint definition
3964 * Deallocates an identity-constraint definition.
3966 static void
3967 xmlSchemaFreeIDC(xmlSchemaIDCPtr idcDef)
3969 xmlSchemaIDCSelectPtr cur, prev;
3971 if (idcDef == NULL)
3972 return;
3973 if (idcDef->annot != NULL)
3974 xmlSchemaFreeAnnot(idcDef->annot);
3975 /* Selector */
3976 if (idcDef->selector != NULL) {
3977 if (idcDef->selector->xpathComp != NULL)
3978 xmlFreePattern((xmlPatternPtr) idcDef->selector->xpathComp);
3979 xmlFree(idcDef->selector);
3981 /* Fields */
3982 if (idcDef->fields != NULL) {
3983 cur = idcDef->fields;
3984 do {
3985 prev = cur;
3986 cur = cur->next;
3987 if (prev->xpathComp != NULL)
3988 xmlFreePattern((xmlPatternPtr) prev->xpathComp);
3989 xmlFree(prev);
3990 } while (cur != NULL);
3992 xmlFree(idcDef);
3996 * xmlSchemaFreeElement:
3997 * @schema: a schema element structure
3999 * Deallocate a Schema Element structure.
4001 static void
4002 xmlSchemaFreeElement(xmlSchemaElementPtr elem)
4004 if (elem == NULL)
4005 return;
4006 if (elem->annot != NULL)
4007 xmlSchemaFreeAnnot(elem->annot);
4008 if (elem->contModel != NULL)
4009 xmlRegFreeRegexp(elem->contModel);
4010 if (elem->defVal != NULL)
4011 xmlSchemaFreeValue(elem->defVal);
4012 xmlFree(elem);
4016 * xmlSchemaFreeFacet:
4017 * @facet: a schema facet structure
4019 * Deallocate a Schema Facet structure.
4021 void
4022 xmlSchemaFreeFacet(xmlSchemaFacetPtr facet)
4024 if (facet == NULL)
4025 return;
4026 if (facet->val != NULL)
4027 xmlSchemaFreeValue(facet->val);
4028 if (facet->regexp != NULL)
4029 xmlRegFreeRegexp(facet->regexp);
4030 if (facet->annot != NULL)
4031 xmlSchemaFreeAnnot(facet->annot);
4032 xmlFree(facet);
4036 * xmlSchemaFreeType:
4037 * @type: a schema type structure
4039 * Deallocate a Schema Type structure.
4041 void
4042 xmlSchemaFreeType(xmlSchemaTypePtr type)
4044 if (type == NULL)
4045 return;
4046 if (type->annot != NULL)
4047 xmlSchemaFreeAnnot(type->annot);
4048 if (type->facets != NULL) {
4049 xmlSchemaFacetPtr facet, next;
4051 facet = type->facets;
4052 while (facet != NULL) {
4053 next = facet->next;
4054 xmlSchemaFreeFacet(facet);
4055 facet = next;
4058 if (type->attrUses != NULL)
4059 xmlSchemaItemListFree((xmlSchemaItemListPtr) type->attrUses);
4060 if (type->memberTypes != NULL)
4061 xmlSchemaFreeTypeLinkList(type->memberTypes);
4062 if (type->facetSet != NULL) {
4063 xmlSchemaFacetLinkPtr next, link;
4065 link = type->facetSet;
4066 do {
4067 next = link->next;
4068 xmlFree(link);
4069 link = next;
4070 } while (link != NULL);
4072 if (type->contModel != NULL)
4073 xmlRegFreeRegexp(type->contModel);
4074 xmlFree(type);
4078 * xmlSchemaFreeModelGroupDef:
4079 * @item: a schema model group definition
4081 * Deallocates a schema model group definition.
4083 static void
4084 xmlSchemaFreeModelGroupDef(xmlSchemaModelGroupDefPtr item)
4086 if (item->annot != NULL)
4087 xmlSchemaFreeAnnot(item->annot);
4088 xmlFree(item);
4092 * xmlSchemaFreeModelGroup:
4093 * @item: a schema model group
4095 * Deallocates a schema model group structure.
4097 static void
4098 xmlSchemaFreeModelGroup(xmlSchemaModelGroupPtr item)
4100 if (item->annot != NULL)
4101 xmlSchemaFreeAnnot(item->annot);
4102 xmlFree(item);
4105 static void
4106 xmlSchemaComponentListFree(xmlSchemaItemListPtr list)
4108 if ((list == NULL) || (list->nbItems == 0))
4109 return;
4111 xmlSchemaTreeItemPtr item;
4112 xmlSchemaTreeItemPtr *items = (xmlSchemaTreeItemPtr *) list->items;
4113 int i;
4115 for (i = 0; i < list->nbItems; i++) {
4116 item = items[i];
4117 if (item == NULL)
4118 continue;
4119 switch (item->type) {
4120 case XML_SCHEMA_TYPE_SIMPLE:
4121 case XML_SCHEMA_TYPE_COMPLEX:
4122 xmlSchemaFreeType((xmlSchemaTypePtr) item);
4123 break;
4124 case XML_SCHEMA_TYPE_ATTRIBUTE:
4125 xmlSchemaFreeAttribute((xmlSchemaAttributePtr) item);
4126 break;
4127 case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
4128 xmlSchemaFreeAttributeUse((xmlSchemaAttributeUsePtr) item);
4129 break;
4130 case XML_SCHEMA_EXTRA_ATTR_USE_PROHIB:
4131 xmlSchemaFreeAttributeUseProhib(
4132 (xmlSchemaAttributeUseProhibPtr) item);
4133 break;
4134 case XML_SCHEMA_TYPE_ELEMENT:
4135 xmlSchemaFreeElement((xmlSchemaElementPtr) item);
4136 break;
4137 case XML_SCHEMA_TYPE_PARTICLE:
4138 if (item->annot != NULL)
4139 xmlSchemaFreeAnnot(item->annot);
4140 xmlFree(item);
4141 break;
4142 case XML_SCHEMA_TYPE_SEQUENCE:
4143 case XML_SCHEMA_TYPE_CHOICE:
4144 case XML_SCHEMA_TYPE_ALL:
4145 xmlSchemaFreeModelGroup((xmlSchemaModelGroupPtr) item);
4146 break;
4147 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
4148 xmlSchemaFreeAttributeGroup(
4149 (xmlSchemaAttributeGroupPtr) item);
4150 break;
4151 case XML_SCHEMA_TYPE_GROUP:
4152 xmlSchemaFreeModelGroupDef(
4153 (xmlSchemaModelGroupDefPtr) item);
4154 break;
4155 case XML_SCHEMA_TYPE_ANY:
4156 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
4157 xmlSchemaFreeWildcard((xmlSchemaWildcardPtr) item);
4158 break;
4159 case XML_SCHEMA_TYPE_IDC_KEY:
4160 case XML_SCHEMA_TYPE_IDC_UNIQUE:
4161 case XML_SCHEMA_TYPE_IDC_KEYREF:
4162 xmlSchemaFreeIDC((xmlSchemaIDCPtr) item);
4163 break;
4164 case XML_SCHEMA_TYPE_NOTATION:
4165 xmlSchemaFreeNotation((xmlSchemaNotationPtr) item);
4166 break;
4167 case XML_SCHEMA_EXTRA_QNAMEREF:
4168 xmlSchemaFreeQNameRef((xmlSchemaQNameRefPtr) item);
4169 break;
4170 default: {
4171 /* TODO: This should never be hit. */
4172 xmlSchemaPSimpleInternalErr(NULL,
4173 "Internal error: xmlSchemaComponentListFree, "
4174 "unexpected component type '%s'\n",
4175 (const xmlChar *) WXS_ITEM_TYPE_NAME(item));
4177 break;
4180 list->nbItems = 0;
4185 * xmlSchemaFree:
4186 * @schema: a schema structure
4188 * Deallocate a Schema structure.
4190 void
4191 xmlSchemaFree(xmlSchemaPtr schema)
4193 if (schema == NULL)
4194 return;
4195 /* @volatiles is not used anymore :-/ */
4196 if (schema->volatiles != NULL)
4197 TODO
4199 * Note that those slots are not responsible for freeing
4200 * schema components anymore; this will now be done by
4201 * the schema buckets.
4203 if (schema->notaDecl != NULL)
4204 xmlHashFree(schema->notaDecl, NULL);
4205 if (schema->attrDecl != NULL)
4206 xmlHashFree(schema->attrDecl, NULL);
4207 if (schema->attrgrpDecl != NULL)
4208 xmlHashFree(schema->attrgrpDecl, NULL);
4209 if (schema->elemDecl != NULL)
4210 xmlHashFree(schema->elemDecl, NULL);
4211 if (schema->typeDecl != NULL)
4212 xmlHashFree(schema->typeDecl, NULL);
4213 if (schema->groupDecl != NULL)
4214 xmlHashFree(schema->groupDecl, NULL);
4215 if (schema->idcDef != NULL)
4216 xmlHashFree(schema->idcDef, NULL);
4218 if (schema->schemasImports != NULL)
4219 xmlHashFree(schema->schemasImports, xmlSchemaBucketFreeEntry);
4220 if (schema->includes != NULL) {
4221 xmlSchemaItemListPtr list = (xmlSchemaItemListPtr) schema->includes;
4222 int i;
4223 for (i = 0; i < list->nbItems; i++) {
4224 xmlSchemaBucketFree((xmlSchemaBucketPtr) list->items[i]);
4226 xmlSchemaItemListFree(list);
4228 if (schema->annot != NULL)
4229 xmlSchemaFreeAnnot(schema->annot);
4230 /* Never free the doc here, since this will be done by the buckets. */
4232 xmlDictFree(schema->dict);
4233 xmlFree(schema);
4236 /************************************************************************
4238 * Debug functions *
4240 ************************************************************************/
4242 #ifdef LIBXML_OUTPUT_ENABLED
4244 static void
4245 xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output); /* forward */
4248 * xmlSchemaElementDump:
4249 * @elem: an element
4250 * @output: the file output
4252 * Dump the element
4254 static void
4255 xmlSchemaElementDump(void *payload, void *data,
4256 const xmlChar * name ATTRIBUTE_UNUSED,
4257 const xmlChar * namespace ATTRIBUTE_UNUSED,
4258 const xmlChar * context ATTRIBUTE_UNUSED)
4260 xmlSchemaElementPtr elem = (xmlSchemaElementPtr) payload;
4261 FILE *output = (FILE *) data;
4262 if (elem == NULL)
4263 return;
4266 fprintf(output, "Element");
4267 if (elem->flags & XML_SCHEMAS_ELEM_GLOBAL)
4268 fprintf(output, " (global)");
4269 fprintf(output, ": '%s' ", elem->name);
4270 if (namespace != NULL)
4271 fprintf(output, "ns '%s'", namespace);
4272 fprintf(output, "\n");
4273 #if 0
4274 if ((elem->minOccurs != 1) || (elem->maxOccurs != 1)) {
4275 fprintf(output, " min %d ", elem->minOccurs);
4276 if (elem->maxOccurs >= UNBOUNDED)
4277 fprintf(output, "max: unbounded\n");
4278 else if (elem->maxOccurs != 1)
4279 fprintf(output, "max: %d\n", elem->maxOccurs);
4280 else
4281 fprintf(output, "\n");
4283 #endif
4285 * Misc other properties.
4287 if ((elem->flags & XML_SCHEMAS_ELEM_NILLABLE) ||
4288 (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT) ||
4289 (elem->flags & XML_SCHEMAS_ELEM_FIXED) ||
4290 (elem->flags & XML_SCHEMAS_ELEM_DEFAULT)) {
4291 fprintf(output, " props: ");
4292 if (elem->flags & XML_SCHEMAS_ELEM_FIXED)
4293 fprintf(output, "[fixed] ");
4294 if (elem->flags & XML_SCHEMAS_ELEM_DEFAULT)
4295 fprintf(output, "[default] ");
4296 if (elem->flags & XML_SCHEMAS_ELEM_ABSTRACT)
4297 fprintf(output, "[abstract] ");
4298 if (elem->flags & XML_SCHEMAS_ELEM_NILLABLE)
4299 fprintf(output, "[nillable] ");
4300 fprintf(output, "\n");
4303 * Default/fixed value.
4305 if (elem->value != NULL)
4306 fprintf(output, " value: '%s'\n", elem->value);
4308 * Type.
4310 if (elem->namedType != NULL) {
4311 fprintf(output, " type: '%s' ", elem->namedType);
4312 if (elem->namedTypeNs != NULL)
4313 fprintf(output, "ns '%s'\n", elem->namedTypeNs);
4314 else
4315 fprintf(output, "\n");
4316 } else if (elem->subtypes != NULL) {
4318 * Dump local types.
4320 xmlSchemaTypeDump(elem->subtypes, output);
4323 * Substitution group.
4325 if (elem->substGroup != NULL) {
4326 fprintf(output, " substitutionGroup: '%s' ", elem->substGroup);
4327 if (elem->substGroupNs != NULL)
4328 fprintf(output, "ns '%s'\n", elem->substGroupNs);
4329 else
4330 fprintf(output, "\n");
4335 * xmlSchemaAnnotDump:
4336 * @output: the file output
4337 * @annot: a annotation
4339 * Dump the annotation
4341 static void
4342 xmlSchemaAnnotDump(FILE * output, xmlSchemaAnnotPtr annot)
4344 xmlChar *content;
4346 if (annot == NULL)
4347 return;
4349 content = xmlNodeGetContent(annot->content);
4350 if (content != NULL) {
4351 fprintf(output, " Annot: %s\n", content);
4352 xmlFree(content);
4353 } else
4354 fprintf(output, " Annot: empty\n");
4358 * xmlSchemaContentModelDump:
4359 * @particle: the schema particle
4360 * @output: the file output
4361 * @depth: the depth used for indentation
4363 * Dump a SchemaType structure
4365 static void
4366 xmlSchemaContentModelDump(xmlSchemaParticlePtr particle, FILE * output, int depth)
4368 xmlChar *str = NULL;
4369 xmlSchemaTreeItemPtr term;
4370 char shift[100];
4371 int i;
4373 if (particle == NULL)
4374 return;
4375 for (i = 0;((i < depth) && (i < 25));i++)
4376 shift[2 * i] = shift[2 * i + 1] = ' ';
4377 shift[2 * i] = shift[2 * i + 1] = 0;
4378 fprintf(output, "%s", shift);
4379 if (particle->children == NULL) {
4380 fprintf(output, "MISSING particle term\n");
4381 return;
4383 term = particle->children;
4384 if (term == NULL) {
4385 fprintf(output, "(NULL)");
4386 } else {
4387 switch (term->type) {
4388 case XML_SCHEMA_TYPE_ELEMENT:
4389 fprintf(output, "ELEM '%s'", xmlSchemaFormatQName(&str,
4390 ((xmlSchemaElementPtr)term)->targetNamespace,
4391 ((xmlSchemaElementPtr)term)->name));
4392 FREE_AND_NULL(str);
4393 break;
4394 case XML_SCHEMA_TYPE_SEQUENCE:
4395 fprintf(output, "SEQUENCE");
4396 break;
4397 case XML_SCHEMA_TYPE_CHOICE:
4398 fprintf(output, "CHOICE");
4399 break;
4400 case XML_SCHEMA_TYPE_ALL:
4401 fprintf(output, "ALL");
4402 break;
4403 case XML_SCHEMA_TYPE_ANY:
4404 fprintf(output, "ANY");
4405 break;
4406 default:
4407 fprintf(output, "UNKNOWN\n");
4408 return;
4411 if (particle->minOccurs != 1)
4412 fprintf(output, " min: %d", particle->minOccurs);
4413 if (particle->maxOccurs >= UNBOUNDED)
4414 fprintf(output, " max: unbounded");
4415 else if (particle->maxOccurs != 1)
4416 fprintf(output, " max: %d", particle->maxOccurs);
4417 fprintf(output, "\n");
4418 if (term &&
4419 ((term->type == XML_SCHEMA_TYPE_SEQUENCE) ||
4420 (term->type == XML_SCHEMA_TYPE_CHOICE) ||
4421 (term->type == XML_SCHEMA_TYPE_ALL)) &&
4422 (term->children != NULL)) {
4423 xmlSchemaContentModelDump((xmlSchemaParticlePtr) term->children,
4424 output, depth +1);
4426 if (particle->next != NULL)
4427 xmlSchemaContentModelDump((xmlSchemaParticlePtr) particle->next,
4428 output, depth);
4432 * xmlSchemaAttrUsesDump:
4433 * @uses: attribute uses list
4434 * @output: the file output
4436 * Dumps a list of attribute use components.
4438 static void
4439 xmlSchemaAttrUsesDump(xmlSchemaItemListPtr uses, FILE * output)
4441 xmlSchemaAttributeUsePtr use;
4442 xmlSchemaAttributeUseProhibPtr prohib;
4443 xmlSchemaQNameRefPtr ref;
4444 const xmlChar *name, *tns;
4445 xmlChar *str = NULL;
4446 int i;
4448 if ((uses == NULL) || (uses->nbItems == 0))
4449 return;
4451 fprintf(output, " attributes:\n");
4452 for (i = 0; i < uses->nbItems; i++) {
4453 use = uses->items[i];
4454 if (use->type == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB) {
4455 fprintf(output, " [prohibition] ");
4456 prohib = (xmlSchemaAttributeUseProhibPtr) use;
4457 name = prohib->name;
4458 tns = prohib->targetNamespace;
4459 } else if (use->type == XML_SCHEMA_EXTRA_QNAMEREF) {
4460 fprintf(output, " [reference] ");
4461 ref = (xmlSchemaQNameRefPtr) use;
4462 name = ref->name;
4463 tns = ref->targetNamespace;
4464 } else {
4465 fprintf(output, " [use] ");
4466 name = WXS_ATTRUSE_DECL_NAME(use);
4467 tns = WXS_ATTRUSE_DECL_TNS(use);
4469 fprintf(output, "'%s'\n",
4470 (const char *) xmlSchemaFormatQName(&str, tns, name));
4471 FREE_AND_NULL(str);
4476 * xmlSchemaTypeDump:
4477 * @output: the file output
4478 * @type: a type structure
4480 * Dump a SchemaType structure
4482 static void
4483 xmlSchemaTypeDump(xmlSchemaTypePtr type, FILE * output)
4485 if (type == NULL) {
4486 fprintf(output, "Type: NULL\n");
4487 return;
4489 fprintf(output, "Type: ");
4490 if (type->name != NULL)
4491 fprintf(output, "'%s' ", type->name);
4492 else
4493 fprintf(output, "(no name) ");
4494 if (type->targetNamespace != NULL)
4495 fprintf(output, "ns '%s' ", type->targetNamespace);
4496 switch (type->type) {
4497 case XML_SCHEMA_TYPE_BASIC:
4498 fprintf(output, "[basic] ");
4499 break;
4500 case XML_SCHEMA_TYPE_SIMPLE:
4501 fprintf(output, "[simple] ");
4502 break;
4503 case XML_SCHEMA_TYPE_COMPLEX:
4504 fprintf(output, "[complex] ");
4505 break;
4506 case XML_SCHEMA_TYPE_SEQUENCE:
4507 fprintf(output, "[sequence] ");
4508 break;
4509 case XML_SCHEMA_TYPE_CHOICE:
4510 fprintf(output, "[choice] ");
4511 break;
4512 case XML_SCHEMA_TYPE_ALL:
4513 fprintf(output, "[all] ");
4514 break;
4515 case XML_SCHEMA_TYPE_UR:
4516 fprintf(output, "[ur] ");
4517 break;
4518 case XML_SCHEMA_TYPE_RESTRICTION:
4519 fprintf(output, "[restriction] ");
4520 break;
4521 case XML_SCHEMA_TYPE_EXTENSION:
4522 fprintf(output, "[extension] ");
4523 break;
4524 default:
4525 fprintf(output, "[unknown type %d] ", type->type);
4526 break;
4528 fprintf(output, "content: ");
4529 switch (type->contentType) {
4530 case XML_SCHEMA_CONTENT_UNKNOWN:
4531 fprintf(output, "[unknown] ");
4532 break;
4533 case XML_SCHEMA_CONTENT_EMPTY:
4534 fprintf(output, "[empty] ");
4535 break;
4536 case XML_SCHEMA_CONTENT_ELEMENTS:
4537 fprintf(output, "[element] ");
4538 break;
4539 case XML_SCHEMA_CONTENT_MIXED:
4540 fprintf(output, "[mixed] ");
4541 break;
4542 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
4543 /* not used. */
4544 break;
4545 case XML_SCHEMA_CONTENT_BASIC:
4546 fprintf(output, "[basic] ");
4547 break;
4548 case XML_SCHEMA_CONTENT_SIMPLE:
4549 fprintf(output, "[simple] ");
4550 break;
4551 case XML_SCHEMA_CONTENT_ANY:
4552 fprintf(output, "[any] ");
4553 break;
4555 fprintf(output, "\n");
4556 if (type->base != NULL) {
4557 fprintf(output, " base type: '%s'", type->base);
4558 if (type->baseNs != NULL)
4559 fprintf(output, " ns '%s'\n", type->baseNs);
4560 else
4561 fprintf(output, "\n");
4563 if (type->attrUses != NULL)
4564 xmlSchemaAttrUsesDump(type->attrUses, output);
4565 if (type->annot != NULL)
4566 xmlSchemaAnnotDump(output, type->annot);
4567 #ifdef DUMP_CONTENT_MODEL
4568 if ((type->type == XML_SCHEMA_TYPE_COMPLEX) &&
4569 (type->subtypes != NULL)) {
4570 xmlSchemaContentModelDump((xmlSchemaParticlePtr) type->subtypes,
4571 output, 1);
4573 #endif
4576 static void
4577 xmlSchemaTypeDumpEntry(void *type, void *output,
4578 const xmlChar *name ATTRIBUTE_UNUSED)
4580 xmlSchemaTypeDump((xmlSchemaTypePtr) type, (FILE *) output);
4584 * xmlSchemaDump:
4585 * @output: the file output
4586 * @schema: a schema structure
4588 * Dump a Schema structure.
4590 void
4591 xmlSchemaDump(FILE * output, xmlSchemaPtr schema)
4593 if (output == NULL)
4594 return;
4595 if (schema == NULL) {
4596 fprintf(output, "Schemas: NULL\n");
4597 return;
4599 fprintf(output, "Schemas: ");
4600 if (schema->name != NULL)
4601 fprintf(output, "%s, ", schema->name);
4602 else
4603 fprintf(output, "no name, ");
4604 if (schema->targetNamespace != NULL)
4605 fprintf(output, "%s", (const char *) schema->targetNamespace);
4606 else
4607 fprintf(output, "no target namespace");
4608 fprintf(output, "\n");
4609 if (schema->annot != NULL)
4610 xmlSchemaAnnotDump(output, schema->annot);
4611 xmlHashScan(schema->typeDecl, xmlSchemaTypeDumpEntry, output);
4612 xmlHashScanFull(schema->elemDecl, xmlSchemaElementDump, output);
4615 #ifdef DEBUG_IDC_NODE_TABLE
4617 * xmlSchemaDebugDumpIDCTable:
4618 * @vctxt: the WXS validation context
4620 * Displays the current IDC table for debug purposes.
4622 static void
4623 xmlSchemaDebugDumpIDCTable(FILE * output,
4624 const xmlChar *namespaceName,
4625 const xmlChar *localName,
4626 xmlSchemaPSVIIDCBindingPtr bind)
4628 xmlChar *str = NULL;
4629 const xmlChar *value;
4630 xmlSchemaPSVIIDCNodePtr tab;
4631 xmlSchemaPSVIIDCKeyPtr key;
4632 int i, j, res;
4634 fprintf(output, "IDC: TABLES on '%s'\n",
4635 xmlSchemaFormatQName(&str, namespaceName, localName));
4636 FREE_AND_NULL(str)
4638 if (bind == NULL)
4639 return;
4640 do {
4641 fprintf(output, "IDC: BINDING '%s' (%d)\n",
4642 xmlSchemaGetComponentQName(&str,
4643 bind->definition), bind->nbNodes);
4644 FREE_AND_NULL(str)
4645 for (i = 0; i < bind->nbNodes; i++) {
4646 tab = bind->nodeTable[i];
4647 fprintf(output, " ( ");
4648 for (j = 0; j < bind->definition->nbFields; j++) {
4649 key = tab->keys[j];
4650 if ((key != NULL) && (key->val != NULL)) {
4651 res = xmlSchemaGetCanonValue(key->val, &value);
4652 if (res >= 0)
4653 fprintf(output, "'%s' ", value);
4654 else
4655 fprintf(output, "CANON-VALUE-FAILED ");
4656 if (res == 0)
4657 FREE_AND_NULL(value)
4658 } else if (key != NULL)
4659 fprintf(output, "(no val), ");
4660 else
4661 fprintf(output, "(key missing), ");
4663 fprintf(output, ")\n");
4665 if (bind->dupls && bind->dupls->nbItems) {
4666 fprintf(output, "IDC: dupls (%d):\n", bind->dupls->nbItems);
4667 for (i = 0; i < bind->dupls->nbItems; i++) {
4668 tab = bind->dupls->items[i];
4669 fprintf(output, " ( ");
4670 for (j = 0; j < bind->definition->nbFields; j++) {
4671 key = tab->keys[j];
4672 if ((key != NULL) && (key->val != NULL)) {
4673 res = xmlSchemaGetCanonValue(key->val, &value);
4674 if (res >= 0)
4675 fprintf(output, "'%s' ", value);
4676 else
4677 fprintf(output, "CANON-VALUE-FAILED ");
4678 if (res == 0)
4679 FREE_AND_NULL(value)
4680 } else if (key != NULL)
4681 fprintf(output, "(no val), ");
4682 else
4683 fprintf(output, "(key missing), ");
4685 fprintf(output, ")\n");
4688 bind = bind->next;
4689 } while (bind != NULL);
4691 #endif /* DEBUG_IDC */
4692 #endif /* LIBXML_OUTPUT_ENABLED */
4694 /************************************************************************
4696 * Utilities *
4698 ************************************************************************/
4701 * xmlSchemaGetPropNode:
4702 * @node: the element node
4703 * @name: the name of the attribute
4705 * Seeks an attribute with a name of @name in
4706 * no namespace.
4708 * Returns the attribute or NULL if not present.
4710 static xmlAttrPtr
4711 xmlSchemaGetPropNode(xmlNodePtr node, const char *name)
4713 xmlAttrPtr prop;
4715 if ((node == NULL) || (name == NULL))
4716 return(NULL);
4717 prop = node->properties;
4718 while (prop != NULL) {
4719 if ((prop->ns == NULL) && xmlStrEqual(prop->name, BAD_CAST name))
4720 return(prop);
4721 prop = prop->next;
4723 return (NULL);
4727 * xmlSchemaGetPropNodeNs:
4728 * @node: the element node
4729 * @uri: the uri
4730 * @name: the name of the attribute
4732 * Seeks an attribute with a local name of @name and
4733 * a namespace URI of @uri.
4735 * Returns the attribute or NULL if not present.
4737 static xmlAttrPtr
4738 xmlSchemaGetPropNodeNs(xmlNodePtr node, const char *uri, const char *name)
4740 xmlAttrPtr prop;
4742 if ((node == NULL) || (name == NULL))
4743 return(NULL);
4744 prop = node->properties;
4745 while (prop != NULL) {
4746 if ((prop->ns != NULL) &&
4747 xmlStrEqual(prop->name, BAD_CAST name) &&
4748 xmlStrEqual(prop->ns->href, BAD_CAST uri))
4749 return(prop);
4750 prop = prop->next;
4752 return (NULL);
4755 static const xmlChar *
4756 xmlSchemaGetNodeContent(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node)
4758 xmlChar *val;
4759 const xmlChar *ret;
4761 val = xmlNodeGetContent(node);
4762 if (val == NULL)
4763 val = xmlStrdup((xmlChar *)"");
4764 ret = xmlDictLookup(ctxt->dict, val, -1);
4765 xmlFree(val);
4766 if (ret == NULL)
4767 xmlSchemaPErrMemory(ctxt, "getting node content", node);
4768 return(ret);
4771 static const xmlChar *
4772 xmlSchemaGetNodeContentNoDict(xmlNodePtr node)
4774 return((const xmlChar*) xmlNodeGetContent(node));
4778 * xmlSchemaGetProp:
4779 * @ctxt: the parser context
4780 * @node: the node
4781 * @name: the property name
4783 * Read a attribute value and internalize the string
4785 * Returns the string or NULL if not present.
4787 static const xmlChar *
4788 xmlSchemaGetProp(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
4789 const char *name)
4791 xmlChar *val;
4792 const xmlChar *ret;
4794 val = xmlGetNoNsProp(node, BAD_CAST name);
4795 if (val == NULL)
4796 return(NULL);
4797 ret = xmlDictLookup(ctxt->dict, val, -1);
4798 xmlFree(val);
4799 return(ret);
4802 /************************************************************************
4804 * Parsing functions *
4806 ************************************************************************/
4808 #define WXS_FIND_GLOBAL_ITEM(slot) \
4809 if (xmlStrEqual(nsName, schema->targetNamespace)) { \
4810 ret = xmlHashLookup(schema->slot, name); \
4811 if (ret != NULL) goto exit; \
4813 if (xmlHashSize(schema->schemasImports) > 1) { \
4814 xmlSchemaImportPtr import; \
4815 if (nsName == NULL) \
4816 import = xmlHashLookup(schema->schemasImports, \
4817 XML_SCHEMAS_NO_NAMESPACE); \
4818 else \
4819 import = xmlHashLookup(schema->schemasImports, nsName); \
4820 if (import == NULL) \
4821 goto exit; \
4822 ret = xmlHashLookup(import->schema->slot, name); \
4826 * xmlSchemaGetElem:
4827 * @schema: the schema context
4828 * @name: the element name
4829 * @ns: the element namespace
4831 * Lookup a global element declaration in the schema.
4833 * Returns the element declaration or NULL if not found.
4835 static xmlSchemaElementPtr
4836 xmlSchemaGetElem(xmlSchemaPtr schema, const xmlChar * name,
4837 const xmlChar * nsName)
4839 xmlSchemaElementPtr ret = NULL;
4841 if ((name == NULL) || (schema == NULL))
4842 return(NULL);
4843 if (schema != NULL) {
4844 WXS_FIND_GLOBAL_ITEM(elemDecl)
4846 exit:
4847 #ifdef DEBUG
4848 if (ret == NULL) {
4849 if (nsName == NULL)
4850 fprintf(stderr, "Unable to lookup element decl. %s", name);
4851 else
4852 fprintf(stderr, "Unable to lookup element decl. %s:%s", name,
4853 nsName);
4855 #endif
4856 return (ret);
4860 * xmlSchemaGetType:
4861 * @schema: the main schema
4862 * @name: the type's name
4863 * nsName: the type's namespace
4865 * Lookup a type in the schemas or the predefined types
4867 * Returns the group definition or NULL if not found.
4869 static xmlSchemaTypePtr
4870 xmlSchemaGetType(xmlSchemaPtr schema, const xmlChar * name,
4871 const xmlChar * nsName)
4873 xmlSchemaTypePtr ret = NULL;
4875 if (name == NULL)
4876 return (NULL);
4877 /* First try the built-in types. */
4878 if ((nsName != NULL) && xmlStrEqual(nsName, xmlSchemaNs)) {
4879 ret = xmlSchemaGetPredefinedType(name, nsName);
4880 if (ret != NULL)
4881 goto exit;
4883 * Note that we try the parsed schemas as well here
4884 * since one might have parsed the S4S, which contain more
4885 * than the built-in types.
4886 * TODO: Can we optimize this?
4889 if (schema != NULL) {
4890 WXS_FIND_GLOBAL_ITEM(typeDecl)
4892 exit:
4894 #ifdef DEBUG
4895 if (ret == NULL) {
4896 if (nsName == NULL)
4897 fprintf(stderr, "Unable to lookup type %s", name);
4898 else
4899 fprintf(stderr, "Unable to lookup type %s:%s", name,
4900 nsName);
4902 #endif
4903 return (ret);
4907 * xmlSchemaGetAttributeDecl:
4908 * @schema: the context of the schema
4909 * @name: the name of the attribute
4910 * @ns: the target namespace of the attribute
4912 * Lookup a an attribute in the schema or imported schemas
4914 * Returns the attribute declaration or NULL if not found.
4916 static xmlSchemaAttributePtr
4917 xmlSchemaGetAttributeDecl(xmlSchemaPtr schema, const xmlChar * name,
4918 const xmlChar * nsName)
4920 xmlSchemaAttributePtr ret = NULL;
4922 if ((name == NULL) || (schema == NULL))
4923 return (NULL);
4924 if (schema != NULL) {
4925 WXS_FIND_GLOBAL_ITEM(attrDecl)
4927 exit:
4928 #ifdef DEBUG
4929 if (ret == NULL) {
4930 if (nsName == NULL)
4931 fprintf(stderr, "Unable to lookup attribute %s", name);
4932 else
4933 fprintf(stderr, "Unable to lookup attribute %s:%s", name,
4934 nsName);
4936 #endif
4937 return (ret);
4941 * xmlSchemaGetAttributeGroup:
4942 * @schema: the context of the schema
4943 * @name: the name of the attribute group
4944 * @ns: the target namespace of the attribute group
4946 * Lookup a an attribute group in the schema or imported schemas
4948 * Returns the attribute group definition or NULL if not found.
4950 static xmlSchemaAttributeGroupPtr
4951 xmlSchemaGetAttributeGroup(xmlSchemaPtr schema, const xmlChar * name,
4952 const xmlChar * nsName)
4954 xmlSchemaAttributeGroupPtr ret = NULL;
4956 if ((name == NULL) || (schema == NULL))
4957 return (NULL);
4958 if (schema != NULL) {
4959 WXS_FIND_GLOBAL_ITEM(attrgrpDecl)
4961 exit:
4962 /* TODO:
4963 if ((ret != NULL) && (ret->redef != NULL)) {
4964 * Return the last redefinition. *
4965 ret = ret->redef;
4968 #ifdef DEBUG
4969 if (ret == NULL) {
4970 if (nsName == NULL)
4971 fprintf(stderr, "Unable to lookup attribute group %s", name);
4972 else
4973 fprintf(stderr, "Unable to lookup attribute group %s:%s", name,
4974 nsName);
4976 #endif
4977 return (ret);
4981 * xmlSchemaGetGroup:
4982 * @schema: the context of the schema
4983 * @name: the name of the group
4984 * @ns: the target namespace of the group
4986 * Lookup a group in the schema or imported schemas
4988 * Returns the group definition or NULL if not found.
4990 static xmlSchemaModelGroupDefPtr
4991 xmlSchemaGetGroup(xmlSchemaPtr schema, const xmlChar * name,
4992 const xmlChar * nsName)
4994 xmlSchemaModelGroupDefPtr ret = NULL;
4996 if ((name == NULL) || (schema == NULL))
4997 return (NULL);
4998 if (schema != NULL) {
4999 WXS_FIND_GLOBAL_ITEM(groupDecl)
5001 exit:
5003 #ifdef DEBUG
5004 if (ret == NULL) {
5005 if (nsName == NULL)
5006 fprintf(stderr, "Unable to lookup group %s", name);
5007 else
5008 fprintf(stderr, "Unable to lookup group %s:%s", name,
5009 nsName);
5011 #endif
5012 return (ret);
5015 static xmlSchemaNotationPtr
5016 xmlSchemaGetNotation(xmlSchemaPtr schema,
5017 const xmlChar *name,
5018 const xmlChar *nsName)
5020 xmlSchemaNotationPtr ret = NULL;
5022 if ((name == NULL) || (schema == NULL))
5023 return (NULL);
5024 if (schema != NULL) {
5025 WXS_FIND_GLOBAL_ITEM(notaDecl)
5027 exit:
5028 return (ret);
5031 static xmlSchemaIDCPtr
5032 xmlSchemaGetIDC(xmlSchemaPtr schema,
5033 const xmlChar *name,
5034 const xmlChar *nsName)
5036 xmlSchemaIDCPtr ret = NULL;
5038 if ((name == NULL) || (schema == NULL))
5039 return (NULL);
5040 if (schema != NULL) {
5041 WXS_FIND_GLOBAL_ITEM(idcDef)
5043 exit:
5044 return (ret);
5048 * xmlSchemaGetNamedComponent:
5049 * @schema: the schema
5050 * @name: the name of the group
5051 * @ns: the target namespace of the group
5053 * Lookup a group in the schema or imported schemas
5055 * Returns the group definition or NULL if not found.
5057 static xmlSchemaBasicItemPtr
5058 xmlSchemaGetNamedComponent(xmlSchemaPtr schema,
5059 xmlSchemaTypeType itemType,
5060 const xmlChar *name,
5061 const xmlChar *targetNs)
5063 switch (itemType) {
5064 case XML_SCHEMA_TYPE_GROUP:
5065 return ((xmlSchemaBasicItemPtr) xmlSchemaGetGroup(schema,
5066 name, targetNs));
5067 case XML_SCHEMA_TYPE_ELEMENT:
5068 return ((xmlSchemaBasicItemPtr) xmlSchemaGetElem(schema,
5069 name, targetNs));
5070 default:
5071 TODO
5072 return (NULL);
5076 /************************************************************************
5078 * Parsing functions *
5080 ************************************************************************/
5082 #define IS_BLANK_NODE(n) \
5083 (((n)->type == XML_TEXT_NODE) && (xmlSchemaIsBlank((n)->content, -1)))
5086 * xmlSchemaIsBlank:
5087 * @str: a string
5088 * @len: the length of the string or -1
5090 * Check if a string is ignorable
5092 * Returns 1 if the string is NULL or made of blanks chars, 0 otherwise
5094 static int
5095 xmlSchemaIsBlank(xmlChar * str, int len)
5097 if (str == NULL)
5098 return (1);
5099 if (len < 0) {
5100 while (*str != 0) {
5101 if (!(IS_BLANK_CH(*str)))
5102 return (0);
5103 str++;
5105 } else while ((*str != 0) && (len != 0)) {
5106 if (!(IS_BLANK_CH(*str)))
5107 return (0);
5108 str++;
5109 len--;
5112 return (1);
5115 #define WXS_COMP_NAME(c, t) ((t) (c))->name
5116 #define WXS_COMP_TNS(c, t) ((t) (c))->targetNamespace
5118 * xmlSchemaFindRedefCompInGraph:
5119 * ATTENTION TODO: This uses pointer comp. for strings.
5121 static xmlSchemaBasicItemPtr
5122 xmlSchemaFindRedefCompInGraph(xmlSchemaBucketPtr bucket,
5123 xmlSchemaTypeType type,
5124 const xmlChar *name,
5125 const xmlChar *nsName)
5127 xmlSchemaBasicItemPtr ret;
5128 int i;
5130 if ((bucket == NULL) || (name == NULL))
5131 return(NULL);
5132 if ((bucket->globals == NULL) ||
5133 (bucket->globals->nbItems == 0))
5134 goto subschemas;
5136 * Search in global components.
5138 for (i = 0; i < bucket->globals->nbItems; i++) {
5139 ret = bucket->globals->items[i];
5140 if (ret->type == type) {
5141 switch (type) {
5142 case XML_SCHEMA_TYPE_COMPLEX:
5143 case XML_SCHEMA_TYPE_SIMPLE:
5144 if ((WXS_COMP_NAME(ret, xmlSchemaTypePtr) == name) &&
5145 (WXS_COMP_TNS(ret, xmlSchemaTypePtr) ==
5146 nsName))
5148 return(ret);
5150 break;
5151 case XML_SCHEMA_TYPE_GROUP:
5152 if ((WXS_COMP_NAME(ret,
5153 xmlSchemaModelGroupDefPtr) == name) &&
5154 (WXS_COMP_TNS(ret,
5155 xmlSchemaModelGroupDefPtr) == nsName))
5157 return(ret);
5159 break;
5160 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
5161 if ((WXS_COMP_NAME(ret,
5162 xmlSchemaAttributeGroupPtr) == name) &&
5163 (WXS_COMP_TNS(ret,
5164 xmlSchemaAttributeGroupPtr) == nsName))
5166 return(ret);
5168 break;
5169 default:
5170 /* Should not be hit. */
5171 return(NULL);
5175 subschemas:
5177 * Process imported/included schemas.
5179 if (bucket->relations != NULL) {
5180 xmlSchemaSchemaRelationPtr rel = bucket->relations;
5183 * TODO: Marking the bucket will not avoid multiple searches
5184 * in the same schema, but avoids at least circularity.
5186 bucket->flags |= XML_SCHEMA_BUCKET_MARKED;
5187 do {
5188 if ((rel->bucket != NULL) &&
5189 ((rel->bucket->flags & XML_SCHEMA_BUCKET_MARKED) == 0)) {
5190 ret = xmlSchemaFindRedefCompInGraph(rel->bucket,
5191 type, name, nsName);
5192 if (ret != NULL)
5193 return(ret);
5195 rel = rel->next;
5196 } while (rel != NULL);
5197 bucket->flags ^= XML_SCHEMA_BUCKET_MARKED;
5199 return(NULL);
5203 * xmlSchemaAddNotation:
5204 * @ctxt: a schema parser context
5205 * @schema: the schema being built
5206 * @name: the item name
5208 * Add an XML schema annotation declaration
5209 * *WARNING* this interface is highly subject to change
5211 * Returns the new structure or NULL in case of error
5213 static xmlSchemaNotationPtr
5214 xmlSchemaAddNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5215 const xmlChar *name, const xmlChar *nsName,
5216 xmlNodePtr node ATTRIBUTE_UNUSED)
5218 xmlSchemaNotationPtr ret = NULL;
5220 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
5221 return (NULL);
5223 ret = (xmlSchemaNotationPtr) xmlMalloc(sizeof(xmlSchemaNotation));
5224 if (ret == NULL) {
5225 xmlSchemaPErrMemory(ctxt, "add annotation", NULL);
5226 return (NULL);
5228 memset(ret, 0, sizeof(xmlSchemaNotation));
5229 ret->type = XML_SCHEMA_TYPE_NOTATION;
5230 ret->name = name;
5231 ret->targetNamespace = nsName;
5232 /* TODO: do we need the node to be set?
5233 * ret->node = node;*/
5234 WXS_ADD_GLOBAL(ctxt, ret);
5235 return (ret);
5239 * xmlSchemaAddAttribute:
5240 * @ctxt: a schema parser context
5241 * @schema: the schema being built
5242 * @name: the item name
5243 * @namespace: the namespace
5245 * Add an XML schema Attribute declaration
5246 * *WARNING* this interface is highly subject to change
5248 * Returns the new structure or NULL in case of error
5250 static xmlSchemaAttributePtr
5251 xmlSchemaAddAttribute(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5252 const xmlChar * name, const xmlChar * nsName,
5253 xmlNodePtr node, int topLevel)
5255 xmlSchemaAttributePtr ret = NULL;
5257 if ((ctxt == NULL) || (schema == NULL))
5258 return (NULL);
5260 ret = (xmlSchemaAttributePtr) xmlMalloc(sizeof(xmlSchemaAttribute));
5261 if (ret == NULL) {
5262 xmlSchemaPErrMemory(ctxt, "allocating attribute", NULL);
5263 return (NULL);
5265 memset(ret, 0, sizeof(xmlSchemaAttribute));
5266 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE;
5267 ret->node = node;
5268 ret->name = name;
5269 ret->targetNamespace = nsName;
5271 if (topLevel)
5272 WXS_ADD_GLOBAL(ctxt, ret);
5273 else
5274 WXS_ADD_LOCAL(ctxt, ret);
5275 WXS_ADD_PENDING(ctxt, ret);
5276 return (ret);
5280 * xmlSchemaAddAttributeUse:
5281 * @ctxt: a schema parser context
5282 * @schema: the schema being built
5283 * @name: the item name
5284 * @namespace: the namespace
5286 * Add an XML schema Attribute declaration
5287 * *WARNING* this interface is highly subject to change
5289 * Returns the new structure or NULL in case of error
5291 static xmlSchemaAttributeUsePtr
5292 xmlSchemaAddAttributeUse(xmlSchemaParserCtxtPtr pctxt,
5293 xmlNodePtr node)
5295 xmlSchemaAttributeUsePtr ret = NULL;
5297 if (pctxt == NULL)
5298 return (NULL);
5300 ret = (xmlSchemaAttributeUsePtr) xmlMalloc(sizeof(xmlSchemaAttributeUse));
5301 if (ret == NULL) {
5302 xmlSchemaPErrMemory(pctxt, "allocating attribute", NULL);
5303 return (NULL);
5305 memset(ret, 0, sizeof(xmlSchemaAttributeUse));
5306 ret->type = XML_SCHEMA_TYPE_ATTRIBUTE_USE;
5307 ret->node = node;
5309 WXS_ADD_LOCAL(pctxt, ret);
5310 return (ret);
5314 * xmlSchemaAddRedef:
5316 * Adds a redefinition information. This is used at a later stage to:
5317 * resolve references to the redefined components and to check constraints.
5319 static xmlSchemaRedefPtr
5320 xmlSchemaAddRedef(xmlSchemaParserCtxtPtr pctxt,
5321 xmlSchemaBucketPtr targetBucket,
5322 void *item,
5323 const xmlChar *refName,
5324 const xmlChar *refTargetNs)
5326 xmlSchemaRedefPtr ret;
5328 ret = (xmlSchemaRedefPtr)
5329 xmlMalloc(sizeof(xmlSchemaRedef));
5330 if (ret == NULL) {
5331 xmlSchemaPErrMemory(pctxt,
5332 "allocating redefinition info", NULL);
5333 return (NULL);
5335 memset(ret, 0, sizeof(xmlSchemaRedef));
5336 ret->item = item;
5337 ret->targetBucket = targetBucket;
5338 ret->refName = refName;
5339 ret->refTargetNs = refTargetNs;
5340 if (WXS_CONSTRUCTOR(pctxt)->redefs == NULL)
5341 WXS_CONSTRUCTOR(pctxt)->redefs = ret;
5342 else
5343 WXS_CONSTRUCTOR(pctxt)->lastRedef->next = ret;
5344 WXS_CONSTRUCTOR(pctxt)->lastRedef = ret;
5346 return (ret);
5350 * xmlSchemaAddAttributeGroupDefinition:
5351 * @ctxt: a schema parser context
5352 * @schema: the schema being built
5353 * @name: the item name
5354 * @nsName: the target namespace
5355 * @node: the corresponding node
5357 * Add an XML schema Attribute Group definition.
5359 * Returns the new structure or NULL in case of error
5361 static xmlSchemaAttributeGroupPtr
5362 xmlSchemaAddAttributeGroupDefinition(xmlSchemaParserCtxtPtr pctxt,
5363 xmlSchemaPtr schema ATTRIBUTE_UNUSED,
5364 const xmlChar *name,
5365 const xmlChar *nsName,
5366 xmlNodePtr node)
5368 xmlSchemaAttributeGroupPtr ret = NULL;
5370 if ((pctxt == NULL) || (name == NULL))
5371 return (NULL);
5373 ret = (xmlSchemaAttributeGroupPtr)
5374 xmlMalloc(sizeof(xmlSchemaAttributeGroup));
5375 if (ret == NULL) {
5376 xmlSchemaPErrMemory(pctxt, "allocating attribute group", NULL);
5377 return (NULL);
5379 memset(ret, 0, sizeof(xmlSchemaAttributeGroup));
5380 ret->type = XML_SCHEMA_TYPE_ATTRIBUTEGROUP;
5381 ret->name = name;
5382 ret->targetNamespace = nsName;
5383 ret->node = node;
5385 /* TODO: Remove the flag. */
5386 ret->flags |= XML_SCHEMAS_ATTRGROUP_GLOBAL;
5387 if (pctxt->isRedefine) {
5388 pctxt->redef = xmlSchemaAddRedef(pctxt, pctxt->redefined,
5389 ret, name, nsName);
5390 if (pctxt->redef == NULL) {
5391 xmlFree(ret);
5392 return(NULL);
5394 pctxt->redefCounter = 0;
5396 WXS_ADD_GLOBAL(pctxt, ret);
5397 WXS_ADD_PENDING(pctxt, ret);
5398 return (ret);
5402 * xmlSchemaAddElement:
5403 * @ctxt: a schema parser context
5404 * @schema: the schema being built
5405 * @name: the type name
5406 * @namespace: the type namespace
5408 * Add an XML schema Element declaration
5409 * *WARNING* this interface is highly subject to change
5411 * Returns the new structure or NULL in case of error
5413 static xmlSchemaElementPtr
5414 xmlSchemaAddElement(xmlSchemaParserCtxtPtr ctxt,
5415 const xmlChar * name, const xmlChar * nsName,
5416 xmlNodePtr node, int topLevel)
5418 xmlSchemaElementPtr ret = NULL;
5420 if ((ctxt == NULL) || (name == NULL))
5421 return (NULL);
5423 ret = (xmlSchemaElementPtr) xmlMalloc(sizeof(xmlSchemaElement));
5424 if (ret == NULL) {
5425 xmlSchemaPErrMemory(ctxt, "allocating element", NULL);
5426 return (NULL);
5428 memset(ret, 0, sizeof(xmlSchemaElement));
5429 ret->type = XML_SCHEMA_TYPE_ELEMENT;
5430 ret->name = name;
5431 ret->targetNamespace = nsName;
5432 ret->node = node;
5434 if (topLevel)
5435 WXS_ADD_GLOBAL(ctxt, ret);
5436 else
5437 WXS_ADD_LOCAL(ctxt, ret);
5438 WXS_ADD_PENDING(ctxt, ret);
5439 return (ret);
5443 * xmlSchemaAddType:
5444 * @ctxt: a schema parser context
5445 * @schema: the schema being built
5446 * @name: the item name
5447 * @namespace: the namespace
5449 * Add an XML schema item
5450 * *WARNING* this interface is highly subject to change
5452 * Returns the new structure or NULL in case of error
5454 static xmlSchemaTypePtr
5455 xmlSchemaAddType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5456 xmlSchemaTypeType type,
5457 const xmlChar * name, const xmlChar * nsName,
5458 xmlNodePtr node, int topLevel)
5460 xmlSchemaTypePtr ret = NULL;
5462 if ((ctxt == NULL) || (schema == NULL))
5463 return (NULL);
5465 ret = (xmlSchemaTypePtr) xmlMalloc(sizeof(xmlSchemaType));
5466 if (ret == NULL) {
5467 xmlSchemaPErrMemory(ctxt, "allocating type", NULL);
5468 return (NULL);
5470 memset(ret, 0, sizeof(xmlSchemaType));
5471 ret->type = type;
5472 ret->name = name;
5473 ret->targetNamespace = nsName;
5474 ret->node = node;
5475 if (topLevel) {
5476 if (ctxt->isRedefine) {
5477 ctxt->redef = xmlSchemaAddRedef(ctxt, ctxt->redefined,
5478 ret, name, nsName);
5479 if (ctxt->redef == NULL) {
5480 xmlFree(ret);
5481 return(NULL);
5483 ctxt->redefCounter = 0;
5485 WXS_ADD_GLOBAL(ctxt, ret);
5486 } else
5487 WXS_ADD_LOCAL(ctxt, ret);
5488 WXS_ADD_PENDING(ctxt, ret);
5489 return (ret);
5492 static xmlSchemaQNameRefPtr
5493 xmlSchemaNewQNameRef(xmlSchemaParserCtxtPtr pctxt,
5494 xmlSchemaTypeType refType,
5495 const xmlChar *refName,
5496 const xmlChar *refNs)
5498 xmlSchemaQNameRefPtr ret;
5500 ret = (xmlSchemaQNameRefPtr)
5501 xmlMalloc(sizeof(xmlSchemaQNameRef));
5502 if (ret == NULL) {
5503 xmlSchemaPErrMemory(pctxt,
5504 "allocating QName reference item", NULL);
5505 return (NULL);
5507 ret->node = NULL;
5508 ret->type = XML_SCHEMA_EXTRA_QNAMEREF;
5509 ret->name = refName;
5510 ret->targetNamespace = refNs;
5511 ret->item = NULL;
5512 ret->itemType = refType;
5514 * Store the reference item in the schema.
5516 WXS_ADD_LOCAL(pctxt, ret);
5517 return (ret);
5520 static xmlSchemaAttributeUseProhibPtr
5521 xmlSchemaAddAttributeUseProhib(xmlSchemaParserCtxtPtr pctxt)
5523 xmlSchemaAttributeUseProhibPtr ret;
5525 ret = (xmlSchemaAttributeUseProhibPtr)
5526 xmlMalloc(sizeof(xmlSchemaAttributeUseProhib));
5527 if (ret == NULL) {
5528 xmlSchemaPErrMemory(pctxt,
5529 "allocating attribute use prohibition", NULL);
5530 return (NULL);
5532 memset(ret, 0, sizeof(xmlSchemaAttributeUseProhib));
5533 ret->type = XML_SCHEMA_EXTRA_ATTR_USE_PROHIB;
5534 WXS_ADD_LOCAL(pctxt, ret);
5535 return (ret);
5540 * xmlSchemaAddModelGroup:
5541 * @ctxt: a schema parser context
5542 * @schema: the schema being built
5543 * @type: the "compositor" type of the model group
5544 * @node: the node in the schema doc
5546 * Adds a schema model group
5547 * *WARNING* this interface is highly subject to change
5549 * Returns the new structure or NULL in case of error
5551 static xmlSchemaModelGroupPtr
5552 xmlSchemaAddModelGroup(xmlSchemaParserCtxtPtr ctxt,
5553 xmlSchemaPtr schema,
5554 xmlSchemaTypeType type,
5555 xmlNodePtr node)
5557 xmlSchemaModelGroupPtr ret = NULL;
5559 if ((ctxt == NULL) || (schema == NULL))
5560 return (NULL);
5562 ret = (xmlSchemaModelGroupPtr)
5563 xmlMalloc(sizeof(xmlSchemaModelGroup));
5564 if (ret == NULL) {
5565 xmlSchemaPErrMemory(ctxt, "allocating model group component",
5566 NULL);
5567 return (NULL);
5569 memset(ret, 0, sizeof(xmlSchemaModelGroup));
5570 ret->type = type;
5571 ret->node = node;
5572 WXS_ADD_LOCAL(ctxt, ret);
5573 if ((type == XML_SCHEMA_TYPE_SEQUENCE) ||
5574 (type == XML_SCHEMA_TYPE_CHOICE))
5575 WXS_ADD_PENDING(ctxt, ret);
5576 return (ret);
5581 * xmlSchemaAddParticle:
5582 * @ctxt: a schema parser context
5583 * @schema: the schema being built
5584 * @node: the corresponding node in the schema doc
5585 * @min: the minOccurs
5586 * @max: the maxOccurs
5588 * Adds an XML schema particle component.
5589 * *WARNING* this interface is highly subject to change
5591 * Returns the new structure or NULL in case of error
5593 static xmlSchemaParticlePtr
5594 xmlSchemaAddParticle(xmlSchemaParserCtxtPtr ctxt,
5595 xmlNodePtr node, int min, int max)
5597 xmlSchemaParticlePtr ret = NULL;
5598 if (ctxt == NULL)
5599 return (NULL);
5601 #ifdef DEBUG
5602 fprintf(stderr, "Adding particle component\n");
5603 #endif
5604 ret = (xmlSchemaParticlePtr)
5605 xmlMalloc(sizeof(xmlSchemaParticle));
5606 if (ret == NULL) {
5607 xmlSchemaPErrMemory(ctxt, "allocating particle component",
5608 NULL);
5609 return (NULL);
5611 ret->type = XML_SCHEMA_TYPE_PARTICLE;
5612 ret->annot = NULL;
5613 ret->node = node;
5614 ret->minOccurs = min;
5615 ret->maxOccurs = max;
5616 ret->next = NULL;
5617 ret->children = NULL;
5619 WXS_ADD_LOCAL(ctxt, ret);
5621 * Note that addition to pending components will be done locally
5622 * to the specific parsing function, since the most particles
5623 * need not to be fixed up (i.e. the reference to be resolved).
5624 * REMOVED: WXS_ADD_PENDING(ctxt, ret);
5626 return (ret);
5630 * xmlSchemaAddModelGroupDefinition:
5631 * @ctxt: a schema validation context
5632 * @schema: the schema being built
5633 * @name: the group name
5635 * Add an XML schema Group definition
5637 * Returns the new structure or NULL in case of error
5639 static xmlSchemaModelGroupDefPtr
5640 xmlSchemaAddModelGroupDefinition(xmlSchemaParserCtxtPtr ctxt,
5641 xmlSchemaPtr schema,
5642 const xmlChar *name,
5643 const xmlChar *nsName,
5644 xmlNodePtr node)
5646 xmlSchemaModelGroupDefPtr ret = NULL;
5648 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
5649 return (NULL);
5651 ret = (xmlSchemaModelGroupDefPtr)
5652 xmlMalloc(sizeof(xmlSchemaModelGroupDef));
5653 if (ret == NULL) {
5654 xmlSchemaPErrMemory(ctxt, "adding group", NULL);
5655 return (NULL);
5657 memset(ret, 0, sizeof(xmlSchemaModelGroupDef));
5658 ret->name = name;
5659 ret->type = XML_SCHEMA_TYPE_GROUP;
5660 ret->node = node;
5661 ret->targetNamespace = nsName;
5663 if (ctxt->isRedefine) {
5664 ctxt->redef = xmlSchemaAddRedef(ctxt, ctxt->redefined,
5665 ret, name, nsName);
5666 if (ctxt->redef == NULL) {
5667 xmlFree(ret);
5668 return(NULL);
5670 ctxt->redefCounter = 0;
5672 WXS_ADD_GLOBAL(ctxt, ret);
5673 WXS_ADD_PENDING(ctxt, ret);
5674 return (ret);
5678 * xmlSchemaNewWildcardNs:
5679 * @ctxt: a schema validation context
5681 * Creates a new wildcard namespace constraint.
5683 * Returns the new structure or NULL in case of error
5685 static xmlSchemaWildcardNsPtr
5686 xmlSchemaNewWildcardNsConstraint(xmlSchemaParserCtxtPtr ctxt)
5688 xmlSchemaWildcardNsPtr ret;
5690 ret = (xmlSchemaWildcardNsPtr)
5691 xmlMalloc(sizeof(xmlSchemaWildcardNs));
5692 if (ret == NULL) {
5693 xmlSchemaPErrMemory(ctxt, "creating wildcard namespace constraint", NULL);
5694 return (NULL);
5696 ret->value = NULL;
5697 ret->next = NULL;
5698 return (ret);
5701 static xmlSchemaIDCPtr
5702 xmlSchemaAddIDC(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5703 const xmlChar *name, const xmlChar *nsName,
5704 int category, xmlNodePtr node)
5706 xmlSchemaIDCPtr ret = NULL;
5708 if ((ctxt == NULL) || (schema == NULL) || (name == NULL))
5709 return (NULL);
5711 ret = (xmlSchemaIDCPtr) xmlMalloc(sizeof(xmlSchemaIDC));
5712 if (ret == NULL) {
5713 xmlSchemaPErrMemory(ctxt,
5714 "allocating an identity-constraint definition", NULL);
5715 return (NULL);
5717 memset(ret, 0, sizeof(xmlSchemaIDC));
5718 /* The target namespace of the parent element declaration. */
5719 ret->targetNamespace = nsName;
5720 ret->name = name;
5721 ret->type = category;
5722 ret->node = node;
5724 WXS_ADD_GLOBAL(ctxt, ret);
5726 * Only keyrefs need to be fixup up.
5728 if (category == XML_SCHEMA_TYPE_IDC_KEYREF)
5729 WXS_ADD_PENDING(ctxt, ret);
5730 return (ret);
5734 * xmlSchemaAddWildcard:
5735 * @ctxt: a schema validation context
5736 * @schema: a schema
5738 * Adds a wildcard.
5739 * It corresponds to a xsd:anyAttribute and xsd:any.
5741 * Returns the new structure or NULL in case of error
5743 static xmlSchemaWildcardPtr
5744 xmlSchemaAddWildcard(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
5745 xmlSchemaTypeType type, xmlNodePtr node)
5747 xmlSchemaWildcardPtr ret = NULL;
5749 if ((ctxt == NULL) || (schema == NULL))
5750 return (NULL);
5752 ret = (xmlSchemaWildcardPtr) xmlMalloc(sizeof(xmlSchemaWildcard));
5753 if (ret == NULL) {
5754 xmlSchemaPErrMemory(ctxt, "adding wildcard", NULL);
5755 return (NULL);
5757 memset(ret, 0, sizeof(xmlSchemaWildcard));
5758 ret->type = type;
5759 ret->node = node;
5760 WXS_ADD_LOCAL(ctxt, ret);
5761 return (ret);
5764 static void
5765 xmlSchemaSubstGroupFree(xmlSchemaSubstGroupPtr group)
5767 if (group == NULL)
5768 return;
5769 if (group->members != NULL)
5770 xmlSchemaItemListFree(group->members);
5771 xmlFree(group);
5774 static void
5775 xmlSchemaSubstGroupFreeEntry(void *group, const xmlChar *name ATTRIBUTE_UNUSED)
5777 xmlSchemaSubstGroupFree((xmlSchemaSubstGroupPtr) group);
5780 static xmlSchemaSubstGroupPtr
5781 xmlSchemaSubstGroupAdd(xmlSchemaParserCtxtPtr pctxt,
5782 xmlSchemaElementPtr head)
5784 xmlSchemaSubstGroupPtr ret;
5786 /* Init subst group hash. */
5787 if (WXS_SUBST_GROUPS(pctxt) == NULL) {
5788 WXS_SUBST_GROUPS(pctxt) = xmlHashCreateDict(10, pctxt->dict);
5789 if (WXS_SUBST_GROUPS(pctxt) == NULL)
5790 return(NULL);
5792 /* Create a new substitution group. */
5793 ret = (xmlSchemaSubstGroupPtr) xmlMalloc(sizeof(xmlSchemaSubstGroup));
5794 if (ret == NULL) {
5795 xmlSchemaPErrMemory(NULL,
5796 "allocating a substitution group container", NULL);
5797 return(NULL);
5799 memset(ret, 0, sizeof(xmlSchemaSubstGroup));
5800 ret->head = head;
5801 /* Create list of members. */
5802 ret->members = xmlSchemaItemListCreate();
5803 if (ret->members == NULL) {
5804 xmlSchemaSubstGroupFree(ret);
5805 return(NULL);
5807 /* Add subst group to hash. */
5808 if (xmlHashAddEntry2(WXS_SUBST_GROUPS(pctxt),
5809 head->name, head->targetNamespace, ret) != 0) {
5810 PERROR_INT("xmlSchemaSubstGroupAdd",
5811 "failed to add a new substitution container");
5812 xmlSchemaSubstGroupFree(ret);
5813 return(NULL);
5815 return(ret);
5818 static xmlSchemaSubstGroupPtr
5819 xmlSchemaSubstGroupGet(xmlSchemaParserCtxtPtr pctxt,
5820 xmlSchemaElementPtr head)
5822 if (WXS_SUBST_GROUPS(pctxt) == NULL)
5823 return(NULL);
5824 return(xmlHashLookup2(WXS_SUBST_GROUPS(pctxt),
5825 head->name, head->targetNamespace));
5830 * xmlSchemaAddElementSubstitutionMember:
5831 * @pctxt: a schema parser context
5832 * @head: the head of the substitution group
5833 * @member: the new member of the substitution group
5835 * Allocate a new annotation structure.
5837 * Returns the newly allocated structure or NULL in case or error
5839 static int
5840 xmlSchemaAddElementSubstitutionMember(xmlSchemaParserCtxtPtr pctxt,
5841 xmlSchemaElementPtr head,
5842 xmlSchemaElementPtr member)
5844 xmlSchemaSubstGroupPtr substGroup = NULL;
5846 if ((pctxt == NULL) || (head == NULL) || (member == NULL))
5847 return (-1);
5849 substGroup = xmlSchemaSubstGroupGet(pctxt, head);
5850 if (substGroup == NULL)
5851 substGroup = xmlSchemaSubstGroupAdd(pctxt, head);
5852 if (substGroup == NULL)
5853 return(-1);
5854 if (xmlSchemaItemListAdd(substGroup->members, member) == -1)
5855 return(-1);
5856 return(0);
5859 /************************************************************************
5861 * Utilities for parsing *
5863 ************************************************************************/
5866 * xmlSchemaPValAttrNodeQNameValue:
5867 * @ctxt: a schema parser context
5868 * @schema: the schema context
5869 * @ownerItem: the parent as a schema object
5870 * @value: the QName value
5871 * @uri: the resulting namespace URI if found
5872 * @local: the resulting local part if found, the attribute value otherwise
5874 * Extracts the local name and the URI of a QName value and validates it.
5875 * This one is intended to be used on attribute values that
5876 * should resolve to schema components.
5878 * Returns 0, in case the QName is valid, a positive error code
5879 * if not valid and -1 if an internal error occurs.
5881 static int
5882 xmlSchemaPValAttrNodeQNameValue(xmlSchemaParserCtxtPtr ctxt,
5883 xmlSchemaPtr schema,
5884 xmlSchemaBasicItemPtr ownerItem,
5885 xmlAttrPtr attr,
5886 const xmlChar *value,
5887 const xmlChar **uri,
5888 const xmlChar **local)
5890 const xmlChar *pref;
5891 xmlNsPtr ns;
5892 int len, ret;
5894 *uri = NULL;
5895 *local = NULL;
5896 ret = xmlValidateQName(value, 1);
5897 if (ret > 0) {
5898 xmlSchemaPSimpleTypeErr(ctxt,
5899 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5900 ownerItem, (xmlNodePtr) attr,
5901 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
5902 NULL, value, NULL, NULL, NULL);
5903 *local = value;
5904 return (ctxt->err);
5905 } else if (ret < 0)
5906 return (-1);
5908 if (!strchr((char *) value, ':')) {
5909 ns = xmlSearchNs(attr->doc, attr->parent, NULL);
5910 if (ns && ns->href && ns->href[0])
5911 *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
5912 else if (schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) {
5913 /* TODO: move XML_SCHEMAS_INCLUDING_CONVERT_NS to the
5914 * parser context. */
5916 * This one takes care of included schemas with no
5917 * target namespace.
5919 *uri = ctxt->targetNamespace;
5921 *local = xmlDictLookup(ctxt->dict, value, -1);
5922 return (0);
5925 * At this point xmlSplitQName3 has to return a local name.
5927 *local = xmlSplitQName3(value, &len);
5928 *local = xmlDictLookup(ctxt->dict, *local, -1);
5929 pref = xmlDictLookup(ctxt->dict, value, len);
5930 ns = xmlSearchNs(attr->doc, attr->parent, pref);
5931 if (ns == NULL) {
5932 xmlSchemaPSimpleTypeErr(ctxt,
5933 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
5934 ownerItem, (xmlNodePtr) attr,
5935 xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), NULL, value,
5936 "The value '%s' of simple type 'xs:QName' has no "
5937 "corresponding namespace declaration in scope", value, NULL);
5938 return (ctxt->err);
5939 } else {
5940 *uri = xmlDictLookup(ctxt->dict, ns->href, -1);
5942 return (0);
5946 * xmlSchemaPValAttrNodeQName:
5947 * @ctxt: a schema parser context
5948 * @schema: the schema context
5949 * @ownerItem: the owner as a schema object
5950 * @attr: the attribute node
5951 * @uri: the resulting namespace URI if found
5952 * @local: the resulting local part if found, the attribute value otherwise
5954 * Extracts and validates the QName of an attribute value.
5955 * This one is intended to be used on attribute values that
5956 * should resolve to schema components.
5958 * Returns 0, in case the QName is valid, a positive error code
5959 * if not valid and -1 if an internal error occurs.
5961 static int
5962 xmlSchemaPValAttrNodeQName(xmlSchemaParserCtxtPtr ctxt,
5963 xmlSchemaPtr schema,
5964 xmlSchemaBasicItemPtr ownerItem,
5965 xmlAttrPtr attr,
5966 const xmlChar **uri,
5967 const xmlChar **local)
5969 const xmlChar *value;
5971 value = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
5972 return (xmlSchemaPValAttrNodeQNameValue(ctxt, schema,
5973 ownerItem, attr, value, uri, local));
5977 * xmlSchemaPValAttrQName:
5978 * @ctxt: a schema parser context
5979 * @schema: the schema context
5980 * @ownerItem: the owner as a schema object
5981 * @ownerElem: the parent node of the attribute
5982 * @name: the name of the attribute
5983 * @uri: the resulting namespace URI if found
5984 * @local: the resulting local part if found, the attribute value otherwise
5986 * Extracts and validates the QName of an attribute value.
5988 * Returns 0, in case the QName is valid, a positive error code
5989 * if not valid and -1 if an internal error occurs.
5991 static int
5992 xmlSchemaPValAttrQName(xmlSchemaParserCtxtPtr ctxt,
5993 xmlSchemaPtr schema,
5994 xmlSchemaBasicItemPtr ownerItem,
5995 xmlNodePtr ownerElem,
5996 const char *name,
5997 const xmlChar **uri,
5998 const xmlChar **local)
6000 xmlAttrPtr attr;
6002 attr = xmlSchemaGetPropNode(ownerElem, name);
6003 if (attr == NULL) {
6004 *local = NULL;
6005 *uri = NULL;
6006 return (0);
6008 return (xmlSchemaPValAttrNodeQName(ctxt, schema,
6009 ownerItem, attr, uri, local));
6013 * xmlSchemaPValAttrID:
6014 * @ctxt: a schema parser context
6016 * Extracts and validates the ID of an attribute value.
6018 * Returns 0, in case the ID is valid, a positive error code
6019 * if not valid and -1 if an internal error occurs.
6021 static int
6022 xmlSchemaPValAttrNodeID(xmlSchemaParserCtxtPtr ctxt, xmlAttrPtr attr)
6024 int ret;
6025 const xmlChar *value;
6027 if (attr == NULL)
6028 return(0);
6029 value = xmlSchemaGetNodeContentNoDict((xmlNodePtr) attr);
6030 ret = xmlValidateNCName(value, 1);
6031 if (ret == 0) {
6033 * NOTE: the IDness might have already be declared in the DTD
6035 if (attr->atype != XML_ATTRIBUTE_ID) {
6036 xmlIDPtr res;
6037 xmlChar *strip;
6040 * TODO: Use xmlSchemaStrip here; it's not exported at this
6041 * moment.
6043 strip = xmlSchemaCollapseString(value);
6044 if (strip != NULL) {
6045 xmlFree((xmlChar *) value);
6046 value = strip;
6048 res = xmlAddID(NULL, attr->doc, value, attr);
6049 if (res == NULL) {
6050 ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
6051 xmlSchemaPSimpleTypeErr(ctxt,
6052 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6053 NULL, (xmlNodePtr) attr,
6054 xmlSchemaGetBuiltInType(XML_SCHEMAS_ID),
6055 NULL, NULL, "Duplicate value '%s' of simple "
6056 "type 'xs:ID'", value, NULL);
6057 } else
6058 attr->atype = XML_ATTRIBUTE_ID;
6060 } else if (ret > 0) {
6061 ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
6062 xmlSchemaPSimpleTypeErr(ctxt,
6063 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6064 NULL, (xmlNodePtr) attr,
6065 xmlSchemaGetBuiltInType(XML_SCHEMAS_ID),
6066 NULL, NULL, "The value '%s' of simple type 'xs:ID' is "
6067 "not a valid 'xs:NCName'",
6068 value, NULL);
6070 if (value != NULL)
6071 xmlFree((xmlChar *)value);
6073 return (ret);
6076 static int
6077 xmlSchemaPValAttrID(xmlSchemaParserCtxtPtr ctxt,
6078 xmlNodePtr ownerElem,
6079 const xmlChar *name)
6081 xmlAttrPtr attr;
6083 attr = xmlSchemaGetPropNode(ownerElem, (const char *) name);
6084 if (attr == NULL)
6085 return(0);
6086 return(xmlSchemaPValAttrNodeID(ctxt, attr));
6091 * xmlGetMaxOccurs:
6092 * @ctxt: a schema validation context
6093 * @node: a subtree containing XML Schema information
6095 * Get the maxOccurs property
6097 * Returns the default if not found, or the value
6099 static int
6100 xmlGetMaxOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
6101 int min, int max, int def, const char *expected)
6103 const xmlChar *val, *cur;
6104 int ret = 0;
6105 xmlAttrPtr attr;
6107 attr = xmlSchemaGetPropNode(node, "maxOccurs");
6108 if (attr == NULL)
6109 return (def);
6110 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6111 if (val == NULL)
6112 return (def);
6114 if (xmlStrEqual(val, (const xmlChar *) "unbounded")) {
6115 if (max != UNBOUNDED) {
6116 xmlSchemaPSimpleTypeErr(ctxt,
6117 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6118 /* XML_SCHEMAP_INVALID_MINOCCURS, */
6119 NULL, (xmlNodePtr) attr, NULL, expected,
6120 val, NULL, NULL, NULL);
6121 return (def);
6122 } else
6123 return (UNBOUNDED); /* encoding it with -1 might be another option */
6126 cur = val;
6127 while (IS_BLANK_CH(*cur))
6128 cur++;
6129 if (*cur == 0) {
6130 xmlSchemaPSimpleTypeErr(ctxt,
6131 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6132 /* XML_SCHEMAP_INVALID_MINOCCURS, */
6133 NULL, (xmlNodePtr) attr, NULL, expected,
6134 val, NULL, NULL, NULL);
6135 return (def);
6137 while ((*cur >= '0') && (*cur <= '9')) {
6138 if (ret > INT_MAX / 10) {
6139 ret = INT_MAX;
6140 } else {
6141 int digit = *cur - '0';
6142 ret *= 10;
6143 if (ret > INT_MAX - digit)
6144 ret = INT_MAX;
6145 else
6146 ret += digit;
6148 cur++;
6150 while (IS_BLANK_CH(*cur))
6151 cur++;
6153 * TODO: Restrict the maximal value to Integer.
6155 if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
6156 xmlSchemaPSimpleTypeErr(ctxt,
6157 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6158 /* XML_SCHEMAP_INVALID_MINOCCURS, */
6159 NULL, (xmlNodePtr) attr, NULL, expected,
6160 val, NULL, NULL, NULL);
6161 return (def);
6163 return (ret);
6167 * xmlGetMinOccurs:
6168 * @ctxt: a schema validation context
6169 * @node: a subtree containing XML Schema information
6171 * Get the minOccurs property
6173 * Returns the default if not found, or the value
6175 static int
6176 xmlGetMinOccurs(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node,
6177 int min, int max, int def, const char *expected)
6179 const xmlChar *val, *cur;
6180 int ret = 0;
6181 xmlAttrPtr attr;
6183 attr = xmlSchemaGetPropNode(node, "minOccurs");
6184 if (attr == NULL)
6185 return (def);
6186 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6187 if (val == NULL)
6188 return (def);
6189 cur = val;
6190 while (IS_BLANK_CH(*cur))
6191 cur++;
6192 if (*cur == 0) {
6193 xmlSchemaPSimpleTypeErr(ctxt,
6194 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6195 /* XML_SCHEMAP_INVALID_MINOCCURS, */
6196 NULL, (xmlNodePtr) attr, NULL, expected,
6197 val, NULL, NULL, NULL);
6198 return (def);
6200 while ((*cur >= '0') && (*cur <= '9')) {
6201 if (ret > INT_MAX / 10) {
6202 ret = INT_MAX;
6203 } else {
6204 int digit = *cur - '0';
6205 ret *= 10;
6206 if (ret > INT_MAX - digit)
6207 ret = INT_MAX;
6208 else
6209 ret += digit;
6211 cur++;
6213 while (IS_BLANK_CH(*cur))
6214 cur++;
6216 * TODO: Restrict the maximal value to Integer.
6218 if ((*cur != 0) || (ret < min) || ((max != -1) && (ret > max))) {
6219 xmlSchemaPSimpleTypeErr(ctxt,
6220 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6221 /* XML_SCHEMAP_INVALID_MINOCCURS, */
6222 NULL, (xmlNodePtr) attr, NULL, expected,
6223 val, NULL, NULL, NULL);
6224 return (def);
6226 return (ret);
6230 * xmlSchemaPGetBoolNodeValue:
6231 * @ctxt: a schema validation context
6232 * @ownerItem: the owner as a schema item
6233 * @node: the node holding the value
6235 * Converts a boolean string value into 1 or 0.
6237 * Returns 0 or 1.
6239 static int
6240 xmlSchemaPGetBoolNodeValue(xmlSchemaParserCtxtPtr ctxt,
6241 xmlSchemaBasicItemPtr ownerItem,
6242 xmlNodePtr node)
6244 xmlChar *value = NULL;
6245 int res = 0;
6247 value = xmlNodeGetContent(node);
6249 * 3.2.2.1 Lexical representation
6250 * An instance of a datatype that is defined as `boolean`
6251 * can have the following legal literals {true, false, 1, 0}.
6253 if (xmlStrEqual(BAD_CAST value, BAD_CAST "true"))
6254 res = 1;
6255 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "false"))
6256 res = 0;
6257 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "1"))
6258 res = 1;
6259 else if (xmlStrEqual(BAD_CAST value, BAD_CAST "0"))
6260 res = 0;
6261 else {
6262 xmlSchemaPSimpleTypeErr(ctxt,
6263 XML_SCHEMAP_INVALID_BOOLEAN,
6264 ownerItem, node,
6265 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
6266 NULL, BAD_CAST value,
6267 NULL, NULL, NULL);
6269 if (value != NULL)
6270 xmlFree(value);
6271 return (res);
6275 * xmlGetBooleanProp:
6276 * @ctxt: a schema validation context
6277 * @node: a subtree containing XML Schema information
6278 * @name: the attribute name
6279 * @def: the default value
6281 * Evaluate if a boolean property is set
6283 * Returns the default if not found, 0 if found to be false,
6284 * 1 if found to be true
6286 static int
6287 xmlGetBooleanProp(xmlSchemaParserCtxtPtr ctxt,
6288 xmlNodePtr node,
6289 const char *name, int def)
6291 const xmlChar *val;
6293 val = xmlSchemaGetProp(ctxt, node, name);
6294 if (val == NULL)
6295 return (def);
6297 * 3.2.2.1 Lexical representation
6298 * An instance of a datatype that is defined as `boolean`
6299 * can have the following legal literals {true, false, 1, 0}.
6301 if (xmlStrEqual(val, BAD_CAST "true"))
6302 def = 1;
6303 else if (xmlStrEqual(val, BAD_CAST "false"))
6304 def = 0;
6305 else if (xmlStrEqual(val, BAD_CAST "1"))
6306 def = 1;
6307 else if (xmlStrEqual(val, BAD_CAST "0"))
6308 def = 0;
6309 else {
6310 xmlSchemaPSimpleTypeErr(ctxt,
6311 XML_SCHEMAP_INVALID_BOOLEAN,
6312 NULL,
6313 (xmlNodePtr) xmlSchemaGetPropNode(node, name),
6314 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
6315 NULL, val, NULL, NULL, NULL);
6317 return (def);
6320 /************************************************************************
6322 * Schema extraction from an Infoset *
6324 ************************************************************************/
6325 static xmlSchemaTypePtr xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr
6326 ctxt, xmlSchemaPtr schema,
6327 xmlNodePtr node,
6328 int topLevel);
6329 static xmlSchemaTypePtr xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr
6330 ctxt,
6331 xmlSchemaPtr schema,
6332 xmlNodePtr node,
6333 int topLevel);
6334 static xmlSchemaTypePtr xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr
6335 ctxt,
6336 xmlSchemaPtr schema,
6337 xmlNodePtr node,
6338 xmlSchemaTypeType parentType);
6339 static xmlSchemaBasicItemPtr
6340 xmlSchemaParseLocalAttribute(xmlSchemaParserCtxtPtr pctxt,
6341 xmlSchemaPtr schema,
6342 xmlNodePtr node,
6343 xmlSchemaItemListPtr uses,
6344 int parentType);
6345 static xmlSchemaTypePtr xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt,
6346 xmlSchemaPtr schema,
6347 xmlNodePtr node);
6348 static xmlSchemaWildcardPtr
6349 xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
6350 xmlSchemaPtr schema, xmlNodePtr node);
6353 * xmlSchemaPValAttrNodeValue:
6355 * @pctxt: a schema parser context
6356 * @ownerItem: the schema object owner if existent
6357 * @attr: the schema attribute node being validated
6358 * @value: the value
6359 * @type: the built-in type to be validated against
6361 * Validates a value against the given built-in type.
6362 * This one is intended to be used internally for validation
6363 * of schema attribute values during parsing of the schema.
6365 * Returns 0 if the value is valid, a positive error code
6366 * number otherwise and -1 in case of an internal or API error.
6368 static int
6369 xmlSchemaPValAttrNodeValue(xmlSchemaParserCtxtPtr pctxt,
6370 xmlSchemaBasicItemPtr ownerItem,
6371 xmlAttrPtr attr,
6372 const xmlChar *value,
6373 xmlSchemaTypePtr type)
6376 int ret = 0;
6379 * NOTE: Should we move this to xmlschematypes.c? Hmm, but this
6380 * one is really meant to be used internally, so better not.
6382 if ((pctxt == NULL) || (type == NULL) || (attr == NULL))
6383 return (-1);
6384 if (type->type != XML_SCHEMA_TYPE_BASIC) {
6385 PERROR_INT("xmlSchemaPValAttrNodeValue",
6386 "the given type is not a built-in type");
6387 return (-1);
6389 switch (type->builtInType) {
6390 case XML_SCHEMAS_NCNAME:
6391 case XML_SCHEMAS_QNAME:
6392 case XML_SCHEMAS_ANYURI:
6393 case XML_SCHEMAS_TOKEN:
6394 case XML_SCHEMAS_LANGUAGE:
6395 ret = xmlSchemaValPredefTypeNode(type, value, NULL,
6396 (xmlNodePtr) attr);
6397 break;
6398 default: {
6399 PERROR_INT("xmlSchemaPValAttrNodeValue",
6400 "validation using the given type is not supported while "
6401 "parsing a schema");
6402 return (-1);
6406 * TODO: Should we use the S4S error codes instead?
6408 if (ret < 0) {
6409 PERROR_INT("xmlSchemaPValAttrNodeValue",
6410 "failed to validate a schema attribute value");
6411 return (-1);
6412 } else if (ret > 0) {
6413 if (WXS_IS_LIST(type))
6414 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
6415 else
6416 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
6417 xmlSchemaPSimpleTypeErr(pctxt,
6418 ret, ownerItem, (xmlNodePtr) attr,
6419 type, NULL, value, NULL, NULL, NULL);
6421 return (ret);
6425 * xmlSchemaPValAttrNode:
6427 * @ctxt: a schema parser context
6428 * @ownerItem: the schema object owner if existent
6429 * @attr: the schema attribute node being validated
6430 * @type: the built-in type to be validated against
6431 * @value: the resulting value if any
6433 * Extracts and validates a value against the given built-in type.
6434 * This one is intended to be used internally for validation
6435 * of schema attribute values during parsing of the schema.
6437 * Returns 0 if the value is valid, a positive error code
6438 * number otherwise and -1 in case of an internal or API error.
6440 static int
6441 xmlSchemaPValAttrNode(xmlSchemaParserCtxtPtr ctxt,
6442 xmlSchemaBasicItemPtr ownerItem,
6443 xmlAttrPtr attr,
6444 xmlSchemaTypePtr type,
6445 const xmlChar **value)
6447 const xmlChar *val;
6449 if ((ctxt == NULL) || (type == NULL) || (attr == NULL))
6450 return (-1);
6452 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6453 if (value != NULL)
6454 *value = val;
6456 return (xmlSchemaPValAttrNodeValue(ctxt, ownerItem, attr,
6457 val, type));
6461 * xmlSchemaPValAttr:
6463 * @ctxt: a schema parser context
6464 * @node: the element node of the attribute
6465 * @ownerItem: the schema object owner if existent
6466 * @ownerElem: the owner element node
6467 * @name: the name of the schema attribute node
6468 * @type: the built-in type to be validated against
6469 * @value: the resulting value if any
6471 * Extracts and validates a value against the given built-in type.
6472 * This one is intended to be used internally for validation
6473 * of schema attribute values during parsing of the schema.
6475 * Returns 0 if the value is valid, a positive error code
6476 * number otherwise and -1 in case of an internal or API error.
6478 static int
6479 xmlSchemaPValAttr(xmlSchemaParserCtxtPtr ctxt,
6480 xmlSchemaBasicItemPtr ownerItem,
6481 xmlNodePtr ownerElem,
6482 const char *name,
6483 xmlSchemaTypePtr type,
6484 const xmlChar **value)
6486 xmlAttrPtr attr;
6488 if ((ctxt == NULL) || (type == NULL)) {
6489 if (value != NULL)
6490 *value = NULL;
6491 return (-1);
6493 if (type->type != XML_SCHEMA_TYPE_BASIC) {
6494 if (value != NULL)
6495 *value = NULL;
6496 xmlSchemaPErr(ctxt, ownerElem,
6497 XML_SCHEMAP_INTERNAL,
6498 "Internal error: xmlSchemaPValAttr, the given "
6499 "type '%s' is not a built-in type.\n",
6500 type->name, NULL);
6501 return (-1);
6503 attr = xmlSchemaGetPropNode(ownerElem, name);
6504 if (attr == NULL) {
6505 if (value != NULL)
6506 *value = NULL;
6507 return (0);
6509 return (xmlSchemaPValAttrNode(ctxt, ownerItem, attr,
6510 type, value));
6513 static int
6514 xmlSchemaCheckReference(xmlSchemaParserCtxtPtr pctxt,
6515 xmlSchemaPtr schema ATTRIBUTE_UNUSED,
6516 xmlNodePtr node,
6517 xmlAttrPtr attr,
6518 const xmlChar *namespaceName)
6520 /* TODO: Pointer comparison instead? */
6521 if (xmlStrEqual(pctxt->targetNamespace, namespaceName))
6522 return (0);
6523 if (xmlStrEqual(xmlSchemaNs, namespaceName))
6524 return (0);
6526 * Check if the referenced namespace was <import>ed.
6528 if (WXS_BUCKET(pctxt)->relations != NULL) {
6529 xmlSchemaSchemaRelationPtr rel;
6531 rel = WXS_BUCKET(pctxt)->relations;
6532 do {
6533 if (WXS_IS_BUCKET_IMPMAIN(rel->type) &&
6534 xmlStrEqual(namespaceName, rel->importNamespace))
6535 return (0);
6536 rel = rel->next;
6537 } while (rel != NULL);
6540 * No matching <import>ed namespace found.
6543 xmlNodePtr n = (attr != NULL) ? (xmlNodePtr) attr : node;
6545 if (namespaceName == NULL)
6546 xmlSchemaCustomErr(ACTXT_CAST pctxt,
6547 XML_SCHEMAP_SRC_RESOLVE, n, NULL,
6548 "References from this schema to components in no "
6549 "namespace are not allowed, since not indicated by an "
6550 "import statement", NULL, NULL);
6551 else
6552 xmlSchemaCustomErr(ACTXT_CAST pctxt,
6553 XML_SCHEMAP_SRC_RESOLVE, n, NULL,
6554 "References from this schema to components in the "
6555 "namespace '%s' are not allowed, since not indicated by an "
6556 "import statement", namespaceName, NULL);
6558 return (XML_SCHEMAP_SRC_RESOLVE);
6562 * xmlSchemaParseLocalAttributes:
6563 * @ctxt: a schema validation context
6564 * @schema: the schema being built
6565 * @node: a subtree containing XML Schema information
6566 * @type: the hosting type where the attributes will be anchored
6568 * Parses attribute uses and attribute declarations and
6569 * attribute group references.
6571 static int
6572 xmlSchemaParseLocalAttributes(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6573 xmlNodePtr *child, xmlSchemaItemListPtr *list,
6574 int parentType, int *hasRefs)
6576 void *item;
6578 while ((IS_SCHEMA((*child), "attribute")) ||
6579 (IS_SCHEMA((*child), "attributeGroup"))) {
6580 if (IS_SCHEMA((*child), "attribute")) {
6581 item = xmlSchemaParseLocalAttribute(ctxt, schema, *child,
6582 *list, parentType);
6583 } else {
6584 item = xmlSchemaParseAttributeGroupRef(ctxt, schema, *child);
6585 if ((item != NULL) && (hasRefs != NULL))
6586 *hasRefs = 1;
6588 if (item != NULL) {
6589 if (*list == NULL) {
6590 /* TODO: Customize grow factor. */
6591 *list = xmlSchemaItemListCreate();
6592 if (*list == NULL)
6593 return(-1);
6595 if (xmlSchemaItemListAddSize(*list, 2, item) == -1)
6596 return(-1);
6598 *child = (*child)->next;
6600 return (0);
6604 * xmlSchemaParseAnnotation:
6605 * @ctxt: a schema validation context
6606 * @schema: the schema being built
6607 * @node: a subtree containing XML Schema information
6609 * parse a XML schema Attribute declaration
6610 * *WARNING* this interface is highly subject to change
6612 * Returns -1 in case of error, 0 if the declaration is improper and
6613 * 1 in case of success.
6615 static xmlSchemaAnnotPtr
6616 xmlSchemaParseAnnotation(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr node, int needed)
6618 xmlSchemaAnnotPtr ret;
6619 xmlNodePtr child = NULL;
6620 xmlAttrPtr attr;
6621 int barked = 0;
6624 * INFO: S4S completed.
6627 * id = ID
6628 * {any attributes with non-schema namespace . . .}>
6629 * Content: (appinfo | documentation)*
6631 if ((ctxt == NULL) || (node == NULL))
6632 return (NULL);
6633 if (needed)
6634 ret = xmlSchemaNewAnnot(ctxt, node);
6635 else
6636 ret = NULL;
6637 attr = node->properties;
6638 while (attr != NULL) {
6639 if (((attr->ns == NULL) &&
6640 (!xmlStrEqual(attr->name, BAD_CAST "id"))) ||
6641 ((attr->ns != NULL) &&
6642 xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
6644 xmlSchemaPIllegalAttrErr(ctxt,
6645 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
6647 attr = attr->next;
6649 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
6651 * And now for the children...
6653 child = node->children;
6654 while (child != NULL) {
6655 if (IS_SCHEMA(child, "appinfo")) {
6656 /* TODO: make available the content of "appinfo". */
6658 * source = anyURI
6659 * {any attributes with non-schema namespace . . .}>
6660 * Content: ({any})*
6662 attr = child->properties;
6663 while (attr != NULL) {
6664 if (((attr->ns == NULL) &&
6665 (!xmlStrEqual(attr->name, BAD_CAST "source"))) ||
6666 ((attr->ns != NULL) &&
6667 xmlStrEqual(attr->ns->href, xmlSchemaNs))) {
6669 xmlSchemaPIllegalAttrErr(ctxt,
6670 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
6672 attr = attr->next;
6674 xmlSchemaPValAttr(ctxt, NULL, child, "source",
6675 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), NULL);
6676 child = child->next;
6677 } else if (IS_SCHEMA(child, "documentation")) {
6678 /* TODO: make available the content of "documentation". */
6680 * source = anyURI
6681 * {any attributes with non-schema namespace . . .}>
6682 * Content: ({any})*
6684 attr = child->properties;
6685 while (attr != NULL) {
6686 if (attr->ns == NULL) {
6687 if (!xmlStrEqual(attr->name, BAD_CAST "source")) {
6688 xmlSchemaPIllegalAttrErr(ctxt,
6689 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
6691 } else {
6692 if (xmlStrEqual(attr->ns->href, xmlSchemaNs) ||
6693 (xmlStrEqual(attr->name, BAD_CAST "lang") &&
6694 (!xmlStrEqual(attr->ns->href, XML_XML_NAMESPACE)))) {
6696 xmlSchemaPIllegalAttrErr(ctxt,
6697 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
6700 attr = attr->next;
6703 * Attribute "xml:lang".
6705 attr = xmlSchemaGetPropNodeNs(child, (const char *) XML_XML_NAMESPACE, "lang");
6706 if (attr != NULL)
6707 xmlSchemaPValAttrNode(ctxt, NULL, attr,
6708 xmlSchemaGetBuiltInType(XML_SCHEMAS_LANGUAGE), NULL);
6709 child = child->next;
6710 } else {
6711 if (!barked)
6712 xmlSchemaPContentErr(ctxt,
6713 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
6714 NULL, node, child, NULL, "(appinfo | documentation)*");
6715 barked = 1;
6716 child = child->next;
6720 return (ret);
6724 * xmlSchemaParseFacet:
6725 * @ctxt: a schema validation context
6726 * @schema: the schema being built
6727 * @node: a subtree containing XML Schema information
6729 * parse a XML schema Facet declaration
6730 * *WARNING* this interface is highly subject to change
6732 * Returns the new type structure or NULL in case of error
6734 static xmlSchemaFacetPtr
6735 xmlSchemaParseFacet(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6736 xmlNodePtr node)
6738 xmlSchemaFacetPtr facet;
6739 xmlNodePtr child = NULL;
6740 const xmlChar *value;
6742 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
6743 return (NULL);
6745 facet = xmlSchemaNewFacet();
6746 if (facet == NULL) {
6747 xmlSchemaPErrMemory(ctxt, "allocating facet", node);
6748 return (NULL);
6750 facet->node = node;
6751 value = xmlSchemaGetProp(ctxt, node, "value");
6752 if (value == NULL) {
6753 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_FACET_NO_VALUE,
6754 "Facet %s has no value\n", node->name, NULL);
6755 xmlSchemaFreeFacet(facet);
6756 return (NULL);
6758 if (IS_SCHEMA(node, "minInclusive")) {
6759 facet->type = XML_SCHEMA_FACET_MININCLUSIVE;
6760 } else if (IS_SCHEMA(node, "minExclusive")) {
6761 facet->type = XML_SCHEMA_FACET_MINEXCLUSIVE;
6762 } else if (IS_SCHEMA(node, "maxInclusive")) {
6763 facet->type = XML_SCHEMA_FACET_MAXINCLUSIVE;
6764 } else if (IS_SCHEMA(node, "maxExclusive")) {
6765 facet->type = XML_SCHEMA_FACET_MAXEXCLUSIVE;
6766 } else if (IS_SCHEMA(node, "totalDigits")) {
6767 facet->type = XML_SCHEMA_FACET_TOTALDIGITS;
6768 } else if (IS_SCHEMA(node, "fractionDigits")) {
6769 facet->type = XML_SCHEMA_FACET_FRACTIONDIGITS;
6770 } else if (IS_SCHEMA(node, "pattern")) {
6771 facet->type = XML_SCHEMA_FACET_PATTERN;
6772 } else if (IS_SCHEMA(node, "enumeration")) {
6773 facet->type = XML_SCHEMA_FACET_ENUMERATION;
6774 } else if (IS_SCHEMA(node, "whiteSpace")) {
6775 facet->type = XML_SCHEMA_FACET_WHITESPACE;
6776 } else if (IS_SCHEMA(node, "length")) {
6777 facet->type = XML_SCHEMA_FACET_LENGTH;
6778 } else if (IS_SCHEMA(node, "maxLength")) {
6779 facet->type = XML_SCHEMA_FACET_MAXLENGTH;
6780 } else if (IS_SCHEMA(node, "minLength")) {
6781 facet->type = XML_SCHEMA_FACET_MINLENGTH;
6782 } else {
6783 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_TYPE,
6784 "Unknown facet type %s\n", node->name, NULL);
6785 xmlSchemaFreeFacet(facet);
6786 return (NULL);
6788 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
6789 facet->value = value;
6790 if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
6791 (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
6792 const xmlChar *fixed;
6794 fixed = xmlSchemaGetProp(ctxt, node, "fixed");
6795 if (fixed != NULL) {
6796 if (xmlStrEqual(fixed, BAD_CAST "true"))
6797 facet->fixed = 1;
6800 child = node->children;
6802 if (IS_SCHEMA(child, "annotation")) {
6803 facet->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
6804 child = child->next;
6806 if (child != NULL) {
6807 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_UNKNOWN_FACET_CHILD,
6808 "Facet %s has unexpected child content\n",
6809 node->name, NULL);
6811 return (facet);
6815 * xmlSchemaParseWildcardNs:
6816 * @ctxt: a schema parser context
6817 * @wildc: the wildcard, already created
6818 * @node: a subtree containing XML Schema information
6820 * Parses the attribute "processContents" and "namespace"
6821 * of a xsd:anyAttribute and xsd:any.
6822 * *WARNING* this interface is highly subject to change
6824 * Returns 0 if everything goes fine, a positive error code
6825 * if something is not valid and -1 if an internal error occurs.
6827 static int
6828 xmlSchemaParseWildcardNs(xmlSchemaParserCtxtPtr ctxt,
6829 xmlSchemaPtr schema ATTRIBUTE_UNUSED,
6830 xmlSchemaWildcardPtr wildc,
6831 xmlNodePtr node)
6833 const xmlChar *pc, *ns, *dictnsItem;
6834 int ret = 0;
6835 xmlChar *nsItem;
6836 xmlSchemaWildcardNsPtr tmp, lastNs = NULL;
6837 xmlAttrPtr attr;
6839 pc = xmlSchemaGetProp(ctxt, node, "processContents");
6840 if ((pc == NULL)
6841 || (xmlStrEqual(pc, (const xmlChar *) "strict"))) {
6842 wildc->processContents = XML_SCHEMAS_ANY_STRICT;
6843 } else if (xmlStrEqual(pc, (const xmlChar *) "skip")) {
6844 wildc->processContents = XML_SCHEMAS_ANY_SKIP;
6845 } else if (xmlStrEqual(pc, (const xmlChar *) "lax")) {
6846 wildc->processContents = XML_SCHEMAS_ANY_LAX;
6847 } else {
6848 xmlSchemaPSimpleTypeErr(ctxt,
6849 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
6850 NULL, node,
6851 NULL, "(strict | skip | lax)", pc,
6852 NULL, NULL, NULL);
6853 wildc->processContents = XML_SCHEMAS_ANY_STRICT;
6854 ret = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
6857 * Build the namespace constraints.
6859 attr = xmlSchemaGetPropNode(node, "namespace");
6860 ns = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
6861 if (ns == NULL)
6862 return (-1);
6863 if ((attr == NULL) || (xmlStrEqual(ns, BAD_CAST "##any")))
6864 wildc->any = 1;
6865 else if (xmlStrEqual(ns, BAD_CAST "##other")) {
6866 wildc->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
6867 if (wildc->negNsSet == NULL) {
6868 return (-1);
6870 wildc->negNsSet->value = ctxt->targetNamespace;
6871 } else {
6872 const xmlChar *end, *cur;
6874 cur = ns;
6875 do {
6876 while (IS_BLANK_CH(*cur))
6877 cur++;
6878 end = cur;
6879 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
6880 end++;
6881 if (end == cur)
6882 break;
6883 nsItem = xmlStrndup(cur, end - cur);
6884 if ((xmlStrEqual(nsItem, BAD_CAST "##other")) ||
6885 (xmlStrEqual(nsItem, BAD_CAST "##any"))) {
6886 xmlSchemaPSimpleTypeErr(ctxt,
6887 XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER,
6888 NULL, (xmlNodePtr) attr,
6889 NULL,
6890 "((##any | ##other) | List of (xs:anyURI | "
6891 "(##targetNamespace | ##local)))",
6892 nsItem, NULL, NULL, NULL);
6893 ret = XML_SCHEMAP_WILDCARD_INVALID_NS_MEMBER;
6894 } else {
6895 if (xmlStrEqual(nsItem, BAD_CAST "##targetNamespace")) {
6896 dictnsItem = ctxt->targetNamespace;
6897 } else if (xmlStrEqual(nsItem, BAD_CAST "##local")) {
6898 dictnsItem = NULL;
6899 } else {
6901 * Validate the item (anyURI).
6903 xmlSchemaPValAttrNodeValue(ctxt, NULL, attr,
6904 nsItem, xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI));
6905 dictnsItem = xmlDictLookup(ctxt->dict, nsItem, -1);
6908 * Avoid duplicate namespaces.
6910 tmp = wildc->nsSet;
6911 while (tmp != NULL) {
6912 if (dictnsItem == tmp->value)
6913 break;
6914 tmp = tmp->next;
6916 if (tmp == NULL) {
6917 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
6918 if (tmp == NULL) {
6919 xmlFree(nsItem);
6920 return (-1);
6922 tmp->value = dictnsItem;
6923 tmp->next = NULL;
6924 if (wildc->nsSet == NULL)
6925 wildc->nsSet = tmp;
6926 else if (lastNs != NULL)
6927 lastNs->next = tmp;
6928 lastNs = tmp;
6932 xmlFree(nsItem);
6933 cur = end;
6934 } while (*cur != 0);
6936 return (ret);
6939 static int
6940 xmlSchemaPCheckParticleCorrect_2(xmlSchemaParserCtxtPtr ctxt,
6941 xmlSchemaParticlePtr item ATTRIBUTE_UNUSED,
6942 xmlNodePtr node,
6943 int minOccurs,
6944 int maxOccurs) {
6946 if ((maxOccurs == 0) && ( minOccurs == 0))
6947 return (0);
6948 if (maxOccurs != UNBOUNDED) {
6950 * TODO: Maybe we should better not create the particle,
6951 * if min/max is invalid, since it could confuse the build of the
6952 * content model.
6955 * 3.9.6 Schema Component Constraint: Particle Correct
6958 if (maxOccurs < 1) {
6960 * 2.2 {max occurs} must be greater than or equal to 1.
6962 xmlSchemaPCustomAttrErr(ctxt,
6963 XML_SCHEMAP_P_PROPS_CORRECT_2_2,
6964 NULL, NULL,
6965 xmlSchemaGetPropNode(node, "maxOccurs"),
6966 "The value must be greater than or equal to 1");
6967 return (XML_SCHEMAP_P_PROPS_CORRECT_2_2);
6968 } else if (minOccurs > maxOccurs) {
6970 * 2.1 {min occurs} must not be greater than {max occurs}.
6972 xmlSchemaPCustomAttrErr(ctxt,
6973 XML_SCHEMAP_P_PROPS_CORRECT_2_1,
6974 NULL, NULL,
6975 xmlSchemaGetPropNode(node, "minOccurs"),
6976 "The value must not be greater than the value of 'maxOccurs'");
6977 return (XML_SCHEMAP_P_PROPS_CORRECT_2_1);
6980 return (0);
6984 * xmlSchemaParseAny:
6985 * @ctxt: a schema validation context
6986 * @schema: the schema being built
6987 * @node: a subtree containing XML Schema information
6989 * Parsea a XML schema <any> element. A particle and wildcard
6990 * will be created (except if minOccurs==maxOccurs==0, in this case
6991 * nothing will be created).
6992 * *WARNING* this interface is highly subject to change
6994 * Returns the particle or NULL in case of error or if minOccurs==maxOccurs==0
6996 static xmlSchemaParticlePtr
6997 xmlSchemaParseAny(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
6998 xmlNodePtr node)
7000 xmlSchemaParticlePtr particle;
7001 xmlNodePtr child = NULL;
7002 xmlSchemaWildcardPtr wild;
7003 int min, max;
7004 xmlAttrPtr attr;
7005 xmlSchemaAnnotPtr annot = NULL;
7007 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7008 return (NULL);
7010 * Check for illegal attributes.
7012 attr = node->properties;
7013 while (attr != NULL) {
7014 if (attr->ns == NULL) {
7015 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7016 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
7017 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
7018 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
7019 (!xmlStrEqual(attr->name, BAD_CAST "processContents"))) {
7020 xmlSchemaPIllegalAttrErr(ctxt,
7021 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7023 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7024 xmlSchemaPIllegalAttrErr(ctxt,
7025 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7027 attr = attr->next;
7029 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
7031 * minOccurs/maxOccurs.
7033 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
7034 "(xs:nonNegativeInteger | unbounded)");
7035 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1,
7036 "xs:nonNegativeInteger");
7037 xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
7039 * Create & parse the wildcard.
7041 wild = xmlSchemaAddWildcard(ctxt, schema, XML_SCHEMA_TYPE_ANY, node);
7042 if (wild == NULL)
7043 return (NULL);
7044 xmlSchemaParseWildcardNs(ctxt, schema, wild, node);
7046 * And now for the children...
7048 child = node->children;
7049 if (IS_SCHEMA(child, "annotation")) {
7050 annot = xmlSchemaParseAnnotation(ctxt, child, 1);
7051 child = child->next;
7053 if (child != NULL) {
7054 xmlSchemaPContentErr(ctxt,
7055 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7056 NULL, node, child,
7057 NULL, "(annotation?)");
7060 * No component if minOccurs==maxOccurs==0.
7062 if ((min == 0) && (max == 0)) {
7063 /* Don't free the wildcard, since it's already on the list. */
7064 return (NULL);
7067 * Create the particle.
7069 particle = xmlSchemaAddParticle(ctxt, node, min, max);
7070 if (particle == NULL)
7071 return (NULL);
7072 particle->annot = annot;
7073 particle->children = (xmlSchemaTreeItemPtr) wild;
7075 return (particle);
7079 * xmlSchemaParseNotation:
7080 * @ctxt: a schema validation context
7081 * @schema: the schema being built
7082 * @node: a subtree containing XML Schema information
7084 * parse a XML schema Notation declaration
7086 * Returns the new structure or NULL in case of error
7088 static xmlSchemaNotationPtr
7089 xmlSchemaParseNotation(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
7090 xmlNodePtr node)
7092 const xmlChar *name;
7093 xmlSchemaNotationPtr ret;
7094 xmlNodePtr child = NULL;
7096 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7097 return (NULL);
7098 name = xmlSchemaGetProp(ctxt, node, "name");
7099 if (name == NULL) {
7100 xmlSchemaPErr2(ctxt, node, child, XML_SCHEMAP_NOTATION_NO_NAME,
7101 "Notation has no name\n", NULL, NULL);
7102 return (NULL);
7104 ret = xmlSchemaAddNotation(ctxt, schema, name,
7105 ctxt->targetNamespace, node);
7106 if (ret == NULL)
7107 return (NULL);
7108 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
7110 child = node->children;
7111 if (IS_SCHEMA(child, "annotation")) {
7112 ret->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
7113 child = child->next;
7115 if (child != NULL) {
7116 xmlSchemaPContentErr(ctxt,
7117 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7118 NULL, node, child,
7119 NULL, "(annotation?)");
7122 return (ret);
7126 * xmlSchemaParseAnyAttribute:
7127 * @ctxt: a schema validation context
7128 * @schema: the schema being built
7129 * @node: a subtree containing XML Schema information
7131 * parse a XML schema AnyAttribute declaration
7132 * *WARNING* this interface is highly subject to change
7134 * Returns a wildcard or NULL.
7136 static xmlSchemaWildcardPtr
7137 xmlSchemaParseAnyAttribute(xmlSchemaParserCtxtPtr ctxt,
7138 xmlSchemaPtr schema, xmlNodePtr node)
7140 xmlSchemaWildcardPtr ret;
7141 xmlNodePtr child = NULL;
7142 xmlAttrPtr attr;
7144 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
7145 return (NULL);
7147 ret = xmlSchemaAddWildcard(ctxt, schema, XML_SCHEMA_TYPE_ANY_ATTRIBUTE,
7148 node);
7149 if (ret == NULL) {
7150 return (NULL);
7153 * Check for illegal attributes.
7155 attr = node->properties;
7156 while (attr != NULL) {
7157 if (attr->ns == NULL) {
7158 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7159 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
7160 (!xmlStrEqual(attr->name, BAD_CAST "processContents"))) {
7161 xmlSchemaPIllegalAttrErr(ctxt,
7162 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7164 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7165 xmlSchemaPIllegalAttrErr(ctxt,
7166 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7168 attr = attr->next;
7170 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
7172 * Parse the namespace list.
7174 if (xmlSchemaParseWildcardNs(ctxt, schema, ret, node) != 0)
7175 return (NULL);
7177 * And now for the children...
7179 child = node->children;
7180 if (IS_SCHEMA(child, "annotation")) {
7181 ret->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
7182 child = child->next;
7184 if (child != NULL) {
7185 xmlSchemaPContentErr(ctxt,
7186 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7187 NULL, node, child,
7188 NULL, "(annotation?)");
7191 return (ret);
7196 * xmlSchemaParseAttribute:
7197 * @ctxt: a schema validation context
7198 * @schema: the schema being built
7199 * @node: a subtree containing XML Schema information
7201 * parse a XML schema Attribute declaration
7202 * *WARNING* this interface is highly subject to change
7204 * Returns the attribute declaration.
7206 static xmlSchemaBasicItemPtr
7207 xmlSchemaParseLocalAttribute(xmlSchemaParserCtxtPtr pctxt,
7208 xmlSchemaPtr schema,
7209 xmlNodePtr node,
7210 xmlSchemaItemListPtr uses,
7211 int parentType)
7213 const xmlChar *attrValue, *name = NULL, *ns = NULL;
7214 xmlSchemaAttributeUsePtr use = NULL;
7215 xmlNodePtr child = NULL;
7216 xmlAttrPtr attr;
7217 const xmlChar *tmpNs = NULL, *tmpName = NULL, *defValue = NULL;
7218 int isRef = 0, occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
7219 int nberrors, hasForm = 0, defValueType = 0;
7221 #define WXS_ATTR_DEF_VAL_DEFAULT 1
7222 #define WXS_ATTR_DEF_VAL_FIXED 2
7225 * 3.2.3 Constraints on XML Representations of Attribute Declarations
7228 if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
7229 return (NULL);
7230 attr = xmlSchemaGetPropNode(node, "ref");
7231 if (attr != NULL) {
7232 if (xmlSchemaPValAttrNodeQName(pctxt, schema,
7233 NULL, attr, &tmpNs, &tmpName) != 0) {
7234 return (NULL);
7236 if (xmlSchemaCheckReference(pctxt, schema, node, attr, tmpNs) != 0)
7237 return(NULL);
7238 isRef = 1;
7240 nberrors = pctxt->nberrors;
7242 * Check for illegal attributes.
7244 attr = node->properties;
7245 while (attr != NULL) {
7246 if (attr->ns == NULL) {
7247 if (isRef) {
7248 if (xmlStrEqual(attr->name, BAD_CAST "id")) {
7249 xmlSchemaPValAttrNodeID(pctxt, attr);
7250 goto attr_next;
7251 } else if (xmlStrEqual(attr->name, BAD_CAST "ref")) {
7252 goto attr_next;
7254 } else {
7255 if (xmlStrEqual(attr->name, BAD_CAST "name")) {
7256 goto attr_next;
7257 } else if (xmlStrEqual(attr->name, BAD_CAST "id")) {
7258 xmlSchemaPValAttrNodeID(pctxt, attr);
7259 goto attr_next;
7260 } else if (xmlStrEqual(attr->name, BAD_CAST "type")) {
7261 xmlSchemaPValAttrNodeQName(pctxt, schema, NULL,
7262 attr, &tmpNs, &tmpName);
7263 goto attr_next;
7264 } else if (xmlStrEqual(attr->name, BAD_CAST "form")) {
7266 * Evaluate the target namespace
7268 hasForm = 1;
7269 attrValue = xmlSchemaGetNodeContent(pctxt,
7270 (xmlNodePtr) attr);
7271 if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
7272 ns = pctxt->targetNamespace;
7273 } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified"))
7275 xmlSchemaPSimpleTypeErr(pctxt,
7276 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
7277 NULL, (xmlNodePtr) attr,
7278 NULL, "(qualified | unqualified)",
7279 attrValue, NULL, NULL, NULL);
7281 goto attr_next;
7284 if (xmlStrEqual(attr->name, BAD_CAST "use")) {
7286 attrValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
7287 /* TODO: Maybe we need to normalize the value beforehand. */
7288 if (xmlStrEqual(attrValue, BAD_CAST "optional"))
7289 occurs = XML_SCHEMAS_ATTR_USE_OPTIONAL;
7290 else if (xmlStrEqual(attrValue, BAD_CAST "prohibited"))
7291 occurs = XML_SCHEMAS_ATTR_USE_PROHIBITED;
7292 else if (xmlStrEqual(attrValue, BAD_CAST "required"))
7293 occurs = XML_SCHEMAS_ATTR_USE_REQUIRED;
7294 else {
7295 xmlSchemaPSimpleTypeErr(pctxt,
7296 XML_SCHEMAP_INVALID_ATTR_USE,
7297 NULL, (xmlNodePtr) attr,
7298 NULL, "(optional | prohibited | required)",
7299 attrValue, NULL, NULL, NULL);
7301 goto attr_next;
7302 } else if (xmlStrEqual(attr->name, BAD_CAST "default")) {
7304 * 3.2.3 : 1
7305 * default and fixed must not both be present.
7307 if (defValue) {
7308 xmlSchemaPMutualExclAttrErr(pctxt,
7309 XML_SCHEMAP_SRC_ATTRIBUTE_1,
7310 NULL, attr, "default", "fixed");
7311 } else {
7312 defValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
7313 defValueType = WXS_ATTR_DEF_VAL_DEFAULT;
7315 goto attr_next;
7316 } else if (xmlStrEqual(attr->name, BAD_CAST "fixed")) {
7318 * 3.2.3 : 1
7319 * default and fixed must not both be present.
7321 if (defValue) {
7322 xmlSchemaPMutualExclAttrErr(pctxt,
7323 XML_SCHEMAP_SRC_ATTRIBUTE_1,
7324 NULL, attr, "default", "fixed");
7325 } else {
7326 defValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
7327 defValueType = WXS_ATTR_DEF_VAL_FIXED;
7329 goto attr_next;
7331 } else if (! xmlStrEqual(attr->ns->href, xmlSchemaNs))
7332 goto attr_next;
7334 xmlSchemaPIllegalAttrErr(pctxt,
7335 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7337 attr_next:
7338 attr = attr->next;
7341 * 3.2.3 : 2
7342 * If default and use are both present, use must have
7343 * the actual value optional.
7345 if ((defValueType == WXS_ATTR_DEF_VAL_DEFAULT) &&
7346 (occurs != XML_SCHEMAS_ATTR_USE_OPTIONAL)) {
7347 xmlSchemaPSimpleTypeErr(pctxt,
7348 XML_SCHEMAP_SRC_ATTRIBUTE_2,
7349 NULL, node, NULL,
7350 "(optional | prohibited | required)", NULL,
7351 "The value of the attribute 'use' must be 'optional' "
7352 "if the attribute 'default' is present",
7353 NULL, NULL);
7356 * We want correct attributes.
7358 if (nberrors != pctxt->nberrors)
7359 return(NULL);
7360 if (! isRef) {
7361 xmlSchemaAttributePtr attrDecl;
7363 /* TODO: move XML_SCHEMAS_QUALIF_ATTR to the parser. */
7364 if ((! hasForm) && (schema->flags & XML_SCHEMAS_QUALIF_ATTR))
7365 ns = pctxt->targetNamespace;
7367 * 3.2.6 Schema Component Constraint: xsi: Not Allowed
7368 * TODO: Move this to the component layer.
7370 if (xmlStrEqual(ns, xmlSchemaInstanceNs)) {
7371 xmlSchemaCustomErr(ACTXT_CAST pctxt,
7372 XML_SCHEMAP_NO_XSI,
7373 node, NULL,
7374 "The target namespace must not match '%s'",
7375 xmlSchemaInstanceNs, NULL);
7377 attr = xmlSchemaGetPropNode(node, "name");
7378 if (attr == NULL) {
7379 xmlSchemaPMissingAttrErr(pctxt, XML_SCHEMAP_S4S_ATTR_MISSING,
7380 NULL, node, "name", NULL);
7381 return (NULL);
7383 if (xmlSchemaPValAttrNode(pctxt, NULL, attr,
7384 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
7385 return (NULL);
7388 * 3.2.6 Schema Component Constraint: xmlns Not Allowed
7389 * TODO: Move this to the component layer.
7391 if (xmlStrEqual(name, BAD_CAST "xmlns")) {
7392 xmlSchemaPSimpleTypeErr(pctxt,
7393 XML_SCHEMAP_NO_XMLNS,
7394 NULL, (xmlNodePtr) attr,
7395 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), NULL, NULL,
7396 "The value of the attribute must not match 'xmlns'",
7397 NULL, NULL);
7398 return (NULL);
7400 if (occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED)
7401 goto check_children;
7403 * Create the attribute use component.
7405 use = xmlSchemaAddAttributeUse(pctxt, node);
7406 if (use == NULL)
7407 return(NULL);
7408 use->occurs = occurs;
7410 * Create the attribute declaration.
7412 attrDecl = xmlSchemaAddAttribute(pctxt, schema, name, ns, node, 0);
7413 if (attrDecl == NULL)
7414 return (NULL);
7415 if (tmpName != NULL) {
7416 attrDecl->typeName = tmpName;
7417 attrDecl->typeNs = tmpNs;
7419 use->attrDecl = attrDecl;
7421 * Value constraint.
7423 if (defValue != NULL) {
7424 attrDecl->defValue = defValue;
7425 if (defValueType == WXS_ATTR_DEF_VAL_FIXED)
7426 attrDecl->flags |= XML_SCHEMAS_ATTR_FIXED;
7428 } else if (occurs != XML_SCHEMAS_ATTR_USE_PROHIBITED) {
7429 xmlSchemaQNameRefPtr ref;
7432 * Create the attribute use component.
7434 use = xmlSchemaAddAttributeUse(pctxt, node);
7435 if (use == NULL)
7436 return(NULL);
7438 * We need to resolve the reference at later stage.
7440 WXS_ADD_PENDING(pctxt, use);
7441 use->occurs = occurs;
7443 * Create a QName reference to the attribute declaration.
7445 ref = xmlSchemaNewQNameRef(pctxt, XML_SCHEMA_TYPE_ATTRIBUTE,
7446 tmpName, tmpNs);
7447 if (ref == NULL)
7448 return(NULL);
7450 * Assign the reference. This will be substituted for the
7451 * referenced attribute declaration when the QName is resolved.
7453 use->attrDecl = WXS_ATTR_CAST ref;
7455 * Value constraint.
7457 if (defValue != NULL)
7458 use->defValue = defValue;
7459 if (defValueType == WXS_ATTR_DEF_VAL_FIXED)
7460 use->flags |= XML_SCHEMA_ATTR_USE_FIXED;
7463 check_children:
7465 * And now for the children...
7467 child = node->children;
7468 if (occurs == XML_SCHEMAS_ATTR_USE_PROHIBITED) {
7469 xmlSchemaAttributeUseProhibPtr prohib;
7471 if (IS_SCHEMA(child, "annotation")) {
7472 xmlSchemaParseAnnotation(pctxt, child, 0);
7473 child = child->next;
7475 if (child != NULL) {
7476 xmlSchemaPContentErr(pctxt,
7477 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7478 NULL, node, child, NULL,
7479 "(annotation?)");
7482 * Check for pointlessness of attribute prohibitions.
7484 if (parentType == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) {
7485 xmlSchemaCustomWarning(ACTXT_CAST pctxt,
7486 XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
7487 node, NULL,
7488 "Skipping attribute use prohibition, since it is "
7489 "pointless inside an <attributeGroup>",
7490 NULL, NULL, NULL);
7491 return(NULL);
7492 } else if (parentType == XML_SCHEMA_TYPE_EXTENSION) {
7493 xmlSchemaCustomWarning(ACTXT_CAST pctxt,
7494 XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
7495 node, NULL,
7496 "Skipping attribute use prohibition, since it is "
7497 "pointless when extending a type",
7498 NULL, NULL, NULL);
7499 return(NULL);
7501 if (! isRef) {
7502 tmpName = name;
7503 tmpNs = ns;
7506 * Check for duplicate attribute prohibitions.
7508 if (uses) {
7509 int i;
7511 for (i = 0; i < uses->nbItems; i++) {
7512 use = uses->items[i];
7513 if ((use->type == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB) &&
7514 (tmpName == (WXS_ATTR_PROHIB_CAST use)->name) &&
7515 (tmpNs == (WXS_ATTR_PROHIB_CAST use)->targetNamespace))
7517 xmlChar *str = NULL;
7519 xmlSchemaCustomWarning(ACTXT_CAST pctxt,
7520 XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
7521 node, NULL,
7522 "Skipping duplicate attribute use prohibition '%s'",
7523 xmlSchemaFormatQName(&str, tmpNs, tmpName),
7524 NULL, NULL);
7525 FREE_AND_NULL(str)
7526 return(NULL);
7531 * Create the attribute prohibition helper component.
7533 prohib = xmlSchemaAddAttributeUseProhib(pctxt);
7534 if (prohib == NULL)
7535 return(NULL);
7536 prohib->node = node;
7537 prohib->name = tmpName;
7538 prohib->targetNamespace = tmpNs;
7539 if (isRef) {
7541 * We need at least to resolve to the attribute declaration.
7543 WXS_ADD_PENDING(pctxt, prohib);
7545 return(WXS_BASIC_CAST prohib);
7546 } else {
7547 if (IS_SCHEMA(child, "annotation")) {
7549 * TODO: Should this go into the attr decl?
7551 use->annot = xmlSchemaParseAnnotation(pctxt, child, 1);
7552 child = child->next;
7554 if (isRef) {
7555 if (child != NULL) {
7556 if (IS_SCHEMA(child, "simpleType"))
7558 * 3.2.3 : 3.2
7559 * If ref is present, then all of <simpleType>,
7560 * form and type must be absent.
7562 xmlSchemaPContentErr(pctxt,
7563 XML_SCHEMAP_SRC_ATTRIBUTE_3_2,
7564 NULL, node, child, NULL,
7565 "(annotation?)");
7566 else
7567 xmlSchemaPContentErr(pctxt,
7568 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7569 NULL, node, child, NULL,
7570 "(annotation?)");
7572 } else {
7573 if (IS_SCHEMA(child, "simpleType")) {
7574 if (WXS_ATTRUSE_DECL(use)->typeName != NULL) {
7576 * 3.2.3 : 4
7577 * type and <simpleType> must not both be present.
7579 xmlSchemaPContentErr(pctxt, XML_SCHEMAP_SRC_ATTRIBUTE_4,
7580 NULL, node, child,
7581 "The attribute 'type' and the <simpleType> child "
7582 "are mutually exclusive", NULL);
7583 } else
7584 WXS_ATTRUSE_TYPEDEF(use) =
7585 xmlSchemaParseSimpleType(pctxt, schema, child, 0);
7586 child = child->next;
7588 if (child != NULL)
7589 xmlSchemaPContentErr(pctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7590 NULL, node, child, NULL,
7591 "(annotation?, simpleType?)");
7594 return (WXS_BASIC_CAST use);
7598 static xmlSchemaAttributePtr
7599 xmlSchemaParseGlobalAttribute(xmlSchemaParserCtxtPtr pctxt,
7600 xmlSchemaPtr schema,
7601 xmlNodePtr node)
7603 const xmlChar *attrValue;
7604 xmlSchemaAttributePtr ret;
7605 xmlNodePtr child = NULL;
7606 xmlAttrPtr attr;
7609 * Note that the w3c spec assumes the schema to be validated with schema
7610 * for schemas beforehand.
7612 * 3.2.3 Constraints on XML Representations of Attribute Declarations
7614 if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
7615 return (NULL);
7617 * 3.2.3 : 3.1
7618 * One of ref or name must be present, but not both
7620 attr = xmlSchemaGetPropNode(node, "name");
7621 if (attr == NULL) {
7622 xmlSchemaPMissingAttrErr(pctxt, XML_SCHEMAP_S4S_ATTR_MISSING,
7623 NULL, node, "name", NULL);
7624 return (NULL);
7626 if (xmlSchemaPValAttrNode(pctxt, NULL, attr,
7627 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &attrValue) != 0) {
7628 return (NULL);
7631 * 3.2.6 Schema Component Constraint: xmlns Not Allowed
7632 * TODO: Move this to the component layer.
7634 if (xmlStrEqual(attrValue, BAD_CAST "xmlns")) {
7635 xmlSchemaPSimpleTypeErr(pctxt,
7636 XML_SCHEMAP_NO_XMLNS,
7637 NULL, (xmlNodePtr) attr,
7638 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), NULL, NULL,
7639 "The value of the attribute must not match 'xmlns'",
7640 NULL, NULL);
7641 return (NULL);
7644 * 3.2.6 Schema Component Constraint: xsi: Not Allowed
7645 * TODO: Move this to the component layer.
7646 * Or better leave it here and add it to the component layer
7647 * if we have a schema construction API.
7649 if (xmlStrEqual(pctxt->targetNamespace, xmlSchemaInstanceNs)) {
7650 xmlSchemaCustomErr(ACTXT_CAST pctxt,
7651 XML_SCHEMAP_NO_XSI, node, NULL,
7652 "The target namespace must not match '%s'",
7653 xmlSchemaInstanceNs, NULL);
7656 ret = xmlSchemaAddAttribute(pctxt, schema, attrValue,
7657 pctxt->targetNamespace, node, 1);
7658 if (ret == NULL)
7659 return (NULL);
7660 ret->flags |= XML_SCHEMAS_ATTR_GLOBAL;
7663 * Check for illegal attributes.
7665 attr = node->properties;
7666 while (attr != NULL) {
7667 if (attr->ns == NULL) {
7668 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
7669 (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
7670 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
7671 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
7672 (!xmlStrEqual(attr->name, BAD_CAST "type")))
7674 xmlSchemaPIllegalAttrErr(pctxt,
7675 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7677 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7678 xmlSchemaPIllegalAttrErr(pctxt,
7679 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7681 attr = attr->next;
7683 xmlSchemaPValAttrQName(pctxt, schema, NULL,
7684 node, "type", &ret->typeNs, &ret->typeName);
7686 xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
7688 * Attribute "fixed".
7690 ret->defValue = xmlSchemaGetProp(pctxt, node, "fixed");
7691 if (ret->defValue != NULL)
7692 ret->flags |= XML_SCHEMAS_ATTR_FIXED;
7694 * Attribute "default".
7696 attr = xmlSchemaGetPropNode(node, "default");
7697 if (attr != NULL) {
7699 * 3.2.3 : 1
7700 * default and fixed must not both be present.
7702 if (ret->flags & XML_SCHEMAS_ATTR_FIXED) {
7703 xmlSchemaPMutualExclAttrErr(pctxt, XML_SCHEMAP_SRC_ATTRIBUTE_1,
7704 WXS_BASIC_CAST ret, attr, "default", "fixed");
7705 } else
7706 ret->defValue = xmlSchemaGetNodeContent(pctxt, (xmlNodePtr) attr);
7709 * And now for the children...
7711 child = node->children;
7712 if (IS_SCHEMA(child, "annotation")) {
7713 ret->annot = xmlSchemaParseAnnotation(pctxt, child, 1);
7714 child = child->next;
7716 if (IS_SCHEMA(child, "simpleType")) {
7717 if (ret->typeName != NULL) {
7719 * 3.2.3 : 4
7720 * type and <simpleType> must not both be present.
7722 xmlSchemaPContentErr(pctxt, XML_SCHEMAP_SRC_ATTRIBUTE_4,
7723 NULL, node, child,
7724 "The attribute 'type' and the <simpleType> child "
7725 "are mutually exclusive", NULL);
7726 } else
7727 ret->subtypes = xmlSchemaParseSimpleType(pctxt, schema, child, 0);
7728 child = child->next;
7730 if (child != NULL)
7731 xmlSchemaPContentErr(pctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7732 NULL, node, child, NULL,
7733 "(annotation?, simpleType?)");
7735 return (ret);
7739 * xmlSchemaParseAttributeGroupRef:
7740 * @ctxt: a schema validation context
7741 * @schema: the schema being built
7742 * @node: a subtree containing XML Schema information
7744 * Parse an attribute group definition reference.
7745 * Note that a reference to an attribute group does not
7746 * correspond to any component at all.
7747 * *WARNING* this interface is highly subject to change
7749 * Returns the attribute group or NULL in case of error.
7751 static xmlSchemaQNameRefPtr
7752 xmlSchemaParseAttributeGroupRef(xmlSchemaParserCtxtPtr pctxt,
7753 xmlSchemaPtr schema,
7754 xmlNodePtr node)
7756 xmlSchemaQNameRefPtr ret;
7757 xmlNodePtr child = NULL;
7758 xmlAttrPtr attr;
7759 const xmlChar *refNs = NULL, *ref = NULL;
7761 if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
7762 return (NULL);
7764 attr = xmlSchemaGetPropNode(node, "ref");
7765 if (attr == NULL) {
7766 xmlSchemaPMissingAttrErr(pctxt,
7767 XML_SCHEMAP_S4S_ATTR_MISSING,
7768 NULL, node, "ref", NULL);
7769 return (NULL);
7771 xmlSchemaPValAttrNodeQName(pctxt, schema,
7772 NULL, attr, &refNs, &ref);
7773 if (xmlSchemaCheckReference(pctxt, schema, node, attr, refNs) != 0)
7774 return(NULL);
7777 * Check for illegal attributes.
7779 attr = node->properties;
7780 while (attr != NULL) {
7781 if (attr->ns == NULL) {
7782 if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
7783 (!xmlStrEqual(attr->name, BAD_CAST "id")))
7785 xmlSchemaPIllegalAttrErr(pctxt,
7786 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7788 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7789 xmlSchemaPIllegalAttrErr(pctxt,
7790 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7792 attr = attr->next;
7794 /* Attribute ID */
7795 xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
7798 * And now for the children...
7800 child = node->children;
7801 if (IS_SCHEMA(child, "annotation")) {
7803 * TODO: We do not have a place to store the annotation, do we?
7805 xmlSchemaParseAnnotation(pctxt, child, 0);
7806 child = child->next;
7808 if (child != NULL) {
7809 xmlSchemaPContentErr(pctxt,
7810 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7811 NULL, node, child, NULL,
7812 "(annotation?)");
7816 * Handle attribute group redefinitions.
7818 if (pctxt->isRedefine && pctxt->redef &&
7819 (pctxt->redef->item->type ==
7820 XML_SCHEMA_TYPE_ATTRIBUTEGROUP) &&
7821 (ref == pctxt->redef->refName) &&
7822 (refNs == pctxt->redef->refTargetNs))
7825 * SPEC src-redefine:
7826 * (7.1) "If it has an <attributeGroup> among its contents
7827 * the `actual value` of whose ref [attribute] is the same
7828 * as the `actual value` of its own name attribute plus
7829 * target namespace, then it must have exactly one such group."
7831 if (pctxt->redefCounter != 0) {
7832 xmlChar *str = NULL;
7834 xmlSchemaCustomErr(ACTXT_CAST pctxt,
7835 XML_SCHEMAP_SRC_REDEFINE, node, NULL,
7836 "The redefining attribute group definition "
7837 "'%s' must not contain more than one "
7838 "reference to the redefined definition",
7839 xmlSchemaFormatQName(&str, refNs, ref), NULL);
7840 FREE_AND_NULL(str);
7841 return(NULL);
7843 pctxt->redefCounter++;
7845 * URGENT TODO: How to ensure that the reference will not be
7846 * handled by the normal component resolution mechanism?
7848 ret = xmlSchemaNewQNameRef(pctxt,
7849 XML_SCHEMA_TYPE_ATTRIBUTEGROUP, ref, refNs);
7850 if (ret == NULL)
7851 return(NULL);
7852 ret->node = node;
7853 pctxt->redef->reference = WXS_BASIC_CAST ret;
7854 } else {
7856 * Create a QName-reference helper component. We will substitute this
7857 * component for the attribute uses of the referenced attribute group
7858 * definition.
7860 ret = xmlSchemaNewQNameRef(pctxt,
7861 XML_SCHEMA_TYPE_ATTRIBUTEGROUP, ref, refNs);
7862 if (ret == NULL)
7863 return(NULL);
7864 ret->node = node;
7865 /* Add to pending items, to be able to resolve the reference. */
7866 WXS_ADD_PENDING(pctxt, ret);
7868 return (ret);
7872 * xmlSchemaParseAttributeGroupDefinition:
7873 * @pctxt: a schema validation context
7874 * @schema: the schema being built
7875 * @node: a subtree containing XML Schema information
7877 * parse a XML schema Attribute Group declaration
7878 * *WARNING* this interface is highly subject to change
7880 * Returns the attribute group definition or NULL in case of error.
7882 static xmlSchemaAttributeGroupPtr
7883 xmlSchemaParseAttributeGroupDefinition(xmlSchemaParserCtxtPtr pctxt,
7884 xmlSchemaPtr schema,
7885 xmlNodePtr node)
7887 const xmlChar *name;
7888 xmlSchemaAttributeGroupPtr ret;
7889 xmlNodePtr child = NULL;
7890 xmlAttrPtr attr;
7891 int hasRefs = 0;
7893 if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
7894 return (NULL);
7896 attr = xmlSchemaGetPropNode(node, "name");
7897 if (attr == NULL) {
7898 xmlSchemaPMissingAttrErr(pctxt,
7899 XML_SCHEMAP_S4S_ATTR_MISSING,
7900 NULL, node, "name", NULL);
7901 return (NULL);
7904 * The name is crucial, exit if invalid.
7906 if (xmlSchemaPValAttrNode(pctxt,
7907 NULL, attr,
7908 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
7909 return (NULL);
7911 ret = xmlSchemaAddAttributeGroupDefinition(pctxt, schema,
7912 name, pctxt->targetNamespace, node);
7913 if (ret == NULL)
7914 return (NULL);
7916 * Check for illegal attributes.
7918 attr = node->properties;
7919 while (attr != NULL) {
7920 if (attr->ns == NULL) {
7921 if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
7922 (!xmlStrEqual(attr->name, BAD_CAST "id")))
7924 xmlSchemaPIllegalAttrErr(pctxt,
7925 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7927 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
7928 xmlSchemaPIllegalAttrErr(pctxt,
7929 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
7931 attr = attr->next;
7933 /* Attribute ID */
7934 xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
7936 * And now for the children...
7938 child = node->children;
7939 if (IS_SCHEMA(child, "annotation")) {
7940 ret->annot = xmlSchemaParseAnnotation(pctxt, child, 1);
7941 child = child->next;
7944 * Parse contained attribute decls/refs.
7946 if (xmlSchemaParseLocalAttributes(pctxt, schema, &child,
7947 (xmlSchemaItemListPtr *) &(ret->attrUses),
7948 XML_SCHEMA_TYPE_ATTRIBUTEGROUP, &hasRefs) == -1)
7949 return(NULL);
7950 if (hasRefs)
7951 ret->flags |= XML_SCHEMAS_ATTRGROUP_HAS_REFS;
7953 * Parse the attribute wildcard.
7955 if (IS_SCHEMA(child, "anyAttribute")) {
7956 ret->attributeWildcard = xmlSchemaParseAnyAttribute(pctxt,
7957 schema, child);
7958 child = child->next;
7960 if (child != NULL) {
7961 xmlSchemaPContentErr(pctxt,
7962 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
7963 NULL, node, child, NULL,
7964 "(annotation?, ((attribute | attributeGroup)*, anyAttribute?))");
7966 return (ret);
7970 * xmlSchemaPValAttrFormDefault:
7971 * @value: the value
7972 * @flags: the flags to be modified
7973 * @flagQualified: the specific flag for "qualified"
7975 * Returns 0 if the value is valid, 1 otherwise.
7977 static int
7978 xmlSchemaPValAttrFormDefault(const xmlChar *value,
7979 int *flags,
7980 int flagQualified)
7982 if (xmlStrEqual(value, BAD_CAST "qualified")) {
7983 if ((*flags & flagQualified) == 0)
7984 *flags |= flagQualified;
7985 } else if (!xmlStrEqual(value, BAD_CAST "unqualified"))
7986 return (1);
7988 return (0);
7992 * xmlSchemaPValAttrBlockFinal:
7993 * @value: the value
7994 * @flags: the flags to be modified
7995 * @flagAll: the specific flag for "#all"
7996 * @flagExtension: the specific flag for "extension"
7997 * @flagRestriction: the specific flag for "restriction"
7998 * @flagSubstitution: the specific flag for "substitution"
7999 * @flagList: the specific flag for "list"
8000 * @flagUnion: the specific flag for "union"
8002 * Validates the value of the attribute "final" and "block". The value
8003 * is converted into the specified flag values and returned in @flags.
8005 * Returns 0 if the value is valid, 1 otherwise.
8008 static int
8009 xmlSchemaPValAttrBlockFinal(const xmlChar *value,
8010 int *flags,
8011 int flagAll,
8012 int flagExtension,
8013 int flagRestriction,
8014 int flagSubstitution,
8015 int flagList,
8016 int flagUnion)
8018 int ret = 0;
8021 * TODO: This does not check for duplicate entries.
8023 if ((flags == NULL) || (value == NULL))
8024 return (-1);
8025 if (value[0] == 0)
8026 return (0);
8027 if (xmlStrEqual(value, BAD_CAST "#all")) {
8028 if (flagAll != -1)
8029 *flags |= flagAll;
8030 else {
8031 if (flagExtension != -1)
8032 *flags |= flagExtension;
8033 if (flagRestriction != -1)
8034 *flags |= flagRestriction;
8035 if (flagSubstitution != -1)
8036 *flags |= flagSubstitution;
8037 if (flagList != -1)
8038 *flags |= flagList;
8039 if (flagUnion != -1)
8040 *flags |= flagUnion;
8042 } else {
8043 const xmlChar *end, *cur = value;
8044 xmlChar *item;
8046 do {
8047 while (IS_BLANK_CH(*cur))
8048 cur++;
8049 end = cur;
8050 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
8051 end++;
8052 if (end == cur)
8053 break;
8054 item = xmlStrndup(cur, end - cur);
8055 if (xmlStrEqual(item, BAD_CAST "extension")) {
8056 if (flagExtension != -1) {
8057 if ((*flags & flagExtension) == 0)
8058 *flags |= flagExtension;
8059 } else
8060 ret = 1;
8061 } else if (xmlStrEqual(item, BAD_CAST "restriction")) {
8062 if (flagRestriction != -1) {
8063 if ((*flags & flagRestriction) == 0)
8064 *flags |= flagRestriction;
8065 } else
8066 ret = 1;
8067 } else if (xmlStrEqual(item, BAD_CAST "substitution")) {
8068 if (flagSubstitution != -1) {
8069 if ((*flags & flagSubstitution) == 0)
8070 *flags |= flagSubstitution;
8071 } else
8072 ret = 1;
8073 } else if (xmlStrEqual(item, BAD_CAST "list")) {
8074 if (flagList != -1) {
8075 if ((*flags & flagList) == 0)
8076 *flags |= flagList;
8077 } else
8078 ret = 1;
8079 } else if (xmlStrEqual(item, BAD_CAST "union")) {
8080 if (flagUnion != -1) {
8081 if ((*flags & flagUnion) == 0)
8082 *flags |= flagUnion;
8083 } else
8084 ret = 1;
8085 } else
8086 ret = 1;
8087 if (item != NULL)
8088 xmlFree(item);
8089 cur = end;
8090 } while ((ret == 0) && (*cur != 0));
8093 return (ret);
8096 static int
8097 xmlSchemaCheckCSelectorXPath(xmlSchemaParserCtxtPtr ctxt,
8098 xmlSchemaIDCPtr idc,
8099 xmlSchemaIDCSelectPtr selector,
8100 xmlAttrPtr attr,
8101 int isField)
8103 xmlNodePtr node;
8106 * c-selector-xpath:
8107 * Schema Component Constraint: Selector Value OK
8109 * TODO: 1 The {selector} must be a valid XPath expression, as defined
8110 * in [XPath].
8112 if (selector == NULL) {
8113 xmlSchemaPErr(ctxt, idc->node,
8114 XML_SCHEMAP_INTERNAL,
8115 "Internal error: xmlSchemaCheckCSelectorXPath, "
8116 "the selector is not specified.\n", NULL, NULL);
8117 return (-1);
8119 if (attr == NULL)
8120 node = idc->node;
8121 else
8122 node = (xmlNodePtr) attr;
8123 if (selector->xpath == NULL) {
8124 xmlSchemaPCustomErr(ctxt,
8125 /* TODO: Adjust error code. */
8126 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8127 NULL, node,
8128 "The XPath expression of the selector is not valid", NULL);
8129 return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE);
8130 } else {
8131 const xmlChar **nsArray = NULL;
8132 xmlNsPtr *nsList = NULL;
8134 * Compile the XPath expression.
8137 * TODO: We need the array of in-scope namespaces for compilation.
8138 * TODO: Call xmlPatterncompile with different options for selector/
8139 * field.
8141 if (attr == NULL)
8142 nsList = NULL;
8143 else
8144 nsList = xmlGetNsList(attr->doc, attr->parent);
8146 * Build an array of prefixes and namespaces.
8148 if (nsList != NULL) {
8149 int i, count = 0;
8151 for (i = 0; nsList[i] != NULL; i++)
8152 count++;
8154 nsArray = (const xmlChar **) xmlMalloc(
8155 (count * 2 + 1) * sizeof(const xmlChar *));
8156 if (nsArray == NULL) {
8157 xmlSchemaPErrMemory(ctxt, "allocating a namespace array",
8158 NULL);
8159 xmlFree(nsList);
8160 return (-1);
8162 for (i = 0; i < count; i++) {
8163 nsArray[2 * i] = nsList[i]->href;
8164 nsArray[2 * i + 1] = nsList[i]->prefix;
8166 nsArray[count * 2] = NULL;
8167 xmlFree(nsList);
8170 * TODO: Differentiate between "selector" and "field".
8172 if (isField)
8173 selector->xpathComp = (void *) xmlPatterncompile(selector->xpath,
8174 NULL, XML_PATTERN_XSFIELD, nsArray);
8175 else
8176 selector->xpathComp = (void *) xmlPatterncompile(selector->xpath,
8177 NULL, XML_PATTERN_XSSEL, nsArray);
8178 if (nsArray != NULL)
8179 xmlFree((xmlChar **) nsArray);
8181 if (selector->xpathComp == NULL) {
8182 xmlSchemaPCustomErr(ctxt,
8183 /* TODO: Adjust error code? */
8184 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8185 NULL, node,
8186 "The XPath expression '%s' could not be "
8187 "compiled", selector->xpath);
8188 return (XML_SCHEMAP_S4S_ATTR_INVALID_VALUE);
8191 return (0);
8194 #define ADD_ANNOTATION(annot) \
8195 xmlSchemaAnnotPtr cur = item->annot; \
8196 if (item->annot == NULL) { \
8197 item->annot = annot; \
8198 return (annot); \
8200 cur = item->annot; \
8201 if (cur->next != NULL) { \
8202 cur = cur->next; \
8204 cur->next = annot;
8207 * xmlSchemaAssignAnnotation:
8208 * @item: the schema component
8209 * @annot: the annotation
8211 * Adds the annotation to the given schema component.
8213 * Returns the given annotation.
8215 static xmlSchemaAnnotPtr
8216 xmlSchemaAddAnnotation(xmlSchemaAnnotItemPtr annItem,
8217 xmlSchemaAnnotPtr annot)
8219 if ((annItem == NULL) || (annot == NULL))
8220 return (NULL);
8221 switch (annItem->type) {
8222 case XML_SCHEMA_TYPE_ELEMENT: {
8223 xmlSchemaElementPtr item = (xmlSchemaElementPtr) annItem;
8224 ADD_ANNOTATION(annot)
8226 break;
8227 case XML_SCHEMA_TYPE_ATTRIBUTE: {
8228 xmlSchemaAttributePtr item = (xmlSchemaAttributePtr) annItem;
8229 ADD_ANNOTATION(annot)
8231 break;
8232 case XML_SCHEMA_TYPE_ANY_ATTRIBUTE:
8233 case XML_SCHEMA_TYPE_ANY: {
8234 xmlSchemaWildcardPtr item = (xmlSchemaWildcardPtr) annItem;
8235 ADD_ANNOTATION(annot)
8237 break;
8238 case XML_SCHEMA_TYPE_PARTICLE:
8239 case XML_SCHEMA_TYPE_IDC_KEY:
8240 case XML_SCHEMA_TYPE_IDC_KEYREF:
8241 case XML_SCHEMA_TYPE_IDC_UNIQUE: {
8242 xmlSchemaAnnotItemPtr item = (xmlSchemaAnnotItemPtr) annItem;
8243 ADD_ANNOTATION(annot)
8245 break;
8246 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP: {
8247 xmlSchemaAttributeGroupPtr item =
8248 (xmlSchemaAttributeGroupPtr) annItem;
8249 ADD_ANNOTATION(annot)
8251 break;
8252 case XML_SCHEMA_TYPE_NOTATION: {
8253 xmlSchemaNotationPtr item = (xmlSchemaNotationPtr) annItem;
8254 ADD_ANNOTATION(annot)
8256 break;
8257 case XML_SCHEMA_FACET_MININCLUSIVE:
8258 case XML_SCHEMA_FACET_MINEXCLUSIVE:
8259 case XML_SCHEMA_FACET_MAXINCLUSIVE:
8260 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
8261 case XML_SCHEMA_FACET_TOTALDIGITS:
8262 case XML_SCHEMA_FACET_FRACTIONDIGITS:
8263 case XML_SCHEMA_FACET_PATTERN:
8264 case XML_SCHEMA_FACET_ENUMERATION:
8265 case XML_SCHEMA_FACET_WHITESPACE:
8266 case XML_SCHEMA_FACET_LENGTH:
8267 case XML_SCHEMA_FACET_MAXLENGTH:
8268 case XML_SCHEMA_FACET_MINLENGTH: {
8269 xmlSchemaFacetPtr item = (xmlSchemaFacetPtr) annItem;
8270 ADD_ANNOTATION(annot)
8272 break;
8273 case XML_SCHEMA_TYPE_SIMPLE:
8274 case XML_SCHEMA_TYPE_COMPLEX: {
8275 xmlSchemaTypePtr item = (xmlSchemaTypePtr) annItem;
8276 ADD_ANNOTATION(annot)
8278 break;
8279 case XML_SCHEMA_TYPE_GROUP: {
8280 xmlSchemaModelGroupDefPtr item = (xmlSchemaModelGroupDefPtr) annItem;
8281 ADD_ANNOTATION(annot)
8283 break;
8284 case XML_SCHEMA_TYPE_SEQUENCE:
8285 case XML_SCHEMA_TYPE_CHOICE:
8286 case XML_SCHEMA_TYPE_ALL: {
8287 xmlSchemaModelGroupPtr item = (xmlSchemaModelGroupPtr) annItem;
8288 ADD_ANNOTATION(annot)
8290 break;
8291 default:
8292 xmlSchemaPCustomErr(NULL,
8293 XML_SCHEMAP_INTERNAL,
8294 NULL, NULL,
8295 "Internal error: xmlSchemaAddAnnotation, "
8296 "The item is not a annotated schema component", NULL);
8297 break;
8299 return (annot);
8303 * xmlSchemaParseIDCSelectorAndField:
8304 * @ctxt: a schema validation context
8305 * @schema: the schema being built
8306 * @node: a subtree containing XML Schema information
8308 * Parses a XML Schema identity-constraint definition's
8309 * <selector> and <field> elements.
8311 * Returns the parsed identity-constraint definition.
8313 static xmlSchemaIDCSelectPtr
8314 xmlSchemaParseIDCSelectorAndField(xmlSchemaParserCtxtPtr ctxt,
8315 xmlSchemaIDCPtr idc,
8316 xmlNodePtr node,
8317 int isField)
8319 xmlSchemaIDCSelectPtr item;
8320 xmlNodePtr child = NULL;
8321 xmlAttrPtr attr;
8324 * Check for illegal attributes.
8326 attr = node->properties;
8327 while (attr != NULL) {
8328 if (attr->ns == NULL) {
8329 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8330 (!xmlStrEqual(attr->name, BAD_CAST "xpath"))) {
8331 xmlSchemaPIllegalAttrErr(ctxt,
8332 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8334 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8335 xmlSchemaPIllegalAttrErr(ctxt,
8336 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8338 attr = attr->next;
8341 * Create the item.
8343 item = (xmlSchemaIDCSelectPtr) xmlMalloc(sizeof(xmlSchemaIDCSelect));
8344 if (item == NULL) {
8345 xmlSchemaPErrMemory(ctxt,
8346 "allocating a 'selector' of an identity-constraint definition",
8347 NULL);
8348 return (NULL);
8350 memset(item, 0, sizeof(xmlSchemaIDCSelect));
8352 * Attribute "xpath" (mandatory).
8354 attr = xmlSchemaGetPropNode(node, "xpath");
8355 if (attr == NULL) {
8356 xmlSchemaPMissingAttrErr(ctxt,
8357 XML_SCHEMAP_S4S_ATTR_MISSING,
8358 NULL, node,
8359 "name", NULL);
8360 } else {
8361 item->xpath = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8363 * URGENT TODO: "field"s have an other syntax than "selector"s.
8366 if (xmlSchemaCheckCSelectorXPath(ctxt, idc, item, attr,
8367 isField) == -1) {
8368 xmlSchemaPErr(ctxt,
8369 (xmlNodePtr) attr,
8370 XML_SCHEMAP_INTERNAL,
8371 "Internal error: xmlSchemaParseIDCSelectorAndField, "
8372 "validating the XPath expression of a IDC selector.\n",
8373 NULL, NULL);
8377 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
8379 * And now for the children...
8381 child = node->children;
8382 if (IS_SCHEMA(child, "annotation")) {
8384 * Add the annotation to the parent IDC.
8386 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) idc,
8387 xmlSchemaParseAnnotation(ctxt, child, 1));
8388 child = child->next;
8390 if (child != NULL) {
8391 xmlSchemaPContentErr(ctxt,
8392 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8393 NULL, node, child,
8394 NULL, "(annotation?)");
8397 return (item);
8401 * xmlSchemaParseIDC:
8402 * @ctxt: a schema validation context
8403 * @schema: the schema being built
8404 * @node: a subtree containing XML Schema information
8406 * Parses a XML Schema identity-constraint definition.
8408 * Returns the parsed identity-constraint definition.
8410 static xmlSchemaIDCPtr
8411 xmlSchemaParseIDC(xmlSchemaParserCtxtPtr ctxt,
8412 xmlSchemaPtr schema,
8413 xmlNodePtr node,
8414 xmlSchemaTypeType idcCategory,
8415 const xmlChar *targetNamespace)
8417 xmlSchemaIDCPtr item = NULL;
8418 xmlNodePtr child = NULL;
8419 xmlAttrPtr attr;
8420 const xmlChar *name = NULL;
8421 xmlSchemaIDCSelectPtr field = NULL, lastField = NULL;
8424 * Check for illegal attributes.
8426 attr = node->properties;
8427 while (attr != NULL) {
8428 if (attr->ns == NULL) {
8429 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8430 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
8431 ((idcCategory != XML_SCHEMA_TYPE_IDC_KEYREF) ||
8432 (!xmlStrEqual(attr->name, BAD_CAST "refer")))) {
8433 xmlSchemaPIllegalAttrErr(ctxt,
8434 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8436 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8437 xmlSchemaPIllegalAttrErr(ctxt,
8438 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8440 attr = attr->next;
8443 * Attribute "name" (mandatory).
8445 attr = xmlSchemaGetPropNode(node, "name");
8446 if (attr == NULL) {
8447 xmlSchemaPMissingAttrErr(ctxt,
8448 XML_SCHEMAP_S4S_ATTR_MISSING,
8449 NULL, node,
8450 "name", NULL);
8451 return (NULL);
8452 } else if (xmlSchemaPValAttrNode(ctxt,
8453 NULL, attr,
8454 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
8455 return (NULL);
8457 /* Create the component. */
8458 item = xmlSchemaAddIDC(ctxt, schema, name, targetNamespace,
8459 idcCategory, node);
8460 if (item == NULL)
8461 return(NULL);
8463 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
8464 if (idcCategory == XML_SCHEMA_TYPE_IDC_KEYREF) {
8466 * Attribute "refer" (mandatory).
8468 attr = xmlSchemaGetPropNode(node, "refer");
8469 if (attr == NULL) {
8470 xmlSchemaPMissingAttrErr(ctxt,
8471 XML_SCHEMAP_S4S_ATTR_MISSING,
8472 NULL, node,
8473 "refer", NULL);
8474 } else {
8476 * Create a reference item.
8478 item->ref = xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_IDC_KEY,
8479 NULL, NULL);
8480 if (item->ref == NULL)
8481 return (NULL);
8482 xmlSchemaPValAttrNodeQName(ctxt, schema,
8483 NULL, attr,
8484 &(item->ref->targetNamespace),
8485 &(item->ref->name));
8486 xmlSchemaCheckReference(ctxt, schema, node, attr,
8487 item->ref->targetNamespace);
8491 * And now for the children...
8493 child = node->children;
8494 if (IS_SCHEMA(child, "annotation")) {
8495 item->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
8496 child = child->next;
8498 if (child == NULL) {
8499 xmlSchemaPContentErr(ctxt,
8500 XML_SCHEMAP_S4S_ELEM_MISSING,
8501 NULL, node, child,
8502 "A child element is missing",
8503 "(annotation?, (selector, field+))");
8506 * Child element <selector>.
8508 if (IS_SCHEMA(child, "selector")) {
8509 item->selector = xmlSchemaParseIDCSelectorAndField(ctxt,
8510 item, child, 0);
8511 child = child->next;
8513 * Child elements <field>.
8515 if (IS_SCHEMA(child, "field")) {
8516 do {
8517 field = xmlSchemaParseIDCSelectorAndField(ctxt,
8518 item, child, 1);
8519 if (field != NULL) {
8520 field->index = item->nbFields;
8521 item->nbFields++;
8522 if (lastField != NULL)
8523 lastField->next = field;
8524 else
8525 item->fields = field;
8526 lastField = field;
8528 child = child->next;
8529 } while (IS_SCHEMA(child, "field"));
8530 } else {
8531 xmlSchemaPContentErr(ctxt,
8532 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8533 NULL, node, child,
8534 NULL, "(annotation?, (selector, field+))");
8537 if (child != NULL) {
8538 xmlSchemaPContentErr(ctxt,
8539 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8540 NULL, node, child,
8541 NULL, "(annotation?, (selector, field+))");
8544 return (item);
8548 * xmlSchemaParseElement:
8549 * @ctxt: a schema validation context
8550 * @schema: the schema being built
8551 * @node: a subtree containing XML Schema information
8552 * @topLevel: indicates if this is global declaration
8554 * Parses a XML schema element declaration.
8555 * *WARNING* this interface is highly subject to change
8557 * Returns the element declaration or a particle; NULL in case
8558 * of an error or if the particle has minOccurs==maxOccurs==0.
8560 static xmlSchemaBasicItemPtr
8561 xmlSchemaParseElement(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
8562 xmlNodePtr node, int *isElemRef, int topLevel)
8564 xmlSchemaElementPtr decl = NULL;
8565 xmlSchemaParticlePtr particle = NULL;
8566 xmlSchemaAnnotPtr annot = NULL;
8567 xmlNodePtr child = NULL;
8568 xmlAttrPtr attr, nameAttr;
8569 int min, max, isRef = 0;
8570 xmlChar *des = NULL;
8572 /* 3.3.3 Constraints on XML Representations of Element Declarations */
8573 /* TODO: Complete implementation of 3.3.6 */
8575 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8576 return (NULL);
8578 if (isElemRef != NULL)
8579 *isElemRef = 0;
8581 * If we get a "ref" attribute on a local <element> we will assume it's
8582 * a reference - even if there's a "name" attribute; this seems to be more
8583 * robust.
8585 nameAttr = xmlSchemaGetPropNode(node, "name");
8586 attr = xmlSchemaGetPropNode(node, "ref");
8587 if ((topLevel) || (attr == NULL)) {
8588 if (nameAttr == NULL) {
8589 xmlSchemaPMissingAttrErr(ctxt,
8590 XML_SCHEMAP_S4S_ATTR_MISSING,
8591 NULL, node, "name", NULL);
8592 return (NULL);
8594 } else
8595 isRef = 1;
8597 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
8598 child = node->children;
8599 if (IS_SCHEMA(child, "annotation")) {
8600 annot = xmlSchemaParseAnnotation(ctxt, child, 1);
8601 child = child->next;
8604 * Skip particle part if a global declaration.
8606 if (topLevel)
8607 goto declaration_part;
8609 * The particle part ==================================================
8611 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
8612 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1, "(xs:nonNegativeInteger | unbounded)");
8613 xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
8614 particle = xmlSchemaAddParticle(ctxt, node, min, max);
8615 if (particle == NULL)
8616 goto return_null;
8618 /* ret->flags |= XML_SCHEMAS_ELEM_REF; */
8620 if (isRef) {
8621 const xmlChar *refNs = NULL, *ref = NULL;
8622 xmlSchemaQNameRefPtr refer = NULL;
8624 * The reference part =============================================
8626 if (isElemRef != NULL)
8627 *isElemRef = 1;
8629 xmlSchemaPValAttrNodeQName(ctxt, schema,
8630 NULL, attr, &refNs, &ref);
8631 xmlSchemaCheckReference(ctxt, schema, node, attr, refNs);
8633 * SPEC (3.3.3 : 2.1) "One of ref or name must be present, but not both"
8635 if (nameAttr != NULL) {
8636 xmlSchemaPMutualExclAttrErr(ctxt,
8637 XML_SCHEMAP_SRC_ELEMENT_2_1, NULL, nameAttr, "ref", "name");
8640 * Check for illegal attributes.
8642 attr = node->properties;
8643 while (attr != NULL) {
8644 if (attr->ns == NULL) {
8645 if (xmlStrEqual(attr->name, BAD_CAST "ref") ||
8646 xmlStrEqual(attr->name, BAD_CAST "name") ||
8647 xmlStrEqual(attr->name, BAD_CAST "id") ||
8648 xmlStrEqual(attr->name, BAD_CAST "maxOccurs") ||
8649 xmlStrEqual(attr->name, BAD_CAST "minOccurs"))
8651 attr = attr->next;
8652 continue;
8653 } else {
8654 /* SPEC (3.3.3 : 2.2) */
8655 xmlSchemaPCustomAttrErr(ctxt,
8656 XML_SCHEMAP_SRC_ELEMENT_2_2,
8657 NULL, NULL, attr,
8658 "Only the attributes 'minOccurs', 'maxOccurs' and "
8659 "'id' are allowed in addition to 'ref'");
8660 break;
8662 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8663 xmlSchemaPIllegalAttrErr(ctxt,
8664 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8666 attr = attr->next;
8669 * No children except <annotation> expected.
8671 if (child != NULL) {
8672 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8673 NULL, node, child, NULL, "(annotation?)");
8675 if ((min == 0) && (max == 0))
8676 goto return_null;
8678 * Create the reference item and attach it to the particle.
8680 refer = xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_ELEMENT,
8681 ref, refNs);
8682 if (refer == NULL)
8683 goto return_null;
8684 particle->children = (xmlSchemaTreeItemPtr) refer;
8685 particle->annot = annot;
8687 * Add the particle to pending components, since the reference
8688 * need to be resolved.
8690 WXS_ADD_PENDING(ctxt, particle);
8691 return ((xmlSchemaBasicItemPtr) particle);
8694 * The declaration part ===============================================
8696 declaration_part:
8698 const xmlChar *ns = NULL, *fixed, *name, *attrValue;
8699 xmlSchemaIDCPtr curIDC = NULL, lastIDC = NULL;
8701 if (xmlSchemaPValAttrNode(ctxt, NULL, nameAttr,
8702 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0)
8703 goto return_null;
8705 * Evaluate the target namespace.
8707 if (topLevel) {
8708 ns = ctxt->targetNamespace;
8709 } else {
8710 attr = xmlSchemaGetPropNode(node, "form");
8711 if (attr != NULL) {
8712 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8713 if (xmlStrEqual(attrValue, BAD_CAST "qualified")) {
8714 ns = ctxt->targetNamespace;
8715 } else if (!xmlStrEqual(attrValue, BAD_CAST "unqualified")) {
8716 xmlSchemaPSimpleTypeErr(ctxt,
8717 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8718 NULL, (xmlNodePtr) attr,
8719 NULL, "(qualified | unqualified)",
8720 attrValue, NULL, NULL, NULL);
8722 } else if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
8723 ns = ctxt->targetNamespace;
8725 decl = xmlSchemaAddElement(ctxt, name, ns, node, topLevel);
8726 if (decl == NULL) {
8727 goto return_null;
8730 * Check for illegal attributes.
8732 attr = node->properties;
8733 while (attr != NULL) {
8734 if (attr->ns == NULL) {
8735 if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
8736 (!xmlStrEqual(attr->name, BAD_CAST "type")) &&
8737 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8738 (!xmlStrEqual(attr->name, BAD_CAST "default")) &&
8739 (!xmlStrEqual(attr->name, BAD_CAST "fixed")) &&
8740 (!xmlStrEqual(attr->name, BAD_CAST "block")) &&
8741 (!xmlStrEqual(attr->name, BAD_CAST "nillable")))
8743 if (topLevel == 0) {
8744 if ((!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
8745 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
8746 (!xmlStrEqual(attr->name, BAD_CAST "form")))
8748 xmlSchemaPIllegalAttrErr(ctxt,
8749 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8751 } else if ((!xmlStrEqual(attr->name, BAD_CAST "final")) &&
8752 (!xmlStrEqual(attr->name, BAD_CAST "abstract")) &&
8753 (!xmlStrEqual(attr->name, BAD_CAST "substitutionGroup"))) {
8755 xmlSchemaPIllegalAttrErr(ctxt,
8756 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8759 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8761 xmlSchemaPIllegalAttrErr(ctxt,
8762 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8764 attr = attr->next;
8767 * Extract/validate attributes.
8769 if (topLevel) {
8771 * Process top attributes of global element declarations here.
8773 decl->flags |= XML_SCHEMAS_ELEM_GLOBAL;
8774 decl->flags |= XML_SCHEMAS_ELEM_TOPLEVEL;
8775 xmlSchemaPValAttrQName(ctxt, schema,
8776 NULL, node, "substitutionGroup",
8777 &(decl->substGroupNs), &(decl->substGroup));
8778 if (xmlGetBooleanProp(ctxt, node, "abstract", 0))
8779 decl->flags |= XML_SCHEMAS_ELEM_ABSTRACT;
8781 * Attribute "final".
8783 attr = xmlSchemaGetPropNode(node, "final");
8784 if (attr == NULL) {
8785 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
8786 decl->flags |= XML_SCHEMAS_ELEM_FINAL_EXTENSION;
8787 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
8788 decl->flags |= XML_SCHEMAS_ELEM_FINAL_RESTRICTION;
8789 } else {
8790 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8791 if (xmlSchemaPValAttrBlockFinal(attrValue, &(decl->flags),
8793 XML_SCHEMAS_ELEM_FINAL_EXTENSION,
8794 XML_SCHEMAS_ELEM_FINAL_RESTRICTION, -1, -1, -1) != 0) {
8795 xmlSchemaPSimpleTypeErr(ctxt,
8796 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8797 NULL, (xmlNodePtr) attr,
8798 NULL, "(#all | List of (extension | restriction))",
8799 attrValue, NULL, NULL, NULL);
8804 * Attribute "block".
8806 attr = xmlSchemaGetPropNode(node, "block");
8807 if (attr == NULL) {
8809 * Apply default "block" values.
8811 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
8812 decl->flags |= XML_SCHEMAS_ELEM_BLOCK_RESTRICTION;
8813 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
8814 decl->flags |= XML_SCHEMAS_ELEM_BLOCK_EXTENSION;
8815 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
8816 decl->flags |= XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION;
8817 } else {
8818 attrValue = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8819 if (xmlSchemaPValAttrBlockFinal(attrValue, &(decl->flags),
8821 XML_SCHEMAS_ELEM_BLOCK_EXTENSION,
8822 XML_SCHEMAS_ELEM_BLOCK_RESTRICTION,
8823 XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION, -1, -1) != 0) {
8824 xmlSchemaPSimpleTypeErr(ctxt,
8825 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
8826 NULL, (xmlNodePtr) attr,
8827 NULL, "(#all | List of (extension | "
8828 "restriction | substitution))", attrValue,
8829 NULL, NULL, NULL);
8832 if (xmlGetBooleanProp(ctxt, node, "nillable", 0))
8833 decl->flags |= XML_SCHEMAS_ELEM_NILLABLE;
8835 attr = xmlSchemaGetPropNode(node, "type");
8836 if (attr != NULL) {
8837 xmlSchemaPValAttrNodeQName(ctxt, schema,
8838 NULL, attr,
8839 &(decl->namedTypeNs), &(decl->namedType));
8840 xmlSchemaCheckReference(ctxt, schema, node,
8841 attr, decl->namedTypeNs);
8843 decl->value = xmlSchemaGetProp(ctxt, node, "default");
8844 attr = xmlSchemaGetPropNode(node, "fixed");
8845 if (attr != NULL) {
8846 fixed = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
8847 if (decl->value != NULL) {
8849 * 3.3.3 : 1
8850 * default and fixed must not both be present.
8852 xmlSchemaPMutualExclAttrErr(ctxt,
8853 XML_SCHEMAP_SRC_ELEMENT_1,
8854 NULL, attr, "default", "fixed");
8855 } else {
8856 decl->flags |= XML_SCHEMAS_ELEM_FIXED;
8857 decl->value = fixed;
8861 * And now for the children...
8863 if (IS_SCHEMA(child, "complexType")) {
8865 * 3.3.3 : 3
8866 * "type" and either <simpleType> or <complexType> are mutually
8867 * exclusive
8869 if (decl->namedType != NULL) {
8870 xmlSchemaPContentErr(ctxt,
8871 XML_SCHEMAP_SRC_ELEMENT_3,
8872 NULL, node, child,
8873 "The attribute 'type' and the <complexType> child are "
8874 "mutually exclusive", NULL);
8875 } else
8876 WXS_ELEM_TYPEDEF(decl) = xmlSchemaParseComplexType(ctxt, schema, child, 0);
8877 child = child->next;
8878 } else if (IS_SCHEMA(child, "simpleType")) {
8880 * 3.3.3 : 3
8881 * "type" and either <simpleType> or <complexType> are
8882 * mutually exclusive
8884 if (decl->namedType != NULL) {
8885 xmlSchemaPContentErr(ctxt,
8886 XML_SCHEMAP_SRC_ELEMENT_3,
8887 NULL, node, child,
8888 "The attribute 'type' and the <simpleType> child are "
8889 "mutually exclusive", NULL);
8890 } else
8891 WXS_ELEM_TYPEDEF(decl) = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
8892 child = child->next;
8894 while ((IS_SCHEMA(child, "unique")) ||
8895 (IS_SCHEMA(child, "key")) || (IS_SCHEMA(child, "keyref"))) {
8896 if (IS_SCHEMA(child, "unique")) {
8897 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
8898 XML_SCHEMA_TYPE_IDC_UNIQUE, decl->targetNamespace);
8899 } else if (IS_SCHEMA(child, "key")) {
8900 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
8901 XML_SCHEMA_TYPE_IDC_KEY, decl->targetNamespace);
8902 } else if (IS_SCHEMA(child, "keyref")) {
8903 curIDC = xmlSchemaParseIDC(ctxt, schema, child,
8904 XML_SCHEMA_TYPE_IDC_KEYREF, decl->targetNamespace);
8906 if (lastIDC != NULL)
8907 lastIDC->next = curIDC;
8908 else
8909 decl->idcs = (void *) curIDC;
8910 lastIDC = curIDC;
8911 child = child->next;
8913 if (child != NULL) {
8914 xmlSchemaPContentErr(ctxt,
8915 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
8916 NULL, node, child,
8917 NULL, "(annotation?, ((simpleType | complexType)?, "
8918 "(unique | key | keyref)*))");
8920 decl->annot = annot;
8923 * NOTE: Element Declaration Representation OK 4. will be checked at a
8924 * different layer.
8926 FREE_AND_NULL(des)
8927 if (topLevel)
8928 return ((xmlSchemaBasicItemPtr) decl);
8929 else {
8930 particle->children = (xmlSchemaTreeItemPtr) decl;
8931 return ((xmlSchemaBasicItemPtr) particle);
8934 return_null:
8935 FREE_AND_NULL(des);
8936 if (annot != NULL) {
8937 if (particle != NULL)
8938 particle->annot = NULL;
8939 if (decl != NULL)
8940 decl->annot = NULL;
8941 xmlSchemaFreeAnnot(annot);
8943 return (NULL);
8947 * xmlSchemaParseUnion:
8948 * @ctxt: a schema validation context
8949 * @schema: the schema being built
8950 * @node: a subtree containing XML Schema information
8952 * parse a XML schema Union definition
8953 * *WARNING* this interface is highly subject to change
8955 * Returns -1 in case of internal error, 0 in case of success and a positive
8956 * error code otherwise.
8958 static int
8959 xmlSchemaParseUnion(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
8960 xmlNodePtr node)
8962 xmlSchemaTypePtr type;
8963 xmlNodePtr child = NULL;
8964 xmlAttrPtr attr;
8965 const xmlChar *cur = NULL;
8967 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
8968 return (-1);
8969 /* Not a component, don't create it. */
8970 type = ctxt->ctxtType;
8972 * Mark the simple type as being of variety "union".
8974 type->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
8976 * SPEC (Base type) (2) "If the <list> or <union> alternative is chosen,
8977 * then the `simple ur-type definition`."
8979 type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
8981 * Check for illegal attributes.
8983 attr = node->properties;
8984 while (attr != NULL) {
8985 if (attr->ns == NULL) {
8986 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
8987 (!xmlStrEqual(attr->name, BAD_CAST "memberTypes"))) {
8988 xmlSchemaPIllegalAttrErr(ctxt,
8989 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8991 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
8992 xmlSchemaPIllegalAttrErr(ctxt,
8993 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
8995 attr = attr->next;
8997 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
8999 * Attribute "memberTypes". This is a list of QNames.
9000 * TODO: Check the value to contain anything.
9002 attr = xmlSchemaGetPropNode(node, "memberTypes");
9003 if (attr != NULL) {
9004 const xmlChar *end;
9005 xmlChar *tmp;
9006 const xmlChar *localName, *nsName;
9007 xmlSchemaTypeLinkPtr link, lastLink = NULL;
9008 xmlSchemaQNameRefPtr ref;
9010 cur = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
9011 if (cur == NULL)
9012 return (-1);
9013 type->base = cur;
9014 do {
9015 while (IS_BLANK_CH(*cur))
9016 cur++;
9017 end = cur;
9018 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
9019 end++;
9020 if (end == cur)
9021 break;
9022 tmp = xmlStrndup(cur, end - cur);
9023 if (tmp == NULL) {
9024 xmlSchemaPErrMemory(ctxt, "xmlSchemaParseUnion, "
9025 "duplicating type name", NULL);
9026 return (-1);
9028 if (xmlSchemaPValAttrNodeQNameValue(ctxt, schema,
9029 NULL, attr, BAD_CAST tmp, &nsName, &localName) == 0) {
9031 * Create the member type link.
9033 link = (xmlSchemaTypeLinkPtr)
9034 xmlMalloc(sizeof(xmlSchemaTypeLink));
9035 if (link == NULL) {
9036 xmlSchemaPErrMemory(ctxt, "xmlSchemaParseUnion, "
9037 "allocating a type link", NULL);
9038 FREE_AND_NULL(tmp)
9039 return (-1);
9041 link->type = NULL;
9042 link->next = NULL;
9043 if (lastLink == NULL)
9044 type->memberTypes = link;
9045 else
9046 lastLink->next = link;
9047 lastLink = link;
9049 * Create a reference item.
9051 ref = xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_SIMPLE,
9052 localName, nsName);
9053 if (ref == NULL) {
9054 FREE_AND_NULL(tmp)
9055 return (-1);
9058 * Assign the reference to the link, it will be resolved
9059 * later during fixup of the union simple type.
9061 link->type = (xmlSchemaTypePtr) ref;
9063 FREE_AND_NULL(tmp)
9064 cur = end;
9065 } while (*cur != 0);
9069 * And now for the children...
9071 child = node->children;
9072 if (IS_SCHEMA(child, "annotation")) {
9074 * Add the annotation to the simple type ancestor.
9076 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
9077 xmlSchemaParseAnnotation(ctxt, child, 1));
9078 child = child->next;
9080 if (IS_SCHEMA(child, "simpleType")) {
9081 xmlSchemaTypePtr subtype, last = NULL;
9084 * Anchor the member types in the "subtypes" field of the
9085 * simple type.
9087 while (IS_SCHEMA(child, "simpleType")) {
9088 subtype = (xmlSchemaTypePtr)
9089 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
9090 if (subtype != NULL) {
9091 if (last == NULL) {
9092 type->subtypes = subtype;
9093 last = subtype;
9094 } else {
9095 last->next = subtype;
9096 last = subtype;
9098 last->next = NULL;
9100 child = child->next;
9103 if (child != NULL) {
9104 xmlSchemaPContentErr(ctxt,
9105 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9106 NULL, node, child, NULL, "(annotation?, simpleType*)");
9108 if ((attr == NULL) && (type->subtypes == NULL)) {
9110 * src-union-memberTypes-or-simpleTypes
9111 * Either the memberTypes [attribute] of the <union> element must
9112 * be non-empty or there must be at least one simpleType [child].
9114 xmlSchemaPCustomErr(ctxt,
9115 XML_SCHEMAP_SRC_UNION_MEMBERTYPES_OR_SIMPLETYPES,
9116 NULL, node,
9117 "Either the attribute 'memberTypes' or "
9118 "at least one <simpleType> child must be present", NULL);
9120 return (0);
9124 * xmlSchemaParseList:
9125 * @ctxt: a schema validation context
9126 * @schema: the schema being built
9127 * @node: a subtree containing XML Schema information
9129 * parse a XML schema List definition
9130 * *WARNING* this interface is highly subject to change
9132 * Returns -1 in case of error, 0 if the declaration is improper and
9133 * 1 in case of success.
9135 static xmlSchemaTypePtr
9136 xmlSchemaParseList(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
9137 xmlNodePtr node)
9139 xmlSchemaTypePtr type;
9140 xmlNodePtr child = NULL;
9141 xmlAttrPtr attr;
9143 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9144 return (NULL);
9145 /* Not a component, don't create it. */
9146 type = ctxt->ctxtType;
9148 * Mark the type as being of variety "list".
9150 type->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
9152 * SPEC (Base type) (2) "If the <list> or <union> alternative is chosen,
9153 * then the `simple ur-type definition`."
9155 type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
9157 * Check for illegal attributes.
9159 attr = node->properties;
9160 while (attr != NULL) {
9161 if (attr->ns == NULL) {
9162 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9163 (!xmlStrEqual(attr->name, BAD_CAST "itemType"))) {
9164 xmlSchemaPIllegalAttrErr(ctxt,
9165 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9167 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9168 xmlSchemaPIllegalAttrErr(ctxt,
9169 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9171 attr = attr->next;
9174 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
9177 * Attribute "itemType". NOTE that we will use the "ref" and "refNs"
9178 * fields for holding the reference to the itemType.
9180 * REVAMP TODO: Use the "base" and "baseNs" fields, since we will remove
9181 * the "ref" fields.
9183 xmlSchemaPValAttrQName(ctxt, schema, NULL,
9184 node, "itemType", &(type->baseNs), &(type->base));
9186 * And now for the children...
9188 child = node->children;
9189 if (IS_SCHEMA(child, "annotation")) {
9190 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
9191 xmlSchemaParseAnnotation(ctxt, child, 1));
9192 child = child->next;
9194 if (IS_SCHEMA(child, "simpleType")) {
9196 * src-list-itemType-or-simpleType
9197 * Either the itemType [attribute] or the <simpleType> [child] of
9198 * the <list> element must be present, but not both.
9200 if (type->base != NULL) {
9201 xmlSchemaPCustomErr(ctxt,
9202 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
9203 NULL, node,
9204 "The attribute 'itemType' and the <simpleType> child "
9205 "are mutually exclusive", NULL);
9206 } else {
9207 type->subtypes = xmlSchemaParseSimpleType(ctxt, schema, child, 0);
9209 child = child->next;
9210 } else if (type->base == NULL) {
9211 xmlSchemaPCustomErr(ctxt,
9212 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
9213 NULL, node,
9214 "Either the attribute 'itemType' or the <simpleType> child "
9215 "must be present", NULL);
9217 if (child != NULL) {
9218 xmlSchemaPContentErr(ctxt,
9219 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9220 NULL, node, child, NULL, "(annotation?, simpleType?)");
9222 if ((type->base == NULL) &&
9223 (type->subtypes == NULL) &&
9224 (xmlSchemaGetPropNode(node, "itemType") == NULL)) {
9225 xmlSchemaPCustomErr(ctxt,
9226 XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
9227 NULL, node,
9228 "Either the attribute 'itemType' or the <simpleType> child "
9229 "must be present", NULL);
9231 return (NULL);
9235 * xmlSchemaParseSimpleType:
9236 * @ctxt: a schema validation context
9237 * @schema: the schema being built
9238 * @node: a subtree containing XML Schema information
9240 * parse a XML schema Simple Type definition
9241 * *WARNING* this interface is highly subject to change
9243 * Returns -1 in case of error, 0 if the declaration is improper and
9244 * 1 in case of success.
9246 static xmlSchemaTypePtr
9247 xmlSchemaParseSimpleType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
9248 xmlNodePtr node, int topLevel)
9250 xmlSchemaTypePtr type, oldCtxtType;
9251 xmlNodePtr child = NULL;
9252 const xmlChar *attrValue = NULL;
9253 xmlAttrPtr attr;
9254 int hasRestriction = 0;
9256 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9257 return (NULL);
9259 if (topLevel) {
9260 attr = xmlSchemaGetPropNode(node, "name");
9261 if (attr == NULL) {
9262 xmlSchemaPMissingAttrErr(ctxt,
9263 XML_SCHEMAP_S4S_ATTR_MISSING,
9264 NULL, node,
9265 "name", NULL);
9266 return (NULL);
9267 } else {
9268 if (xmlSchemaPValAttrNode(ctxt,
9269 NULL, attr,
9270 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &attrValue) != 0)
9271 return (NULL);
9273 * Skip built-in types.
9275 if (ctxt->isS4S) {
9276 xmlSchemaTypePtr biType;
9278 if (ctxt->isRedefine) {
9280 * REDEFINE: Disallow redefinition of built-in-types.
9281 * TODO: It seems that the spec does not say anything
9282 * about this case.
9284 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_SRC_REDEFINE,
9285 NULL, node,
9286 "Redefinition of built-in simple types is not "
9287 "supported", NULL);
9288 return(NULL);
9290 biType = xmlSchemaGetPredefinedType(attrValue, xmlSchemaNs);
9291 if (biType != NULL)
9292 return (biType);
9297 * TargetNamespace:
9298 * SPEC "The `actual value` of the targetNamespace [attribute]
9299 * of the <schema> ancestor element information item if present,
9300 * otherwise `absent`.
9302 if (topLevel == 0) {
9303 #ifdef ENABLE_NAMED_LOCALS
9304 char buf[40];
9305 #endif
9307 * Parse as local simple type definition.
9309 #ifdef ENABLE_NAMED_LOCALS
9310 snprintf(buf, 39, "#ST%d", ctxt->counter++ + 1);
9311 type = xmlSchemaAddType(ctxt, schema,
9312 XML_SCHEMA_TYPE_SIMPLE,
9313 xmlDictLookup(ctxt->dict, (const xmlChar *)buf, -1),
9314 ctxt->targetNamespace, node, 0);
9315 #else
9316 type = xmlSchemaAddType(ctxt, schema,
9317 XML_SCHEMA_TYPE_SIMPLE,
9318 NULL, ctxt->targetNamespace, node, 0);
9319 #endif
9320 if (type == NULL)
9321 return (NULL);
9322 type->type = XML_SCHEMA_TYPE_SIMPLE;
9323 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
9325 * Check for illegal attributes.
9327 attr = node->properties;
9328 while (attr != NULL) {
9329 if (attr->ns == NULL) {
9330 if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
9331 xmlSchemaPIllegalAttrErr(ctxt,
9332 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9334 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9335 xmlSchemaPIllegalAttrErr(ctxt,
9336 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9338 attr = attr->next;
9340 } else {
9342 * Parse as global simple type definition.
9344 * Note that attrValue is the value of the attribute "name" here.
9346 type = xmlSchemaAddType(ctxt, schema, XML_SCHEMA_TYPE_SIMPLE,
9347 attrValue, ctxt->targetNamespace, node, 1);
9348 if (type == NULL)
9349 return (NULL);
9350 type->type = XML_SCHEMA_TYPE_SIMPLE;
9351 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
9352 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
9354 * Check for illegal attributes.
9356 attr = node->properties;
9357 while (attr != NULL) {
9358 if (attr->ns == NULL) {
9359 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9360 (!xmlStrEqual(attr->name, BAD_CAST "name")) &&
9361 (!xmlStrEqual(attr->name, BAD_CAST "final"))) {
9362 xmlSchemaPIllegalAttrErr(ctxt,
9363 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9365 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9366 xmlSchemaPIllegalAttrErr(ctxt,
9367 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9369 attr = attr->next;
9372 * Attribute "final".
9374 attr = xmlSchemaGetPropNode(node, "final");
9375 if (attr == NULL) {
9376 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
9377 type->flags |= XML_SCHEMAS_TYPE_FINAL_RESTRICTION;
9378 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST)
9379 type->flags |= XML_SCHEMAS_TYPE_FINAL_LIST;
9380 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION)
9381 type->flags |= XML_SCHEMAS_TYPE_FINAL_UNION;
9382 } else {
9383 attrValue = xmlSchemaGetProp(ctxt, node, "final");
9384 if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
9385 -1, -1, XML_SCHEMAS_TYPE_FINAL_RESTRICTION, -1,
9386 XML_SCHEMAS_TYPE_FINAL_LIST,
9387 XML_SCHEMAS_TYPE_FINAL_UNION) != 0) {
9389 xmlSchemaPSimpleTypeErr(ctxt,
9390 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
9391 WXS_BASIC_CAST type, (xmlNodePtr) attr,
9392 NULL, "(#all | List of (list | union | restriction)",
9393 attrValue, NULL, NULL, NULL);
9397 type->targetNamespace = ctxt->targetNamespace;
9398 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
9400 * And now for the children...
9402 oldCtxtType = ctxt->ctxtType;
9404 ctxt->ctxtType = type;
9406 child = node->children;
9407 if (IS_SCHEMA(child, "annotation")) {
9408 type->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
9409 child = child->next;
9411 if (child == NULL) {
9412 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_MISSING,
9413 NULL, node, child, NULL,
9414 "(annotation?, (restriction | list | union))");
9415 } else if (IS_SCHEMA(child, "restriction")) {
9416 xmlSchemaParseRestriction(ctxt, schema, child,
9417 XML_SCHEMA_TYPE_SIMPLE);
9418 hasRestriction = 1;
9419 child = child->next;
9420 } else if (IS_SCHEMA(child, "list")) {
9421 xmlSchemaParseList(ctxt, schema, child);
9422 child = child->next;
9423 } else if (IS_SCHEMA(child, "union")) {
9424 xmlSchemaParseUnion(ctxt, schema, child);
9425 child = child->next;
9427 if (child != NULL) {
9428 xmlSchemaPContentErr(ctxt, XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9429 NULL, node, child, NULL,
9430 "(annotation?, (restriction | list | union))");
9433 * REDEFINE: SPEC src-redefine (5)
9434 * "Within the [children], each <simpleType> must have a
9435 * <restriction> among its [children] ... the `actual value` of whose
9436 * base [attribute] must be the same as the `actual value` of its own
9437 * name attribute plus target namespace;"
9439 if (topLevel && ctxt->isRedefine && (! hasRestriction)) {
9440 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_SRC_REDEFINE,
9441 NULL, node, "This is a redefinition, thus the "
9442 "<simpleType> must have a <restriction> child", NULL);
9445 ctxt->ctxtType = oldCtxtType;
9446 return (type);
9450 * xmlSchemaParseModelGroupDefRef:
9451 * @ctxt: the parser context
9452 * @schema: the schema being built
9453 * @node: the node
9455 * Parses a reference to a model group definition.
9457 * We will return a particle component with a qname-component or
9458 * NULL in case of an error.
9460 static xmlSchemaTreeItemPtr
9461 xmlSchemaParseModelGroupDefRef(xmlSchemaParserCtxtPtr ctxt,
9462 xmlSchemaPtr schema,
9463 xmlNodePtr node)
9465 xmlSchemaParticlePtr item;
9466 xmlNodePtr child = NULL;
9467 xmlAttrPtr attr;
9468 const xmlChar *ref = NULL, *refNs = NULL;
9469 int min, max;
9471 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9472 return (NULL);
9474 attr = xmlSchemaGetPropNode(node, "ref");
9475 if (attr == NULL) {
9476 xmlSchemaPMissingAttrErr(ctxt,
9477 XML_SCHEMAP_S4S_ATTR_MISSING,
9478 NULL, node, "ref", NULL);
9479 return (NULL);
9480 } else if (xmlSchemaPValAttrNodeQName(ctxt, schema, NULL,
9481 attr, &refNs, &ref) != 0) {
9482 return (NULL);
9484 xmlSchemaCheckReference(ctxt, schema, node, attr, refNs);
9485 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
9486 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
9487 "(xs:nonNegativeInteger | unbounded)");
9489 * Check for illegal attributes.
9491 attr = node->properties;
9492 while (attr != NULL) {
9493 if (attr->ns == NULL) {
9494 if ((!xmlStrEqual(attr->name, BAD_CAST "ref")) &&
9495 (!xmlStrEqual(attr->name, BAD_CAST "id")) &&
9496 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs")) &&
9497 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs"))) {
9498 xmlSchemaPIllegalAttrErr(ctxt,
9499 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9501 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9502 xmlSchemaPIllegalAttrErr(ctxt,
9503 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9505 attr = attr->next;
9507 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
9508 item = xmlSchemaAddParticle(ctxt, node, min, max);
9509 if (item == NULL)
9510 return (NULL);
9512 * Create a qname-reference and set as the term; it will be substituted
9513 * for the model group after the reference has been resolved.
9515 item->children = (xmlSchemaTreeItemPtr)
9516 xmlSchemaNewQNameRef(ctxt, XML_SCHEMA_TYPE_GROUP, ref, refNs);
9517 xmlSchemaPCheckParticleCorrect_2(ctxt, item, node, min, max);
9519 * And now for the children...
9521 child = node->children;
9522 /* TODO: Is annotation even allowed for a model group reference? */
9523 if (IS_SCHEMA(child, "annotation")) {
9525 * TODO: What to do exactly with the annotation?
9527 item->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
9528 child = child->next;
9530 if (child != NULL) {
9531 xmlSchemaPContentErr(ctxt,
9532 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9533 NULL, node, child, NULL,
9534 "(annotation?)");
9537 * Corresponds to no component at all if minOccurs==maxOccurs==0.
9539 if ((min == 0) && (max == 0))
9540 return (NULL);
9542 return ((xmlSchemaTreeItemPtr) item);
9546 * xmlSchemaParseModelGroupDefinition:
9547 * @ctxt: a schema validation context
9548 * @schema: the schema being built
9549 * @node: a subtree containing XML Schema information
9551 * Parses a XML schema model group definition.
9553 * Note that the constraint src-redefine (6.2) can't be applied until
9554 * references have been resolved. So we will do this at the
9555 * component fixup level.
9557 * *WARNING* this interface is highly subject to change
9559 * Returns -1 in case of error, 0 if the declaration is improper and
9560 * 1 in case of success.
9562 static xmlSchemaModelGroupDefPtr
9563 xmlSchemaParseModelGroupDefinition(xmlSchemaParserCtxtPtr ctxt,
9564 xmlSchemaPtr schema,
9565 xmlNodePtr node)
9567 xmlSchemaModelGroupDefPtr item;
9568 xmlNodePtr child = NULL;
9569 xmlAttrPtr attr;
9570 const xmlChar *name;
9572 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
9573 return (NULL);
9575 attr = xmlSchemaGetPropNode(node, "name");
9576 if (attr == NULL) {
9577 xmlSchemaPMissingAttrErr(ctxt,
9578 XML_SCHEMAP_S4S_ATTR_MISSING,
9579 NULL, node,
9580 "name", NULL);
9581 return (NULL);
9582 } else if (xmlSchemaPValAttrNode(ctxt, NULL, attr,
9583 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
9584 return (NULL);
9586 item = xmlSchemaAddModelGroupDefinition(ctxt, schema, name,
9587 ctxt->targetNamespace, node);
9588 if (item == NULL)
9589 return (NULL);
9591 * Check for illegal attributes.
9593 attr = node->properties;
9594 while (attr != NULL) {
9595 if (attr->ns == NULL) {
9596 if ((!xmlStrEqual(attr->name, BAD_CAST "name")) &&
9597 (!xmlStrEqual(attr->name, BAD_CAST "id"))) {
9598 xmlSchemaPIllegalAttrErr(ctxt,
9599 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9601 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
9602 xmlSchemaPIllegalAttrErr(ctxt,
9603 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
9605 attr = attr->next;
9607 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
9609 * And now for the children...
9611 child = node->children;
9612 if (IS_SCHEMA(child, "annotation")) {
9613 item->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
9614 child = child->next;
9616 if (IS_SCHEMA(child, "all")) {
9617 item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
9618 XML_SCHEMA_TYPE_ALL, 0);
9619 child = child->next;
9620 } else if (IS_SCHEMA(child, "choice")) {
9621 item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
9622 XML_SCHEMA_TYPE_CHOICE, 0);
9623 child = child->next;
9624 } else if (IS_SCHEMA(child, "sequence")) {
9625 item->children = xmlSchemaParseModelGroup(ctxt, schema, child,
9626 XML_SCHEMA_TYPE_SEQUENCE, 0);
9627 child = child->next;
9632 if (child != NULL) {
9633 xmlSchemaPContentErr(ctxt,
9634 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9635 NULL, node, child, NULL,
9636 "(annotation?, (all | choice | sequence)?)");
9638 return (item);
9642 * xmlSchemaCleanupDoc:
9643 * @ctxt: a schema validation context
9644 * @node: the root of the document.
9646 * removes unwanted nodes in a schemas document tree
9648 static void
9649 xmlSchemaCleanupDoc(xmlSchemaParserCtxtPtr ctxt, xmlNodePtr root)
9651 xmlNodePtr delete, cur;
9653 if ((ctxt == NULL) || (root == NULL)) return;
9656 * Remove all the blank text nodes
9658 delete = NULL;
9659 cur = root;
9660 while (cur != NULL) {
9661 if (delete != NULL) {
9662 xmlUnlinkNode(delete);
9663 xmlFreeNode(delete);
9664 delete = NULL;
9666 if (cur->type == XML_TEXT_NODE) {
9667 if (IS_BLANK_NODE(cur)) {
9668 if (xmlNodeGetSpacePreserve(cur) != 1) {
9669 delete = cur;
9672 } else if ((cur->type != XML_ELEMENT_NODE) &&
9673 (cur->type != XML_CDATA_SECTION_NODE)) {
9674 delete = cur;
9675 goto skip_children;
9679 * Skip to next node
9681 if (cur->children != NULL) {
9682 if ((cur->children->type != XML_ENTITY_DECL) &&
9683 (cur->children->type != XML_ENTITY_REF_NODE) &&
9684 (cur->children->type != XML_ENTITY_NODE)) {
9685 cur = cur->children;
9686 continue;
9689 skip_children:
9690 if (cur->next != NULL) {
9691 cur = cur->next;
9692 continue;
9695 do {
9696 cur = cur->parent;
9697 if (cur == NULL)
9698 break;
9699 if (cur == root) {
9700 cur = NULL;
9701 break;
9703 if (cur->next != NULL) {
9704 cur = cur->next;
9705 break;
9707 } while (cur != NULL);
9709 if (delete != NULL) {
9710 xmlUnlinkNode(delete);
9711 xmlFreeNode(delete);
9712 delete = NULL;
9717 static void
9718 xmlSchemaClearSchemaDefaults(xmlSchemaPtr schema)
9720 if (schema->flags & XML_SCHEMAS_QUALIF_ELEM)
9721 schema->flags ^= XML_SCHEMAS_QUALIF_ELEM;
9723 if (schema->flags & XML_SCHEMAS_QUALIF_ATTR)
9724 schema->flags ^= XML_SCHEMAS_QUALIF_ATTR;
9726 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
9727 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_EXTENSION;
9728 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
9729 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION;
9730 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_LIST)
9731 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_LIST;
9732 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_UNION)
9733 schema->flags ^= XML_SCHEMAS_FINAL_DEFAULT_UNION;
9735 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
9736 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION;
9737 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
9738 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION;
9739 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION)
9740 schema->flags ^= XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION;
9743 static int
9744 xmlSchemaParseSchemaElement(xmlSchemaParserCtxtPtr ctxt,
9745 xmlSchemaPtr schema,
9746 xmlNodePtr node)
9748 xmlAttrPtr attr;
9749 const xmlChar *val;
9750 int res = 0, oldErrs = ctxt->nberrors;
9753 * Those flags should be moved to the parser context flags,
9754 * since they are not visible at the component level. I.e.
9755 * they are used if processing schema *documents* only.
9757 res = xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
9758 HFAILURE;
9761 * Since the version is of type xs:token, we won't bother to
9762 * check it.
9764 /* REMOVED:
9765 attr = xmlSchemaGetPropNode(node, "version");
9766 if (attr != NULL) {
9767 res = xmlSchemaPValAttrNode(ctxt, NULL, NULL, attr,
9768 xmlSchemaGetBuiltInType(XML_SCHEMAS_TOKEN), &val);
9769 HFAILURE;
9772 attr = xmlSchemaGetPropNode(node, "targetNamespace");
9773 if (attr != NULL) {
9774 res = xmlSchemaPValAttrNode(ctxt, NULL, attr,
9775 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI), NULL);
9776 HFAILURE;
9777 if (res != 0) {
9778 ctxt->stop = XML_SCHEMAP_S4S_ATTR_INVALID_VALUE;
9779 goto exit;
9782 attr = xmlSchemaGetPropNode(node, "elementFormDefault");
9783 if (attr != NULL) {
9784 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
9785 res = xmlSchemaPValAttrFormDefault(val, &schema->flags,
9786 XML_SCHEMAS_QUALIF_ELEM);
9787 HFAILURE;
9788 if (res != 0) {
9789 xmlSchemaPSimpleTypeErr(ctxt,
9790 XML_SCHEMAP_ELEMFORMDEFAULT_VALUE,
9791 NULL, (xmlNodePtr) attr, NULL,
9792 "(qualified | unqualified)", val, NULL, NULL, NULL);
9795 attr = xmlSchemaGetPropNode(node, "attributeFormDefault");
9796 if (attr != NULL) {
9797 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
9798 res = xmlSchemaPValAttrFormDefault(val, &schema->flags,
9799 XML_SCHEMAS_QUALIF_ATTR);
9800 HFAILURE;
9801 if (res != 0) {
9802 xmlSchemaPSimpleTypeErr(ctxt,
9803 XML_SCHEMAP_ATTRFORMDEFAULT_VALUE,
9804 NULL, (xmlNodePtr) attr, NULL,
9805 "(qualified | unqualified)", val, NULL, NULL, NULL);
9808 attr = xmlSchemaGetPropNode(node, "finalDefault");
9809 if (attr != NULL) {
9810 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
9811 res = xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
9812 XML_SCHEMAS_FINAL_DEFAULT_EXTENSION,
9813 XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION,
9815 XML_SCHEMAS_FINAL_DEFAULT_LIST,
9816 XML_SCHEMAS_FINAL_DEFAULT_UNION);
9817 HFAILURE;
9818 if (res != 0) {
9819 xmlSchemaPSimpleTypeErr(ctxt,
9820 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
9821 NULL, (xmlNodePtr) attr, NULL,
9822 "(#all | List of (extension | restriction | list | union))",
9823 val, NULL, NULL, NULL);
9826 attr = xmlSchemaGetPropNode(node, "blockDefault");
9827 if (attr != NULL) {
9828 val = xmlSchemaGetNodeContent(ctxt, (xmlNodePtr) attr);
9829 res = xmlSchemaPValAttrBlockFinal(val, &(schema->flags), -1,
9830 XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION,
9831 XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION,
9832 XML_SCHEMAS_BLOCK_DEFAULT_SUBSTITUTION, -1, -1);
9833 HFAILURE;
9834 if (res != 0) {
9835 xmlSchemaPSimpleTypeErr(ctxt,
9836 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
9837 NULL, (xmlNodePtr) attr, NULL,
9838 "(#all | List of (extension | restriction | substitution))",
9839 val, NULL, NULL, NULL);
9843 exit:
9844 if (oldErrs != ctxt->nberrors)
9845 res = ctxt->err;
9846 return(res);
9847 exit_failure:
9848 return(-1);
9852 * xmlSchemaParseSchemaTopLevel:
9853 * @ctxt: a schema validation context
9854 * @schema: the schemas
9855 * @nodes: the list of top level nodes
9857 * Returns the internal XML Schema structure built from the resource or
9858 * NULL in case of error
9860 static int
9861 xmlSchemaParseSchemaTopLevel(xmlSchemaParserCtxtPtr ctxt,
9862 xmlSchemaPtr schema, xmlNodePtr nodes)
9864 xmlNodePtr child;
9865 xmlSchemaAnnotPtr annot;
9866 int res = 0, oldErrs, tmpOldErrs;
9868 if ((ctxt == NULL) || (schema == NULL) || (nodes == NULL))
9869 return(-1);
9871 oldErrs = ctxt->nberrors;
9872 child = nodes;
9873 while ((IS_SCHEMA(child, "include")) ||
9874 (IS_SCHEMA(child, "import")) ||
9875 (IS_SCHEMA(child, "redefine")) ||
9876 (IS_SCHEMA(child, "annotation"))) {
9877 if (IS_SCHEMA(child, "annotation")) {
9878 annot = xmlSchemaParseAnnotation(ctxt, child, 1);
9879 if (schema->annot == NULL)
9880 schema->annot = annot;
9881 else
9882 xmlSchemaFreeAnnot(annot);
9883 } else if (IS_SCHEMA(child, "import")) {
9884 tmpOldErrs = ctxt->nberrors;
9885 res = xmlSchemaParseImport(ctxt, schema, child);
9886 HFAILURE;
9887 HSTOP(ctxt);
9888 if (tmpOldErrs != ctxt->nberrors)
9889 goto exit;
9890 } else if (IS_SCHEMA(child, "include")) {
9891 tmpOldErrs = ctxt->nberrors;
9892 res = xmlSchemaParseInclude(ctxt, schema, child);
9893 HFAILURE;
9894 HSTOP(ctxt);
9895 if (tmpOldErrs != ctxt->nberrors)
9896 goto exit;
9897 } else if (IS_SCHEMA(child, "redefine")) {
9898 tmpOldErrs = ctxt->nberrors;
9899 res = xmlSchemaParseRedefine(ctxt, schema, child);
9900 HFAILURE;
9901 HSTOP(ctxt);
9902 if (tmpOldErrs != ctxt->nberrors)
9903 goto exit;
9905 child = child->next;
9908 * URGENT TODO: Change the functions to return int results.
9909 * We need especially to catch internal errors.
9911 while (child != NULL) {
9912 if (IS_SCHEMA(child, "complexType")) {
9913 xmlSchemaParseComplexType(ctxt, schema, child, 1);
9914 child = child->next;
9915 } else if (IS_SCHEMA(child, "simpleType")) {
9916 xmlSchemaParseSimpleType(ctxt, schema, child, 1);
9917 child = child->next;
9918 } else if (IS_SCHEMA(child, "element")) {
9919 xmlSchemaParseElement(ctxt, schema, child, NULL, 1);
9920 child = child->next;
9921 } else if (IS_SCHEMA(child, "attribute")) {
9922 xmlSchemaParseGlobalAttribute(ctxt, schema, child);
9923 child = child->next;
9924 } else if (IS_SCHEMA(child, "attributeGroup")) {
9925 xmlSchemaParseAttributeGroupDefinition(ctxt, schema, child);
9926 child = child->next;
9927 } else if (IS_SCHEMA(child, "group")) {
9928 xmlSchemaParseModelGroupDefinition(ctxt, schema, child);
9929 child = child->next;
9930 } else if (IS_SCHEMA(child, "notation")) {
9931 xmlSchemaParseNotation(ctxt, schema, child);
9932 child = child->next;
9933 } else {
9934 xmlSchemaPContentErr(ctxt,
9935 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
9936 NULL, child->parent, child,
9937 NULL, "((include | import | redefine | annotation)*, "
9938 "(((simpleType | complexType | group | attributeGroup) "
9939 "| element | attribute | notation), annotation*)*)");
9940 child = child->next;
9942 while (IS_SCHEMA(child, "annotation")) {
9944 * TODO: We should add all annotations.
9946 annot = xmlSchemaParseAnnotation(ctxt, child, 1);
9947 if (schema->annot == NULL)
9948 schema->annot = annot;
9949 else
9950 xmlSchemaFreeAnnot(annot);
9951 child = child->next;
9954 exit:
9955 ctxt->ctxtType = NULL;
9956 if (oldErrs != ctxt->nberrors)
9957 res = ctxt->err;
9958 return(res);
9959 exit_failure:
9960 return(-1);
9963 static xmlSchemaSchemaRelationPtr
9964 xmlSchemaSchemaRelationCreate(void)
9966 xmlSchemaSchemaRelationPtr ret;
9968 ret = (xmlSchemaSchemaRelationPtr)
9969 xmlMalloc(sizeof(xmlSchemaSchemaRelation));
9970 if (ret == NULL) {
9971 xmlSchemaPErrMemory(NULL, "allocating schema relation", NULL);
9972 return(NULL);
9974 memset(ret, 0, sizeof(xmlSchemaSchemaRelation));
9975 return(ret);
9978 #if 0
9979 static void
9980 xmlSchemaSchemaRelationFree(xmlSchemaSchemaRelationPtr rel)
9982 xmlFree(rel);
9984 #endif
9986 static void
9987 xmlSchemaRedefListFree(xmlSchemaRedefPtr redef)
9989 xmlSchemaRedefPtr prev;
9991 while (redef != NULL) {
9992 prev = redef;
9993 redef = redef->next;
9994 xmlFree(prev);
9998 static void
9999 xmlSchemaConstructionCtxtFree(xmlSchemaConstructionCtxtPtr con)
10002 * After the construction context has been freed, there will be
10003 * no schema graph available any more. Only the schema buckets
10004 * will stay alive, which are put into the "schemasImports" and
10005 * "includes" slots of the xmlSchema.
10007 if (con->buckets != NULL)
10008 xmlSchemaItemListFree(con->buckets);
10009 if (con->pending != NULL)
10010 xmlSchemaItemListFree(con->pending);
10011 if (con->substGroups != NULL)
10012 xmlHashFree(con->substGroups, xmlSchemaSubstGroupFreeEntry);
10013 if (con->redefs != NULL)
10014 xmlSchemaRedefListFree(con->redefs);
10015 if (con->dict != NULL)
10016 xmlDictFree(con->dict);
10017 xmlFree(con);
10020 static xmlSchemaConstructionCtxtPtr
10021 xmlSchemaConstructionCtxtCreate(xmlDictPtr dict)
10023 xmlSchemaConstructionCtxtPtr ret;
10025 ret = (xmlSchemaConstructionCtxtPtr)
10026 xmlMalloc(sizeof(xmlSchemaConstructionCtxt));
10027 if (ret == NULL) {
10028 xmlSchemaPErrMemory(NULL,
10029 "allocating schema construction context", NULL);
10030 return (NULL);
10032 memset(ret, 0, sizeof(xmlSchemaConstructionCtxt));
10034 ret->buckets = xmlSchemaItemListCreate();
10035 if (ret->buckets == NULL) {
10036 xmlSchemaPErrMemory(NULL,
10037 "allocating list of schema buckets", NULL);
10038 xmlFree(ret);
10039 return (NULL);
10041 ret->pending = xmlSchemaItemListCreate();
10042 if (ret->pending == NULL) {
10043 xmlSchemaPErrMemory(NULL,
10044 "allocating list of pending global components", NULL);
10045 xmlSchemaConstructionCtxtFree(ret);
10046 return (NULL);
10048 ret->dict = dict;
10049 xmlDictReference(dict);
10050 return(ret);
10053 static xmlSchemaParserCtxtPtr
10054 xmlSchemaParserCtxtCreate(void)
10056 xmlSchemaParserCtxtPtr ret;
10058 ret = (xmlSchemaParserCtxtPtr) xmlMalloc(sizeof(xmlSchemaParserCtxt));
10059 if (ret == NULL) {
10060 xmlSchemaPErrMemory(NULL, "allocating schema parser context",
10061 NULL);
10062 return (NULL);
10064 memset(ret, 0, sizeof(xmlSchemaParserCtxt));
10065 ret->type = XML_SCHEMA_CTXT_PARSER;
10066 ret->attrProhibs = xmlSchemaItemListCreate();
10067 if (ret->attrProhibs == NULL) {
10068 xmlFree(ret);
10069 return(NULL);
10071 return(ret);
10075 * xmlSchemaNewParserCtxtUseDict:
10076 * @URL: the location of the schema
10077 * @dict: the dictionary to be used
10079 * Create an XML Schemas parse context for that file/resource expected
10080 * to contain an XML Schemas file.
10082 * Returns the parser context or NULL in case of error
10084 static xmlSchemaParserCtxtPtr
10085 xmlSchemaNewParserCtxtUseDict(const char *URL, xmlDictPtr dict)
10087 xmlSchemaParserCtxtPtr ret;
10089 ret = xmlSchemaParserCtxtCreate();
10090 if (ret == NULL)
10091 return (NULL);
10092 ret->dict = dict;
10093 xmlDictReference(dict);
10094 if (URL != NULL)
10095 ret->URL = xmlDictLookup(dict, (const xmlChar *) URL, -1);
10096 return (ret);
10099 static int
10100 xmlSchemaCreatePCtxtOnVCtxt(xmlSchemaValidCtxtPtr vctxt)
10102 if (vctxt->pctxt == NULL) {
10103 if (vctxt->schema != NULL)
10104 vctxt->pctxt =
10105 xmlSchemaNewParserCtxtUseDict("*", vctxt->schema->dict);
10106 else
10107 vctxt->pctxt = xmlSchemaNewParserCtxt("*");
10108 if (vctxt->pctxt == NULL) {
10109 VERROR_INT("xmlSchemaCreatePCtxtOnVCtxt",
10110 "failed to create a temp. parser context");
10111 return (-1);
10113 /* TODO: Pass user data. */
10114 xmlSchemaSetParserErrors(vctxt->pctxt, vctxt->error,
10115 vctxt->warning, vctxt->errCtxt);
10116 xmlSchemaSetParserStructuredErrors(vctxt->pctxt, vctxt->serror,
10117 vctxt->errCtxt);
10119 return (0);
10123 * xmlSchemaGetSchemaBucket:
10124 * @pctxt: the schema parser context
10125 * @schemaLocation: the URI of the schema document
10127 * Returns a schema bucket if it was already parsed.
10129 * Returns a schema bucket if it was already parsed from
10130 * @schemaLocation, NULL otherwise.
10132 static xmlSchemaBucketPtr
10133 xmlSchemaGetSchemaBucket(xmlSchemaParserCtxtPtr pctxt,
10134 const xmlChar *schemaLocation)
10136 xmlSchemaBucketPtr cur;
10137 xmlSchemaItemListPtr list;
10139 list = pctxt->constructor->buckets;
10140 if (list->nbItems == 0)
10141 return(NULL);
10142 else {
10143 int i;
10144 for (i = 0; i < list->nbItems; i++) {
10145 cur = (xmlSchemaBucketPtr) list->items[i];
10146 /* Pointer comparison! */
10147 if (cur->schemaLocation == schemaLocation)
10148 return(cur);
10151 return(NULL);
10154 static xmlSchemaBucketPtr
10155 xmlSchemaGetChameleonSchemaBucket(xmlSchemaParserCtxtPtr pctxt,
10156 const xmlChar *schemaLocation,
10157 const xmlChar *targetNamespace)
10159 xmlSchemaBucketPtr cur;
10160 xmlSchemaItemListPtr list;
10162 list = pctxt->constructor->buckets;
10163 if (list->nbItems == 0)
10164 return(NULL);
10165 else {
10166 int i;
10167 for (i = 0; i < list->nbItems; i++) {
10168 cur = (xmlSchemaBucketPtr) list->items[i];
10169 /* Pointer comparison! */
10170 if ((cur->origTargetNamespace == NULL) &&
10171 (cur->schemaLocation == schemaLocation) &&
10172 (cur->targetNamespace == targetNamespace))
10173 return(cur);
10176 return(NULL);
10180 #define IS_BAD_SCHEMA_DOC(b) \
10181 (((b)->doc == NULL) && ((b)->schemaLocation != NULL))
10183 static xmlSchemaBucketPtr
10184 xmlSchemaGetSchemaBucketByTNS(xmlSchemaParserCtxtPtr pctxt,
10185 const xmlChar *targetNamespace,
10186 int imported)
10188 xmlSchemaBucketPtr cur;
10189 xmlSchemaItemListPtr list;
10191 list = pctxt->constructor->buckets;
10192 if (list->nbItems == 0)
10193 return(NULL);
10194 else {
10195 int i;
10196 for (i = 0; i < list->nbItems; i++) {
10197 cur = (xmlSchemaBucketPtr) list->items[i];
10198 if ((! IS_BAD_SCHEMA_DOC(cur)) &&
10199 (cur->origTargetNamespace == targetNamespace) &&
10200 ((imported && cur->imported) ||
10201 ((!imported) && (!cur->imported))))
10202 return(cur);
10205 return(NULL);
10208 static int
10209 xmlSchemaParseNewDocWithContext(xmlSchemaParserCtxtPtr pctxt,
10210 xmlSchemaPtr schema,
10211 xmlSchemaBucketPtr bucket)
10213 int oldFlags;
10214 xmlDocPtr oldDoc;
10215 xmlNodePtr node;
10216 int ret, oldErrs;
10217 xmlSchemaBucketPtr oldbucket = pctxt->constructor->bucket;
10220 * Save old values; reset the *main* schema.
10221 * URGENT TODO: This is not good; move the per-document information
10222 * to the parser. Get rid of passing the main schema to the
10223 * parsing functions.
10225 oldFlags = schema->flags;
10226 oldDoc = schema->doc;
10227 if (schema->flags != 0)
10228 xmlSchemaClearSchemaDefaults(schema);
10229 schema->doc = bucket->doc;
10230 pctxt->schema = schema;
10232 * Keep the current target namespace on the parser *not* on the
10233 * main schema.
10235 pctxt->targetNamespace = bucket->targetNamespace;
10236 WXS_CONSTRUCTOR(pctxt)->bucket = bucket;
10238 if ((bucket->targetNamespace != NULL) &&
10239 xmlStrEqual(bucket->targetNamespace, xmlSchemaNs)) {
10241 * We are parsing the schema for schemas!
10243 pctxt->isS4S = 1;
10245 /* Mark it as parsed, even if parsing fails. */
10246 bucket->parsed++;
10247 /* Compile the schema doc. */
10248 node = xmlDocGetRootElement(bucket->doc);
10249 ret = xmlSchemaParseSchemaElement(pctxt, schema, node);
10250 if (ret != 0)
10251 goto exit;
10252 /* An empty schema; just get out. */
10253 if (node->children == NULL)
10254 goto exit;
10255 oldErrs = pctxt->nberrors;
10256 ret = xmlSchemaParseSchemaTopLevel(pctxt, schema, node->children);
10257 if (ret != 0)
10258 goto exit;
10260 * TODO: Not nice, but I'm not 100% sure we will get always an error
10261 * as a result of the above functions; so better rely on pctxt->err
10262 * as well.
10264 if ((ret == 0) && (oldErrs != pctxt->nberrors)) {
10265 ret = pctxt->err;
10266 goto exit;
10269 exit:
10270 WXS_CONSTRUCTOR(pctxt)->bucket = oldbucket;
10271 /* Restore schema values. */
10272 schema->doc = oldDoc;
10273 schema->flags = oldFlags;
10274 return(ret);
10277 static int
10278 xmlSchemaParseNewDoc(xmlSchemaParserCtxtPtr pctxt,
10279 xmlSchemaPtr schema,
10280 xmlSchemaBucketPtr bucket)
10282 xmlSchemaParserCtxtPtr newpctxt;
10283 int res = 0;
10285 if (bucket == NULL)
10286 return(0);
10287 if (bucket->parsed) {
10288 PERROR_INT("xmlSchemaParseNewDoc",
10289 "reparsing a schema doc");
10290 return(-1);
10292 if (bucket->doc == NULL) {
10293 PERROR_INT("xmlSchemaParseNewDoc",
10294 "parsing a schema doc, but there's no doc");
10295 return(-1);
10297 if (pctxt->constructor == NULL) {
10298 PERROR_INT("xmlSchemaParseNewDoc",
10299 "no constructor");
10300 return(-1);
10302 /* Create and init the temporary parser context. */
10303 newpctxt = xmlSchemaNewParserCtxtUseDict(
10304 (const char *) bucket->schemaLocation, pctxt->dict);
10305 if (newpctxt == NULL)
10306 return(-1);
10307 newpctxt->constructor = pctxt->constructor;
10309 * TODO: Can we avoid that the parser knows about the main schema?
10310 * It would be better if he knows about the current schema bucket
10311 * only.
10313 newpctxt->schema = schema;
10314 xmlSchemaSetParserErrors(newpctxt, pctxt->error, pctxt->warning,
10315 pctxt->errCtxt);
10316 xmlSchemaSetParserStructuredErrors(newpctxt, pctxt->serror,
10317 pctxt->errCtxt);
10318 newpctxt->counter = pctxt->counter;
10321 res = xmlSchemaParseNewDocWithContext(newpctxt, schema, bucket);
10323 /* Channel back errors and cleanup the temporary parser context. */
10324 if (res != 0)
10325 pctxt->err = res;
10326 pctxt->nberrors += newpctxt->nberrors;
10327 pctxt->counter = newpctxt->counter;
10328 newpctxt->constructor = NULL;
10329 /* Free the parser context. */
10330 xmlSchemaFreeParserCtxt(newpctxt);
10331 return(res);
10334 static void
10335 xmlSchemaSchemaRelationAddChild(xmlSchemaBucketPtr bucket,
10336 xmlSchemaSchemaRelationPtr rel)
10338 xmlSchemaSchemaRelationPtr cur = bucket->relations;
10340 if (cur == NULL) {
10341 bucket->relations = rel;
10342 return;
10344 while (cur->next != NULL)
10345 cur = cur->next;
10346 cur->next = rel;
10350 static const xmlChar *
10351 xmlSchemaBuildAbsoluteURI(xmlDictPtr dict, const xmlChar* location,
10352 xmlNodePtr ctxtNode)
10355 * Build an absolute location URI.
10357 if (location != NULL) {
10358 if (ctxtNode == NULL)
10359 return(location);
10360 else {
10361 xmlChar *base, *URI;
10362 const xmlChar *ret = NULL;
10364 base = xmlNodeGetBase(ctxtNode->doc, ctxtNode);
10365 if (base == NULL) {
10366 URI = xmlBuildURI(location, ctxtNode->doc->URL);
10367 } else {
10368 URI = xmlBuildURI(location, base);
10369 xmlFree(base);
10371 if (URI != NULL) {
10372 ret = xmlDictLookup(dict, URI, -1);
10373 xmlFree(URI);
10374 return(ret);
10378 return(NULL);
10384 * xmlSchemaAddSchemaDoc:
10385 * @pctxt: a schema validation context
10386 * @schema: the schema being built
10387 * @node: a subtree containing XML Schema information
10389 * Parse an included (and to-be-redefined) XML schema document.
10391 * Returns 0 on success, a positive error code on errors and
10392 * -1 in case of an internal or API error.
10395 static int
10396 xmlSchemaAddSchemaDoc(xmlSchemaParserCtxtPtr pctxt,
10397 int type, /* import or include or redefine */
10398 const xmlChar *schemaLocation,
10399 xmlDocPtr schemaDoc,
10400 const char *schemaBuffer,
10401 int schemaBufferLen,
10402 xmlNodePtr invokingNode,
10403 const xmlChar *sourceTargetNamespace,
10404 const xmlChar *importNamespace,
10405 xmlSchemaBucketPtr *bucket)
10407 const xmlChar *targetNamespace = NULL;
10408 xmlSchemaSchemaRelationPtr relation = NULL;
10409 xmlDocPtr doc = NULL;
10410 int res = 0, err = 0, located = 0, preserveDoc = 0;
10411 xmlSchemaBucketPtr bkt = NULL;
10413 if (bucket != NULL)
10414 *bucket = NULL;
10416 switch (type) {
10417 case XML_SCHEMA_SCHEMA_IMPORT:
10418 case XML_SCHEMA_SCHEMA_MAIN:
10419 err = XML_SCHEMAP_SRC_IMPORT;
10420 break;
10421 case XML_SCHEMA_SCHEMA_INCLUDE:
10422 err = XML_SCHEMAP_SRC_INCLUDE;
10423 break;
10424 case XML_SCHEMA_SCHEMA_REDEFINE:
10425 err = XML_SCHEMAP_SRC_REDEFINE;
10426 break;
10430 /* Special handling for the main schema:
10431 * skip the location and relation logic and just parse the doc.
10432 * We need just a bucket to be returned in this case.
10434 if ((type == XML_SCHEMA_SCHEMA_MAIN) || (! WXS_HAS_BUCKETS(pctxt)))
10435 goto doc_load;
10437 /* Note that we expect the location to be an absolute URI. */
10438 if (schemaLocation != NULL) {
10439 bkt = xmlSchemaGetSchemaBucket(pctxt, schemaLocation);
10440 if ((bkt != NULL) &&
10441 (pctxt->constructor->bucket == bkt)) {
10442 /* Report self-imports/inclusions/redefinitions. */
10444 xmlSchemaCustomErr(ACTXT_CAST pctxt, err,
10445 invokingNode, NULL,
10446 "The schema must not import/include/redefine itself",
10447 NULL, NULL);
10448 goto exit;
10452 * Create a relation for the graph of schemas.
10454 relation = xmlSchemaSchemaRelationCreate();
10455 if (relation == NULL)
10456 return(-1);
10457 xmlSchemaSchemaRelationAddChild(pctxt->constructor->bucket,
10458 relation);
10459 relation->type = type;
10462 * Save the namespace import information.
10464 if (WXS_IS_BUCKET_IMPMAIN(type)) {
10465 relation->importNamespace = importNamespace;
10466 if (schemaLocation == NULL) {
10468 * No location; this is just an import of the namespace.
10469 * Note that we don't assign a bucket to the relation
10470 * in this case.
10472 goto exit;
10474 targetNamespace = importNamespace;
10477 /* Did we already fetch the doc? */
10478 if (bkt != NULL) {
10479 if ((WXS_IS_BUCKET_IMPMAIN(type)) && (! bkt->imported)) {
10481 * We included/redefined and then try to import a schema,
10482 * but the new location provided for import was different.
10484 if (schemaLocation == NULL)
10485 schemaLocation = BAD_CAST "in_memory_buffer";
10486 if (!xmlStrEqual(schemaLocation,
10487 bkt->schemaLocation)) {
10488 xmlSchemaCustomErr(ACTXT_CAST pctxt, err,
10489 invokingNode, NULL,
10490 "The schema document '%s' cannot be imported, since "
10491 "it was already included or redefined",
10492 schemaLocation, NULL);
10493 goto exit;
10495 } else if ((! WXS_IS_BUCKET_IMPMAIN(type)) && (bkt->imported)) {
10497 * We imported and then try to include/redefine a schema,
10498 * but the new location provided for the include/redefine
10499 * was different.
10501 if (schemaLocation == NULL)
10502 schemaLocation = BAD_CAST "in_memory_buffer";
10503 if (!xmlStrEqual(schemaLocation,
10504 bkt->schemaLocation)) {
10505 xmlSchemaCustomErr(ACTXT_CAST pctxt, err,
10506 invokingNode, NULL,
10507 "The schema document '%s' cannot be included or "
10508 "redefined, since it was already imported",
10509 schemaLocation, NULL);
10510 goto exit;
10515 if (WXS_IS_BUCKET_IMPMAIN(type)) {
10517 * Given that the schemaLocation [attribute] is only a hint, it is open
10518 * to applications to ignore all but the first <import> for a given
10519 * namespace, regardless of the `actual value` of schemaLocation, but
10520 * such a strategy risks missing useful information when new
10521 * schemaLocations are offered.
10523 * We will use the first <import> that comes with a location.
10524 * Further <import>s *with* a location, will result in an error.
10525 * TODO: Better would be to just report a warning here, but
10526 * we'll try it this way until someone complains.
10528 * Schema Document Location Strategy:
10529 * 3 Based on the namespace name, identify an existing schema document,
10530 * either as a resource which is an XML document or a <schema> element
10531 * information item, in some local schema repository;
10532 * 5 Attempt to resolve the namespace name to locate such a resource.
10534 * NOTE: (3) and (5) are not supported.
10536 if (bkt != NULL) {
10537 relation->bucket = bkt;
10538 goto exit;
10540 bkt = xmlSchemaGetSchemaBucketByTNS(pctxt,
10541 importNamespace, 1);
10543 if (bkt != NULL) {
10544 relation->bucket = bkt;
10545 if (bkt->schemaLocation == NULL) {
10546 /* First given location of the schema; load the doc. */
10547 bkt->schemaLocation = schemaLocation;
10548 } else {
10549 if (!xmlStrEqual(schemaLocation,
10550 bkt->schemaLocation)) {
10552 * Additional location given; just skip it.
10553 * URGENT TODO: We should report a warning here.
10554 * res = XML_SCHEMAP_SRC_IMPORT;
10556 if (schemaLocation == NULL)
10557 schemaLocation = BAD_CAST "in_memory_buffer";
10559 xmlSchemaCustomWarning(ACTXT_CAST pctxt,
10560 XML_SCHEMAP_WARN_SKIP_SCHEMA,
10561 invokingNode, NULL,
10562 "Skipping import of schema located at '%s' for the "
10563 "namespace '%s', since this namespace was already "
10564 "imported with the schema located at '%s'",
10565 schemaLocation, importNamespace, bkt->schemaLocation);
10567 goto exit;
10571 * No bucket + first location: load the doc and create a
10572 * bucket.
10574 } else {
10575 /* <include> and <redefine> */
10576 if (bkt != NULL) {
10578 if ((bkt->origTargetNamespace == NULL) &&
10579 (bkt->targetNamespace != sourceTargetNamespace)) {
10580 xmlSchemaBucketPtr chamel;
10583 * Chameleon include/redefine: skip loading only if it was
10584 * already build for the targetNamespace of the including
10585 * schema.
10588 * URGENT TODO: If the schema is a chameleon-include then copy
10589 * the components into the including schema and modify the
10590 * targetNamespace of those components, do nothing otherwise.
10591 * NOTE: This is currently worked-around by compiling the
10592 * chameleon for every distinct including targetNamespace; thus
10593 * not performant at the moment.
10594 * TODO: Check when the namespace in wildcards for chameleons
10595 * needs to be converted: before we built wildcard intersections
10596 * or after.
10597 * Answer: after!
10599 chamel = xmlSchemaGetChameleonSchemaBucket(pctxt,
10600 schemaLocation, sourceTargetNamespace);
10601 if (chamel != NULL) {
10602 /* A fitting chameleon was already parsed; NOP. */
10603 relation->bucket = chamel;
10604 goto exit;
10607 * We need to parse the chameleon again for a different
10608 * targetNamespace.
10609 * CHAMELEON TODO: Optimize this by only parsing the
10610 * chameleon once, and then copying the components to
10611 * the new targetNamespace.
10613 bkt = NULL;
10614 } else {
10615 relation->bucket = bkt;
10616 goto exit;
10620 if ((bkt != NULL) && (bkt->doc != NULL)) {
10621 PERROR_INT("xmlSchemaAddSchemaDoc",
10622 "trying to load a schema doc, but a doc is already "
10623 "assigned to the schema bucket");
10624 goto exit_failure;
10627 doc_load:
10629 * Load the document.
10631 if (schemaDoc != NULL) {
10632 doc = schemaDoc;
10633 /* Don' free this one, since it was provided by the caller. */
10634 preserveDoc = 1;
10635 /* TODO: Does the context or the doc hold the location? */
10636 if (schemaDoc->URL != NULL)
10637 schemaLocation = xmlDictLookup(pctxt->dict,
10638 schemaDoc->URL, -1);
10639 else
10640 schemaLocation = BAD_CAST "in_memory_buffer";
10641 } else if ((schemaLocation != NULL) || (schemaBuffer != NULL)) {
10642 xmlParserCtxtPtr parserCtxt;
10644 parserCtxt = xmlNewParserCtxt();
10645 if (parserCtxt == NULL) {
10646 xmlSchemaPErrMemory(NULL, "xmlSchemaGetDoc, "
10647 "allocating a parser context", NULL);
10648 goto exit_failure;
10650 if ((pctxt->dict != NULL) && (parserCtxt->dict != NULL)) {
10652 * TODO: Do we have to burden the schema parser dict with all
10653 * the content of the schema doc?
10655 xmlDictFree(parserCtxt->dict);
10656 parserCtxt->dict = pctxt->dict;
10657 xmlDictReference(parserCtxt->dict);
10659 if (schemaLocation != NULL) {
10660 /* Parse from file. */
10661 doc = xmlCtxtReadFile(parserCtxt, (const char *) schemaLocation,
10662 NULL, SCHEMAS_PARSE_OPTIONS);
10663 } else if (schemaBuffer != NULL) {
10664 /* Parse from memory buffer. */
10665 doc = xmlCtxtReadMemory(parserCtxt, schemaBuffer, schemaBufferLen,
10666 NULL, NULL, SCHEMAS_PARSE_OPTIONS);
10667 schemaLocation = BAD_CAST "in_memory_buffer";
10668 if (doc != NULL)
10669 doc->URL = xmlStrdup(schemaLocation);
10672 * For <import>:
10673 * 2.1 The referent is (a fragment of) a resource which is an
10674 * XML document (see clause 1.1), which in turn corresponds to
10675 * a <schema> element information item in a well-formed information
10676 * set, which in turn corresponds to a valid schema.
10677 * TODO: (2.1) fragments of XML documents are not supported.
10679 * 2.2 The referent is a <schema> element information item in
10680 * a well-formed information set, which in turn corresponds
10681 * to a valid schema.
10682 * TODO: (2.2) is not supported.
10684 if (doc == NULL) {
10685 xmlErrorPtr lerr;
10686 lerr = xmlGetLastError();
10688 * Check if this a parser error, or if the document could
10689 * just not be located.
10690 * TODO: Try to find specific error codes to react only on
10691 * localisation failures.
10693 if ((lerr == NULL) || (lerr->domain != XML_FROM_IO)) {
10695 * We assume a parser error here.
10697 located = 1;
10698 /* TODO: Error code ?? */
10699 res = XML_SCHEMAP_SRC_IMPORT_2_1;
10700 xmlSchemaCustomErr(ACTXT_CAST pctxt, res,
10701 invokingNode, NULL,
10702 "Failed to parse the XML resource '%s'",
10703 schemaLocation, NULL);
10706 xmlFreeParserCtxt(parserCtxt);
10707 if ((doc == NULL) && located)
10708 goto exit_error;
10709 } else {
10710 xmlSchemaPErr(pctxt, NULL,
10711 XML_SCHEMAP_NOTHING_TO_PARSE,
10712 "No information for parsing was provided with the "
10713 "given schema parser context.\n",
10714 NULL, NULL);
10715 goto exit_failure;
10718 * Preprocess the document.
10720 if (doc != NULL) {
10721 xmlNodePtr docElem = NULL;
10723 located = 1;
10724 docElem = xmlDocGetRootElement(doc);
10725 if (docElem == NULL) {
10726 xmlSchemaCustomErr(ACTXT_CAST pctxt, XML_SCHEMAP_NOROOT,
10727 invokingNode, NULL,
10728 "The document '%s' has no document element",
10729 schemaLocation, NULL);
10730 goto exit_error;
10733 * Remove all the blank text nodes.
10735 xmlSchemaCleanupDoc(pctxt, docElem);
10737 * Check the schema's top level element.
10739 if (!IS_SCHEMA(docElem, "schema")) {
10740 xmlSchemaCustomErr(ACTXT_CAST pctxt, XML_SCHEMAP_NOT_SCHEMA,
10741 invokingNode, NULL,
10742 "The XML document '%s' is not a schema document",
10743 schemaLocation, NULL);
10744 goto exit_error;
10747 * Note that we don't apply a type check for the
10748 * targetNamespace value here.
10750 targetNamespace = xmlSchemaGetProp(pctxt, docElem,
10751 "targetNamespace");
10754 /* after_doc_loading: */
10755 if ((bkt == NULL) && located) {
10756 /* Only create a bucket if the schema was located. */
10757 bkt = xmlSchemaBucketCreate(pctxt, type,
10758 targetNamespace);
10759 if (bkt == NULL)
10760 goto exit_failure;
10762 if (bkt != NULL) {
10763 bkt->schemaLocation = schemaLocation;
10764 bkt->located = located;
10765 if (doc != NULL) {
10766 bkt->doc = doc;
10767 bkt->targetNamespace = targetNamespace;
10768 bkt->origTargetNamespace = targetNamespace;
10769 if (preserveDoc)
10770 bkt->preserveDoc = 1;
10772 if (WXS_IS_BUCKET_IMPMAIN(type))
10773 bkt->imported++;
10775 * Add it to the graph of schemas.
10777 if (relation != NULL)
10778 relation->bucket = bkt;
10781 exit:
10783 * Return the bucket explicitly; this is needed for the
10784 * main schema.
10786 if (bucket != NULL)
10787 *bucket = bkt;
10788 return (0);
10790 exit_error:
10791 if ((doc != NULL) && (! preserveDoc)) {
10792 xmlFreeDoc(doc);
10793 if (bkt != NULL)
10794 bkt->doc = NULL;
10796 return(pctxt->err);
10798 exit_failure:
10799 if ((doc != NULL) && (! preserveDoc)) {
10800 xmlFreeDoc(doc);
10801 if (bkt != NULL)
10802 bkt->doc = NULL;
10804 return (-1);
10808 * xmlSchemaParseImport:
10809 * @ctxt: a schema validation context
10810 * @schema: the schema being built
10811 * @node: a subtree containing XML Schema information
10813 * parse a XML schema Import definition
10814 * *WARNING* this interface is highly subject to change
10816 * Returns 0 in case of success, a positive error code if
10817 * not valid and -1 in case of an internal error.
10819 static int
10820 xmlSchemaParseImport(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema,
10821 xmlNodePtr node)
10823 xmlNodePtr child;
10824 const xmlChar *namespaceName = NULL, *schemaLocation = NULL;
10825 const xmlChar *thisTargetNamespace;
10826 xmlAttrPtr attr;
10827 int ret = 0;
10828 xmlSchemaBucketPtr bucket = NULL;
10830 if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
10831 return (-1);
10834 * Check for illegal attributes.
10836 attr = node->properties;
10837 while (attr != NULL) {
10838 if (attr->ns == NULL) {
10839 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
10840 (!xmlStrEqual(attr->name, BAD_CAST "namespace")) &&
10841 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
10842 xmlSchemaPIllegalAttrErr(pctxt,
10843 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
10845 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
10846 xmlSchemaPIllegalAttrErr(pctxt,
10847 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
10849 attr = attr->next;
10852 * Extract and validate attributes.
10854 if (xmlSchemaPValAttr(pctxt, NULL, node,
10855 "namespace", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
10856 &namespaceName) != 0) {
10857 xmlSchemaPSimpleTypeErr(pctxt,
10858 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
10859 NULL, node,
10860 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
10861 NULL, namespaceName, NULL, NULL, NULL);
10862 return (pctxt->err);
10865 if (xmlSchemaPValAttr(pctxt, NULL, node,
10866 "schemaLocation", xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
10867 &schemaLocation) != 0) {
10868 xmlSchemaPSimpleTypeErr(pctxt,
10869 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
10870 NULL, node,
10871 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
10872 NULL, schemaLocation, NULL, NULL, NULL);
10873 return (pctxt->err);
10876 * And now for the children...
10878 child = node->children;
10879 if (IS_SCHEMA(child, "annotation")) {
10881 * the annotation here is simply discarded ...
10882 * TODO: really?
10884 child = child->next;
10886 if (child != NULL) {
10887 xmlSchemaPContentErr(pctxt,
10888 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
10889 NULL, node, child, NULL,
10890 "(annotation?)");
10893 * Apply additional constraints.
10895 * Note that it is important to use the original @targetNamespace
10896 * (or none at all), to rule out imports of schemas _with_ a
10897 * @targetNamespace if the importing schema is a chameleon schema
10898 * (with no @targetNamespace).
10900 thisTargetNamespace = WXS_BUCKET(pctxt)->origTargetNamespace;
10901 if (namespaceName != NULL) {
10903 * 1.1 If the namespace [attribute] is present, then its `actual value`
10904 * must not match the `actual value` of the enclosing <schema>'s
10905 * targetNamespace [attribute].
10907 if (xmlStrEqual(thisTargetNamespace, namespaceName)) {
10908 xmlSchemaPCustomErr(pctxt,
10909 XML_SCHEMAP_SRC_IMPORT_1_1,
10910 NULL, node,
10911 "The value of the attribute 'namespace' must not match "
10912 "the target namespace '%s' of the importing schema",
10913 thisTargetNamespace);
10914 return (pctxt->err);
10916 } else {
10918 * 1.2 If the namespace [attribute] is not present, then the enclosing
10919 * <schema> must have a targetNamespace [attribute].
10921 if (thisTargetNamespace == NULL) {
10922 xmlSchemaPCustomErr(pctxt,
10923 XML_SCHEMAP_SRC_IMPORT_1_2,
10924 NULL, node,
10925 "The attribute 'namespace' must be existent if "
10926 "the importing schema has no target namespace",
10927 NULL);
10928 return (pctxt->err);
10932 * Locate and acquire the schema document.
10934 if (schemaLocation != NULL)
10935 schemaLocation = xmlSchemaBuildAbsoluteURI(pctxt->dict,
10936 schemaLocation, node);
10937 ret = xmlSchemaAddSchemaDoc(pctxt, XML_SCHEMA_SCHEMA_IMPORT,
10938 schemaLocation, NULL, NULL, 0, node, thisTargetNamespace,
10939 namespaceName, &bucket);
10941 if (ret != 0)
10942 return(ret);
10945 * For <import>: "It is *not* an error for the application
10946 * schema reference strategy to fail."
10947 * So just don't parse if no schema document was found.
10948 * Note that we will get no bucket if the schema could not be
10949 * located or if there was no schemaLocation.
10951 if ((bucket == NULL) && (schemaLocation != NULL)) {
10952 xmlSchemaCustomWarning(ACTXT_CAST pctxt,
10953 XML_SCHEMAP_WARN_UNLOCATED_SCHEMA,
10954 node, NULL,
10955 "Failed to locate a schema at location '%s'. "
10956 "Skipping the import", schemaLocation, NULL, NULL);
10959 if ((bucket != NULL) && CAN_PARSE_SCHEMA(bucket)) {
10960 ret = xmlSchemaParseNewDoc(pctxt, schema, bucket);
10963 return (ret);
10966 static int
10967 xmlSchemaParseIncludeOrRedefineAttrs(xmlSchemaParserCtxtPtr pctxt,
10968 xmlSchemaPtr schema,
10969 xmlNodePtr node,
10970 xmlChar **schemaLocation,
10971 int type)
10973 xmlAttrPtr attr;
10975 if ((pctxt == NULL) || (schema == NULL) || (node == NULL) ||
10976 (schemaLocation == NULL))
10977 return (-1);
10979 *schemaLocation = NULL;
10981 * Check for illegal attributes.
10982 * Applies for both <include> and <redefine>.
10984 attr = node->properties;
10985 while (attr != NULL) {
10986 if (attr->ns == NULL) {
10987 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
10988 (!xmlStrEqual(attr->name, BAD_CAST "schemaLocation"))) {
10989 xmlSchemaPIllegalAttrErr(pctxt,
10990 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
10992 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
10993 xmlSchemaPIllegalAttrErr(pctxt,
10994 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
10996 attr = attr->next;
10998 xmlSchemaPValAttrID(pctxt, node, BAD_CAST "id");
11000 * Preliminary step, extract the URI-Reference and make an URI
11001 * from the base.
11004 * Attribute "schemaLocation" is mandatory.
11006 attr = xmlSchemaGetPropNode(node, "schemaLocation");
11007 if (attr != NULL) {
11008 xmlChar *base = NULL;
11009 xmlChar *uri = NULL;
11011 if (xmlSchemaPValAttrNode(pctxt, NULL, attr,
11012 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYURI),
11013 (const xmlChar **) schemaLocation) != 0)
11014 goto exit_error;
11015 base = xmlNodeGetBase(node->doc, node);
11016 if (base == NULL) {
11017 uri = xmlBuildURI(*schemaLocation, node->doc->URL);
11018 } else {
11019 uri = xmlBuildURI(*schemaLocation, base);
11020 xmlFree(base);
11022 if (uri == NULL) {
11023 PERROR_INT("xmlSchemaParseIncludeOrRedefine",
11024 "could not build an URI from the schemaLocation")
11025 goto exit_failure;
11027 (*schemaLocation) = (xmlChar *) xmlDictLookup(pctxt->dict, uri, -1);
11028 xmlFree(uri);
11029 } else {
11030 xmlSchemaPMissingAttrErr(pctxt,
11031 XML_SCHEMAP_S4S_ATTR_MISSING,
11032 NULL, node, "schemaLocation", NULL);
11033 goto exit_error;
11036 * Report self-inclusion and self-redefinition.
11038 if (xmlStrEqual(*schemaLocation, pctxt->URL)) {
11039 if (type == XML_SCHEMA_SCHEMA_REDEFINE) {
11040 xmlSchemaPCustomErr(pctxt,
11041 XML_SCHEMAP_SRC_REDEFINE,
11042 NULL, node,
11043 "The schema document '%s' cannot redefine itself.",
11044 *schemaLocation);
11045 } else {
11046 xmlSchemaPCustomErr(pctxt,
11047 XML_SCHEMAP_SRC_INCLUDE,
11048 NULL, node,
11049 "The schema document '%s' cannot include itself.",
11050 *schemaLocation);
11052 goto exit_error;
11055 return(0);
11056 exit_error:
11057 return(pctxt->err);
11058 exit_failure:
11059 return(-1);
11062 static int
11063 xmlSchemaParseIncludeOrRedefine(xmlSchemaParserCtxtPtr pctxt,
11064 xmlSchemaPtr schema,
11065 xmlNodePtr node,
11066 int type)
11068 xmlNodePtr child = NULL;
11069 const xmlChar *schemaLocation = NULL;
11070 int res = 0; /* hasRedefinitions = 0 */
11071 int isChameleon = 0, wasChameleon = 0;
11072 xmlSchemaBucketPtr bucket = NULL;
11074 if ((pctxt == NULL) || (schema == NULL) || (node == NULL))
11075 return (-1);
11078 * Parse attributes. Note that the returned schemaLocation will
11079 * be already converted to an absolute URI.
11081 res = xmlSchemaParseIncludeOrRedefineAttrs(pctxt, schema,
11082 node, (xmlChar **) (&schemaLocation), type);
11083 if (res != 0)
11084 return(res);
11086 * Load and add the schema document.
11088 res = xmlSchemaAddSchemaDoc(pctxt, type, schemaLocation, NULL,
11089 NULL, 0, node, pctxt->targetNamespace, NULL, &bucket);
11090 if (res != 0)
11091 return(res);
11093 * If we get no schema bucket back, then this means that the schema
11094 * document could not be located or was broken XML or was not
11095 * a schema document.
11097 if ((bucket == NULL) || (bucket->doc == NULL)) {
11098 if (type == XML_SCHEMA_SCHEMA_INCLUDE) {
11100 * WARNING for <include>:
11101 * We will raise an error if the schema cannot be located
11102 * for inclusions, since the that was the feedback from the
11103 * schema people. I.e. the following spec piece will *not* be
11104 * satisfied:
11105 * SPEC src-include: "It is not an error for the `actual value` of the
11106 * schemaLocation [attribute] to fail to resolve it all, in which
11107 * case no corresponding inclusion is performed.
11108 * So do we need a warning report here?"
11110 res = XML_SCHEMAP_SRC_INCLUDE;
11111 xmlSchemaCustomErr(ACTXT_CAST pctxt, res,
11112 node, NULL,
11113 "Failed to load the document '%s' for inclusion",
11114 schemaLocation, NULL);
11115 } else {
11117 * NOTE: This was changed to raise an error even if no redefinitions
11118 * are specified.
11120 * SPEC src-redefine (1)
11121 * "If there are any element information items among the [children]
11122 * other than <annotation> then the `actual value` of the
11123 * schemaLocation [attribute] must successfully resolve."
11124 * TODO: Ask the WG if a the location has always to resolve
11125 * here as well!
11127 res = XML_SCHEMAP_SRC_REDEFINE;
11128 xmlSchemaCustomErr(ACTXT_CAST pctxt, res,
11129 node, NULL,
11130 "Failed to load the document '%s' for redefinition",
11131 schemaLocation, NULL);
11133 } else {
11135 * Check targetNamespace sanity before parsing the new schema.
11136 * TODO: Note that we won't check further content if the
11137 * targetNamespace was bad.
11139 if (bucket->origTargetNamespace != NULL) {
11141 * SPEC src-include (2.1)
11142 * "SII has a targetNamespace [attribute], and its `actual
11143 * value` is identical to the `actual value` of the targetNamespace
11144 * [attribute] of SII' (which must have such an [attribute])."
11146 if (pctxt->targetNamespace == NULL) {
11147 xmlSchemaCustomErr(ACTXT_CAST pctxt,
11148 XML_SCHEMAP_SRC_INCLUDE,
11149 node, NULL,
11150 "The target namespace of the included/redefined schema "
11151 "'%s' has to be absent, since the including/redefining "
11152 "schema has no target namespace",
11153 schemaLocation, NULL);
11154 goto exit_error;
11155 } else if (!xmlStrEqual(bucket->origTargetNamespace,
11156 pctxt->targetNamespace)) {
11157 /* TODO: Change error function. */
11158 xmlSchemaPCustomErrExt(pctxt,
11159 XML_SCHEMAP_SRC_INCLUDE,
11160 NULL, node,
11161 "The target namespace '%s' of the included/redefined "
11162 "schema '%s' differs from '%s' of the "
11163 "including/redefining schema",
11164 bucket->origTargetNamespace, schemaLocation,
11165 pctxt->targetNamespace);
11166 goto exit_error;
11168 } else if (pctxt->targetNamespace != NULL) {
11170 * Chameleons: the original target namespace will
11171 * differ from the resulting namespace.
11173 isChameleon = 1;
11174 bucket->targetNamespace = pctxt->targetNamespace;
11178 * Parse the schema.
11180 if (bucket && (!bucket->parsed) && (bucket->doc != NULL)) {
11181 if (isChameleon) {
11182 /* TODO: Get rid of this flag on the schema itself. */
11183 if ((schema->flags & XML_SCHEMAS_INCLUDING_CONVERT_NS) == 0) {
11184 schema->flags |= XML_SCHEMAS_INCLUDING_CONVERT_NS;
11185 } else
11186 wasChameleon = 1;
11188 xmlSchemaParseNewDoc(pctxt, schema, bucket);
11189 /* Restore chameleon flag. */
11190 if (isChameleon && (!wasChameleon))
11191 schema->flags ^= XML_SCHEMAS_INCLUDING_CONVERT_NS;
11194 * And now for the children...
11196 child = node->children;
11197 if (type == XML_SCHEMA_SCHEMA_REDEFINE) {
11199 * Parse (simpleType | complexType | group | attributeGroup))*
11201 pctxt->redefined = bucket;
11203 * How to proceed if the redefined schema was not located?
11205 pctxt->isRedefine = 1;
11206 while (IS_SCHEMA(child, "annotation") ||
11207 IS_SCHEMA(child, "simpleType") ||
11208 IS_SCHEMA(child, "complexType") ||
11209 IS_SCHEMA(child, "group") ||
11210 IS_SCHEMA(child, "attributeGroup")) {
11211 if (IS_SCHEMA(child, "annotation")) {
11213 * TODO: discard or not?
11215 } else if (IS_SCHEMA(child, "simpleType")) {
11216 xmlSchemaParseSimpleType(pctxt, schema, child, 1);
11217 } else if (IS_SCHEMA(child, "complexType")) {
11218 xmlSchemaParseComplexType(pctxt, schema, child, 1);
11219 /* hasRedefinitions = 1; */
11220 } else if (IS_SCHEMA(child, "group")) {
11221 /* hasRedefinitions = 1; */
11222 xmlSchemaParseModelGroupDefinition(pctxt,
11223 schema, child);
11224 } else if (IS_SCHEMA(child, "attributeGroup")) {
11225 /* hasRedefinitions = 1; */
11226 xmlSchemaParseAttributeGroupDefinition(pctxt, schema,
11227 child);
11229 child = child->next;
11231 pctxt->redefined = NULL;
11232 pctxt->isRedefine = 0;
11233 } else {
11234 if (IS_SCHEMA(child, "annotation")) {
11236 * TODO: discard or not?
11238 child = child->next;
11241 if (child != NULL) {
11242 res = XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED;
11243 if (type == XML_SCHEMA_SCHEMA_REDEFINE) {
11244 xmlSchemaPContentErr(pctxt, res,
11245 NULL, node, child, NULL,
11246 "(annotation | (simpleType | complexType | group | attributeGroup))*");
11247 } else {
11248 xmlSchemaPContentErr(pctxt, res,
11249 NULL, node, child, NULL,
11250 "(annotation?)");
11253 return(res);
11255 exit_error:
11256 return(pctxt->err);
11259 static int
11260 xmlSchemaParseRedefine(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema,
11261 xmlNodePtr node)
11263 int res;
11264 #ifndef ENABLE_REDEFINE
11265 TODO
11266 return(0);
11267 #endif
11268 res = xmlSchemaParseIncludeOrRedefine(pctxt, schema, node,
11269 XML_SCHEMA_SCHEMA_REDEFINE);
11270 if (res != 0)
11271 return(res);
11272 return(0);
11275 static int
11276 xmlSchemaParseInclude(xmlSchemaParserCtxtPtr pctxt, xmlSchemaPtr schema,
11277 xmlNodePtr node)
11279 int res;
11281 res = xmlSchemaParseIncludeOrRedefine(pctxt, schema, node,
11282 XML_SCHEMA_SCHEMA_INCLUDE);
11283 if (res != 0)
11284 return(res);
11285 return(0);
11289 * xmlSchemaParseModelGroup:
11290 * @ctxt: a schema validation context
11291 * @schema: the schema being built
11292 * @node: a subtree containing XML Schema information
11293 * @type: the "compositor" type
11294 * @particleNeeded: if a a model group with a particle
11296 * parse a XML schema Sequence definition.
11297 * Applies parts of:
11298 * Schema Representation Constraint:
11299 * Redefinition Constraints and Semantics (src-redefine)
11300 * (6.1), (6.1.1), (6.1.2)
11302 * Schema Component Constraint:
11303 * All Group Limited (cos-all-limited) (2)
11304 * TODO: Actually this should go to component-level checks,
11305 * but is done here due to performance. Move it to an other layer
11306 * is schema construction via an API is implemented.
11308 * *WARNING* this interface is highly subject to change
11310 * Returns -1 in case of error, 0 if the declaration is improper and
11311 * 1 in case of success.
11313 static xmlSchemaTreeItemPtr
11314 xmlSchemaParseModelGroup(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
11315 xmlNodePtr node, xmlSchemaTypeType type,
11316 int withParticle)
11318 xmlSchemaModelGroupPtr item;
11319 xmlSchemaParticlePtr particle = NULL;
11320 xmlNodePtr child = NULL;
11321 xmlAttrPtr attr;
11322 int min = 1, max = 1, isElemRef, hasRefs = 0;
11324 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
11325 return (NULL);
11327 * Create a model group with the given compositor.
11329 item = xmlSchemaAddModelGroup(ctxt, schema, type, node);
11330 if (item == NULL)
11331 return (NULL);
11333 if (withParticle) {
11334 if (type == XML_SCHEMA_TYPE_ALL) {
11335 min = xmlGetMinOccurs(ctxt, node, 0, 1, 1, "(0 | 1)");
11336 max = xmlGetMaxOccurs(ctxt, node, 1, 1, 1, "1");
11337 } else {
11338 /* choice + sequence */
11339 min = xmlGetMinOccurs(ctxt, node, 0, -1, 1, "xs:nonNegativeInteger");
11340 max = xmlGetMaxOccurs(ctxt, node, 0, UNBOUNDED, 1,
11341 "(xs:nonNegativeInteger | unbounded)");
11343 xmlSchemaPCheckParticleCorrect_2(ctxt, NULL, node, min, max);
11345 * Create a particle
11347 particle = xmlSchemaAddParticle(ctxt, node, min, max);
11348 if (particle == NULL)
11349 return (NULL);
11350 particle->children = (xmlSchemaTreeItemPtr) item;
11352 * Check for illegal attributes.
11354 attr = node->properties;
11355 while (attr != NULL) {
11356 if (attr->ns == NULL) {
11357 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
11358 (!xmlStrEqual(attr->name, BAD_CAST "maxOccurs")) &&
11359 (!xmlStrEqual(attr->name, BAD_CAST "minOccurs"))) {
11360 xmlSchemaPIllegalAttrErr(ctxt,
11361 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11363 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
11364 xmlSchemaPIllegalAttrErr(ctxt,
11365 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11367 attr = attr->next;
11369 } else {
11371 * Check for illegal attributes.
11373 attr = node->properties;
11374 while (attr != NULL) {
11375 if (attr->ns == NULL) {
11376 if (!xmlStrEqual(attr->name, BAD_CAST "id")) {
11377 xmlSchemaPIllegalAttrErr(ctxt,
11378 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11380 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
11381 xmlSchemaPIllegalAttrErr(ctxt,
11382 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11384 attr = attr->next;
11389 * Extract and validate attributes.
11391 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
11393 * And now for the children...
11395 child = node->children;
11396 if (IS_SCHEMA(child, "annotation")) {
11397 item->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
11398 child = child->next;
11400 if (type == XML_SCHEMA_TYPE_ALL) {
11401 xmlSchemaParticlePtr part, last = NULL;
11403 while (IS_SCHEMA(child, "element")) {
11404 part = (xmlSchemaParticlePtr) xmlSchemaParseElement(ctxt,
11405 schema, child, &isElemRef, 0);
11407 * SPEC cos-all-limited (2)
11408 * "The {max occurs} of all the particles in the {particles}
11409 * of the ('all') group must be 0 or 1.
11411 if (part != NULL) {
11412 if (isElemRef)
11413 hasRefs++;
11414 if (part->minOccurs > 1) {
11415 xmlSchemaPCustomErr(ctxt,
11416 XML_SCHEMAP_COS_ALL_LIMITED,
11417 NULL, child,
11418 "Invalid value for minOccurs (must be 0 or 1)",
11419 NULL);
11420 /* Reset to 1. */
11421 part->minOccurs = 1;
11423 if (part->maxOccurs > 1) {
11424 xmlSchemaPCustomErr(ctxt,
11425 XML_SCHEMAP_COS_ALL_LIMITED,
11426 NULL, child,
11427 "Invalid value for maxOccurs (must be 0 or 1)",
11428 NULL);
11429 /* Reset to 1. */
11430 part->maxOccurs = 1;
11432 if (last == NULL)
11433 item->children = (xmlSchemaTreeItemPtr) part;
11434 else
11435 last->next = (xmlSchemaTreeItemPtr) part;
11436 last = part;
11438 child = child->next;
11440 if (child != NULL) {
11441 xmlSchemaPContentErr(ctxt,
11442 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11443 NULL, node, child, NULL,
11444 "(annotation?, (annotation?, element*)");
11446 } else {
11447 /* choice + sequence */
11448 xmlSchemaTreeItemPtr part = NULL, last = NULL;
11450 while ((IS_SCHEMA(child, "element")) ||
11451 (IS_SCHEMA(child, "group")) ||
11452 (IS_SCHEMA(child, "any")) ||
11453 (IS_SCHEMA(child, "choice")) ||
11454 (IS_SCHEMA(child, "sequence"))) {
11456 if (IS_SCHEMA(child, "element")) {
11457 part = (xmlSchemaTreeItemPtr)
11458 xmlSchemaParseElement(ctxt, schema, child, &isElemRef, 0);
11459 if (part && isElemRef)
11460 hasRefs++;
11461 } else if (IS_SCHEMA(child, "group")) {
11462 part =
11463 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
11464 if (part != NULL)
11465 hasRefs++;
11467 * Handle redefinitions.
11469 if (ctxt->isRedefine && ctxt->redef &&
11470 (ctxt->redef->item->type == XML_SCHEMA_TYPE_GROUP) &&
11471 part && part->children)
11473 if ((xmlSchemaGetQNameRefName(part->children) ==
11474 ctxt->redef->refName) &&
11475 (xmlSchemaGetQNameRefTargetNs(part->children) ==
11476 ctxt->redef->refTargetNs))
11479 * SPEC src-redefine:
11480 * (6.1) "If it has a <group> among its contents at
11481 * some level the `actual value` of whose ref
11482 * [attribute] is the same as the `actual value` of
11483 * its own name attribute plus target namespace, then
11484 * all of the following must be true:"
11485 * (6.1.1) "It must have exactly one such group."
11487 if (ctxt->redefCounter != 0) {
11488 xmlChar *str = NULL;
11490 xmlSchemaCustomErr(ACTXT_CAST ctxt,
11491 XML_SCHEMAP_SRC_REDEFINE, child, NULL,
11492 "The redefining model group definition "
11493 "'%s' must not contain more than one "
11494 "reference to the redefined definition",
11495 xmlSchemaFormatQName(&str,
11496 ctxt->redef->refTargetNs,
11497 ctxt->redef->refName),
11498 NULL);
11499 FREE_AND_NULL(str)
11500 part = NULL;
11501 } else if (((WXS_PARTICLE(part))->minOccurs != 1) ||
11502 ((WXS_PARTICLE(part))->maxOccurs != 1))
11504 xmlChar *str = NULL;
11506 * SPEC src-redefine:
11507 * (6.1.2) "The `actual value` of both that
11508 * group's minOccurs and maxOccurs [attribute]
11509 * must be 1 (or `absent`).
11511 xmlSchemaCustomErr(ACTXT_CAST ctxt,
11512 XML_SCHEMAP_SRC_REDEFINE, child, NULL,
11513 "The redefining model group definition "
11514 "'%s' must not contain a reference to the "
11515 "redefined definition with a "
11516 "maxOccurs/minOccurs other than 1",
11517 xmlSchemaFormatQName(&str,
11518 ctxt->redef->refTargetNs,
11519 ctxt->redef->refName),
11520 NULL);
11521 FREE_AND_NULL(str)
11522 part = NULL;
11524 ctxt->redef->reference = WXS_BASIC_CAST part;
11525 ctxt->redefCounter++;
11528 } else if (IS_SCHEMA(child, "any")) {
11529 part = (xmlSchemaTreeItemPtr)
11530 xmlSchemaParseAny(ctxt, schema, child);
11531 } else if (IS_SCHEMA(child, "choice")) {
11532 part = xmlSchemaParseModelGroup(ctxt, schema, child,
11533 XML_SCHEMA_TYPE_CHOICE, 1);
11534 } else if (IS_SCHEMA(child, "sequence")) {
11535 part = xmlSchemaParseModelGroup(ctxt, schema, child,
11536 XML_SCHEMA_TYPE_SEQUENCE, 1);
11538 if (part != NULL) {
11539 if (last == NULL)
11540 item->children = part;
11541 else
11542 last->next = part;
11543 last = part;
11545 child = child->next;
11547 if (child != NULL) {
11548 xmlSchemaPContentErr(ctxt,
11549 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11550 NULL, node, child, NULL,
11551 "(annotation?, (element | group | choice | sequence | any)*)");
11554 if ((max == 0) && (min == 0))
11555 return (NULL);
11556 if (hasRefs) {
11558 * We need to resolve references.
11560 WXS_ADD_PENDING(ctxt, item);
11562 if (withParticle)
11563 return ((xmlSchemaTreeItemPtr) particle);
11564 else
11565 return ((xmlSchemaTreeItemPtr) item);
11569 * xmlSchemaParseRestriction:
11570 * @ctxt: a schema validation context
11571 * @schema: the schema being built
11572 * @node: a subtree containing XML Schema information
11574 * parse a XML schema Restriction definition
11575 * *WARNING* this interface is highly subject to change
11577 * Returns the type definition or NULL in case of error
11579 static xmlSchemaTypePtr
11580 xmlSchemaParseRestriction(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
11581 xmlNodePtr node, xmlSchemaTypeType parentType)
11583 xmlSchemaTypePtr type;
11584 xmlNodePtr child = NULL;
11585 xmlAttrPtr attr;
11587 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
11588 return (NULL);
11589 /* Not a component, don't create it. */
11590 type = ctxt->ctxtType;
11591 type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
11594 * Check for illegal attributes.
11596 attr = node->properties;
11597 while (attr != NULL) {
11598 if (attr->ns == NULL) {
11599 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
11600 (!xmlStrEqual(attr->name, BAD_CAST "base"))) {
11601 xmlSchemaPIllegalAttrErr(ctxt,
11602 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11604 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
11605 xmlSchemaPIllegalAttrErr(ctxt,
11606 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11608 attr = attr->next;
11611 * Extract and validate attributes.
11613 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
11615 * Attribute
11618 * Extract the base type. The "base" attribute is mandatory if inside
11619 * a complex type or if redefining.
11621 * SPEC (1.2) "...otherwise (<restriction> has no <simpleType> "
11622 * among its [children]), the simple type definition which is
11623 * the {content type} of the type definition `resolved` to by
11624 * the `actual value` of the base [attribute]"
11626 if (xmlSchemaPValAttrQName(ctxt, schema, NULL, node, "base",
11627 &(type->baseNs), &(type->base)) == 0)
11629 if ((type->base == NULL) && (type->type == XML_SCHEMA_TYPE_COMPLEX)) {
11630 xmlSchemaPMissingAttrErr(ctxt,
11631 XML_SCHEMAP_S4S_ATTR_MISSING,
11632 NULL, node, "base", NULL);
11633 } else if ((ctxt->isRedefine) &&
11634 (type->flags & XML_SCHEMAS_TYPE_GLOBAL))
11636 if (type->base == NULL) {
11637 xmlSchemaPMissingAttrErr(ctxt,
11638 XML_SCHEMAP_S4S_ATTR_MISSING,
11639 NULL, node, "base", NULL);
11640 } else if ((! xmlStrEqual(type->base, type->name)) ||
11641 (! xmlStrEqual(type->baseNs, type->targetNamespace)))
11643 xmlChar *str1 = NULL, *str2 = NULL;
11645 * REDEFINE: SPEC src-redefine (5)
11646 * "Within the [children], each <simpleType> must have a
11647 * <restriction> among its [children] ... the `actual value` of
11648 * whose base [attribute] must be the same as the `actual value`
11649 * of its own name attribute plus target namespace;"
11651 xmlSchemaPCustomErrExt(ctxt, XML_SCHEMAP_SRC_REDEFINE,
11652 NULL, node, "This is a redefinition, but the QName "
11653 "value '%s' of the 'base' attribute does not match the "
11654 "type's designation '%s'",
11655 xmlSchemaFormatQName(&str1, type->baseNs, type->base),
11656 xmlSchemaFormatQName(&str2, type->targetNamespace,
11657 type->name), NULL);
11658 FREE_AND_NULL(str1);
11659 FREE_AND_NULL(str2);
11660 /* Avoid confusion and erase the values. */
11661 type->base = NULL;
11662 type->baseNs = NULL;
11667 * And now for the children...
11669 child = node->children;
11670 if (IS_SCHEMA(child, "annotation")) {
11672 * Add the annotation to the simple type ancestor.
11674 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
11675 xmlSchemaParseAnnotation(ctxt, child, 1));
11676 child = child->next;
11678 if (parentType == XML_SCHEMA_TYPE_SIMPLE) {
11680 * Corresponds to <simpleType><restriction><simpleType>.
11682 if (IS_SCHEMA(child, "simpleType")) {
11683 if (type->base != NULL) {
11685 * src-restriction-base-or-simpleType
11686 * Either the base [attribute] or the simpleType [child] of the
11687 * <restriction> element must be present, but not both.
11689 xmlSchemaPContentErr(ctxt,
11690 XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
11691 NULL, node, child,
11692 "The attribute 'base' and the <simpleType> child are "
11693 "mutually exclusive", NULL);
11694 } else {
11695 type->baseType = (xmlSchemaTypePtr)
11696 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
11698 child = child->next;
11699 } else if (type->base == NULL) {
11700 xmlSchemaPContentErr(ctxt,
11701 XML_SCHEMAP_SRC_RESTRICTION_BASE_OR_SIMPLETYPE,
11702 NULL, node, child,
11703 "Either the attribute 'base' or a <simpleType> child "
11704 "must be present", NULL);
11706 } else if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11708 * Corresponds to <complexType><complexContent><restriction>...
11709 * followed by:
11711 * Model groups <all>, <choice> and <sequence>.
11713 if (IS_SCHEMA(child, "all")) {
11714 type->subtypes = (xmlSchemaTypePtr)
11715 xmlSchemaParseModelGroup(ctxt, schema, child,
11716 XML_SCHEMA_TYPE_ALL, 1);
11717 child = child->next;
11718 } else if (IS_SCHEMA(child, "choice")) {
11719 type->subtypes = (xmlSchemaTypePtr)
11720 xmlSchemaParseModelGroup(ctxt,
11721 schema, child, XML_SCHEMA_TYPE_CHOICE, 1);
11722 child = child->next;
11723 } else if (IS_SCHEMA(child, "sequence")) {
11724 type->subtypes = (xmlSchemaTypePtr)
11725 xmlSchemaParseModelGroup(ctxt, schema, child,
11726 XML_SCHEMA_TYPE_SEQUENCE, 1);
11727 child = child->next;
11729 * Model group reference <group>.
11731 } else if (IS_SCHEMA(child, "group")) {
11732 type->subtypes = (xmlSchemaTypePtr)
11733 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
11735 * Note that the reference will be resolved in
11736 * xmlSchemaResolveTypeReferences();
11738 child = child->next;
11740 } else if (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
11742 * Corresponds to <complexType><simpleContent><restriction>...
11744 * "1.1 the simple type definition corresponding to the <simpleType>
11745 * among the [children] of <restriction> if there is one;"
11747 if (IS_SCHEMA(child, "simpleType")) {
11749 * We will store the to-be-restricted simple type in
11750 * type->contentTypeDef *temporarily*.
11752 type->contentTypeDef = (xmlSchemaTypePtr)
11753 xmlSchemaParseSimpleType(ctxt, schema, child, 0);
11754 if ( type->contentTypeDef == NULL)
11755 return (NULL);
11756 child = child->next;
11760 if ((parentType == XML_SCHEMA_TYPE_SIMPLE) ||
11761 (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT)) {
11762 xmlSchemaFacetPtr facet, lastfacet = NULL;
11764 * Corresponds to <complexType><simpleContent><restriction>...
11765 * <simpleType><restriction>...
11769 * Add the facets to the simple type ancestor.
11772 * TODO: Datatypes: 4.1.3 Constraints on XML Representation of
11773 * Simple Type Definition Schema Representation Constraint:
11774 * *Single Facet Value*
11776 while ((IS_SCHEMA(child, "minInclusive")) ||
11777 (IS_SCHEMA(child, "minExclusive")) ||
11778 (IS_SCHEMA(child, "maxInclusive")) ||
11779 (IS_SCHEMA(child, "maxExclusive")) ||
11780 (IS_SCHEMA(child, "totalDigits")) ||
11781 (IS_SCHEMA(child, "fractionDigits")) ||
11782 (IS_SCHEMA(child, "pattern")) ||
11783 (IS_SCHEMA(child, "enumeration")) ||
11784 (IS_SCHEMA(child, "whiteSpace")) ||
11785 (IS_SCHEMA(child, "length")) ||
11786 (IS_SCHEMA(child, "maxLength")) ||
11787 (IS_SCHEMA(child, "minLength"))) {
11788 facet = xmlSchemaParseFacet(ctxt, schema, child);
11789 if (facet != NULL) {
11790 if (lastfacet == NULL)
11791 type->facets = facet;
11792 else
11793 lastfacet->next = facet;
11794 lastfacet = facet;
11795 lastfacet->next = NULL;
11797 child = child->next;
11800 * Create links for derivation and validation.
11802 if (type->facets != NULL) {
11803 xmlSchemaFacetLinkPtr facetLink, lastFacetLink = NULL;
11805 facet = type->facets;
11806 do {
11807 facetLink = (xmlSchemaFacetLinkPtr)
11808 xmlMalloc(sizeof(xmlSchemaFacetLink));
11809 if (facetLink == NULL) {
11810 xmlSchemaPErrMemory(ctxt, "allocating a facet link", NULL);
11811 xmlFree(facetLink);
11812 return (NULL);
11814 facetLink->facet = facet;
11815 facetLink->next = NULL;
11816 if (lastFacetLink == NULL)
11817 type->facetSet = facetLink;
11818 else
11819 lastFacetLink->next = facetLink;
11820 lastFacetLink = facetLink;
11821 facet = facet->next;
11822 } while (facet != NULL);
11825 if (type->type == XML_SCHEMA_TYPE_COMPLEX) {
11827 * Attribute uses/declarations.
11829 if (xmlSchemaParseLocalAttributes(ctxt, schema, &child,
11830 (xmlSchemaItemListPtr *) &(type->attrUses),
11831 XML_SCHEMA_TYPE_RESTRICTION, NULL) == -1)
11832 return(NULL);
11834 * Attribute wildcard.
11836 if (IS_SCHEMA(child, "anyAttribute")) {
11837 type->attributeWildcard =
11838 xmlSchemaParseAnyAttribute(ctxt, schema, child);
11839 child = child->next;
11842 if (child != NULL) {
11843 if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11844 xmlSchemaPContentErr(ctxt,
11845 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11846 NULL, node, child, NULL,
11847 "annotation?, (group | all | choice | sequence)?, "
11848 "((attribute | attributeGroup)*, anyAttribute?))");
11849 } else if (parentType == XML_SCHEMA_TYPE_SIMPLE_CONTENT) {
11850 xmlSchemaPContentErr(ctxt,
11851 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11852 NULL, node, child, NULL,
11853 "(annotation?, (simpleType?, (minExclusive | minInclusive | "
11854 "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
11855 "length | minLength | maxLength | enumeration | whiteSpace | "
11856 "pattern)*)?, ((attribute | attributeGroup)*, anyAttribute?))");
11857 } else {
11858 /* Simple type */
11859 xmlSchemaPContentErr(ctxt,
11860 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11861 NULL, node, child, NULL,
11862 "(annotation?, (simpleType?, (minExclusive | minInclusive | "
11863 "maxExclusive | maxInclusive | totalDigits | fractionDigits | "
11864 "length | minLength | maxLength | enumeration | whiteSpace | "
11865 "pattern)*))");
11868 return (NULL);
11872 * xmlSchemaParseExtension:
11873 * @ctxt: a schema validation context
11874 * @schema: the schema being built
11875 * @node: a subtree containing XML Schema information
11877 * Parses an <extension>, which is found inside a
11878 * <simpleContent> or <complexContent>.
11879 * *WARNING* this interface is highly subject to change.
11881 * TODO: Returns the type definition or NULL in case of error
11883 static xmlSchemaTypePtr
11884 xmlSchemaParseExtension(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
11885 xmlNodePtr node, xmlSchemaTypeType parentType)
11887 xmlSchemaTypePtr type;
11888 xmlNodePtr child = NULL;
11889 xmlAttrPtr attr;
11891 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
11892 return (NULL);
11893 /* Not a component, don't create it. */
11894 type = ctxt->ctxtType;
11895 type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_EXTENSION;
11898 * Check for illegal attributes.
11900 attr = node->properties;
11901 while (attr != NULL) {
11902 if (attr->ns == NULL) {
11903 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
11904 (!xmlStrEqual(attr->name, BAD_CAST "base"))) {
11905 xmlSchemaPIllegalAttrErr(ctxt,
11906 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11908 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
11909 xmlSchemaPIllegalAttrErr(ctxt,
11910 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
11912 attr = attr->next;
11915 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
11918 * Attribute "base" - mandatory.
11920 if ((xmlSchemaPValAttrQName(ctxt, schema, NULL, node,
11921 "base", &(type->baseNs), &(type->base)) == 0) &&
11922 (type->base == NULL)) {
11923 xmlSchemaPMissingAttrErr(ctxt,
11924 XML_SCHEMAP_S4S_ATTR_MISSING,
11925 NULL, node, "base", NULL);
11928 * And now for the children...
11930 child = node->children;
11931 if (IS_SCHEMA(child, "annotation")) {
11933 * Add the annotation to the type ancestor.
11935 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
11936 xmlSchemaParseAnnotation(ctxt, child, 1));
11937 child = child->next;
11939 if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11941 * Corresponds to <complexType><complexContent><extension>... and:
11943 * Model groups <all>, <choice>, <sequence> and <group>.
11945 if (IS_SCHEMA(child, "all")) {
11946 type->subtypes = (xmlSchemaTypePtr)
11947 xmlSchemaParseModelGroup(ctxt, schema,
11948 child, XML_SCHEMA_TYPE_ALL, 1);
11949 child = child->next;
11950 } else if (IS_SCHEMA(child, "choice")) {
11951 type->subtypes = (xmlSchemaTypePtr)
11952 xmlSchemaParseModelGroup(ctxt, schema,
11953 child, XML_SCHEMA_TYPE_CHOICE, 1);
11954 child = child->next;
11955 } else if (IS_SCHEMA(child, "sequence")) {
11956 type->subtypes = (xmlSchemaTypePtr)
11957 xmlSchemaParseModelGroup(ctxt, schema,
11958 child, XML_SCHEMA_TYPE_SEQUENCE, 1);
11959 child = child->next;
11960 } else if (IS_SCHEMA(child, "group")) {
11961 type->subtypes = (xmlSchemaTypePtr)
11962 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
11964 * Note that the reference will be resolved in
11965 * xmlSchemaResolveTypeReferences();
11967 child = child->next;
11970 if (child != NULL) {
11972 * Attribute uses/declarations.
11974 if (xmlSchemaParseLocalAttributes(ctxt, schema, &child,
11975 (xmlSchemaItemListPtr *) &(type->attrUses),
11976 XML_SCHEMA_TYPE_EXTENSION, NULL) == -1)
11977 return(NULL);
11979 * Attribute wildcard.
11981 if (IS_SCHEMA(child, "anyAttribute")) {
11982 ctxt->ctxtType->attributeWildcard =
11983 xmlSchemaParseAnyAttribute(ctxt, schema, child);
11984 child = child->next;
11987 if (child != NULL) {
11988 if (parentType == XML_SCHEMA_TYPE_COMPLEX_CONTENT) {
11989 /* Complex content extension. */
11990 xmlSchemaPContentErr(ctxt,
11991 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11992 NULL, node, child, NULL,
11993 "(annotation?, ((group | all | choice | sequence)?, "
11994 "((attribute | attributeGroup)*, anyAttribute?)))");
11995 } else {
11996 /* Simple content extension. */
11997 xmlSchemaPContentErr(ctxt,
11998 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
11999 NULL, node, child, NULL,
12000 "(annotation?, ((attribute | attributeGroup)*, "
12001 "anyAttribute?))");
12004 return (NULL);
12008 * xmlSchemaParseSimpleContent:
12009 * @ctxt: a schema validation context
12010 * @schema: the schema being built
12011 * @node: a subtree containing XML Schema information
12013 * parse a XML schema SimpleContent definition
12014 * *WARNING* this interface is highly subject to change
12016 * Returns the type definition or NULL in case of error
12018 static int
12019 xmlSchemaParseSimpleContent(xmlSchemaParserCtxtPtr ctxt,
12020 xmlSchemaPtr schema, xmlNodePtr node,
12021 int *hasRestrictionOrExtension)
12023 xmlSchemaTypePtr type;
12024 xmlNodePtr child = NULL;
12025 xmlAttrPtr attr;
12027 if ((ctxt == NULL) || (schema == NULL) || (node == NULL) ||
12028 (hasRestrictionOrExtension == NULL))
12029 return (-1);
12030 *hasRestrictionOrExtension = 0;
12031 /* Not a component, don't create it. */
12032 type = ctxt->ctxtType;
12033 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
12035 * Check for illegal attributes.
12037 attr = node->properties;
12038 while (attr != NULL) {
12039 if (attr->ns == NULL) {
12040 if ((!xmlStrEqual(attr->name, BAD_CAST "id"))) {
12041 xmlSchemaPIllegalAttrErr(ctxt,
12042 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
12044 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
12045 xmlSchemaPIllegalAttrErr(ctxt,
12046 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
12048 attr = attr->next;
12051 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
12054 * And now for the children...
12056 child = node->children;
12057 if (IS_SCHEMA(child, "annotation")) {
12059 * Add the annotation to the complex type ancestor.
12061 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
12062 xmlSchemaParseAnnotation(ctxt, child, 1));
12063 child = child->next;
12065 if (child == NULL) {
12066 xmlSchemaPContentErr(ctxt,
12067 XML_SCHEMAP_S4S_ELEM_MISSING,
12068 NULL, node, NULL, NULL,
12069 "(annotation?, (restriction | extension))");
12071 if (child == NULL) {
12072 xmlSchemaPContentErr(ctxt,
12073 XML_SCHEMAP_S4S_ELEM_MISSING,
12074 NULL, node, NULL, NULL,
12075 "(annotation?, (restriction | extension))");
12077 if (IS_SCHEMA(child, "restriction")) {
12078 xmlSchemaParseRestriction(ctxt, schema, child,
12079 XML_SCHEMA_TYPE_SIMPLE_CONTENT);
12080 (*hasRestrictionOrExtension) = 1;
12081 child = child->next;
12082 } else if (IS_SCHEMA(child, "extension")) {
12083 xmlSchemaParseExtension(ctxt, schema, child,
12084 XML_SCHEMA_TYPE_SIMPLE_CONTENT);
12085 (*hasRestrictionOrExtension) = 1;
12086 child = child->next;
12088 if (child != NULL) {
12089 xmlSchemaPContentErr(ctxt,
12090 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
12091 NULL, node, child, NULL,
12092 "(annotation?, (restriction | extension))");
12094 return (0);
12098 * xmlSchemaParseComplexContent:
12099 * @ctxt: a schema validation context
12100 * @schema: the schema being built
12101 * @node: a subtree containing XML Schema information
12103 * parse a XML schema ComplexContent definition
12104 * *WARNING* this interface is highly subject to change
12106 * Returns the type definition or NULL in case of error
12108 static int
12109 xmlSchemaParseComplexContent(xmlSchemaParserCtxtPtr ctxt,
12110 xmlSchemaPtr schema, xmlNodePtr node,
12111 int *hasRestrictionOrExtension)
12113 xmlSchemaTypePtr type;
12114 xmlNodePtr child = NULL;
12115 xmlAttrPtr attr;
12117 if ((ctxt == NULL) || (schema == NULL) || (node == NULL) ||
12118 (hasRestrictionOrExtension == NULL))
12119 return (-1);
12120 *hasRestrictionOrExtension = 0;
12121 /* Not a component, don't create it. */
12122 type = ctxt->ctxtType;
12124 * Check for illegal attributes.
12126 attr = node->properties;
12127 while (attr != NULL) {
12128 if (attr->ns == NULL) {
12129 if ((!xmlStrEqual(attr->name, BAD_CAST "id")) &&
12130 (!xmlStrEqual(attr->name, BAD_CAST "mixed")))
12132 xmlSchemaPIllegalAttrErr(ctxt,
12133 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
12135 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
12136 xmlSchemaPIllegalAttrErr(ctxt,
12137 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
12139 attr = attr->next;
12142 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
12145 * Set the 'mixed' on the complex type ancestor.
12147 if (xmlGetBooleanProp(ctxt, node, "mixed", 0)) {
12148 if ((type->flags & XML_SCHEMAS_TYPE_MIXED) == 0)
12149 type->flags |= XML_SCHEMAS_TYPE_MIXED;
12151 child = node->children;
12152 if (IS_SCHEMA(child, "annotation")) {
12154 * Add the annotation to the complex type ancestor.
12156 xmlSchemaAddAnnotation((xmlSchemaAnnotItemPtr) type,
12157 xmlSchemaParseAnnotation(ctxt, child, 1));
12158 child = child->next;
12160 if (child == NULL) {
12161 xmlSchemaPContentErr(ctxt,
12162 XML_SCHEMAP_S4S_ELEM_MISSING,
12163 NULL, node, NULL,
12164 NULL, "(annotation?, (restriction | extension))");
12166 if (child == NULL) {
12167 xmlSchemaPContentErr(ctxt,
12168 XML_SCHEMAP_S4S_ELEM_MISSING,
12169 NULL, node, NULL,
12170 NULL, "(annotation?, (restriction | extension))");
12172 if (IS_SCHEMA(child, "restriction")) {
12173 xmlSchemaParseRestriction(ctxt, schema, child,
12174 XML_SCHEMA_TYPE_COMPLEX_CONTENT);
12175 (*hasRestrictionOrExtension) = 1;
12176 child = child->next;
12177 } else if (IS_SCHEMA(child, "extension")) {
12178 xmlSchemaParseExtension(ctxt, schema, child,
12179 XML_SCHEMA_TYPE_COMPLEX_CONTENT);
12180 (*hasRestrictionOrExtension) = 1;
12181 child = child->next;
12183 if (child != NULL) {
12184 xmlSchemaPContentErr(ctxt,
12185 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
12186 NULL, node, child,
12187 NULL, "(annotation?, (restriction | extension))");
12189 return (0);
12193 * xmlSchemaParseComplexType:
12194 * @ctxt: a schema validation context
12195 * @schema: the schema being built
12196 * @node: a subtree containing XML Schema information
12198 * parse a XML schema Complex Type definition
12199 * *WARNING* this interface is highly subject to change
12201 * Returns the type definition or NULL in case of error
12203 static xmlSchemaTypePtr
12204 xmlSchemaParseComplexType(xmlSchemaParserCtxtPtr ctxt, xmlSchemaPtr schema,
12205 xmlNodePtr node, int topLevel)
12207 xmlSchemaTypePtr type, ctxtType;
12208 xmlNodePtr child = NULL;
12209 const xmlChar *name = NULL;
12210 xmlAttrPtr attr;
12211 const xmlChar *attrValue;
12212 #ifdef ENABLE_NAMED_LOCALS
12213 char buf[40];
12214 #endif
12215 int final = 0, block = 0, hasRestrictionOrExtension = 0;
12218 if ((ctxt == NULL) || (schema == NULL) || (node == NULL))
12219 return (NULL);
12221 ctxtType = ctxt->ctxtType;
12223 if (topLevel) {
12224 attr = xmlSchemaGetPropNode(node, "name");
12225 if (attr == NULL) {
12226 xmlSchemaPMissingAttrErr(ctxt,
12227 XML_SCHEMAP_S4S_ATTR_MISSING, NULL, node, "name", NULL);
12228 return (NULL);
12229 } else if (xmlSchemaPValAttrNode(ctxt, NULL, attr,
12230 xmlSchemaGetBuiltInType(XML_SCHEMAS_NCNAME), &name) != 0) {
12231 return (NULL);
12235 if (topLevel == 0) {
12237 * Parse as local complex type definition.
12239 #ifdef ENABLE_NAMED_LOCALS
12240 snprintf(buf, 39, "#CT%d", ctxt->counter++ + 1);
12241 type = xmlSchemaAddType(ctxt, schema,
12242 XML_SCHEMA_TYPE_COMPLEX,
12243 xmlDictLookup(ctxt->dict, (const xmlChar *)buf, -1),
12244 ctxt->targetNamespace, node, 0);
12245 #else
12246 type = xmlSchemaAddType(ctxt, schema,
12247 XML_SCHEMA_TYPE_COMPLEX,
12248 NULL, ctxt->targetNamespace, node, 0);
12249 #endif
12250 if (type == NULL)
12251 return (NULL);
12252 name = type->name;
12253 type->node = node;
12254 type->type = XML_SCHEMA_TYPE_COMPLEX;
12256 * TODO: We need the target namespace.
12258 } else {
12260 * Parse as global complex type definition.
12262 type = xmlSchemaAddType(ctxt, schema,
12263 XML_SCHEMA_TYPE_COMPLEX,
12264 name, ctxt->targetNamespace, node, 1);
12265 if (type == NULL)
12266 return (NULL);
12267 type->node = node;
12268 type->type = XML_SCHEMA_TYPE_COMPLEX;
12269 type->flags |= XML_SCHEMAS_TYPE_GLOBAL;
12271 type->targetNamespace = ctxt->targetNamespace;
12273 * Handle attributes.
12275 attr = node->properties;
12276 while (attr != NULL) {
12277 if (attr->ns == NULL) {
12278 if (xmlStrEqual(attr->name, BAD_CAST "id")) {
12280 * Attribute "id".
12282 xmlSchemaPValAttrID(ctxt, node, BAD_CAST "id");
12283 } else if (xmlStrEqual(attr->name, BAD_CAST "mixed")) {
12285 * Attribute "mixed".
12287 if (xmlSchemaPGetBoolNodeValue(ctxt,
12288 NULL, (xmlNodePtr) attr))
12289 type->flags |= XML_SCHEMAS_TYPE_MIXED;
12290 } else if (topLevel) {
12292 * Attributes of global complex type definitions.
12294 if (xmlStrEqual(attr->name, BAD_CAST "name")) {
12295 /* Pass. */
12296 } else if (xmlStrEqual(attr->name, BAD_CAST "abstract")) {
12298 * Attribute "abstract".
12300 if (xmlSchemaPGetBoolNodeValue(ctxt,
12301 NULL, (xmlNodePtr) attr))
12302 type->flags |= XML_SCHEMAS_TYPE_ABSTRACT;
12303 } else if (xmlStrEqual(attr->name, BAD_CAST "final")) {
12305 * Attribute "final".
12307 attrValue = xmlSchemaGetNodeContent(ctxt,
12308 (xmlNodePtr) attr);
12309 if (xmlSchemaPValAttrBlockFinal(attrValue,
12310 &(type->flags),
12312 XML_SCHEMAS_TYPE_FINAL_EXTENSION,
12313 XML_SCHEMAS_TYPE_FINAL_RESTRICTION,
12314 -1, -1, -1) != 0)
12316 xmlSchemaPSimpleTypeErr(ctxt,
12317 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
12318 NULL, (xmlNodePtr) attr, NULL,
12319 "(#all | List of (extension | restriction))",
12320 attrValue, NULL, NULL, NULL);
12321 } else
12322 final = 1;
12323 } else if (xmlStrEqual(attr->name, BAD_CAST "block")) {
12325 * Attribute "block".
12327 attrValue = xmlSchemaGetNodeContent(ctxt,
12328 (xmlNodePtr) attr);
12329 if (xmlSchemaPValAttrBlockFinal(attrValue, &(type->flags),
12331 XML_SCHEMAS_TYPE_BLOCK_EXTENSION,
12332 XML_SCHEMAS_TYPE_BLOCK_RESTRICTION,
12333 -1, -1, -1) != 0) {
12334 xmlSchemaPSimpleTypeErr(ctxt,
12335 XML_SCHEMAP_S4S_ATTR_INVALID_VALUE,
12336 NULL, (xmlNodePtr) attr, NULL,
12337 "(#all | List of (extension | restriction)) ",
12338 attrValue, NULL, NULL, NULL);
12339 } else
12340 block = 1;
12341 } else {
12342 xmlSchemaPIllegalAttrErr(ctxt,
12343 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
12345 } else {
12346 xmlSchemaPIllegalAttrErr(ctxt,
12347 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
12349 } else if (xmlStrEqual(attr->ns->href, xmlSchemaNs)) {
12350 xmlSchemaPIllegalAttrErr(ctxt,
12351 XML_SCHEMAP_S4S_ATTR_NOT_ALLOWED, NULL, attr);
12353 attr = attr->next;
12355 if (! block) {
12357 * Apply default "block" values.
12359 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_RESTRICTION)
12360 type->flags |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
12361 if (schema->flags & XML_SCHEMAS_BLOCK_DEFAULT_EXTENSION)
12362 type->flags |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
12364 if (! final) {
12366 * Apply default "block" values.
12368 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_RESTRICTION)
12369 type->flags |= XML_SCHEMAS_TYPE_FINAL_RESTRICTION;
12370 if (schema->flags & XML_SCHEMAS_FINAL_DEFAULT_EXTENSION)
12371 type->flags |= XML_SCHEMAS_TYPE_FINAL_EXTENSION;
12374 * And now for the children...
12376 child = node->children;
12377 if (IS_SCHEMA(child, "annotation")) {
12378 type->annot = xmlSchemaParseAnnotation(ctxt, child, 1);
12379 child = child->next;
12381 ctxt->ctxtType = type;
12382 if (IS_SCHEMA(child, "simpleContent")) {
12384 * <complexType><simpleContent>...
12385 * 3.4.3 : 2.2
12386 * Specifying mixed='true' when the <simpleContent>
12387 * alternative is chosen has no effect
12389 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
12390 type->flags ^= XML_SCHEMAS_TYPE_MIXED;
12391 xmlSchemaParseSimpleContent(ctxt, schema, child,
12392 &hasRestrictionOrExtension);
12393 child = child->next;
12394 } else if (IS_SCHEMA(child, "complexContent")) {
12396 * <complexType><complexContent>...
12398 type->contentType = XML_SCHEMA_CONTENT_EMPTY;
12399 xmlSchemaParseComplexContent(ctxt, schema, child,
12400 &hasRestrictionOrExtension);
12401 child = child->next;
12402 } else {
12404 * E.g <complexType><sequence>... or <complexType><attribute>... etc.
12406 * SPEC
12407 * "...the third alternative (neither <simpleContent> nor
12408 * <complexContent>) is chosen. This case is understood as shorthand
12409 * for complex content restricting the `ur-type definition`, and the
12410 * details of the mappings should be modified as necessary.
12412 type->baseType = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
12413 type->flags |= XML_SCHEMAS_TYPE_DERIVATION_METHOD_RESTRICTION;
12415 * Parse model groups.
12417 if (IS_SCHEMA(child, "all")) {
12418 type->subtypes = (xmlSchemaTypePtr)
12419 xmlSchemaParseModelGroup(ctxt, schema, child,
12420 XML_SCHEMA_TYPE_ALL, 1);
12421 child = child->next;
12422 } else if (IS_SCHEMA(child, "choice")) {
12423 type->subtypes = (xmlSchemaTypePtr)
12424 xmlSchemaParseModelGroup(ctxt, schema, child,
12425 XML_SCHEMA_TYPE_CHOICE, 1);
12426 child = child->next;
12427 } else if (IS_SCHEMA(child, "sequence")) {
12428 type->subtypes = (xmlSchemaTypePtr)
12429 xmlSchemaParseModelGroup(ctxt, schema, child,
12430 XML_SCHEMA_TYPE_SEQUENCE, 1);
12431 child = child->next;
12432 } else if (IS_SCHEMA(child, "group")) {
12433 type->subtypes = (xmlSchemaTypePtr)
12434 xmlSchemaParseModelGroupDefRef(ctxt, schema, child);
12436 * Note that the reference will be resolved in
12437 * xmlSchemaResolveTypeReferences();
12439 child = child->next;
12442 * Parse attribute decls/refs.
12444 if (xmlSchemaParseLocalAttributes(ctxt, schema, &child,
12445 (xmlSchemaItemListPtr *) &(type->attrUses),
12446 XML_SCHEMA_TYPE_RESTRICTION, NULL) == -1)
12447 return(NULL);
12449 * Parse attribute wildcard.
12451 if (IS_SCHEMA(child, "anyAttribute")) {
12452 type->attributeWildcard = xmlSchemaParseAnyAttribute(ctxt, schema, child);
12453 child = child->next;
12456 if (child != NULL) {
12457 xmlSchemaPContentErr(ctxt,
12458 XML_SCHEMAP_S4S_ELEM_NOT_ALLOWED,
12459 NULL, node, child,
12460 NULL, "(annotation?, (simpleContent | complexContent | "
12461 "((group | all | choice | sequence)?, ((attribute | "
12462 "attributeGroup)*, anyAttribute?))))");
12465 * REDEFINE: SPEC src-redefine (5)
12467 if (topLevel && ctxt->isRedefine && (! hasRestrictionOrExtension)) {
12468 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_SRC_REDEFINE,
12469 NULL, node, "This is a redefinition, thus the "
12470 "<complexType> must have a <restriction> or <extension> "
12471 "grand-child", NULL);
12473 ctxt->ctxtType = ctxtType;
12474 return (type);
12477 /************************************************************************
12479 * Validating using Schemas *
12481 ************************************************************************/
12483 /************************************************************************
12485 * Reading/Writing Schemas *
12487 ************************************************************************/
12489 #if 0 /* Will be enabled if it is clear what options are needed. */
12491 * xmlSchemaParserCtxtSetOptions:
12492 * @ctxt: a schema parser context
12493 * @options: a combination of xmlSchemaParserOption
12495 * Sets the options to be used during the parse.
12497 * Returns 0 in case of success, -1 in case of an
12498 * API error.
12500 static int
12501 xmlSchemaParserCtxtSetOptions(xmlSchemaParserCtxtPtr ctxt,
12502 int options)
12505 int i;
12507 if (ctxt == NULL)
12508 return (-1);
12510 * WARNING: Change the start value if adding to the
12511 * xmlSchemaParseOption.
12513 for (i = 1; i < (int) sizeof(int) * 8; i++) {
12514 if (options & 1<<i) {
12515 return (-1);
12518 ctxt->options = options;
12519 return (0);
12523 * xmlSchemaValidCtxtGetOptions:
12524 * @ctxt: a schema parser context
12526 * Returns the option combination of the parser context.
12528 static int
12529 xmlSchemaParserCtxtGetOptions(xmlSchemaParserCtxtPtr ctxt)
12532 if (ctxt == NULL)
12533 return (-1);
12534 else
12535 return (ctxt->options);
12537 #endif
12540 * xmlSchemaNewParserCtxt:
12541 * @URL: the location of the schema
12543 * Create an XML Schemas parse context for that file/resource expected
12544 * to contain an XML Schemas file.
12546 * Returns the parser context or NULL in case of error
12548 xmlSchemaParserCtxtPtr
12549 xmlSchemaNewParserCtxt(const char *URL)
12551 xmlSchemaParserCtxtPtr ret;
12553 if (URL == NULL)
12554 return (NULL);
12556 ret = xmlSchemaParserCtxtCreate();
12557 if (ret == NULL)
12558 return(NULL);
12559 ret->dict = xmlDictCreate();
12560 ret->URL = xmlDictLookup(ret->dict, (const xmlChar *) URL, -1);
12561 return (ret);
12565 * xmlSchemaNewMemParserCtxt:
12566 * @buffer: a pointer to a char array containing the schemas
12567 * @size: the size of the array
12569 * Create an XML Schemas parse context for that memory buffer expected
12570 * to contain an XML Schemas file.
12572 * Returns the parser context or NULL in case of error
12574 xmlSchemaParserCtxtPtr
12575 xmlSchemaNewMemParserCtxt(const char *buffer, int size)
12577 xmlSchemaParserCtxtPtr ret;
12579 if ((buffer == NULL) || (size <= 0))
12580 return (NULL);
12581 ret = xmlSchemaParserCtxtCreate();
12582 if (ret == NULL)
12583 return(NULL);
12584 ret->buffer = buffer;
12585 ret->size = size;
12586 ret->dict = xmlDictCreate();
12587 return (ret);
12591 * xmlSchemaNewDocParserCtxt:
12592 * @doc: a preparsed document tree
12594 * Create an XML Schemas parse context for that document.
12595 * NB. The document may be modified during the parsing process.
12597 * Returns the parser context or NULL in case of error
12599 xmlSchemaParserCtxtPtr
12600 xmlSchemaNewDocParserCtxt(xmlDocPtr doc)
12602 xmlSchemaParserCtxtPtr ret;
12604 if (doc == NULL)
12605 return (NULL);
12606 ret = xmlSchemaParserCtxtCreate();
12607 if (ret == NULL)
12608 return(NULL);
12609 ret->doc = doc;
12610 ret->dict = xmlDictCreate();
12611 /* The application has responsibility for the document */
12612 ret->preserve = 1;
12614 return (ret);
12618 * xmlSchemaFreeParserCtxt:
12619 * @ctxt: the schema parser context
12621 * Free the resources associated to the schema parser context
12623 void
12624 xmlSchemaFreeParserCtxt(xmlSchemaParserCtxtPtr ctxt)
12626 if (ctxt == NULL)
12627 return;
12628 if (ctxt->doc != NULL && !ctxt->preserve)
12629 xmlFreeDoc(ctxt->doc);
12630 if (ctxt->vctxt != NULL) {
12631 xmlSchemaFreeValidCtxt(ctxt->vctxt);
12633 if (ctxt->ownsConstructor && (ctxt->constructor != NULL)) {
12634 xmlSchemaConstructionCtxtFree(ctxt->constructor);
12635 ctxt->constructor = NULL;
12636 ctxt->ownsConstructor = 0;
12638 if (ctxt->attrProhibs != NULL)
12639 xmlSchemaItemListFree(ctxt->attrProhibs);
12640 xmlDictFree(ctxt->dict);
12641 xmlFree(ctxt);
12644 /************************************************************************
12646 * Building the content models *
12648 ************************************************************************/
12651 * xmlSchemaBuildContentModelForSubstGroup:
12653 * Returns 1 if nillable, 0 otherwise
12655 static int
12656 xmlSchemaBuildContentModelForSubstGroup(xmlSchemaParserCtxtPtr pctxt,
12657 xmlSchemaParticlePtr particle, int counter, xmlAutomataStatePtr end)
12659 xmlAutomataStatePtr start, tmp;
12660 xmlSchemaElementPtr elemDecl, member;
12661 xmlSchemaSubstGroupPtr substGroup;
12662 int i;
12663 int ret = 0;
12665 elemDecl = (xmlSchemaElementPtr) particle->children;
12667 * Wrap the substitution group with a CHOICE.
12669 start = pctxt->state;
12670 if (end == NULL)
12671 end = xmlAutomataNewState(pctxt->am);
12672 substGroup = xmlSchemaSubstGroupGet(pctxt, elemDecl);
12673 if (substGroup == NULL) {
12674 xmlSchemaPErr(pctxt, WXS_ITEM_NODE(particle),
12675 XML_SCHEMAP_INTERNAL,
12676 "Internal error: xmlSchemaBuildContentModelForSubstGroup, "
12677 "declaration is marked having a subst. group but none "
12678 "available.\n", elemDecl->name, NULL);
12679 return(0);
12681 if (counter >= 0) {
12683 * NOTE that we put the declaration in, even if it's abstract.
12684 * However, an error will be raised during *validation* if an element
12685 * information item shall be validated against an abstract element
12686 * declaration.
12688 tmp = xmlAutomataNewCountedTrans(pctxt->am, start, NULL, counter);
12689 xmlAutomataNewTransition2(pctxt->am, tmp, end,
12690 elemDecl->name, elemDecl->targetNamespace, elemDecl);
12692 * Add subst. group members.
12694 for (i = 0; i < substGroup->members->nbItems; i++) {
12695 member = (xmlSchemaElementPtr) substGroup->members->items[i];
12696 xmlAutomataNewTransition2(pctxt->am, tmp, end,
12697 member->name, member->targetNamespace, member);
12699 } else if (particle->maxOccurs == 1) {
12701 * NOTE that we put the declaration in, even if it's abstract,
12703 xmlAutomataNewEpsilon(pctxt->am,
12704 xmlAutomataNewTransition2(pctxt->am,
12705 start, NULL,
12706 elemDecl->name, elemDecl->targetNamespace, elemDecl), end);
12708 * Add subst. group members.
12710 for (i = 0; i < substGroup->members->nbItems; i++) {
12711 member = (xmlSchemaElementPtr) substGroup->members->items[i];
12713 * NOTE: This fixes bug #341150. xmlAutomataNewOnceTrans2()
12714 * was incorrectly used instead of xmlAutomataNewTransition2()
12715 * (seems like a copy&paste bug from the XML_SCHEMA_TYPE_ALL
12716 * section in xmlSchemaBuildAContentModel() ).
12717 * TODO: Check if xmlAutomataNewOnceTrans2() was instead
12718 * intended for the above "counter" section originally. I.e.,
12719 * check xs:all with subst-groups.
12721 * tmp = xmlAutomataNewOnceTrans2(pctxt->am, start, NULL,
12722 * member->name, member->targetNamespace,
12723 * 1, 1, member);
12725 tmp = xmlAutomataNewTransition2(pctxt->am, start, NULL,
12726 member->name, member->targetNamespace, member);
12727 xmlAutomataNewEpsilon(pctxt->am, tmp, end);
12729 } else {
12730 xmlAutomataStatePtr hop;
12731 int maxOccurs = particle->maxOccurs == UNBOUNDED ?
12732 UNBOUNDED : particle->maxOccurs - 1;
12733 int minOccurs = particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
12735 counter =
12736 xmlAutomataNewCounter(pctxt->am, minOccurs,
12737 maxOccurs);
12738 hop = xmlAutomataNewState(pctxt->am);
12740 xmlAutomataNewEpsilon(pctxt->am,
12741 xmlAutomataNewTransition2(pctxt->am,
12742 start, NULL,
12743 elemDecl->name, elemDecl->targetNamespace, elemDecl),
12744 hop);
12746 * Add subst. group members.
12748 for (i = 0; i < substGroup->members->nbItems; i++) {
12749 member = (xmlSchemaElementPtr) substGroup->members->items[i];
12750 xmlAutomataNewEpsilon(pctxt->am,
12751 xmlAutomataNewTransition2(pctxt->am,
12752 start, NULL,
12753 member->name, member->targetNamespace, member),
12754 hop);
12756 xmlAutomataNewCountedTrans(pctxt->am, hop, start, counter);
12757 xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
12759 if (particle->minOccurs == 0) {
12760 xmlAutomataNewEpsilon(pctxt->am, start, end);
12761 ret = 1;
12763 pctxt->state = end;
12764 return(ret);
12768 * xmlSchemaBuildContentModelForElement:
12770 * Returns 1 if nillable, 0 otherwise
12772 static int
12773 xmlSchemaBuildContentModelForElement(xmlSchemaParserCtxtPtr ctxt,
12774 xmlSchemaParticlePtr particle)
12776 int ret = 0;
12778 if (((xmlSchemaElementPtr) particle->children)->flags &
12779 XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) {
12781 * Substitution groups.
12783 ret = xmlSchemaBuildContentModelForSubstGroup(ctxt, particle, -1, NULL);
12784 } else {
12785 xmlSchemaElementPtr elemDecl;
12786 xmlAutomataStatePtr start;
12788 elemDecl = (xmlSchemaElementPtr) particle->children;
12790 if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT)
12791 return(0);
12792 if (particle->maxOccurs == 1) {
12793 start = ctxt->state;
12794 ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
12795 elemDecl->name, elemDecl->targetNamespace, elemDecl);
12796 } else if ((particle->maxOccurs >= UNBOUNDED) &&
12797 (particle->minOccurs < 2)) {
12798 /* Special case. */
12799 start = ctxt->state;
12800 ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
12801 elemDecl->name, elemDecl->targetNamespace, elemDecl);
12802 ctxt->state = xmlAutomataNewTransition2(ctxt->am, ctxt->state, ctxt->state,
12803 elemDecl->name, elemDecl->targetNamespace, elemDecl);
12804 } else {
12805 int counter;
12806 int maxOccurs = particle->maxOccurs == UNBOUNDED ?
12807 UNBOUNDED : particle->maxOccurs - 1;
12808 int minOccurs = particle->minOccurs < 1 ?
12809 0 : particle->minOccurs - 1;
12811 start = xmlAutomataNewEpsilon(ctxt->am, ctxt->state, NULL);
12812 counter = xmlAutomataNewCounter(ctxt->am, minOccurs, maxOccurs);
12813 ctxt->state = xmlAutomataNewTransition2(ctxt->am, start, NULL,
12814 elemDecl->name, elemDecl->targetNamespace, elemDecl);
12815 xmlAutomataNewCountedTrans(ctxt->am, ctxt->state, start, counter);
12816 ctxt->state = xmlAutomataNewCounterTrans(ctxt->am, ctxt->state,
12817 NULL, counter);
12819 if (particle->minOccurs == 0) {
12820 xmlAutomataNewEpsilon(ctxt->am, start, ctxt->state);
12821 ret = 1;
12824 return(ret);
12828 * xmlSchemaBuildAContentModel:
12829 * @ctxt: the schema parser context
12830 * @particle: the particle component
12831 * @name: the complex type's name whose content is being built
12833 * Create the automaton for the {content type} of a complex type.
12835 * Returns 1 if the content is nillable, 0 otherwise
12837 static int
12838 xmlSchemaBuildAContentModel(xmlSchemaParserCtxtPtr pctxt,
12839 xmlSchemaParticlePtr particle)
12841 int ret = 0, tmp2;
12843 if (particle == NULL) {
12844 PERROR_INT("xmlSchemaBuildAContentModel", "particle is NULL");
12845 return(1);
12847 if (particle->children == NULL) {
12849 * Just return in this case. A missing "term" of the particle
12850 * might arise due to an invalid "term" component.
12852 return(1);
12855 switch (particle->children->type) {
12856 case XML_SCHEMA_TYPE_ANY: {
12857 xmlAutomataStatePtr start, end;
12858 xmlSchemaWildcardPtr wild;
12859 xmlSchemaWildcardNsPtr ns;
12861 wild = (xmlSchemaWildcardPtr) particle->children;
12863 start = pctxt->state;
12864 end = xmlAutomataNewState(pctxt->am);
12866 if (particle->maxOccurs == 1) {
12867 if (wild->any == 1) {
12869 * We need to add both transitions:
12871 * 1. the {"*", "*"} for elements in a namespace.
12873 pctxt->state =
12874 xmlAutomataNewTransition2(pctxt->am,
12875 start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
12876 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
12878 * 2. the {"*"} for elements in no namespace.
12880 pctxt->state =
12881 xmlAutomataNewTransition2(pctxt->am,
12882 start, NULL, BAD_CAST "*", NULL, wild);
12883 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
12885 } else if (wild->nsSet != NULL) {
12886 ns = wild->nsSet;
12887 do {
12888 pctxt->state = start;
12889 pctxt->state = xmlAutomataNewTransition2(pctxt->am,
12890 pctxt->state, NULL, BAD_CAST "*", ns->value, wild);
12891 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
12892 ns = ns->next;
12893 } while (ns != NULL);
12895 } else if (wild->negNsSet != NULL) {
12896 pctxt->state = xmlAutomataNewNegTrans(pctxt->am,
12897 start, end, BAD_CAST "*", wild->negNsSet->value,
12898 wild);
12900 } else {
12901 int counter;
12902 xmlAutomataStatePtr hop;
12903 int maxOccurs =
12904 particle->maxOccurs == UNBOUNDED ? UNBOUNDED :
12905 particle->maxOccurs - 1;
12906 int minOccurs =
12907 particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
12909 counter = xmlAutomataNewCounter(pctxt->am, minOccurs, maxOccurs);
12910 hop = xmlAutomataNewState(pctxt->am);
12911 if (wild->any == 1) {
12912 pctxt->state =
12913 xmlAutomataNewTransition2(pctxt->am,
12914 start, NULL, BAD_CAST "*", BAD_CAST "*", wild);
12915 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
12916 pctxt->state =
12917 xmlAutomataNewTransition2(pctxt->am,
12918 start, NULL, BAD_CAST "*", NULL, wild);
12919 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
12920 } else if (wild->nsSet != NULL) {
12921 ns = wild->nsSet;
12922 do {
12923 pctxt->state =
12924 xmlAutomataNewTransition2(pctxt->am,
12925 start, NULL, BAD_CAST "*", ns->value, wild);
12926 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
12927 ns = ns->next;
12928 } while (ns != NULL);
12930 } else if (wild->negNsSet != NULL) {
12931 pctxt->state = xmlAutomataNewNegTrans(pctxt->am,
12932 start, hop, BAD_CAST "*", wild->negNsSet->value,
12933 wild);
12935 xmlAutomataNewCountedTrans(pctxt->am, hop, start, counter);
12936 xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
12938 if (particle->minOccurs == 0) {
12939 xmlAutomataNewEpsilon(pctxt->am, start, end);
12940 ret = 1;
12942 pctxt->state = end;
12943 break;
12945 case XML_SCHEMA_TYPE_ELEMENT:
12946 ret = xmlSchemaBuildContentModelForElement(pctxt, particle);
12947 break;
12948 case XML_SCHEMA_TYPE_SEQUENCE:{
12949 xmlSchemaTreeItemPtr sub;
12951 ret = 1;
12953 * If max and min occurrences are default (1) then
12954 * simply iterate over the particles of the <sequence>.
12956 if ((particle->minOccurs == 1) && (particle->maxOccurs == 1)) {
12957 sub = particle->children->children;
12959 while (sub != NULL) {
12960 tmp2 = xmlSchemaBuildAContentModel(pctxt,
12961 (xmlSchemaParticlePtr) sub);
12962 if (tmp2 != 1) ret = 0;
12963 sub = sub->next;
12965 } else {
12966 xmlAutomataStatePtr oldstate = pctxt->state;
12968 if (particle->maxOccurs >= UNBOUNDED) {
12969 if (particle->minOccurs > 1) {
12970 xmlAutomataStatePtr tmp;
12971 int counter;
12973 pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
12974 oldstate, NULL);
12975 oldstate = pctxt->state;
12977 counter = xmlAutomataNewCounter(pctxt->am,
12978 particle->minOccurs - 1, UNBOUNDED);
12980 sub = particle->children->children;
12981 while (sub != NULL) {
12982 tmp2 = xmlSchemaBuildAContentModel(pctxt,
12983 (xmlSchemaParticlePtr) sub);
12984 if (tmp2 != 1) ret = 0;
12985 sub = sub->next;
12987 tmp = pctxt->state;
12988 xmlAutomataNewCountedTrans(pctxt->am, tmp,
12989 oldstate, counter);
12990 pctxt->state =
12991 xmlAutomataNewCounterTrans(pctxt->am, tmp,
12992 NULL, counter);
12993 if (ret == 1)
12994 xmlAutomataNewEpsilon(pctxt->am,
12995 oldstate, pctxt->state);
12997 } else {
12998 pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
12999 oldstate, NULL);
13000 oldstate = pctxt->state;
13002 sub = particle->children->children;
13003 while (sub != NULL) {
13004 tmp2 = xmlSchemaBuildAContentModel(pctxt,
13005 (xmlSchemaParticlePtr) sub);
13006 if (tmp2 != 1) ret = 0;
13007 sub = sub->next;
13009 xmlAutomataNewEpsilon(pctxt->am, pctxt->state,
13010 oldstate);
13012 * epsilon needed to block previous trans from
13013 * being allowed to enter back from another
13014 * construct
13016 pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
13017 pctxt->state, NULL);
13018 if (particle->minOccurs == 0) {
13019 xmlAutomataNewEpsilon(pctxt->am,
13020 oldstate, pctxt->state);
13021 ret = 1;
13024 } else if ((particle->maxOccurs > 1)
13025 || (particle->minOccurs > 1)) {
13026 xmlAutomataStatePtr tmp;
13027 int counter;
13029 pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
13030 oldstate, NULL);
13031 oldstate = pctxt->state;
13033 counter = xmlAutomataNewCounter(pctxt->am,
13034 particle->minOccurs - 1,
13035 particle->maxOccurs - 1);
13037 sub = particle->children->children;
13038 while (sub != NULL) {
13039 tmp2 = xmlSchemaBuildAContentModel(pctxt,
13040 (xmlSchemaParticlePtr) sub);
13041 if (tmp2 != 1) ret = 0;
13042 sub = sub->next;
13044 tmp = pctxt->state;
13045 xmlAutomataNewCountedTrans(pctxt->am,
13046 tmp, oldstate, counter);
13047 pctxt->state =
13048 xmlAutomataNewCounterTrans(pctxt->am, tmp, NULL,
13049 counter);
13050 if ((particle->minOccurs == 0) || (ret == 1)) {
13051 xmlAutomataNewEpsilon(pctxt->am,
13052 oldstate, pctxt->state);
13053 ret = 1;
13055 } else {
13056 sub = particle->children->children;
13057 while (sub != NULL) {
13058 tmp2 = xmlSchemaBuildAContentModel(pctxt,
13059 (xmlSchemaParticlePtr) sub);
13060 if (tmp2 != 1) ret = 0;
13061 sub = sub->next;
13065 * epsilon needed to block previous trans from
13066 * being allowed to enter back from another
13067 * construct
13069 pctxt->state = xmlAutomataNewEpsilon(pctxt->am,
13070 pctxt->state, NULL);
13072 if (particle->minOccurs == 0) {
13073 xmlAutomataNewEpsilon(pctxt->am, oldstate,
13074 pctxt->state);
13075 ret = 1;
13079 break;
13081 case XML_SCHEMA_TYPE_CHOICE:{
13082 xmlSchemaTreeItemPtr sub;
13083 xmlAutomataStatePtr start, end;
13085 ret = 0;
13086 start = pctxt->state;
13087 end = xmlAutomataNewState(pctxt->am);
13090 * iterate over the subtypes and remerge the end with an
13091 * epsilon transition
13093 if (particle->maxOccurs == 1) {
13094 sub = particle->children->children;
13095 while (sub != NULL) {
13096 pctxt->state = start;
13097 tmp2 = xmlSchemaBuildAContentModel(pctxt,
13098 (xmlSchemaParticlePtr) sub);
13099 if (tmp2 == 1) ret = 1;
13100 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, end);
13101 sub = sub->next;
13103 } else {
13104 int counter;
13105 xmlAutomataStatePtr hop, base;
13106 int maxOccurs = particle->maxOccurs == UNBOUNDED ?
13107 UNBOUNDED : particle->maxOccurs - 1;
13108 int minOccurs =
13109 particle->minOccurs < 1 ? 0 : particle->minOccurs - 1;
13112 * use a counter to keep track of the number of transitions
13113 * which went through the choice.
13115 counter =
13116 xmlAutomataNewCounter(pctxt->am, minOccurs, maxOccurs);
13117 hop = xmlAutomataNewState(pctxt->am);
13118 base = xmlAutomataNewState(pctxt->am);
13120 sub = particle->children->children;
13121 while (sub != NULL) {
13122 pctxt->state = base;
13123 tmp2 = xmlSchemaBuildAContentModel(pctxt,
13124 (xmlSchemaParticlePtr) sub);
13125 if (tmp2 == 1) ret = 1;
13126 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, hop);
13127 sub = sub->next;
13129 xmlAutomataNewEpsilon(pctxt->am, start, base);
13130 xmlAutomataNewCountedTrans(pctxt->am, hop, base, counter);
13131 xmlAutomataNewCounterTrans(pctxt->am, hop, end, counter);
13132 if (ret == 1)
13133 xmlAutomataNewEpsilon(pctxt->am, base, end);
13135 if (particle->minOccurs == 0) {
13136 xmlAutomataNewEpsilon(pctxt->am, start, end);
13137 ret = 1;
13139 pctxt->state = end;
13140 break;
13142 case XML_SCHEMA_TYPE_ALL:{
13143 xmlAutomataStatePtr start, tmp;
13144 xmlSchemaParticlePtr sub;
13145 xmlSchemaElementPtr elemDecl;
13147 ret = 1;
13149 sub = (xmlSchemaParticlePtr) particle->children->children;
13150 if (sub == NULL)
13151 break;
13153 ret = 0;
13155 start = pctxt->state;
13156 tmp = xmlAutomataNewState(pctxt->am);
13157 xmlAutomataNewEpsilon(pctxt->am, pctxt->state, tmp);
13158 pctxt->state = tmp;
13159 while (sub != NULL) {
13160 pctxt->state = tmp;
13162 elemDecl = (xmlSchemaElementPtr) sub->children;
13163 if (elemDecl == NULL) {
13164 PERROR_INT("xmlSchemaBuildAContentModel",
13165 "<element> particle has no term");
13166 return(ret);
13169 * NOTE: The {max occurs} of all the particles in the
13170 * {particles} of the group must be 0 or 1; this is
13171 * already ensured during the parse of the content of
13172 * <all>.
13174 if (elemDecl->flags & XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) {
13175 int counter;
13178 * This is an abstract group, we need to share
13179 * the same counter for all the element transitions
13180 * derived from the group
13182 counter = xmlAutomataNewCounter(pctxt->am,
13183 sub->minOccurs, sub->maxOccurs);
13184 xmlSchemaBuildContentModelForSubstGroup(pctxt,
13185 sub, counter, pctxt->state);
13186 } else {
13187 if ((sub->minOccurs == 1) &&
13188 (sub->maxOccurs == 1)) {
13189 xmlAutomataNewOnceTrans2(pctxt->am, pctxt->state,
13190 pctxt->state,
13191 elemDecl->name,
13192 elemDecl->targetNamespace,
13193 1, 1, elemDecl);
13194 } else if ((sub->minOccurs == 0) &&
13195 (sub->maxOccurs == 1)) {
13197 xmlAutomataNewCountTrans2(pctxt->am, pctxt->state,
13198 pctxt->state,
13199 elemDecl->name,
13200 elemDecl->targetNamespace,
13203 elemDecl);
13206 sub = (xmlSchemaParticlePtr) sub->next;
13208 pctxt->state =
13209 xmlAutomataNewAllTrans(pctxt->am, pctxt->state, NULL, 0);
13210 if (particle->minOccurs == 0) {
13211 xmlAutomataNewEpsilon(pctxt->am, start, pctxt->state);
13212 ret = 1;
13214 break;
13216 case XML_SCHEMA_TYPE_GROUP:
13218 * If we hit a model group definition, then this means that
13219 * it was empty, thus was not substituted for the containing
13220 * model group. Just do nothing in this case.
13221 * TODO: But the group should be substituted and not occur at
13222 * all in the content model at this point. Fix this.
13224 ret = 1;
13225 break;
13226 default:
13227 xmlSchemaInternalErr2(ACTXT_CAST pctxt,
13228 "xmlSchemaBuildAContentModel",
13229 "found unexpected term of type '%s' in content model",
13230 WXS_ITEM_TYPE_NAME(particle->children), NULL);
13231 return(ret);
13233 return(ret);
13237 * xmlSchemaBuildContentModel:
13238 * @ctxt: the schema parser context
13239 * @type: the complex type definition
13240 * @name: the element name
13242 * Builds the content model of the complex type.
13244 static void
13245 xmlSchemaBuildContentModel(xmlSchemaTypePtr type,
13246 xmlSchemaParserCtxtPtr ctxt)
13248 if ((type->type != XML_SCHEMA_TYPE_COMPLEX) ||
13249 (type->contModel != NULL) ||
13250 ((type->contentType != XML_SCHEMA_CONTENT_ELEMENTS) &&
13251 (type->contentType != XML_SCHEMA_CONTENT_MIXED)))
13252 return;
13254 #ifdef DEBUG_CONTENT
13255 xmlGenericError(xmlGenericErrorContext,
13256 "Building content model for %s\n", name);
13257 #endif
13258 ctxt->am = NULL;
13259 ctxt->am = xmlNewAutomata();
13260 if (ctxt->am == NULL) {
13261 xmlGenericError(xmlGenericErrorContext,
13262 "Cannot create automata for complex type %s\n", type->name);
13263 return;
13265 ctxt->state = xmlAutomataGetInitState(ctxt->am);
13267 * Build the automaton.
13269 xmlSchemaBuildAContentModel(ctxt, WXS_TYPE_PARTICLE(type));
13270 xmlAutomataSetFinalState(ctxt->am, ctxt->state);
13271 type->contModel = xmlAutomataCompile(ctxt->am);
13272 if (type->contModel == NULL) {
13273 xmlSchemaPCustomErr(ctxt,
13274 XML_SCHEMAP_INTERNAL,
13275 WXS_BASIC_CAST type, type->node,
13276 "Failed to compile the content model", NULL);
13277 } else if (xmlRegexpIsDeterminist(type->contModel) != 1) {
13278 xmlSchemaPCustomErr(ctxt,
13279 XML_SCHEMAP_NOT_DETERMINISTIC,
13280 /* XML_SCHEMAS_ERR_NOTDETERMINIST, */
13281 WXS_BASIC_CAST type, type->node,
13282 "The content model is not determinist", NULL);
13283 } else {
13284 #ifdef DEBUG_CONTENT_REGEXP
13285 xmlGenericError(xmlGenericErrorContext,
13286 "Content model of %s:\n", type->name);
13287 xmlRegexpPrint(stderr, type->contModel);
13288 #endif
13290 ctxt->state = NULL;
13291 xmlFreeAutomata(ctxt->am);
13292 ctxt->am = NULL;
13296 * xmlSchemaResolveElementReferences:
13297 * @elem: the schema element context
13298 * @ctxt: the schema parser context
13300 * Resolves the references of an element declaration
13301 * or particle, which has an element declaration as it's
13302 * term.
13304 static void
13305 xmlSchemaResolveElementReferences(xmlSchemaElementPtr elemDecl,
13306 xmlSchemaParserCtxtPtr ctxt)
13308 if ((ctxt == NULL) || (elemDecl == NULL) ||
13309 ((elemDecl != NULL) &&
13310 (elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_RESOLVED)))
13311 return;
13312 elemDecl->flags |= XML_SCHEMAS_ELEM_INTERNAL_RESOLVED;
13314 if ((elemDecl->subtypes == NULL) && (elemDecl->namedType != NULL)) {
13315 xmlSchemaTypePtr type;
13317 /* (type definition) ... otherwise the type definition `resolved`
13318 * to by the `actual value` of the type [attribute] ...
13320 type = xmlSchemaGetType(ctxt->schema, elemDecl->namedType,
13321 elemDecl->namedTypeNs);
13322 if (type == NULL) {
13323 xmlSchemaPResCompAttrErr(ctxt,
13324 XML_SCHEMAP_SRC_RESOLVE,
13325 WXS_BASIC_CAST elemDecl, elemDecl->node,
13326 "type", elemDecl->namedType, elemDecl->namedTypeNs,
13327 XML_SCHEMA_TYPE_BASIC, "type definition");
13328 } else
13329 elemDecl->subtypes = type;
13331 if (elemDecl->substGroup != NULL) {
13332 xmlSchemaElementPtr substHead;
13335 * FIXME TODO: Do we need a new field in _xmlSchemaElement for
13336 * substitutionGroup?
13338 substHead = xmlSchemaGetElem(ctxt->schema, elemDecl->substGroup,
13339 elemDecl->substGroupNs);
13340 if (substHead == NULL) {
13341 xmlSchemaPResCompAttrErr(ctxt,
13342 XML_SCHEMAP_SRC_RESOLVE,
13343 WXS_BASIC_CAST elemDecl, NULL,
13344 "substitutionGroup", elemDecl->substGroup,
13345 elemDecl->substGroupNs, XML_SCHEMA_TYPE_ELEMENT, NULL);
13346 } else {
13347 xmlSchemaResolveElementReferences(substHead, ctxt);
13349 * Set the "substitution group affiliation".
13350 * NOTE that now we use the "refDecl" field for this.
13352 WXS_SUBST_HEAD(elemDecl) = substHead;
13354 * The type definitions is set to:
13355 * SPEC "...the {type definition} of the element
13356 * declaration `resolved` to by the `actual value`
13357 * of the substitutionGroup [attribute], if present"
13359 if (elemDecl->subtypes == NULL) {
13360 if (substHead->subtypes == NULL) {
13362 * This can happen with self-referencing substitution
13363 * groups. The cycle will be detected later, but we have
13364 * to set subtypes to avoid null-pointer dereferences.
13366 elemDecl->subtypes = xmlSchemaGetBuiltInType(
13367 XML_SCHEMAS_ANYTYPE);
13368 } else {
13369 elemDecl->subtypes = substHead->subtypes;
13375 * SPEC "The definition of anyType serves as the default type definition
13376 * for element declarations whose XML representation does not specify one."
13378 if ((elemDecl->subtypes == NULL) &&
13379 (elemDecl->namedType == NULL) &&
13380 (elemDecl->substGroup == NULL))
13381 elemDecl->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
13385 * xmlSchemaResolveUnionMemberTypes:
13386 * @ctxt: the schema parser context
13387 * @type: the schema simple type definition
13389 * Checks and builds the "member type definitions" property of the union
13390 * simple type. This handles part (1), part (2) is done in
13391 * xmlSchemaFinishMemberTypeDefinitionsProperty()
13393 * Returns -1 in case of an internal error, 0 otherwise.
13395 static int
13396 xmlSchemaResolveUnionMemberTypes(xmlSchemaParserCtxtPtr ctxt,
13397 xmlSchemaTypePtr type)
13400 xmlSchemaTypeLinkPtr link, lastLink, newLink;
13401 xmlSchemaTypePtr memberType;
13404 * SPEC (1) "If the <union> alternative is chosen, then [Definition:]
13405 * define the explicit members as the type definitions `resolved`
13406 * to by the items in the `actual value` of the memberTypes [attribute],
13407 * if any, followed by the type definitions corresponding to the
13408 * <simpleType>s among the [children] of <union>, if any."
13411 * Resolve references.
13413 link = type->memberTypes;
13414 lastLink = NULL;
13415 while (link != NULL) {
13416 const xmlChar *name, *nsName;
13418 name = ((xmlSchemaQNameRefPtr) link->type)->name;
13419 nsName = ((xmlSchemaQNameRefPtr) link->type)->targetNamespace;
13421 memberType = xmlSchemaGetType(ctxt->schema, name, nsName);
13422 if ((memberType == NULL) || (! WXS_IS_SIMPLE(memberType))) {
13423 xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
13424 WXS_BASIC_CAST type, type->node, "memberTypes",
13425 name, nsName, XML_SCHEMA_TYPE_SIMPLE, NULL);
13427 * Remove the member type link.
13429 if (lastLink == NULL)
13430 type->memberTypes = link->next;
13431 else
13432 lastLink->next = link->next;
13433 newLink = link;
13434 link = link->next;
13435 xmlFree(newLink);
13436 } else {
13437 link->type = memberType;
13438 lastLink = link;
13439 link = link->next;
13443 * Add local simple types,
13445 memberType = type->subtypes;
13446 while (memberType != NULL) {
13447 link = (xmlSchemaTypeLinkPtr) xmlMalloc(sizeof(xmlSchemaTypeLink));
13448 if (link == NULL) {
13449 xmlSchemaPErrMemory(ctxt, "allocating a type link", NULL);
13450 return (-1);
13452 link->type = memberType;
13453 link->next = NULL;
13454 if (lastLink == NULL)
13455 type->memberTypes = link;
13456 else
13457 lastLink->next = link;
13458 lastLink = link;
13459 memberType = memberType->next;
13461 return (0);
13465 * xmlSchemaIsDerivedFromBuiltInType:
13466 * @ctxt: the schema parser context
13467 * @type: the type definition
13468 * @valType: the value type
13471 * Returns 1 if the type has the given value type, or
13472 * is derived from such a type.
13474 static int
13475 xmlSchemaIsDerivedFromBuiltInType(xmlSchemaTypePtr type, int valType)
13477 if (type == NULL)
13478 return (0);
13479 if (WXS_IS_COMPLEX(type))
13480 return (0);
13481 if (type->type == XML_SCHEMA_TYPE_BASIC) {
13482 if (type->builtInType == valType)
13483 return(1);
13484 if ((type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) ||
13485 (type->builtInType == XML_SCHEMAS_ANYTYPE))
13486 return (0);
13487 return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
13489 return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
13492 #if 0
13494 * xmlSchemaIsDerivedFromBuiltInType:
13495 * @ctxt: the schema parser context
13496 * @type: the type definition
13497 * @valType: the value type
13500 * Returns 1 if the type has the given value type, or
13501 * is derived from such a type.
13503 static int
13504 xmlSchemaIsUserDerivedFromBuiltInType(xmlSchemaTypePtr type, int valType)
13506 if (type == NULL)
13507 return (0);
13508 if (WXS_IS_COMPLEX(type))
13509 return (0);
13510 if (type->type == XML_SCHEMA_TYPE_BASIC) {
13511 if (type->builtInType == valType)
13512 return(1);
13513 return (0);
13514 } else
13515 return(xmlSchemaIsDerivedFromBuiltInType(type->subtypes, valType));
13517 return (0);
13520 static xmlSchemaTypePtr
13521 xmlSchemaQueryBuiltInType(xmlSchemaTypePtr type)
13523 if (type == NULL)
13524 return (NULL);
13525 if (WXS_IS_COMPLEX(type))
13526 return (NULL);
13527 if (type->type == XML_SCHEMA_TYPE_BASIC)
13528 return(type);
13529 return(xmlSchemaQueryBuiltInType(type->subtypes));
13531 #endif
13534 * xmlSchemaGetPrimitiveType:
13535 * @type: the simpleType definition
13537 * Returns the primitive type of the given type or
13538 * NULL in case of error.
13540 static xmlSchemaTypePtr
13541 xmlSchemaGetPrimitiveType(xmlSchemaTypePtr type)
13544 while (type != NULL) {
13546 * Note that anySimpleType is actually not a primitive type
13547 * but we need that here.
13549 if ((type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) ||
13550 (type->flags & XML_SCHEMAS_TYPE_BUILTIN_PRIMITIVE))
13551 return (type);
13552 type = type->baseType;
13555 return (NULL);
13558 #if 0
13560 * xmlSchemaGetBuiltInTypeAncestor:
13561 * @type: the simpleType definition
13563 * Returns the primitive type of the given type or
13564 * NULL in case of error.
13566 static xmlSchemaTypePtr
13567 xmlSchemaGetBuiltInTypeAncestor(xmlSchemaTypePtr type)
13569 if (WXS_IS_LIST(type) || WXS_IS_UNION(type))
13570 return (0);
13571 while (type != NULL) {
13572 if (type->type == XML_SCHEMA_TYPE_BASIC)
13573 return (type);
13574 type = type->baseType;
13577 return (NULL);
13579 #endif
13582 * xmlSchemaCloneWildcardNsConstraints:
13583 * @ctxt: the schema parser context
13584 * @dest: the destination wildcard
13585 * @source: the source wildcard
13587 * Clones the namespace constraints of source
13588 * and assigns them to dest.
13589 * Returns -1 on internal error, 0 otherwise.
13591 static int
13592 xmlSchemaCloneWildcardNsConstraints(xmlSchemaParserCtxtPtr ctxt,
13593 xmlSchemaWildcardPtr dest,
13594 xmlSchemaWildcardPtr source)
13596 xmlSchemaWildcardNsPtr cur, tmp, last;
13598 if ((source == NULL) || (dest == NULL))
13599 return(-1);
13600 dest->any = source->any;
13601 cur = source->nsSet;
13602 last = NULL;
13603 while (cur != NULL) {
13604 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
13605 if (tmp == NULL)
13606 return(-1);
13607 tmp->value = cur->value;
13608 if (last == NULL)
13609 dest->nsSet = tmp;
13610 else
13611 last->next = tmp;
13612 last = tmp;
13613 cur = cur->next;
13615 if (dest->negNsSet != NULL)
13616 xmlSchemaFreeWildcardNsSet(dest->negNsSet);
13617 if (source->negNsSet != NULL) {
13618 dest->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13619 if (dest->negNsSet == NULL)
13620 return(-1);
13621 dest->negNsSet->value = source->negNsSet->value;
13622 } else
13623 dest->negNsSet = NULL;
13624 return(0);
13628 * xmlSchemaUnionWildcards:
13629 * @ctxt: the schema parser context
13630 * @completeWild: the first wildcard
13631 * @curWild: the second wildcard
13633 * Unions the namespace constraints of the given wildcards.
13634 * @completeWild will hold the resulting union.
13635 * Returns a positive error code on failure, -1 in case of an
13636 * internal error, 0 otherwise.
13638 static int
13639 xmlSchemaUnionWildcards(xmlSchemaParserCtxtPtr ctxt,
13640 xmlSchemaWildcardPtr completeWild,
13641 xmlSchemaWildcardPtr curWild)
13643 xmlSchemaWildcardNsPtr cur, curB, tmp;
13646 * 1 If O1 and O2 are the same value, then that value must be the
13647 * value.
13649 if ((completeWild->any == curWild->any) &&
13650 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
13651 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
13653 if ((completeWild->negNsSet == NULL) ||
13654 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
13656 if (completeWild->nsSet != NULL) {
13657 int found = 0;
13660 * Check equality of sets.
13662 cur = completeWild->nsSet;
13663 while (cur != NULL) {
13664 found = 0;
13665 curB = curWild->nsSet;
13666 while (curB != NULL) {
13667 if (cur->value == curB->value) {
13668 found = 1;
13669 break;
13671 curB = curB->next;
13673 if (!found)
13674 break;
13675 cur = cur->next;
13677 if (found)
13678 return(0);
13679 } else
13680 return(0);
13684 * 2 If either O1 or O2 is any, then any must be the value
13686 if (completeWild->any != curWild->any) {
13687 if (completeWild->any == 0) {
13688 completeWild->any = 1;
13689 if (completeWild->nsSet != NULL) {
13690 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13691 completeWild->nsSet = NULL;
13693 if (completeWild->negNsSet != NULL) {
13694 xmlFree(completeWild->negNsSet);
13695 completeWild->negNsSet = NULL;
13698 return (0);
13701 * 3 If both O1 and O2 are sets of (namespace names or `absent`),
13702 * then the union of those sets must be the value.
13704 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
13705 int found;
13706 xmlSchemaWildcardNsPtr start;
13708 cur = curWild->nsSet;
13709 start = completeWild->nsSet;
13710 while (cur != NULL) {
13711 found = 0;
13712 curB = start;
13713 while (curB != NULL) {
13714 if (cur->value == curB->value) {
13715 found = 1;
13716 break;
13718 curB = curB->next;
13720 if (!found) {
13721 tmp = xmlSchemaNewWildcardNsConstraint(ctxt);
13722 if (tmp == NULL)
13723 return (-1);
13724 tmp->value = cur->value;
13725 tmp->next = completeWild->nsSet;
13726 completeWild->nsSet = tmp;
13728 cur = cur->next;
13731 return(0);
13734 * 4 If the two are negations of different values (namespace names
13735 * or `absent`), then a pair of not and `absent` must be the value.
13737 if ((completeWild->negNsSet != NULL) &&
13738 (curWild->negNsSet != NULL) &&
13739 (completeWild->negNsSet->value != curWild->negNsSet->value)) {
13740 completeWild->negNsSet->value = NULL;
13742 return(0);
13745 * 5.
13747 if (((completeWild->negNsSet != NULL) &&
13748 (completeWild->negNsSet->value != NULL) &&
13749 (curWild->nsSet != NULL)) ||
13750 ((curWild->negNsSet != NULL) &&
13751 (curWild->negNsSet->value != NULL) &&
13752 (completeWild->nsSet != NULL))) {
13754 int nsFound, absentFound = 0;
13756 if (completeWild->nsSet != NULL) {
13757 cur = completeWild->nsSet;
13758 curB = curWild->negNsSet;
13759 } else {
13760 cur = curWild->nsSet;
13761 curB = completeWild->negNsSet;
13763 nsFound = 0;
13764 while (cur != NULL) {
13765 if (cur->value == NULL)
13766 absentFound = 1;
13767 else if (cur->value == curB->value)
13768 nsFound = 1;
13769 if (nsFound && absentFound)
13770 break;
13771 cur = cur->next;
13774 if (nsFound && absentFound) {
13776 * 5.1 If the set S includes both the negated namespace
13777 * name and `absent`, then any must be the value.
13779 completeWild->any = 1;
13780 if (completeWild->nsSet != NULL) {
13781 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13782 completeWild->nsSet = NULL;
13784 if (completeWild->negNsSet != NULL) {
13785 xmlFree(completeWild->negNsSet);
13786 completeWild->negNsSet = NULL;
13788 } else if (nsFound && (!absentFound)) {
13790 * 5.2 If the set S includes the negated namespace name
13791 * but not `absent`, then a pair of not and `absent` must
13792 * be the value.
13794 if (completeWild->nsSet != NULL) {
13795 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13796 completeWild->nsSet = NULL;
13798 if (completeWild->negNsSet == NULL) {
13799 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13800 if (completeWild->negNsSet == NULL)
13801 return (-1);
13803 completeWild->negNsSet->value = NULL;
13804 } else if ((!nsFound) && absentFound) {
13806 * 5.3 If the set S includes `absent` but not the negated
13807 * namespace name, then the union is not expressible.
13809 xmlSchemaPErr(ctxt, completeWild->node,
13810 XML_SCHEMAP_UNION_NOT_EXPRESSIBLE,
13811 "The union of the wildcard is not expressible.\n",
13812 NULL, NULL);
13813 return(XML_SCHEMAP_UNION_NOT_EXPRESSIBLE);
13814 } else if ((!nsFound) && (!absentFound)) {
13816 * 5.4 If the set S does not include either the negated namespace
13817 * name or `absent`, then whichever of O1 or O2 is a pair of not
13818 * and a namespace name must be the value.
13820 if (completeWild->negNsSet == NULL) {
13821 if (completeWild->nsSet != NULL) {
13822 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13823 completeWild->nsSet = NULL;
13825 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13826 if (completeWild->negNsSet == NULL)
13827 return (-1);
13828 completeWild->negNsSet->value = curWild->negNsSet->value;
13831 return (0);
13834 * 6.
13836 if (((completeWild->negNsSet != NULL) &&
13837 (completeWild->negNsSet->value == NULL) &&
13838 (curWild->nsSet != NULL)) ||
13839 ((curWild->negNsSet != NULL) &&
13840 (curWild->negNsSet->value == NULL) &&
13841 (completeWild->nsSet != NULL))) {
13843 if (completeWild->nsSet != NULL) {
13844 cur = completeWild->nsSet;
13845 } else {
13846 cur = curWild->nsSet;
13848 while (cur != NULL) {
13849 if (cur->value == NULL) {
13851 * 6.1 If the set S includes `absent`, then any must be the
13852 * value.
13854 completeWild->any = 1;
13855 if (completeWild->nsSet != NULL) {
13856 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13857 completeWild->nsSet = NULL;
13859 if (completeWild->negNsSet != NULL) {
13860 xmlFree(completeWild->negNsSet);
13861 completeWild->negNsSet = NULL;
13863 return (0);
13865 cur = cur->next;
13867 if (completeWild->negNsSet == NULL) {
13869 * 6.2 If the set S does not include `absent`, then a pair of not
13870 * and `absent` must be the value.
13872 if (completeWild->nsSet != NULL) {
13873 xmlSchemaFreeWildcardNsSet(completeWild->nsSet);
13874 completeWild->nsSet = NULL;
13876 completeWild->negNsSet = xmlSchemaNewWildcardNsConstraint(ctxt);
13877 if (completeWild->negNsSet == NULL)
13878 return (-1);
13879 completeWild->negNsSet->value = NULL;
13881 return (0);
13883 return (0);
13888 * xmlSchemaIntersectWildcards:
13889 * @ctxt: the schema parser context
13890 * @completeWild: the first wildcard
13891 * @curWild: the second wildcard
13893 * Intersects the namespace constraints of the given wildcards.
13894 * @completeWild will hold the resulting intersection.
13895 * Returns a positive error code on failure, -1 in case of an
13896 * internal error, 0 otherwise.
13898 static int
13899 xmlSchemaIntersectWildcards(xmlSchemaParserCtxtPtr ctxt,
13900 xmlSchemaWildcardPtr completeWild,
13901 xmlSchemaWildcardPtr curWild)
13903 xmlSchemaWildcardNsPtr cur, curB, prev, tmp;
13906 * 1 If O1 and O2 are the same value, then that value must be the
13907 * value.
13909 if ((completeWild->any == curWild->any) &&
13910 ((completeWild->nsSet == NULL) == (curWild->nsSet == NULL)) &&
13911 ((completeWild->negNsSet == NULL) == (curWild->negNsSet == NULL))) {
13913 if ((completeWild->negNsSet == NULL) ||
13914 (completeWild->negNsSet->value == curWild->negNsSet->value)) {
13916 if (completeWild->nsSet != NULL) {
13917 int found = 0;
13920 * Check equality of sets.
13922 cur = completeWild->nsSet;
13923 while (cur != NULL) {
13924 found = 0;
13925 curB = curWild->nsSet;
13926 while (curB != NULL) {
13927 if (cur->value == curB->value) {
13928 found = 1;
13929 break;
13931 curB = curB->next;
13933 if (!found)
13934 break;
13935 cur = cur->next;
13937 if (found)
13938 return(0);
13939 } else
13940 return(0);
13944 * 2 If either O1 or O2 is any, then the other must be the value.
13946 if ((completeWild->any != curWild->any) && (completeWild->any)) {
13947 if (xmlSchemaCloneWildcardNsConstraints(ctxt, completeWild, curWild) == -1)
13948 return(-1);
13949 return(0);
13952 * 3 If either O1 or O2 is a pair of not and a value (a namespace
13953 * name or `absent`) and the other is a set of (namespace names or
13954 * `absent`), then that set, minus the negated value if it was in
13955 * the set, minus `absent` if it was in the set, must be the value.
13957 if (((completeWild->negNsSet != NULL) && (curWild->nsSet != NULL)) ||
13958 ((curWild->negNsSet != NULL) && (completeWild->nsSet != NULL))) {
13959 const xmlChar *neg;
13961 if (completeWild->nsSet == NULL) {
13962 neg = completeWild->negNsSet->value;
13963 if (xmlSchemaCloneWildcardNsConstraints(ctxt, completeWild, curWild) == -1)
13964 return(-1);
13965 } else
13966 neg = curWild->negNsSet->value;
13968 * Remove absent and negated.
13970 prev = NULL;
13971 cur = completeWild->nsSet;
13972 while (cur != NULL) {
13973 if (cur->value == NULL) {
13974 if (prev == NULL)
13975 completeWild->nsSet = cur->next;
13976 else
13977 prev->next = cur->next;
13978 xmlFree(cur);
13979 break;
13981 prev = cur;
13982 cur = cur->next;
13984 if (neg != NULL) {
13985 prev = NULL;
13986 cur = completeWild->nsSet;
13987 while (cur != NULL) {
13988 if (cur->value == neg) {
13989 if (prev == NULL)
13990 completeWild->nsSet = cur->next;
13991 else
13992 prev->next = cur->next;
13993 xmlFree(cur);
13994 break;
13996 prev = cur;
13997 cur = cur->next;
14001 return(0);
14004 * 4 If both O1 and O2 are sets of (namespace names or `absent`),
14005 * then the intersection of those sets must be the value.
14007 if ((completeWild->nsSet != NULL) && (curWild->nsSet != NULL)) {
14008 int found;
14010 cur = completeWild->nsSet;
14011 prev = NULL;
14012 while (cur != NULL) {
14013 found = 0;
14014 curB = curWild->nsSet;
14015 while (curB != NULL) {
14016 if (cur->value == curB->value) {
14017 found = 1;
14018 break;
14020 curB = curB->next;
14022 if (!found) {
14023 if (prev == NULL)
14024 completeWild->nsSet = cur->next;
14025 else
14026 prev->next = cur->next;
14027 tmp = cur->next;
14028 xmlFree(cur);
14029 cur = tmp;
14030 continue;
14032 prev = cur;
14033 cur = cur->next;
14036 return(0);
14038 /* 5 If the two are negations of different namespace names,
14039 * then the intersection is not expressible
14041 if ((completeWild->negNsSet != NULL) &&
14042 (curWild->negNsSet != NULL) &&
14043 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
14044 (completeWild->negNsSet->value != NULL) &&
14045 (curWild->negNsSet->value != NULL)) {
14047 xmlSchemaPErr(ctxt, completeWild->node, XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE,
14048 "The intersection of the wildcard is not expressible.\n",
14049 NULL, NULL);
14050 return(XML_SCHEMAP_INTERSECTION_NOT_EXPRESSIBLE);
14053 * 6 If the one is a negation of a namespace name and the other
14054 * is a negation of `absent`, then the one which is the negation
14055 * of a namespace name must be the value.
14057 if ((completeWild->negNsSet != NULL) && (curWild->negNsSet != NULL) &&
14058 (completeWild->negNsSet->value != curWild->negNsSet->value) &&
14059 (completeWild->negNsSet->value == NULL)) {
14060 completeWild->negNsSet->value = curWild->negNsSet->value;
14062 return(0);
14066 * xmlSchemaIsWildcardNsConstraintSubset:
14067 * @ctxt: the schema parser context
14068 * @sub: the first wildcard
14069 * @super: the second wildcard
14071 * Schema Component Constraint: Wildcard Subset (cos-ns-subset)
14073 * Returns 0 if the namespace constraint of @sub is an intensional
14074 * subset of @super, 1 otherwise.
14076 static int
14077 xmlSchemaCheckCOSNSSubset(xmlSchemaWildcardPtr sub,
14078 xmlSchemaWildcardPtr super)
14081 * 1 super must be any.
14083 if (super->any)
14084 return (0);
14086 * 2.1 sub must be a pair of not and a namespace name or `absent`.
14087 * 2.2 super must be a pair of not and the same value.
14089 if ((sub->negNsSet != NULL) &&
14090 (super->negNsSet != NULL) &&
14091 (sub->negNsSet->value == super->negNsSet->value))
14092 return (0);
14094 * 3.1 sub must be a set whose members are either namespace names or `absent`.
14096 if (sub->nsSet != NULL) {
14098 * 3.2.1 super must be the same set or a superset thereof.
14100 if (super->nsSet != NULL) {
14101 xmlSchemaWildcardNsPtr cur, curB;
14102 int found = 0;
14104 cur = sub->nsSet;
14105 while (cur != NULL) {
14106 found = 0;
14107 curB = super->nsSet;
14108 while (curB != NULL) {
14109 if (cur->value == curB->value) {
14110 found = 1;
14111 break;
14113 curB = curB->next;
14115 if (!found)
14116 return (1);
14117 cur = cur->next;
14119 if (found)
14120 return (0);
14121 } else if (super->negNsSet != NULL) {
14122 xmlSchemaWildcardNsPtr cur;
14124 * 3.2.2 super must be a pair of not and a namespace name or
14125 * `absent` and that value must not be in sub's set.
14127 cur = sub->nsSet;
14128 while (cur != NULL) {
14129 if (cur->value == super->negNsSet->value)
14130 return (1);
14131 cur = cur->next;
14133 return (0);
14136 return (1);
14139 static int
14140 xmlSchemaGetEffectiveValueConstraint(xmlSchemaAttributeUsePtr attruse,
14141 int *fixed,
14142 const xmlChar **value,
14143 xmlSchemaValPtr *val)
14145 *fixed = 0;
14146 *value = NULL;
14147 if (val != 0)
14148 *val = NULL;
14150 if (attruse->defValue != NULL) {
14151 *value = attruse->defValue;
14152 if (val != NULL)
14153 *val = attruse->defVal;
14154 if (attruse->flags & XML_SCHEMA_ATTR_USE_FIXED)
14155 *fixed = 1;
14156 return(1);
14157 } else if ((attruse->attrDecl != NULL) &&
14158 (attruse->attrDecl->defValue != NULL)) {
14159 *value = attruse->attrDecl->defValue;
14160 if (val != NULL)
14161 *val = attruse->attrDecl->defVal;
14162 if (attruse->attrDecl->flags & XML_SCHEMAS_ATTR_FIXED)
14163 *fixed = 1;
14164 return(1);
14166 return(0);
14169 * xmlSchemaCheckCVCWildcardNamespace:
14170 * @wild: the wildcard
14171 * @ns: the namespace
14173 * Validation Rule: Wildcard allows Namespace Name
14174 * (cvc-wildcard-namespace)
14176 * Returns 0 if the given namespace matches the wildcard,
14177 * 1 otherwise and -1 on API errors.
14179 static int
14180 xmlSchemaCheckCVCWildcardNamespace(xmlSchemaWildcardPtr wild,
14181 const xmlChar* ns)
14183 if (wild == NULL)
14184 return(-1);
14186 if (wild->any)
14187 return(0);
14188 else if (wild->nsSet != NULL) {
14189 xmlSchemaWildcardNsPtr cur;
14191 cur = wild->nsSet;
14192 while (cur != NULL) {
14193 if (xmlStrEqual(cur->value, ns))
14194 return(0);
14195 cur = cur->next;
14197 } else if ((wild->negNsSet != NULL) && (ns != NULL) &&
14198 (!xmlStrEqual(wild->negNsSet->value, ns)))
14199 return(0);
14201 return(1);
14204 #define XML_SCHEMA_ACTION_DERIVE 0
14205 #define XML_SCHEMA_ACTION_REDEFINE 1
14207 #define WXS_ACTION_STR(a) \
14208 ((a) == XML_SCHEMA_ACTION_DERIVE) ? (const xmlChar *) "base" : (const xmlChar *) "redefined"
14211 * Schema Component Constraint:
14212 * Derivation Valid (Restriction, Complex)
14213 * derivation-ok-restriction (2) - (4)
14215 * ATTENTION:
14216 * In XML Schema 1.1 this will be:
14217 * Validation Rule:
14218 * Checking complex type subsumption (practicalSubsumption) (1, 2 and 3)
14221 static int
14222 xmlSchemaCheckDerivationOKRestriction2to4(xmlSchemaParserCtxtPtr pctxt,
14223 int action,
14224 xmlSchemaBasicItemPtr item,
14225 xmlSchemaBasicItemPtr baseItem,
14226 xmlSchemaItemListPtr uses,
14227 xmlSchemaItemListPtr baseUses,
14228 xmlSchemaWildcardPtr wild,
14229 xmlSchemaWildcardPtr baseWild)
14231 xmlSchemaAttributeUsePtr cur = NULL, bcur;
14232 int i, j, found; /* err = 0; */
14233 const xmlChar *bEffValue;
14234 int effFixed;
14236 if (uses != NULL) {
14237 for (i = 0; i < uses->nbItems; i++) {
14238 cur = uses->items[i];
14239 found = 0;
14240 if (baseUses == NULL)
14241 goto not_found;
14242 for (j = 0; j < baseUses->nbItems; j++) {
14243 bcur = baseUses->items[j];
14244 if ((WXS_ATTRUSE_DECL_NAME(cur) ==
14245 WXS_ATTRUSE_DECL_NAME(bcur)) &&
14246 (WXS_ATTRUSE_DECL_TNS(cur) ==
14247 WXS_ATTRUSE_DECL_TNS(bcur)))
14250 * (2.1) "If there is an attribute use in the {attribute
14251 * uses} of the {base type definition} (call this B) whose
14252 * {attribute declaration} has the same {name} and {target
14253 * namespace}, then all of the following must be true:"
14255 found = 1;
14257 if ((cur->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
14258 (bcur->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED))
14260 xmlChar *str = NULL;
14262 * (2.1.1) "one of the following must be true:"
14263 * (2.1.1.1) "B's {required} is false."
14264 * (2.1.1.2) "R's {required} is true."
14266 xmlSchemaPAttrUseErr4(pctxt,
14267 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_1,
14268 WXS_ITEM_NODE(item), item, cur,
14269 "The 'optional' attribute use is inconsistent "
14270 "with the corresponding 'required' attribute use of "
14271 "the %s %s",
14272 WXS_ACTION_STR(action),
14273 xmlSchemaGetComponentDesignation(&str, baseItem),
14274 NULL, NULL);
14275 FREE_AND_NULL(str);
14276 /* err = pctxt->err; */
14277 } else if (xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST pctxt,
14278 WXS_ATTRUSE_TYPEDEF(cur),
14279 WXS_ATTRUSE_TYPEDEF(bcur), 0) != 0)
14281 xmlChar *strA = NULL, *strB = NULL, *strC = NULL;
14284 * SPEC (2.1.2) "R's {attribute declaration}'s
14285 * {type definition} must be validly derived from
14286 * B's {type definition} given the empty set as
14287 * defined in Type Derivation OK (Simple) ($3.14.6)."
14289 xmlSchemaPAttrUseErr4(pctxt,
14290 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_2,
14291 WXS_ITEM_NODE(item), item, cur,
14292 "The attribute declaration's %s "
14293 "is not validly derived from "
14294 "the corresponding %s of the "
14295 "attribute declaration in the %s %s",
14296 xmlSchemaGetComponentDesignation(&strA,
14297 WXS_ATTRUSE_TYPEDEF(cur)),
14298 xmlSchemaGetComponentDesignation(&strB,
14299 WXS_ATTRUSE_TYPEDEF(bcur)),
14300 WXS_ACTION_STR(action),
14301 xmlSchemaGetComponentDesignation(&strC, baseItem));
14302 /* xmlSchemaGetComponentDesignation(&str, baseItem), */
14303 FREE_AND_NULL(strA);
14304 FREE_AND_NULL(strB);
14305 FREE_AND_NULL(strC);
14306 /* err = pctxt->err; */
14307 } else {
14309 * 2.1.3 [Definition:] Let the effective value
14310 * constraint of an attribute use be its {value
14311 * constraint}, if present, otherwise its {attribute
14312 * declaration}'s {value constraint} .
14314 xmlSchemaGetEffectiveValueConstraint(bcur,
14315 &effFixed, &bEffValue, NULL);
14317 * 2.1.3 ... one of the following must be true
14319 * 2.1.3.1 B's `effective value constraint` is
14320 * `absent` or default.
14322 if ((bEffValue != NULL) &&
14323 (effFixed == 1)) {
14324 const xmlChar *rEffValue = NULL;
14326 xmlSchemaGetEffectiveValueConstraint(bcur,
14327 &effFixed, &rEffValue, NULL);
14329 * 2.1.3.2 R's `effective value constraint` is
14330 * fixed with the same string as B's.
14331 * MAYBE TODO: Compare the computed values.
14332 * Hmm, it says "same string" so
14333 * string-equality might really be sufficient.
14335 if ((effFixed == 0) ||
14336 (! WXS_ARE_DEFAULT_STR_EQUAL(rEffValue, bEffValue)))
14338 xmlChar *str = NULL;
14340 xmlSchemaPAttrUseErr4(pctxt,
14341 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_1_3,
14342 WXS_ITEM_NODE(item), item, cur,
14343 "The effective value constraint of the "
14344 "attribute use is inconsistent with "
14345 "its correspondent in the %s %s",
14346 WXS_ACTION_STR(action),
14347 xmlSchemaGetComponentDesignation(&str,
14348 baseItem),
14349 NULL, NULL);
14350 FREE_AND_NULL(str);
14351 /* err = pctxt->err; */
14355 break;
14358 not_found:
14359 if (!found) {
14361 * (2.2) "otherwise the {base type definition} must have an
14362 * {attribute wildcard} and the {target namespace} of the
14363 * R's {attribute declaration} must be `valid` with respect
14364 * to that wildcard, as defined in Wildcard allows Namespace
14365 * Name ($3.10.4)."
14367 if ((baseWild == NULL) ||
14368 (xmlSchemaCheckCVCWildcardNamespace(baseWild,
14369 (WXS_ATTRUSE_DECL(cur))->targetNamespace) != 0))
14371 xmlChar *str = NULL;
14373 xmlSchemaPAttrUseErr4(pctxt,
14374 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_2_2,
14375 WXS_ITEM_NODE(item), item, cur,
14376 "Neither a matching attribute use, "
14377 "nor a matching wildcard exists in the %s %s",
14378 WXS_ACTION_STR(action),
14379 xmlSchemaGetComponentDesignation(&str, baseItem),
14380 NULL, NULL);
14381 FREE_AND_NULL(str);
14382 /* err = pctxt->err; */
14388 * SPEC derivation-ok-restriction (3):
14389 * (3) "For each attribute use in the {attribute uses} of the {base type
14390 * definition} whose {required} is true, there must be an attribute
14391 * use with an {attribute declaration} with the same {name} and
14392 * {target namespace} as its {attribute declaration} in the {attribute
14393 * uses} of the complex type definition itself whose {required} is true.
14395 if (baseUses != NULL) {
14396 for (j = 0; j < baseUses->nbItems; j++) {
14397 bcur = baseUses->items[j];
14398 if (bcur->occurs != XML_SCHEMAS_ATTR_USE_REQUIRED)
14399 continue;
14400 found = 0;
14401 if (uses != NULL) {
14402 for (i = 0; i < uses->nbItems; i++) {
14403 cur = uses->items[i];
14404 if ((WXS_ATTRUSE_DECL_NAME(cur) ==
14405 WXS_ATTRUSE_DECL_NAME(bcur)) &&
14406 (WXS_ATTRUSE_DECL_TNS(cur) ==
14407 WXS_ATTRUSE_DECL_TNS(bcur))) {
14408 found = 1;
14409 break;
14413 if (!found) {
14414 xmlChar *strA = NULL, *strB = NULL;
14416 xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14417 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_3,
14418 NULL, item,
14419 "A matching attribute use for the "
14420 "'required' %s of the %s %s is missing",
14421 xmlSchemaGetComponentDesignation(&strA, bcur),
14422 WXS_ACTION_STR(action),
14423 xmlSchemaGetComponentDesignation(&strB, baseItem),
14424 NULL);
14425 FREE_AND_NULL(strA);
14426 FREE_AND_NULL(strB);
14431 * derivation-ok-restriction (4)
14433 if (wild != NULL) {
14435 * (4) "If there is an {attribute wildcard}, all of the
14436 * following must be true:"
14438 if (baseWild == NULL) {
14439 xmlChar *str = NULL;
14442 * (4.1) "The {base type definition} must also have one."
14444 xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14445 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_1,
14446 NULL, item,
14447 "The %s has an attribute wildcard, "
14448 "but the %s %s '%s' does not have one",
14449 WXS_ITEM_TYPE_NAME(item),
14450 WXS_ACTION_STR(action),
14451 WXS_ITEM_TYPE_NAME(baseItem),
14452 xmlSchemaGetComponentQName(&str, baseItem));
14453 FREE_AND_NULL(str);
14454 return(pctxt->err);
14455 } else if ((baseWild->any == 0) &&
14456 xmlSchemaCheckCOSNSSubset(wild, baseWild))
14458 xmlChar *str = NULL;
14460 * (4.2) "The complex type definition's {attribute wildcard}'s
14461 * {namespace constraint} must be a subset of the {base type
14462 * definition}'s {attribute wildcard}'s {namespace constraint},
14463 * as defined by Wildcard Subset ($3.10.6)."
14465 xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14466 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_2,
14467 NULL, item,
14468 "The attribute wildcard is not a valid "
14469 "subset of the wildcard in the %s %s '%s'",
14470 WXS_ACTION_STR(action),
14471 WXS_ITEM_TYPE_NAME(baseItem),
14472 xmlSchemaGetComponentQName(&str, baseItem),
14473 NULL);
14474 FREE_AND_NULL(str);
14475 return(pctxt->err);
14477 /* 4.3 Unless the {base type definition} is the `ur-type
14478 * definition`, the complex type definition's {attribute
14479 * wildcard}'s {process contents} must be identical to or
14480 * stronger than the {base type definition}'s {attribute
14481 * wildcard}'s {process contents}, where strict is stronger
14482 * than lax is stronger than skip.
14484 if ((! WXS_IS_ANYTYPE(baseItem)) &&
14485 (wild->processContents < baseWild->processContents)) {
14486 xmlChar *str = NULL;
14487 xmlSchemaCustomErr4(ACTXT_CAST pctxt,
14488 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_4_3,
14489 NULL, baseItem,
14490 "The {process contents} of the attribute wildcard is "
14491 "weaker than the one in the %s %s '%s'",
14492 WXS_ACTION_STR(action),
14493 WXS_ITEM_TYPE_NAME(baseItem),
14494 xmlSchemaGetComponentQName(&str, baseItem),
14495 NULL);
14496 FREE_AND_NULL(str)
14497 return(pctxt->err);
14500 return(0);
14504 static int
14505 xmlSchemaExpandAttributeGroupRefs(xmlSchemaParserCtxtPtr pctxt,
14506 xmlSchemaBasicItemPtr item,
14507 xmlSchemaWildcardPtr *completeWild,
14508 xmlSchemaItemListPtr list,
14509 xmlSchemaItemListPtr prohibs);
14511 * xmlSchemaFixupTypeAttributeUses:
14512 * @ctxt: the schema parser context
14513 * @type: the complex type definition
14516 * Builds the wildcard and the attribute uses on the given complex type.
14517 * Returns -1 if an internal error occurs, 0 otherwise.
14519 * ATTENTION TODO: Experimentally this uses pointer comparisons for
14520 * strings, so recheck this if we start to hardcode some schemata, since
14521 * they might not be in the same dict.
14522 * NOTE: It is allowed to "extend" the xs:anyType type.
14524 static int
14525 xmlSchemaFixupTypeAttributeUses(xmlSchemaParserCtxtPtr pctxt,
14526 xmlSchemaTypePtr type)
14528 xmlSchemaTypePtr baseType = NULL;
14529 xmlSchemaAttributeUsePtr use;
14530 xmlSchemaItemListPtr uses, baseUses, prohibs = NULL;
14532 if (type->baseType == NULL) {
14533 PERROR_INT("xmlSchemaFixupTypeAttributeUses",
14534 "no base type");
14535 return (-1);
14537 baseType = type->baseType;
14538 if (WXS_IS_TYPE_NOT_FIXED(baseType))
14539 if (xmlSchemaTypeFixup(baseType, ACTXT_CAST pctxt) == -1)
14540 return(-1);
14542 uses = type->attrUses;
14543 baseUses = baseType->attrUses;
14545 * Expand attribute group references. And build the 'complete'
14546 * wildcard, i.e. intersect multiple wildcards.
14547 * Move attribute prohibitions into a separate list.
14549 if (uses != NULL) {
14550 if (WXS_IS_RESTRICTION(type)) {
14552 * This one will transfer all attr. prohibitions
14553 * into pctxt->attrProhibs.
14555 if (xmlSchemaExpandAttributeGroupRefs(pctxt,
14556 WXS_BASIC_CAST type, &(type->attributeWildcard), uses,
14557 pctxt->attrProhibs) == -1)
14559 PERROR_INT("xmlSchemaFixupTypeAttributeUses",
14560 "failed to expand attributes");
14561 return(-1);
14563 if (pctxt->attrProhibs->nbItems != 0)
14564 prohibs = pctxt->attrProhibs;
14565 } else {
14566 if (xmlSchemaExpandAttributeGroupRefs(pctxt,
14567 WXS_BASIC_CAST type, &(type->attributeWildcard), uses,
14568 NULL) == -1)
14570 PERROR_INT("xmlSchemaFixupTypeAttributeUses",
14571 "failed to expand attributes");
14572 return(-1);
14577 * Inherit the attribute uses of the base type.
14579 if (baseUses != NULL) {
14580 int i, j;
14581 xmlSchemaAttributeUseProhibPtr pro;
14583 if (WXS_IS_RESTRICTION(type)) {
14584 int usesCount;
14585 xmlSchemaAttributeUsePtr tmp;
14587 if (uses != NULL)
14588 usesCount = uses->nbItems;
14589 else
14590 usesCount = 0;
14592 /* Restriction. */
14593 for (i = 0; i < baseUses->nbItems; i++) {
14594 use = baseUses->items[i];
14595 if (prohibs) {
14597 * Filter out prohibited uses.
14599 for (j = 0; j < prohibs->nbItems; j++) {
14600 pro = prohibs->items[j];
14601 if ((WXS_ATTRUSE_DECL_NAME(use) == pro->name) &&
14602 (WXS_ATTRUSE_DECL_TNS(use) ==
14603 pro->targetNamespace))
14605 goto inherit_next;
14609 if (usesCount) {
14611 * Filter out existing uses.
14613 for (j = 0; j < usesCount; j++) {
14614 tmp = uses->items[j];
14615 if ((WXS_ATTRUSE_DECL_NAME(use) ==
14616 WXS_ATTRUSE_DECL_NAME(tmp)) &&
14617 (WXS_ATTRUSE_DECL_TNS(use) ==
14618 WXS_ATTRUSE_DECL_TNS(tmp)))
14620 goto inherit_next;
14624 if (uses == NULL) {
14625 type->attrUses = xmlSchemaItemListCreate();
14626 if (type->attrUses == NULL)
14627 goto exit_failure;
14628 uses = type->attrUses;
14630 xmlSchemaItemListAddSize(uses, 2, use);
14631 inherit_next: {}
14633 } else {
14634 /* Extension. */
14635 for (i = 0; i < baseUses->nbItems; i++) {
14636 use = baseUses->items[i];
14637 if (uses == NULL) {
14638 type->attrUses = xmlSchemaItemListCreate();
14639 if (type->attrUses == NULL)
14640 goto exit_failure;
14641 uses = type->attrUses;
14643 xmlSchemaItemListAddSize(uses, baseUses->nbItems, use);
14648 * Shrink attr. uses.
14650 if (uses) {
14651 if (uses->nbItems == 0) {
14652 xmlSchemaItemListFree(uses);
14653 type->attrUses = NULL;
14656 * TODO: We could shrink the size of the array
14657 * to fit the actual number of items.
14661 * Compute the complete wildcard.
14663 if (WXS_IS_EXTENSION(type)) {
14664 if (baseType->attributeWildcard != NULL) {
14666 * (3.2.2.1) "If the `base wildcard` is non-`absent`, then
14667 * the appropriate case among the following:"
14669 if (type->attributeWildcard != NULL) {
14671 * Union the complete wildcard with the base wildcard.
14672 * SPEC {attribute wildcard}
14673 * (3.2.2.1.2) "otherwise a wildcard whose {process contents}
14674 * and {annotation} are those of the `complete wildcard`,
14675 * and whose {namespace constraint} is the intensional union
14676 * of the {namespace constraint} of the `complete wildcard`
14677 * and of the `base wildcard`, as defined in Attribute
14678 * Wildcard Union ($3.10.6)."
14680 if (xmlSchemaUnionWildcards(pctxt, type->attributeWildcard,
14681 baseType->attributeWildcard) == -1)
14682 goto exit_failure;
14683 } else {
14685 * (3.2.2.1.1) "If the `complete wildcard` is `absent`,
14686 * then the `base wildcard`."
14688 type->attributeWildcard = baseType->attributeWildcard;
14690 } else {
14692 * (3.2.2.2) "otherwise (the `base wildcard` is `absent`) the
14693 * `complete wildcard`"
14694 * NOOP
14697 } else {
14699 * SPEC {attribute wildcard}
14700 * (3.1) "If the <restriction> alternative is chosen, then the
14701 * `complete wildcard`;"
14702 * NOOP
14706 return (0);
14708 exit_failure:
14709 return(-1);
14713 * xmlSchemaTypeFinalContains:
14714 * @schema: the schema
14715 * @type: the type definition
14716 * @final: the final
14718 * Evaluates if a type definition contains the given "final".
14719 * This does take "finalDefault" into account as well.
14721 * Returns 1 if the type does contain the given "final",
14722 * 0 otherwise.
14724 static int
14725 xmlSchemaTypeFinalContains(xmlSchemaTypePtr type, int final)
14727 if (type == NULL)
14728 return (0);
14729 if (type->flags & final)
14730 return (1);
14731 else
14732 return (0);
14736 * xmlSchemaGetUnionSimpleTypeMemberTypes:
14737 * @type: the Union Simple Type
14739 * Returns a list of member types of @type if existing,
14740 * returns NULL otherwise.
14742 static xmlSchemaTypeLinkPtr
14743 xmlSchemaGetUnionSimpleTypeMemberTypes(xmlSchemaTypePtr type)
14745 while ((type != NULL) && (type->type == XML_SCHEMA_TYPE_SIMPLE)) {
14746 if (type->memberTypes != NULL)
14747 return (type->memberTypes);
14748 else
14749 type = type->baseType;
14751 return (NULL);
14754 #if 0
14756 * xmlSchemaGetParticleTotalRangeMin:
14757 * @particle: the particle
14759 * Schema Component Constraint: Effective Total Range
14760 * (all and sequence) + (choice)
14762 * Returns the minimum Effective Total Range.
14764 static int
14765 xmlSchemaGetParticleTotalRangeMin(xmlSchemaParticlePtr particle)
14767 if ((particle->children == NULL) ||
14768 (particle->minOccurs == 0))
14769 return (0);
14770 if (particle->children->type == XML_SCHEMA_TYPE_CHOICE) {
14771 int min = -1, cur;
14772 xmlSchemaParticlePtr part =
14773 (xmlSchemaParticlePtr) particle->children->children;
14775 if (part == NULL)
14776 return (0);
14777 while (part != NULL) {
14778 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14779 (part->children->type == XML_SCHEMA_TYPE_ANY))
14780 cur = part->minOccurs;
14781 else
14782 cur = xmlSchemaGetParticleTotalRangeMin(part);
14783 if (cur == 0)
14784 return (0);
14785 if ((min > cur) || (min == -1))
14786 min = cur;
14787 part = (xmlSchemaParticlePtr) part->next;
14789 return (particle->minOccurs * min);
14790 } else {
14791 /* <all> and <sequence> */
14792 int sum = 0;
14793 xmlSchemaParticlePtr part =
14794 (xmlSchemaParticlePtr) particle->children->children;
14796 if (part == NULL)
14797 return (0);
14798 do {
14799 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14800 (part->children->type == XML_SCHEMA_TYPE_ANY))
14801 sum += part->minOccurs;
14802 else
14803 sum += xmlSchemaGetParticleTotalRangeMin(part);
14804 part = (xmlSchemaParticlePtr) part->next;
14805 } while (part != NULL);
14806 return (particle->minOccurs * sum);
14811 * xmlSchemaGetParticleTotalRangeMax:
14812 * @particle: the particle
14814 * Schema Component Constraint: Effective Total Range
14815 * (all and sequence) + (choice)
14817 * Returns the maximum Effective Total Range.
14819 static int
14820 xmlSchemaGetParticleTotalRangeMax(xmlSchemaParticlePtr particle)
14822 if ((particle->children == NULL) ||
14823 (particle->children->children == NULL))
14824 return (0);
14825 if (particle->children->type == XML_SCHEMA_TYPE_CHOICE) {
14826 int max = -1, cur;
14827 xmlSchemaParticlePtr part =
14828 (xmlSchemaParticlePtr) particle->children->children;
14830 for (; part != NULL; part = (xmlSchemaParticlePtr) part->next) {
14831 if (part->children == NULL)
14832 continue;
14833 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14834 (part->children->type == XML_SCHEMA_TYPE_ANY))
14835 cur = part->maxOccurs;
14836 else
14837 cur = xmlSchemaGetParticleTotalRangeMax(part);
14838 if (cur == UNBOUNDED)
14839 return (UNBOUNDED);
14840 if ((max < cur) || (max == -1))
14841 max = cur;
14843 /* TODO: Handle overflows? */
14844 return (particle->maxOccurs * max);
14845 } else {
14846 /* <all> and <sequence> */
14847 int sum = 0, cur;
14848 xmlSchemaParticlePtr part =
14849 (xmlSchemaParticlePtr) particle->children->children;
14851 for (; part != NULL; part = (xmlSchemaParticlePtr) part->next) {
14852 if (part->children == NULL)
14853 continue;
14854 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14855 (part->children->type == XML_SCHEMA_TYPE_ANY))
14856 cur = part->maxOccurs;
14857 else
14858 cur = xmlSchemaGetParticleTotalRangeMax(part);
14859 if (cur == UNBOUNDED)
14860 return (UNBOUNDED);
14861 if ((cur > 0) && (particle->maxOccurs == UNBOUNDED))
14862 return (UNBOUNDED);
14863 sum += cur;
14865 /* TODO: Handle overflows? */
14866 return (particle->maxOccurs * sum);
14869 #endif
14872 * xmlSchemaGetParticleEmptiable:
14873 * @particle: the particle
14875 * Returns 1 if emptiable, 0 otherwise.
14877 static int
14878 xmlSchemaGetParticleEmptiable(xmlSchemaParticlePtr particle)
14880 xmlSchemaParticlePtr part;
14881 int emptiable;
14883 if ((particle->children == NULL) || (particle->minOccurs == 0))
14884 return (1);
14886 part = (xmlSchemaParticlePtr) particle->children->children;
14887 if (part == NULL)
14888 return (1);
14890 while (part != NULL) {
14891 if ((part->children->type == XML_SCHEMA_TYPE_ELEMENT) ||
14892 (part->children->type == XML_SCHEMA_TYPE_ANY))
14893 emptiable = (part->minOccurs == 0);
14894 else
14895 emptiable = xmlSchemaGetParticleEmptiable(part);
14896 if (particle->children->type == XML_SCHEMA_TYPE_CHOICE) {
14897 if (emptiable)
14898 return (1);
14899 } else {
14900 /* <all> and <sequence> */
14901 if (!emptiable)
14902 return (0);
14904 part = (xmlSchemaParticlePtr) part->next;
14907 if (particle->children->type == XML_SCHEMA_TYPE_CHOICE)
14908 return (0);
14909 else
14910 return (1);
14914 * xmlSchemaIsParticleEmptiable:
14915 * @particle: the particle
14917 * Schema Component Constraint: Particle Emptiable
14918 * Checks whether the given particle is emptiable.
14920 * Returns 1 if emptiable, 0 otherwise.
14922 static int
14923 xmlSchemaIsParticleEmptiable(xmlSchemaParticlePtr particle)
14926 * SPEC (1) "Its {min occurs} is 0."
14928 if ((particle == NULL) || (particle->minOccurs == 0) ||
14929 (particle->children == NULL))
14930 return (1);
14932 * SPEC (2) "Its {term} is a group and the minimum part of the
14933 * effective total range of that group, [...] is 0."
14935 if (WXS_IS_MODEL_GROUP(particle->children))
14936 return (xmlSchemaGetParticleEmptiable(particle));
14937 return (0);
14941 * xmlSchemaCheckCOSSTDerivedOK:
14942 * @actxt: a context
14943 * @type: the derived simple type definition
14944 * @baseType: the base type definition
14945 * @subset: the subset of ('restriction', etc.)
14947 * Schema Component Constraint:
14948 * Type Derivation OK (Simple) (cos-st-derived-OK)
14950 * Checks whether @type can be validly
14951 * derived from @baseType.
14953 * Returns 0 on success, an positive error code otherwise.
14955 static int
14956 xmlSchemaCheckCOSSTDerivedOK(xmlSchemaAbstractCtxtPtr actxt,
14957 xmlSchemaTypePtr type,
14958 xmlSchemaTypePtr baseType,
14959 int subset)
14962 * 1 They are the same type definition.
14963 * TODO: The identity check might have to be more complex than this.
14965 if (type == baseType)
14966 return (0);
14968 * 2.1 restriction is not in the subset, or in the {final}
14969 * of its own {base type definition};
14971 * NOTE that this will be used also via "xsi:type".
14973 * TODO: Revise this, it looks strange. How can the "type"
14974 * not be fixed or *in* fixing?
14976 if (WXS_IS_TYPE_NOT_FIXED(type))
14977 if (xmlSchemaTypeFixup(type, actxt) == -1)
14978 return(-1);
14979 if (WXS_IS_TYPE_NOT_FIXED(baseType))
14980 if (xmlSchemaTypeFixup(baseType, actxt) == -1)
14981 return(-1);
14982 if ((subset & SUBSET_RESTRICTION) ||
14983 (xmlSchemaTypeFinalContains(type->baseType,
14984 XML_SCHEMAS_TYPE_FINAL_RESTRICTION))) {
14985 return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_1);
14987 /* 2.2 */
14988 if (type->baseType == baseType) {
14990 * 2.2.1 D's `base type definition` is B.
14992 return (0);
14995 * 2.2.2 D's `base type definition` is not the `ur-type definition`
14996 * and is validly derived from B given the subset, as defined by this
14997 * constraint.
14999 if ((! WXS_IS_ANYTYPE(type->baseType)) &&
15000 (xmlSchemaCheckCOSSTDerivedOK(actxt, type->baseType,
15001 baseType, subset) == 0)) {
15002 return (0);
15005 * 2.2.3 D's {variety} is list or union and B is the `simple ur-type
15006 * definition`.
15008 if (WXS_IS_ANY_SIMPLE_TYPE(baseType) &&
15009 (WXS_IS_LIST(type) || WXS_IS_UNION(type))) {
15010 return (0);
15013 * 2.2.4 B's {variety} is union and D is validly derived from a type
15014 * definition in B's {member type definitions} given the subset, as
15015 * defined by this constraint.
15017 * NOTE: This seems not to involve built-in types, since there is no
15018 * built-in Union Simple Type.
15020 if (WXS_IS_UNION(baseType)) {
15021 xmlSchemaTypeLinkPtr cur;
15023 cur = baseType->memberTypes;
15024 while (cur != NULL) {
15025 if (WXS_IS_TYPE_NOT_FIXED(cur->type))
15026 if (xmlSchemaTypeFixup(cur->type, actxt) == -1)
15027 return(-1);
15028 if (xmlSchemaCheckCOSSTDerivedOK(actxt,
15029 type, cur->type, subset) == 0)
15032 * It just has to be validly derived from at least one
15033 * member-type.
15035 return (0);
15037 cur = cur->next;
15040 return (XML_SCHEMAP_COS_ST_DERIVED_OK_2_2);
15044 * xmlSchemaCheckTypeDefCircularInternal:
15045 * @pctxt: the schema parser context
15046 * @ctxtType: the type definition
15047 * @ancestor: an ancestor of @ctxtType
15049 * Checks st-props-correct (2) + ct-props-correct (3).
15050 * Circular type definitions are not allowed.
15052 * Returns XML_SCHEMAP_ST_PROPS_CORRECT_2 if the given type is
15053 * circular, 0 otherwise.
15055 static int
15056 xmlSchemaCheckTypeDefCircularInternal(xmlSchemaParserCtxtPtr pctxt,
15057 xmlSchemaTypePtr ctxtType,
15058 xmlSchemaTypePtr ancestor)
15060 int ret;
15062 if ((ancestor == NULL) || (ancestor->type == XML_SCHEMA_TYPE_BASIC))
15063 return (0);
15065 if (ctxtType == ancestor) {
15066 xmlSchemaPCustomErr(pctxt,
15067 XML_SCHEMAP_ST_PROPS_CORRECT_2,
15068 WXS_BASIC_CAST ctxtType, WXS_ITEM_NODE(ctxtType),
15069 "The definition is circular", NULL);
15070 return (XML_SCHEMAP_ST_PROPS_CORRECT_2);
15072 if (ancestor->flags & XML_SCHEMAS_TYPE_MARKED) {
15074 * Avoid infinite recursion on circular types not yet checked.
15076 return (0);
15078 ancestor->flags |= XML_SCHEMAS_TYPE_MARKED;
15079 ret = xmlSchemaCheckTypeDefCircularInternal(pctxt, ctxtType,
15080 ancestor->baseType);
15081 ancestor->flags ^= XML_SCHEMAS_TYPE_MARKED;
15082 return (ret);
15086 * xmlSchemaCheckTypeDefCircular:
15087 * @item: the complex/simple type definition
15088 * @ctxt: the parser context
15089 * @name: the name
15091 * Checks for circular type definitions.
15093 static void
15094 xmlSchemaCheckTypeDefCircular(xmlSchemaTypePtr item,
15095 xmlSchemaParserCtxtPtr ctxt)
15097 if ((item == NULL) ||
15098 (item->type == XML_SCHEMA_TYPE_BASIC) ||
15099 (item->baseType == NULL))
15100 return;
15101 xmlSchemaCheckTypeDefCircularInternal(ctxt, item,
15102 item->baseType);
15106 * Simple Type Definition Representation OK (src-simple-type) 4
15108 * "4 Circular union type definition is disallowed. That is, if the
15109 * <union> alternative is chosen, there must not be any entries in the
15110 * memberTypes [attribute] at any depth which resolve to the component
15111 * corresponding to the <simpleType>."
15113 * Note that this should work on the *representation* of a component,
15114 * thus assumes any union types in the member types not being yet
15115 * substituted. At this stage we need the variety of the types
15116 * to be already computed.
15118 static int
15119 xmlSchemaCheckUnionTypeDefCircularRecur(xmlSchemaParserCtxtPtr pctxt,
15120 xmlSchemaTypePtr ctxType,
15121 xmlSchemaTypeLinkPtr members)
15123 xmlSchemaTypeLinkPtr member;
15124 xmlSchemaTypePtr memberType;
15126 member = members;
15127 while (member != NULL) {
15128 memberType = member->type;
15129 while ((memberType != NULL) &&
15130 (memberType->type != XML_SCHEMA_TYPE_BASIC)) {
15131 if (memberType == ctxType) {
15132 xmlSchemaPCustomErr(pctxt,
15133 XML_SCHEMAP_SRC_SIMPLE_TYPE_4,
15134 WXS_BASIC_CAST ctxType, NULL,
15135 "The union type definition is circular", NULL);
15136 return (XML_SCHEMAP_SRC_SIMPLE_TYPE_4);
15138 if ((WXS_IS_UNION(memberType)) &&
15139 ((memberType->flags & XML_SCHEMAS_TYPE_MARKED) == 0))
15141 int res;
15142 memberType->flags |= XML_SCHEMAS_TYPE_MARKED;
15143 res = xmlSchemaCheckUnionTypeDefCircularRecur(pctxt,
15144 ctxType,
15145 xmlSchemaGetUnionSimpleTypeMemberTypes(memberType));
15146 memberType->flags ^= XML_SCHEMAS_TYPE_MARKED;
15147 if (res != 0)
15148 return(res);
15150 memberType = memberType->baseType;
15152 member = member->next;
15154 return(0);
15157 static int
15158 xmlSchemaCheckUnionTypeDefCircular(xmlSchemaParserCtxtPtr pctxt,
15159 xmlSchemaTypePtr type)
15161 if (! WXS_IS_UNION(type))
15162 return(0);
15163 return(xmlSchemaCheckUnionTypeDefCircularRecur(pctxt, type,
15164 type->memberTypes));
15168 * xmlSchemaResolveTypeReferences:
15169 * @item: the complex/simple type definition
15170 * @ctxt: the parser context
15171 * @name: the name
15173 * Resolves type definition references
15175 static void
15176 xmlSchemaResolveTypeReferences(xmlSchemaTypePtr typeDef,
15177 xmlSchemaParserCtxtPtr ctxt)
15179 if (typeDef == NULL)
15180 return;
15183 * Resolve the base type.
15185 if (typeDef->baseType == NULL) {
15186 typeDef->baseType = xmlSchemaGetType(ctxt->schema,
15187 typeDef->base, typeDef->baseNs);
15188 if (typeDef->baseType == NULL) {
15189 xmlSchemaPResCompAttrErr(ctxt,
15190 XML_SCHEMAP_SRC_RESOLVE,
15191 WXS_BASIC_CAST typeDef, typeDef->node,
15192 "base", typeDef->base, typeDef->baseNs,
15193 XML_SCHEMA_TYPE_SIMPLE, NULL);
15194 return;
15197 if (WXS_IS_SIMPLE(typeDef)) {
15198 if (WXS_IS_UNION(typeDef)) {
15200 * Resolve the memberTypes.
15202 xmlSchemaResolveUnionMemberTypes(ctxt, typeDef);
15203 return;
15204 } else if (WXS_IS_LIST(typeDef)) {
15206 * Resolve the itemType.
15208 if ((typeDef->subtypes == NULL) && (typeDef->base != NULL)) {
15210 typeDef->subtypes = xmlSchemaGetType(ctxt->schema,
15211 typeDef->base, typeDef->baseNs);
15213 if ((typeDef->subtypes == NULL) ||
15214 (! WXS_IS_SIMPLE(typeDef->subtypes)))
15216 typeDef->subtypes = NULL;
15217 xmlSchemaPResCompAttrErr(ctxt,
15218 XML_SCHEMAP_SRC_RESOLVE,
15219 WXS_BASIC_CAST typeDef, typeDef->node,
15220 "itemType", typeDef->base, typeDef->baseNs,
15221 XML_SCHEMA_TYPE_SIMPLE, NULL);
15224 return;
15228 * The ball of letters below means, that if we have a particle
15229 * which has a QName-helper component as its {term}, we want
15230 * to resolve it...
15232 else if ((WXS_TYPE_CONTENTTYPE(typeDef) != NULL) &&
15233 ((WXS_TYPE_CONTENTTYPE(typeDef))->type ==
15234 XML_SCHEMA_TYPE_PARTICLE) &&
15235 (WXS_TYPE_PARTICLE_TERM(typeDef) != NULL) &&
15236 ((WXS_TYPE_PARTICLE_TERM(typeDef))->type ==
15237 XML_SCHEMA_EXTRA_QNAMEREF))
15239 xmlSchemaQNameRefPtr ref =
15240 WXS_QNAME_CAST WXS_TYPE_PARTICLE_TERM(typeDef);
15241 xmlSchemaModelGroupDefPtr groupDef;
15244 * URGENT TODO: Test this.
15246 WXS_TYPE_PARTICLE_TERM(typeDef) = NULL;
15248 * Resolve the MG definition reference.
15250 groupDef =
15251 WXS_MODEL_GROUPDEF_CAST xmlSchemaGetNamedComponent(ctxt->schema,
15252 ref->itemType, ref->name, ref->targetNamespace);
15253 if (groupDef == NULL) {
15254 xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
15255 NULL, WXS_ITEM_NODE(WXS_TYPE_PARTICLE(typeDef)),
15256 "ref", ref->name, ref->targetNamespace, ref->itemType,
15257 NULL);
15258 /* Remove the particle. */
15259 WXS_TYPE_CONTENTTYPE(typeDef) = NULL;
15260 } else if (WXS_MODELGROUPDEF_MODEL(groupDef) == NULL)
15261 /* Remove the particle. */
15262 WXS_TYPE_CONTENTTYPE(typeDef) = NULL;
15263 else {
15265 * Assign the MG definition's {model group} to the
15266 * particle's {term}.
15268 WXS_TYPE_PARTICLE_TERM(typeDef) = WXS_MODELGROUPDEF_MODEL(groupDef);
15270 if (WXS_MODELGROUPDEF_MODEL(groupDef)->type == XML_SCHEMA_TYPE_ALL) {
15272 * SPEC cos-all-limited (1.2)
15273 * "1.2 the {term} property of a particle with
15274 * {max occurs}=1 which is part of a pair which constitutes
15275 * the {content type} of a complex type definition."
15277 if ((WXS_TYPE_PARTICLE(typeDef))->maxOccurs != 1) {
15278 xmlSchemaCustomErr(ACTXT_CAST ctxt,
15279 /* TODO: error code */
15280 XML_SCHEMAP_COS_ALL_LIMITED,
15281 WXS_ITEM_NODE(WXS_TYPE_PARTICLE(typeDef)), NULL,
15282 "The particle's {max occurs} must be 1, since the "
15283 "reference resolves to an 'all' model group",
15284 NULL, NULL);
15294 * xmlSchemaCheckSTPropsCorrect:
15295 * @ctxt: the schema parser context
15296 * @type: the simple type definition
15298 * Checks st-props-correct.
15300 * Returns 0 if the properties are correct,
15301 * if not, a positive error code and -1 on internal
15302 * errors.
15304 static int
15305 xmlSchemaCheckSTPropsCorrect(xmlSchemaParserCtxtPtr ctxt,
15306 xmlSchemaTypePtr type)
15308 xmlSchemaTypePtr baseType = type->baseType;
15309 xmlChar *str = NULL;
15311 /* STATE: error funcs converted. */
15313 * Schema Component Constraint: Simple Type Definition Properties Correct
15315 * NOTE: This is somehow redundant, since we actually built a simple type
15316 * to have all the needed information; this acts as an self test.
15318 /* Base type: If the datatype has been `derived` by `restriction`
15319 * then the Simple Type Definition component from which it is `derived`,
15320 * otherwise the Simple Type Definition for anySimpleType ($4.1.6).
15322 if (baseType == NULL) {
15324 * TODO: Think about: "modulo the impact of Missing
15325 * Sub-components ($5.3)."
15327 xmlSchemaPCustomErr(ctxt,
15328 XML_SCHEMAP_ST_PROPS_CORRECT_1,
15329 WXS_BASIC_CAST type, NULL,
15330 "No base type existent", NULL);
15331 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
15334 if (! WXS_IS_SIMPLE(baseType)) {
15335 xmlSchemaPCustomErr(ctxt,
15336 XML_SCHEMAP_ST_PROPS_CORRECT_1,
15337 WXS_BASIC_CAST type, NULL,
15338 "The base type '%s' is not a simple type",
15339 xmlSchemaGetComponentQName(&str, baseType));
15340 FREE_AND_NULL(str)
15341 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
15343 if ((WXS_IS_LIST(type) || WXS_IS_UNION(type)) &&
15344 (WXS_IS_RESTRICTION(type) == 0) &&
15345 ((! WXS_IS_ANY_SIMPLE_TYPE(baseType)) &&
15346 (baseType->type != XML_SCHEMA_TYPE_SIMPLE))) {
15347 xmlSchemaPCustomErr(ctxt,
15348 XML_SCHEMAP_ST_PROPS_CORRECT_1,
15349 WXS_BASIC_CAST type, NULL,
15350 "A type, derived by list or union, must have "
15351 "the simple ur-type definition as base type, not '%s'",
15352 xmlSchemaGetComponentQName(&str, baseType));
15353 FREE_AND_NULL(str)
15354 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
15357 * Variety: One of {atomic, list, union}.
15359 if ((! WXS_IS_ATOMIC(type)) && (! WXS_IS_UNION(type)) &&
15360 (! WXS_IS_LIST(type))) {
15361 xmlSchemaPCustomErr(ctxt,
15362 XML_SCHEMAP_ST_PROPS_CORRECT_1,
15363 WXS_BASIC_CAST type, NULL,
15364 "The variety is absent", NULL);
15365 return (XML_SCHEMAP_ST_PROPS_CORRECT_1);
15367 /* TODO: Finish this. Hmm, is this finished? */
15370 * 3 The {final} of the {base type definition} must not contain restriction.
15372 if (xmlSchemaTypeFinalContains(baseType,
15373 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
15374 xmlSchemaPCustomErr(ctxt,
15375 XML_SCHEMAP_ST_PROPS_CORRECT_3,
15376 WXS_BASIC_CAST type, NULL,
15377 "The 'final' of its base type '%s' must not contain "
15378 "'restriction'",
15379 xmlSchemaGetComponentQName(&str, baseType));
15380 FREE_AND_NULL(str)
15381 return (XML_SCHEMAP_ST_PROPS_CORRECT_3);
15385 * 2 All simple type definitions must be derived ultimately from the `simple
15386 * ur-type definition` (so circular definitions are disallowed). That is, it
15387 * must be possible to reach a built-in primitive datatype or the `simple
15388 * ur-type definition` by repeatedly following the {base type definition}.
15390 * NOTE: this is done in xmlSchemaCheckTypeDefCircular().
15392 return (0);
15396 * xmlSchemaCheckCOSSTRestricts:
15397 * @ctxt: the schema parser context
15398 * @type: the simple type definition
15400 * Schema Component Constraint:
15401 * Derivation Valid (Restriction, Simple) (cos-st-restricts)
15403 * Checks if the given @type (simpleType) is derived validly by restriction.
15404 * STATUS:
15406 * Returns -1 on internal errors, 0 if the type is validly derived,
15407 * a positive error code otherwise.
15409 static int
15410 xmlSchemaCheckCOSSTRestricts(xmlSchemaParserCtxtPtr pctxt,
15411 xmlSchemaTypePtr type)
15413 xmlChar *str = NULL;
15415 if (type->type != XML_SCHEMA_TYPE_SIMPLE) {
15416 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15417 "given type is not a user-derived simpleType");
15418 return (-1);
15421 if (WXS_IS_ATOMIC(type)) {
15422 xmlSchemaTypePtr primitive;
15424 * 1.1 The {base type definition} must be an atomic simple
15425 * type definition or a built-in primitive datatype.
15427 if (! WXS_IS_ATOMIC(type->baseType)) {
15428 xmlSchemaPCustomErr(pctxt,
15429 XML_SCHEMAP_COS_ST_RESTRICTS_1_1,
15430 WXS_BASIC_CAST type, NULL,
15431 "The base type '%s' is not an atomic simple type",
15432 xmlSchemaGetComponentQName(&str, type->baseType));
15433 FREE_AND_NULL(str)
15434 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_1);
15436 /* 1.2 The {final} of the {base type definition} must not contain
15437 * restriction.
15439 /* OPTIMIZE TODO : This is already done in xmlSchemaCheckStPropsCorrect */
15440 if (xmlSchemaTypeFinalContains(type->baseType,
15441 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
15442 xmlSchemaPCustomErr(pctxt,
15443 XML_SCHEMAP_COS_ST_RESTRICTS_1_2,
15444 WXS_BASIC_CAST type, NULL,
15445 "The final of its base type '%s' must not contain 'restriction'",
15446 xmlSchemaGetComponentQName(&str, type->baseType));
15447 FREE_AND_NULL(str)
15448 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_2);
15452 * 1.3.1 DF must be an allowed constraining facet for the {primitive
15453 * type definition}, as specified in the appropriate subsection of 3.2
15454 * Primitive datatypes.
15456 if (type->facets != NULL) {
15457 xmlSchemaFacetPtr facet;
15458 int ok = 1;
15460 primitive = xmlSchemaGetPrimitiveType(type);
15461 if (primitive == NULL) {
15462 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15463 "failed to get primitive type");
15464 return (-1);
15466 facet = type->facets;
15467 do {
15468 if (xmlSchemaIsBuiltInTypeFacet(primitive, facet->type) == 0) {
15469 ok = 0;
15470 xmlSchemaPIllegalFacetAtomicErr(pctxt,
15471 XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1,
15472 type, primitive, facet);
15474 facet = facet->next;
15475 } while (facet != NULL);
15476 if (ok == 0)
15477 return (XML_SCHEMAP_COS_ST_RESTRICTS_1_3_1);
15480 * SPEC (1.3.2) "If there is a facet of the same kind in the {facets}
15481 * of the {base type definition} (call this BF),then the DF's {value}
15482 * must be a valid restriction of BF's {value} as defined in
15483 * [XML Schemas: Datatypes]."
15485 * NOTE (1.3.2) Facet derivation constraints are currently handled in
15486 * xmlSchemaDeriveAndValidateFacets()
15488 } else if (WXS_IS_LIST(type)) {
15489 xmlSchemaTypePtr itemType = NULL;
15491 itemType = type->subtypes;
15492 if ((itemType == NULL) || (! WXS_IS_SIMPLE(itemType))) {
15493 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15494 "failed to evaluate the item type");
15495 return (-1);
15497 if (WXS_IS_TYPE_NOT_FIXED(itemType))
15498 xmlSchemaTypeFixup(itemType, ACTXT_CAST pctxt);
15500 * 2.1 The {item type definition} must have a {variety} of atomic or
15501 * union (in which case all the {member type definitions}
15502 * must be atomic).
15504 if ((! WXS_IS_ATOMIC(itemType)) &&
15505 (! WXS_IS_UNION(itemType))) {
15506 xmlSchemaPCustomErr(pctxt,
15507 XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
15508 WXS_BASIC_CAST type, NULL,
15509 "The item type '%s' does not have a variety of atomic or union",
15510 xmlSchemaGetComponentQName(&str, itemType));
15511 FREE_AND_NULL(str)
15512 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
15513 } else if (WXS_IS_UNION(itemType)) {
15514 xmlSchemaTypeLinkPtr member;
15516 member = itemType->memberTypes;
15517 while (member != NULL) {
15518 if (! WXS_IS_ATOMIC(member->type)) {
15519 xmlSchemaPCustomErr(pctxt,
15520 XML_SCHEMAP_COS_ST_RESTRICTS_2_1,
15521 WXS_BASIC_CAST type, NULL,
15522 "The item type is a union type, but the "
15523 "member type '%s' of this item type is not atomic",
15524 xmlSchemaGetComponentQName(&str, member->type));
15525 FREE_AND_NULL(str)
15526 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_1);
15528 member = member->next;
15532 if (WXS_IS_ANY_SIMPLE_TYPE(type->baseType)) {
15533 xmlSchemaFacetPtr facet;
15535 * This is the case if we have: <simpleType><list ..
15538 * 2.3.1
15539 * 2.3.1.1 The {final} of the {item type definition} must not
15540 * contain list.
15542 if (xmlSchemaTypeFinalContains(itemType,
15543 XML_SCHEMAS_TYPE_FINAL_LIST)) {
15544 xmlSchemaPCustomErr(pctxt,
15545 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1,
15546 WXS_BASIC_CAST type, NULL,
15547 "The final of its item type '%s' must not contain 'list'",
15548 xmlSchemaGetComponentQName(&str, itemType));
15549 FREE_AND_NULL(str)
15550 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_1);
15553 * 2.3.1.2 The {facets} must only contain the whiteSpace
15554 * facet component.
15555 * OPTIMIZE TODO: the S4S already disallows any facet
15556 * to be specified.
15558 if (type->facets != NULL) {
15559 facet = type->facets;
15560 do {
15561 if (facet->type != XML_SCHEMA_FACET_WHITESPACE) {
15562 xmlSchemaPIllegalFacetListUnionErr(pctxt,
15563 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2,
15564 type, facet);
15565 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_1_2);
15567 facet = facet->next;
15568 } while (facet != NULL);
15571 * MAYBE TODO: (Hmm, not really) Datatypes states:
15572 * A `list` datatype can be `derived` from an `atomic` datatype
15573 * whose `lexical space` allows space (such as string or anyURI)or
15574 * a `union` datatype any of whose {member type definitions}'s
15575 * `lexical space` allows space.
15577 } else {
15579 * This is the case if we have: <simpleType><restriction ...
15580 * I.e. the variety of "list" is inherited.
15583 * 2.3.2
15584 * 2.3.2.1 The {base type definition} must have a {variety} of list.
15586 if (! WXS_IS_LIST(type->baseType)) {
15587 xmlSchemaPCustomErr(pctxt,
15588 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1,
15589 WXS_BASIC_CAST type, NULL,
15590 "The base type '%s' must be a list type",
15591 xmlSchemaGetComponentQName(&str, type->baseType));
15592 FREE_AND_NULL(str)
15593 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_1);
15596 * 2.3.2.2 The {final} of the {base type definition} must not
15597 * contain restriction.
15599 if (xmlSchemaTypeFinalContains(type->baseType,
15600 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
15601 xmlSchemaPCustomErr(pctxt,
15602 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2,
15603 WXS_BASIC_CAST type, NULL,
15604 "The 'final' of the base type '%s' must not contain 'restriction'",
15605 xmlSchemaGetComponentQName(&str, type->baseType));
15606 FREE_AND_NULL(str)
15607 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_2);
15610 * 2.3.2.3 The {item type definition} must be validly derived
15611 * from the {base type definition}'s {item type definition} given
15612 * the empty set, as defined in Type Derivation OK (Simple) ($3.14.6).
15615 xmlSchemaTypePtr baseItemType;
15617 baseItemType = type->baseType->subtypes;
15618 if ((baseItemType == NULL) || (! WXS_IS_SIMPLE(baseItemType))) {
15619 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15620 "failed to eval the item type of a base type");
15621 return (-1);
15623 if ((itemType != baseItemType) &&
15624 (xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST pctxt, itemType,
15625 baseItemType, 0) != 0)) {
15626 xmlChar *strBIT = NULL, *strBT = NULL;
15627 xmlSchemaPCustomErrExt(pctxt,
15628 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3,
15629 WXS_BASIC_CAST type, NULL,
15630 "The item type '%s' is not validly derived from "
15631 "the item type '%s' of the base type '%s'",
15632 xmlSchemaGetComponentQName(&str, itemType),
15633 xmlSchemaGetComponentQName(&strBIT, baseItemType),
15634 xmlSchemaGetComponentQName(&strBT, type->baseType));
15636 FREE_AND_NULL(str)
15637 FREE_AND_NULL(strBIT)
15638 FREE_AND_NULL(strBT)
15639 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_3);
15643 if (type->facets != NULL) {
15644 xmlSchemaFacetPtr facet;
15645 int ok = 1;
15647 * 2.3.2.4 Only length, minLength, maxLength, whiteSpace, pattern
15648 * and enumeration facet components are allowed among the {facets}.
15650 facet = type->facets;
15651 do {
15652 switch (facet->type) {
15653 case XML_SCHEMA_FACET_LENGTH:
15654 case XML_SCHEMA_FACET_MINLENGTH:
15655 case XML_SCHEMA_FACET_MAXLENGTH:
15656 case XML_SCHEMA_FACET_WHITESPACE:
15658 * TODO: 2.5.1.2 List datatypes
15659 * The value of `whiteSpace` is fixed to the value collapse.
15661 case XML_SCHEMA_FACET_PATTERN:
15662 case XML_SCHEMA_FACET_ENUMERATION:
15663 break;
15664 default: {
15665 xmlSchemaPIllegalFacetListUnionErr(pctxt,
15666 XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4,
15667 type, facet);
15669 * We could return, but it's nicer to report all
15670 * invalid facets.
15672 ok = 0;
15675 facet = facet->next;
15676 } while (facet != NULL);
15677 if (ok == 0)
15678 return (XML_SCHEMAP_COS_ST_RESTRICTS_2_3_2_4);
15680 * SPEC (2.3.2.5) (same as 1.3.2)
15682 * NOTE (2.3.2.5) This is currently done in
15683 * xmlSchemaDeriveAndValidateFacets()
15687 } else if (WXS_IS_UNION(type)) {
15689 * 3.1 The {member type definitions} must all have {variety} of
15690 * atomic or list.
15692 xmlSchemaTypeLinkPtr member;
15694 member = type->memberTypes;
15695 while (member != NULL) {
15696 if (WXS_IS_TYPE_NOT_FIXED(member->type))
15697 xmlSchemaTypeFixup(member->type, ACTXT_CAST pctxt);
15699 if ((! WXS_IS_ATOMIC(member->type)) &&
15700 (! WXS_IS_LIST(member->type))) {
15701 xmlSchemaPCustomErr(pctxt,
15702 XML_SCHEMAP_COS_ST_RESTRICTS_3_1,
15703 WXS_BASIC_CAST type, NULL,
15704 "The member type '%s' is neither an atomic, nor a list type",
15705 xmlSchemaGetComponentQName(&str, member->type));
15706 FREE_AND_NULL(str)
15707 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_1);
15709 member = member->next;
15712 * 3.3.1 If the {base type definition} is the `simple ur-type
15713 * definition`
15715 if (type->baseType->builtInType == XML_SCHEMAS_ANYSIMPLETYPE) {
15717 * 3.3.1.1 All of the {member type definitions} must have a
15718 * {final} which does not contain union.
15720 member = type->memberTypes;
15721 while (member != NULL) {
15722 if (xmlSchemaTypeFinalContains(member->type,
15723 XML_SCHEMAS_TYPE_FINAL_UNION)) {
15724 xmlSchemaPCustomErr(pctxt,
15725 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1,
15726 WXS_BASIC_CAST type, NULL,
15727 "The 'final' of member type '%s' contains 'union'",
15728 xmlSchemaGetComponentQName(&str, member->type));
15729 FREE_AND_NULL(str)
15730 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1);
15732 member = member->next;
15735 * 3.3.1.2 The {facets} must be empty.
15737 if (type->facetSet != NULL) {
15738 xmlSchemaPCustomErr(pctxt,
15739 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2,
15740 WXS_BASIC_CAST type, NULL,
15741 "No facets allowed", NULL);
15742 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_1_2);
15744 } else {
15746 * 3.3.2.1 The {base type definition} must have a {variety} of union.
15747 * I.e. the variety of "list" is inherited.
15749 if (! WXS_IS_UNION(type->baseType)) {
15750 xmlSchemaPCustomErr(pctxt,
15751 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1,
15752 WXS_BASIC_CAST type, NULL,
15753 "The base type '%s' is not a union type",
15754 xmlSchemaGetComponentQName(&str, type->baseType));
15755 FREE_AND_NULL(str)
15756 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_1);
15759 * 3.3.2.2 The {final} of the {base type definition} must not contain restriction.
15761 if (xmlSchemaTypeFinalContains(type->baseType,
15762 XML_SCHEMAS_TYPE_FINAL_RESTRICTION)) {
15763 xmlSchemaPCustomErr(pctxt,
15764 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2,
15765 WXS_BASIC_CAST type, NULL,
15766 "The 'final' of its base type '%s' must not contain 'restriction'",
15767 xmlSchemaGetComponentQName(&str, type->baseType));
15768 FREE_AND_NULL(str)
15769 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_2);
15772 * 3.3.2.3 The {member type definitions}, in order, must be validly
15773 * derived from the corresponding type definitions in the {base
15774 * type definition}'s {member type definitions} given the empty set,
15775 * as defined in Type Derivation OK (Simple) ($3.14.6).
15778 xmlSchemaTypeLinkPtr baseMember;
15781 * OPTIMIZE: if the type is restricting, it has no local defined
15782 * member types and inherits the member types of the base type;
15783 * thus a check for equality can be skipped.
15786 * Even worse: I cannot see a scenario where a restricting
15787 * union simple type can have other member types as the member
15788 * types of it's base type. This check seems not necessary with
15789 * respect to the derivation process in libxml2.
15790 * But necessary if constructing types with an API.
15792 if (type->memberTypes != NULL) {
15793 member = type->memberTypes;
15794 baseMember = xmlSchemaGetUnionSimpleTypeMemberTypes(type->baseType);
15795 if ((member == NULL) && (baseMember != NULL)) {
15796 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15797 "different number of member types in base");
15799 while (member != NULL) {
15800 if (baseMember == NULL) {
15801 PERROR_INT("xmlSchemaCheckCOSSTRestricts",
15802 "different number of member types in base");
15803 } else if ((member->type != baseMember->type) &&
15804 (xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST pctxt,
15805 member->type, baseMember->type, 0) != 0)) {
15806 xmlChar *strBMT = NULL, *strBT = NULL;
15808 xmlSchemaPCustomErrExt(pctxt,
15809 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3,
15810 WXS_BASIC_CAST type, NULL,
15811 "The member type %s is not validly "
15812 "derived from its corresponding member "
15813 "type %s of the base type %s",
15814 xmlSchemaGetComponentQName(&str, member->type),
15815 xmlSchemaGetComponentQName(&strBMT, baseMember->type),
15816 xmlSchemaGetComponentQName(&strBT, type->baseType));
15817 FREE_AND_NULL(str)
15818 FREE_AND_NULL(strBMT)
15819 FREE_AND_NULL(strBT)
15820 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_3);
15822 member = member->next;
15823 if (baseMember != NULL)
15824 baseMember = baseMember->next;
15829 * 3.3.2.4 Only pattern and enumeration facet components are
15830 * allowed among the {facets}.
15832 if (type->facets != NULL) {
15833 xmlSchemaFacetPtr facet;
15834 int ok = 1;
15836 facet = type->facets;
15837 do {
15838 if ((facet->type != XML_SCHEMA_FACET_PATTERN) &&
15839 (facet->type != XML_SCHEMA_FACET_ENUMERATION)) {
15840 xmlSchemaPIllegalFacetListUnionErr(pctxt,
15841 XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4,
15842 type, facet);
15843 ok = 0;
15845 facet = facet->next;
15846 } while (facet != NULL);
15847 if (ok == 0)
15848 return (XML_SCHEMAP_COS_ST_RESTRICTS_3_3_2_4);
15852 * SPEC (3.3.2.5) (same as 1.3.2)
15854 * NOTE (3.3.2.5) This is currently done in
15855 * xmlSchemaDeriveAndValidateFacets()
15860 return (0);
15864 * xmlSchemaCheckSRCSimpleType:
15865 * @ctxt: the schema parser context
15866 * @type: the simple type definition
15868 * Checks crc-simple-type constraints.
15870 * Returns 0 if the constraints are satisfied,
15871 * if not a positive error code and -1 on internal
15872 * errors.
15874 #if 0
15875 static int
15876 xmlSchemaCheckSRCSimpleType(xmlSchemaParserCtxtPtr ctxt,
15877 xmlSchemaTypePtr type)
15880 * src-simple-type.1 The corresponding simple type definition, if any,
15881 * must satisfy the conditions set out in Constraints on Simple Type
15882 * Definition Schema Components ($3.14.6).
15884 if (WXS_IS_RESTRICTION(type)) {
15886 * src-simple-type.2 "If the <restriction> alternative is chosen,
15887 * either it must have a base [attribute] or a <simpleType> among its
15888 * [children], but not both."
15889 * NOTE: This is checked in the parse function of <restriction>.
15894 } else if (WXS_IS_LIST(type)) {
15895 /* src-simple-type.3 "If the <list> alternative is chosen, either it must have
15896 * an itemType [attribute] or a <simpleType> among its [children],
15897 * but not both."
15899 * NOTE: This is checked in the parse function of <list>.
15901 } else if (WXS_IS_UNION(type)) {
15903 * src-simple-type.4 is checked in xmlSchemaCheckUnionTypeDefCircular().
15906 return (0);
15908 #endif
15910 static int
15911 xmlSchemaCreateVCtxtOnPCtxt(xmlSchemaParserCtxtPtr ctxt)
15913 if (ctxt->vctxt == NULL) {
15914 ctxt->vctxt = xmlSchemaNewValidCtxt(NULL);
15915 if (ctxt->vctxt == NULL) {
15916 xmlSchemaPErr(ctxt, NULL,
15917 XML_SCHEMAP_INTERNAL,
15918 "Internal error: xmlSchemaCreateVCtxtOnPCtxt, "
15919 "failed to create a temp. validation context.\n",
15920 NULL, NULL);
15921 return (-1);
15923 /* TODO: Pass user data. */
15924 xmlSchemaSetValidErrors(ctxt->vctxt,
15925 ctxt->error, ctxt->warning, ctxt->errCtxt);
15926 xmlSchemaSetValidStructuredErrors(ctxt->vctxt,
15927 ctxt->serror, ctxt->errCtxt);
15929 return (0);
15932 static int
15933 xmlSchemaVCheckCVCSimpleType(xmlSchemaAbstractCtxtPtr actxt,
15934 xmlNodePtr node,
15935 xmlSchemaTypePtr type,
15936 const xmlChar *value,
15937 xmlSchemaValPtr *retVal,
15938 int fireErrors,
15939 int normalize,
15940 int isNormalized);
15943 * xmlSchemaParseCheckCOSValidDefault:
15944 * @pctxt: the schema parser context
15945 * @type: the simple type definition
15946 * @value: the default value
15947 * @node: an optional node (the holder of the value)
15949 * Schema Component Constraint: Element Default Valid (Immediate)
15950 * (cos-valid-default)
15951 * This will be used by the parser only. For the validator there's
15952 * an other version.
15954 * Returns 0 if the constraints are satisfied,
15955 * if not, a positive error code and -1 on internal
15956 * errors.
15958 static int
15959 xmlSchemaParseCheckCOSValidDefault(xmlSchemaParserCtxtPtr pctxt,
15960 xmlNodePtr node,
15961 xmlSchemaTypePtr type,
15962 const xmlChar *value,
15963 xmlSchemaValPtr *val)
15965 int ret = 0;
15968 * cos-valid-default:
15969 * Schema Component Constraint: Element Default Valid (Immediate)
15970 * For a string to be a valid default with respect to a type
15971 * definition the appropriate case among the following must be true:
15973 if WXS_IS_COMPLEX(type) {
15975 * Complex type.
15977 * SPEC (2.1) "its {content type} must be a simple type definition
15978 * or mixed."
15979 * SPEC (2.2.2) "If the {content type} is mixed, then the {content
15980 * type}'s particle must be `emptiable` as defined by
15981 * Particle Emptiable ($3.9.6)."
15983 if ((! WXS_HAS_SIMPLE_CONTENT(type)) &&
15984 ((! WXS_HAS_MIXED_CONTENT(type)) || (! WXS_EMPTIABLE(type)))) {
15985 /* NOTE that this covers (2.2.2) as well. */
15986 xmlSchemaPCustomErr(pctxt,
15987 XML_SCHEMAP_COS_VALID_DEFAULT_2_1,
15988 WXS_BASIC_CAST type, type->node,
15989 "For a string to be a valid default, the type definition "
15990 "must be a simple type or a complex type with mixed content "
15991 "and a particle emptiable", NULL);
15992 return(XML_SCHEMAP_COS_VALID_DEFAULT_2_1);
15996 * 1 If the type definition is a simple type definition, then the string
15997 * must be `valid` with respect to that definition as defined by String
15998 * Valid ($3.14.4).
16000 * AND
16002 * 2.2.1 If the {content type} is a simple type definition, then the
16003 * string must be `valid` with respect to that simple type definition
16004 * as defined by String Valid ($3.14.4).
16006 if (WXS_IS_SIMPLE(type))
16007 ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST pctxt, node,
16008 type, value, val, 1, 1, 0);
16009 else if (WXS_HAS_SIMPLE_CONTENT(type))
16010 ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST pctxt, node,
16011 type->contentTypeDef, value, val, 1, 1, 0);
16012 else
16013 return (ret);
16015 if (ret < 0) {
16016 PERROR_INT("xmlSchemaParseCheckCOSValidDefault",
16017 "calling xmlSchemaVCheckCVCSimpleType()");
16020 return (ret);
16024 * xmlSchemaCheckCTPropsCorrect:
16025 * @ctxt: the schema parser context
16026 * @type: the complex type definition
16028 *.(4.6) Constraints on Complex Type Definition Schema Components
16029 * Schema Component Constraint:
16030 * Complex Type Definition Properties Correct (ct-props-correct)
16031 * STATUS: (seems) complete
16033 * Returns 0 if the constraints are satisfied, a positive
16034 * error code if not and -1 if an internal error occurred.
16036 static int
16037 xmlSchemaCheckCTPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
16038 xmlSchemaTypePtr type)
16041 * TODO: Correct the error code; XML_SCHEMAP_SRC_CT_1 is used temporarily.
16043 * SPEC (1) "The values of the properties of a complex type definition must
16044 * be as described in the property tableau in The Complex Type Definition
16045 * Schema Component ($3.4.1), modulo the impact of Missing
16046 * Sub-components ($5.3)."
16048 if ((type->baseType != NULL) &&
16049 (WXS_IS_SIMPLE(type->baseType)) &&
16050 (WXS_IS_EXTENSION(type) == 0)) {
16052 * SPEC (2) "If the {base type definition} is a simple type definition,
16053 * the {derivation method} must be extension."
16055 xmlSchemaCustomErr(ACTXT_CAST pctxt,
16056 XML_SCHEMAP_SRC_CT_1,
16057 NULL, WXS_BASIC_CAST type,
16058 "If the base type is a simple type, the derivation method must be "
16059 "'extension'", NULL, NULL);
16060 return (XML_SCHEMAP_SRC_CT_1);
16063 * SPEC (3) "Circular definitions are disallowed, except for the `ur-type
16064 * definition`. That is, it must be possible to reach the `ur-type
16065 * definition` by repeatedly following the {base type definition}."
16067 * NOTE (3) is done in xmlSchemaCheckTypeDefCircular().
16070 * NOTE that (4) and (5) need the following:
16071 * - attribute uses need to be already inherited (apply attr. prohibitions)
16072 * - attribute group references need to be expanded already
16073 * - simple types need to be typefixed already
16075 if (type->attrUses &&
16076 (((xmlSchemaItemListPtr) type->attrUses)->nbItems > 1))
16078 xmlSchemaItemListPtr uses = (xmlSchemaItemListPtr) type->attrUses;
16079 xmlSchemaAttributeUsePtr use, tmp;
16080 int i, j, hasId = 0;
16082 for (i = uses->nbItems -1; i >= 0; i--) {
16083 use = uses->items[i];
16086 * SPEC ct-props-correct
16087 * (4) "Two distinct attribute declarations in the
16088 * {attribute uses} must not have identical {name}s and
16089 * {target namespace}s."
16091 if (i > 0) {
16092 for (j = i -1; j >= 0; j--) {
16093 tmp = uses->items[j];
16094 if ((WXS_ATTRUSE_DECL_NAME(use) ==
16095 WXS_ATTRUSE_DECL_NAME(tmp)) &&
16096 (WXS_ATTRUSE_DECL_TNS(use) ==
16097 WXS_ATTRUSE_DECL_TNS(tmp)))
16099 xmlChar *str = NULL;
16101 xmlSchemaCustomErr(ACTXT_CAST pctxt,
16102 XML_SCHEMAP_AG_PROPS_CORRECT,
16103 NULL, WXS_BASIC_CAST type,
16104 "Duplicate %s",
16105 xmlSchemaGetComponentDesignation(&str, use),
16106 NULL);
16107 FREE_AND_NULL(str);
16109 * Remove the duplicate.
16111 if (xmlSchemaItemListRemove(uses, i) == -1)
16112 goto exit_failure;
16113 goto next_use;
16118 * SPEC ct-props-correct
16119 * (5) "Two distinct attribute declarations in the
16120 * {attribute uses} must not have {type definition}s which
16121 * are or are derived from ID."
16123 if (WXS_ATTRUSE_TYPEDEF(use) != NULL) {
16124 if (xmlSchemaIsDerivedFromBuiltInType(
16125 WXS_ATTRUSE_TYPEDEF(use), XML_SCHEMAS_ID))
16127 if (hasId) {
16128 xmlChar *str = NULL;
16130 xmlSchemaCustomErr(ACTXT_CAST pctxt,
16131 XML_SCHEMAP_AG_PROPS_CORRECT,
16132 NULL, WXS_BASIC_CAST type,
16133 "There must not exist more than one attribute "
16134 "declaration of type 'xs:ID' "
16135 "(or derived from 'xs:ID'). The %s violates this "
16136 "constraint",
16137 xmlSchemaGetComponentDesignation(&str, use),
16138 NULL);
16139 FREE_AND_NULL(str);
16140 if (xmlSchemaItemListRemove(uses, i) == -1)
16141 goto exit_failure;
16144 hasId = 1;
16147 next_use: {}
16150 return (0);
16151 exit_failure:
16152 return(-1);
16155 static int
16156 xmlSchemaAreEqualTypes(xmlSchemaTypePtr typeA,
16157 xmlSchemaTypePtr typeB)
16160 * TODO: This should implement component-identity
16161 * in the future.
16163 if ((typeA == NULL) || (typeB == NULL))
16164 return (0);
16165 return (typeA == typeB);
16169 * xmlSchemaCheckCOSCTDerivedOK:
16170 * @ctxt: the schema parser context
16171 * @type: the to-be derived complex type definition
16172 * @baseType: the base complex type definition
16173 * @set: the given set
16175 * Schema Component Constraint:
16176 * Type Derivation OK (Complex) (cos-ct-derived-ok)
16178 * STATUS: completed
16180 * Returns 0 if the constraints are satisfied, or 1
16181 * if not.
16183 static int
16184 xmlSchemaCheckCOSCTDerivedOK(xmlSchemaAbstractCtxtPtr actxt,
16185 xmlSchemaTypePtr type,
16186 xmlSchemaTypePtr baseType,
16187 int set)
16189 int equal = xmlSchemaAreEqualTypes(type, baseType);
16190 /* TODO: Error codes. */
16192 * SPEC "For a complex type definition (call it D, for derived)
16193 * to be validly derived from a type definition (call this
16194 * B, for base) given a subset of {extension, restriction}
16195 * all of the following must be true:"
16197 if (! equal) {
16199 * SPEC (1) "If B and D are not the same type definition, then the
16200 * {derivation method} of D must not be in the subset."
16202 if (((set & SUBSET_EXTENSION) && (WXS_IS_EXTENSION(type))) ||
16203 ((set & SUBSET_RESTRICTION) && (WXS_IS_RESTRICTION(type))))
16204 return (1);
16205 } else {
16207 * SPEC (2.1) "B and D must be the same type definition."
16209 return (0);
16212 * SPEC (2.2) "B must be D's {base type definition}."
16214 if (type->baseType == baseType)
16215 return (0);
16217 * SPEC (2.3.1) "D's {base type definition} must not be the `ur-type
16218 * definition`."
16220 if (WXS_IS_ANYTYPE(type->baseType))
16221 return (1);
16223 if (WXS_IS_COMPLEX(type->baseType)) {
16225 * SPEC (2.3.2.1) "If D's {base type definition} is complex, then it
16226 * must be validly derived from B given the subset as defined by this
16227 * constraint."
16229 return (xmlSchemaCheckCOSCTDerivedOK(actxt, type->baseType,
16230 baseType, set));
16231 } else {
16233 * SPEC (2.3.2.2) "If D's {base type definition} is simple, then it
16234 * must be validly derived from B given the subset as defined in Type
16235 * Derivation OK (Simple) ($3.14.6).
16237 return (xmlSchemaCheckCOSSTDerivedOK(actxt, type->baseType,
16238 baseType, set));
16243 * xmlSchemaCheckCOSDerivedOK:
16244 * @type: the derived simple type definition
16245 * @baseType: the base type definition
16247 * Calls:
16248 * Type Derivation OK (Simple) AND Type Derivation OK (Complex)
16250 * Checks whether @type can be validly derived from @baseType.
16252 * Returns 0 on success, an positive error code otherwise.
16254 static int
16255 xmlSchemaCheckCOSDerivedOK(xmlSchemaAbstractCtxtPtr actxt,
16256 xmlSchemaTypePtr type,
16257 xmlSchemaTypePtr baseType,
16258 int set)
16260 if (WXS_IS_SIMPLE(type))
16261 return (xmlSchemaCheckCOSSTDerivedOK(actxt, type, baseType, set));
16262 else
16263 return (xmlSchemaCheckCOSCTDerivedOK(actxt, type, baseType, set));
16267 * xmlSchemaCheckCOSCTExtends:
16268 * @ctxt: the schema parser context
16269 * @type: the complex type definition
16271 * (3.4.6) Constraints on Complex Type Definition Schema Components
16272 * Schema Component Constraint:
16273 * Derivation Valid (Extension) (cos-ct-extends)
16275 * STATUS:
16276 * missing:
16277 * (1.5)
16278 * (1.4.3.2.2.2) "Particle Valid (Extension)"
16280 * Returns 0 if the constraints are satisfied, a positive
16281 * error code if not and -1 if an internal error occurred.
16283 static int
16284 xmlSchemaCheckCOSCTExtends(xmlSchemaParserCtxtPtr ctxt,
16285 xmlSchemaTypePtr type)
16287 xmlSchemaTypePtr base = type->baseType;
16289 * TODO: Correct the error code; XML_SCHEMAP_COS_CT_EXTENDS_1_1 is used
16290 * temporarily only.
16293 * SPEC (1) "If the {base type definition} is a complex type definition,
16294 * then all of the following must be true:"
16296 if (WXS_IS_COMPLEX(base)) {
16298 * SPEC (1.1) "The {final} of the {base type definition} must not
16299 * contain extension."
16301 if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
16302 xmlSchemaPCustomErr(ctxt,
16303 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
16304 WXS_BASIC_CAST type, NULL,
16305 "The 'final' of the base type definition "
16306 "contains 'extension'", NULL);
16307 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16311 * ATTENTION: The constrains (1.2) and (1.3) are not applied,
16312 * since they are automatically satisfied through the
16313 * inheriting mechanism.
16314 * Note that even if redefining components, the inheriting mechanism
16315 * is used.
16317 #if 0
16319 * SPEC (1.2) "Its {attribute uses} must be a subset of the {attribute
16320 * uses}
16321 * of the complex type definition itself, that is, for every attribute
16322 * use in the {attribute uses} of the {base type definition}, there
16323 * must be an attribute use in the {attribute uses} of the complex
16324 * type definition itself whose {attribute declaration} has the same
16325 * {name}, {target namespace} and {type definition} as its attribute
16326 * declaration"
16328 if (base->attrUses != NULL) {
16329 int i, j, found;
16330 xmlSchemaAttributeUsePtr use, buse;
16332 for (i = 0; i < (WXS_LIST_CAST base->attrUses)->nbItems; i ++) {
16333 buse = (WXS_LIST_CAST base->attrUses)->items[i];
16334 found = 0;
16335 if (type->attrUses != NULL) {
16336 use = (WXS_LIST_CAST type->attrUses)->items[j];
16337 for (j = 0; j < (WXS_LIST_CAST type->attrUses)->nbItems; j ++)
16339 if ((WXS_ATTRUSE_DECL_NAME(use) ==
16340 WXS_ATTRUSE_DECL_NAME(buse)) &&
16341 (WXS_ATTRUSE_DECL_TNS(use) ==
16342 WXS_ATTRUSE_DECL_TNS(buse)) &&
16343 (WXS_ATTRUSE_TYPEDEF(use) ==
16344 WXS_ATTRUSE_TYPEDEF(buse))
16346 found = 1;
16347 break;
16351 if (! found) {
16352 xmlChar *str = NULL;
16354 xmlSchemaCustomErr(ACTXT_CAST ctxt,
16355 XML_SCHEMAP_COS_CT_EXTENDS_1_2,
16356 NULL, WXS_BASIC_CAST type,
16358 * TODO: The report does not indicate that also the
16359 * type needs to be the same.
16361 "This type is missing a matching correspondent "
16362 "for its {base type}'s %s in its {attribute uses}",
16363 xmlSchemaGetComponentDesignation(&str,
16364 buse->children),
16365 NULL);
16366 FREE_AND_NULL(str)
16371 * SPEC (1.3) "If it has an {attribute wildcard}, the complex type
16372 * definition must also have one, and the base type definition's
16373 * {attribute wildcard}'s {namespace constraint} must be a subset
16374 * of the complex type definition's {attribute wildcard}'s {namespace
16375 * constraint}, as defined by Wildcard Subset ($3.10.6)."
16379 * MAYBE TODO: Enable if ever needed. But this will be needed only
16380 * if created the type via a schema construction API.
16382 if (base->attributeWildcard != NULL) {
16383 if (type->attributeWildcard == NULL) {
16384 xmlChar *str = NULL;
16386 xmlSchemaCustomErr(ACTXT_CAST pctxt,
16387 XML_SCHEMAP_COS_CT_EXTENDS_1_3,
16388 NULL, type,
16389 "The base %s has an attribute wildcard, "
16390 "but this type is missing an attribute wildcard",
16391 xmlSchemaGetComponentDesignation(&str, base));
16392 FREE_AND_NULL(str)
16394 } else if (xmlSchemaCheckCOSNSSubset(
16395 base->attributeWildcard, type->attributeWildcard))
16397 xmlChar *str = NULL;
16399 xmlSchemaCustomErr(ACTXT_CAST pctxt,
16400 XML_SCHEMAP_COS_CT_EXTENDS_1_3,
16401 NULL, type,
16402 "The attribute wildcard is not a valid "
16403 "superset of the one in the base %s",
16404 xmlSchemaGetComponentDesignation(&str, base));
16405 FREE_AND_NULL(str)
16408 #endif
16410 * SPEC (1.4) "One of the following must be true:"
16412 if ((type->contentTypeDef != NULL) &&
16413 (type->contentTypeDef == base->contentTypeDef)) {
16415 * SPEC (1.4.1) "The {content type} of the {base type definition}
16416 * and the {content type} of the complex type definition itself
16417 * must be the same simple type definition"
16418 * PASS
16420 } else if ((type->contentType == XML_SCHEMA_CONTENT_EMPTY) &&
16421 (base->contentType == XML_SCHEMA_CONTENT_EMPTY) ) {
16423 * SPEC (1.4.2) "The {content type} of both the {base type
16424 * definition} and the complex type definition itself must
16425 * be empty."
16426 * PASS
16428 } else {
16430 * SPEC (1.4.3) "All of the following must be true:"
16432 if (type->subtypes == NULL) {
16434 * SPEC 1.4.3.1 The {content type} of the complex type
16435 * definition itself must specify a particle.
16437 xmlSchemaPCustomErr(ctxt,
16438 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
16439 WXS_BASIC_CAST type, NULL,
16440 "The content type must specify a particle", NULL);
16441 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16444 * SPEC (1.4.3.2) "One of the following must be true:"
16446 if (base->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16448 * SPEC (1.4.3.2.1) "The {content type} of the {base type
16449 * definition} must be empty.
16450 * PASS
16452 } else {
16454 * SPEC (1.4.3.2.2) "All of the following must be true:"
16456 if ((type->contentType != base->contentType) ||
16457 ((type->contentType != XML_SCHEMA_CONTENT_MIXED) &&
16458 (type->contentType != XML_SCHEMA_CONTENT_ELEMENTS))) {
16460 * SPEC (1.4.3.2.2.1) "Both {content type}s must be mixed
16461 * or both must be element-only."
16463 xmlSchemaPCustomErr(ctxt,
16464 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
16465 WXS_BASIC_CAST type, NULL,
16466 "The content type of both, the type and its base "
16467 "type, must either 'mixed' or 'element-only'", NULL);
16468 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16471 * URGENT TODO SPEC (1.4.3.2.2.2) "The particle of the
16472 * complex type definition must be a `valid extension`
16473 * of the {base type definition}'s particle, as defined
16474 * in Particle Valid (Extension) ($3.9.6)."
16476 * NOTE that we won't check "Particle Valid (Extension)",
16477 * since it is ensured by the derivation process in
16478 * xmlSchemaTypeFixup(). We need to implement this when heading
16479 * for a construction API
16480 * TODO: !! This is needed to be checked if redefining a type !!
16484 * URGENT TODO (1.5)
16487 } else {
16489 * SPEC (2) "If the {base type definition} is a simple type definition,
16490 * then all of the following must be true:"
16492 if (type->contentTypeDef != base) {
16494 * SPEC (2.1) "The {content type} must be the same simple type
16495 * definition."
16497 xmlSchemaPCustomErr(ctxt,
16498 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
16499 WXS_BASIC_CAST type, NULL,
16500 "The content type must be the simple base type", NULL);
16501 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16503 if (base->flags & XML_SCHEMAS_TYPE_FINAL_EXTENSION) {
16505 * SPEC (2.2) "The {final} of the {base type definition} must not
16506 * contain extension"
16507 * NOTE that this is the same as (1.1).
16509 xmlSchemaPCustomErr(ctxt,
16510 XML_SCHEMAP_COS_CT_EXTENDS_1_1,
16511 WXS_BASIC_CAST type, NULL,
16512 "The 'final' of the base type definition "
16513 "contains 'extension'", NULL);
16514 return (XML_SCHEMAP_COS_CT_EXTENDS_1_1);
16517 return (0);
16521 * xmlSchemaCheckDerivationOKRestriction:
16522 * @ctxt: the schema parser context
16523 * @type: the complex type definition
16525 * (3.4.6) Constraints on Complex Type Definition Schema Components
16526 * Schema Component Constraint:
16527 * Derivation Valid (Restriction, Complex) (derivation-ok-restriction)
16529 * STATUS:
16530 * missing:
16531 * (5.4.2) ???
16533 * ATTENTION:
16534 * In XML Schema 1.1 this will be:
16535 * Validation Rule: Checking complex type subsumption
16537 * Returns 0 if the constraints are satisfied, a positive
16538 * error code if not and -1 if an internal error occurred.
16540 static int
16541 xmlSchemaCheckDerivationOKRestriction(xmlSchemaParserCtxtPtr ctxt,
16542 xmlSchemaTypePtr type)
16544 xmlSchemaTypePtr base;
16547 * TODO: Correct the error code; XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1 is used
16548 * temporarily only.
16550 base = type->baseType;
16551 if (! WXS_IS_COMPLEX(base)) {
16552 xmlSchemaCustomErr(ACTXT_CAST ctxt,
16553 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16554 type->node, WXS_BASIC_CAST type,
16555 "The base type must be a complex type", NULL, NULL);
16556 return(ctxt->err);
16558 if (base->flags & XML_SCHEMAS_TYPE_FINAL_RESTRICTION) {
16560 * SPEC (1) "The {base type definition} must be a complex type
16561 * definition whose {final} does not contain restriction."
16563 xmlSchemaCustomErr(ACTXT_CAST ctxt,
16564 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16565 type->node, WXS_BASIC_CAST type,
16566 "The 'final' of the base type definition "
16567 "contains 'restriction'", NULL, NULL);
16568 return (ctxt->err);
16571 * SPEC (2), (3) and (4)
16572 * Those are handled in a separate function, since the
16573 * same constraints are needed for redefinition of
16574 * attribute groups as well.
16576 if (xmlSchemaCheckDerivationOKRestriction2to4(ctxt,
16577 XML_SCHEMA_ACTION_DERIVE,
16578 WXS_BASIC_CAST type, WXS_BASIC_CAST base,
16579 type->attrUses, base->attrUses,
16580 type->attributeWildcard,
16581 base->attributeWildcard) == -1)
16583 return(-1);
16586 * SPEC (5) "One of the following must be true:"
16588 if (base->builtInType == XML_SCHEMAS_ANYTYPE) {
16590 * SPEC (5.1) "The {base type definition} must be the
16591 * `ur-type definition`."
16592 * PASS
16594 } else if ((type->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
16595 (type->contentType == XML_SCHEMA_CONTENT_BASIC)) {
16597 * SPEC (5.2.1) "The {content type} of the complex type definition
16598 * must be a simple type definition"
16600 * SPEC (5.2.2) "One of the following must be true:"
16602 if ((base->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
16603 (base->contentType == XML_SCHEMA_CONTENT_BASIC))
16605 int err;
16607 * SPEC (5.2.2.1) "The {content type} of the {base type
16608 * definition} must be a simple type definition from which
16609 * the {content type} is validly derived given the empty
16610 * set as defined in Type Derivation OK (Simple) ($3.14.6)."
16612 * ATTENTION TODO: This seems not needed if the type implicitly
16613 * derived from the base type.
16616 err = xmlSchemaCheckCOSSTDerivedOK(ACTXT_CAST ctxt,
16617 type->contentTypeDef, base->contentTypeDef, 0);
16618 if (err != 0) {
16619 xmlChar *strA = NULL, *strB = NULL;
16621 if (err == -1)
16622 return(-1);
16623 xmlSchemaCustomErr(ACTXT_CAST ctxt,
16624 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16625 NULL, WXS_BASIC_CAST type,
16626 "The {content type} %s is not validly derived from the "
16627 "base type's {content type} %s",
16628 xmlSchemaGetComponentDesignation(&strA,
16629 type->contentTypeDef),
16630 xmlSchemaGetComponentDesignation(&strB,
16631 base->contentTypeDef));
16632 FREE_AND_NULL(strA);
16633 FREE_AND_NULL(strB);
16634 return(ctxt->err);
16636 } else if ((base->contentType == XML_SCHEMA_CONTENT_MIXED) &&
16637 (xmlSchemaIsParticleEmptiable(
16638 (xmlSchemaParticlePtr) base->subtypes))) {
16640 * SPEC (5.2.2.2) "The {base type definition} must be mixed
16641 * and have a particle which is `emptiable` as defined in
16642 * Particle Emptiable ($3.9.6)."
16643 * PASS
16645 } else {
16646 xmlSchemaPCustomErr(ctxt,
16647 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16648 WXS_BASIC_CAST type, NULL,
16649 "The content type of the base type must be either "
16650 "a simple type or 'mixed' and an emptiable particle", NULL);
16651 return (ctxt->err);
16653 } else if (type->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16655 * SPEC (5.3.1) "The {content type} of the complex type itself must
16656 * be empty"
16658 if (base->contentType == XML_SCHEMA_CONTENT_EMPTY) {
16660 * SPEC (5.3.2.1) "The {content type} of the {base type
16661 * definition} must also be empty."
16662 * PASS
16664 } else if (((base->contentType == XML_SCHEMA_CONTENT_ELEMENTS) ||
16665 (base->contentType == XML_SCHEMA_CONTENT_MIXED)) &&
16666 xmlSchemaIsParticleEmptiable(
16667 (xmlSchemaParticlePtr) base->subtypes)) {
16669 * SPEC (5.3.2.2) "The {content type} of the {base type
16670 * definition} must be elementOnly or mixed and have a particle
16671 * which is `emptiable` as defined in Particle Emptiable ($3.9.6)."
16672 * PASS
16674 } else {
16675 xmlSchemaPCustomErr(ctxt,
16676 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16677 WXS_BASIC_CAST type, NULL,
16678 "The content type of the base type must be either "
16679 "empty or 'mixed' (or 'elements-only') and an emptiable "
16680 "particle", NULL);
16681 return (ctxt->err);
16683 } else if ((type->contentType == XML_SCHEMA_CONTENT_ELEMENTS) ||
16684 WXS_HAS_MIXED_CONTENT(type)) {
16686 * SPEC (5.4.1.1) "The {content type} of the complex type definition
16687 * itself must be element-only"
16689 if (WXS_HAS_MIXED_CONTENT(type) && (! WXS_HAS_MIXED_CONTENT(base))) {
16691 * SPEC (5.4.1.2) "The {content type} of the complex type
16692 * definition itself and of the {base type definition} must be
16693 * mixed"
16695 xmlSchemaPCustomErr(ctxt,
16696 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16697 WXS_BASIC_CAST type, NULL,
16698 "If the content type is 'mixed', then the content type of the "
16699 "base type must also be 'mixed'", NULL);
16700 return (ctxt->err);
16703 * SPEC (5.4.2) "The particle of the complex type definition itself
16704 * must be a `valid restriction` of the particle of the {content
16705 * type} of the {base type definition} as defined in Particle Valid
16706 * (Restriction) ($3.9.6).
16708 * URGENT TODO: (5.4.2)
16710 } else {
16711 xmlSchemaPCustomErr(ctxt,
16712 XML_SCHEMAP_DERIVATION_OK_RESTRICTION_1,
16713 WXS_BASIC_CAST type, NULL,
16714 "The type is not a valid restriction of its base type", NULL);
16715 return (ctxt->err);
16717 return (0);
16721 * xmlSchemaCheckCTComponent:
16722 * @ctxt: the schema parser context
16723 * @type: the complex type definition
16725 * (3.4.6) Constraints on Complex Type Definition Schema Components
16727 * Returns 0 if the constraints are satisfied, a positive
16728 * error code if not and -1 if an internal error occurred.
16730 static int
16731 xmlSchemaCheckCTComponent(xmlSchemaParserCtxtPtr ctxt,
16732 xmlSchemaTypePtr type)
16734 int ret;
16736 * Complex Type Definition Properties Correct
16738 ret = xmlSchemaCheckCTPropsCorrect(ctxt, type);
16739 if (ret != 0)
16740 return (ret);
16741 if (WXS_IS_EXTENSION(type))
16742 ret = xmlSchemaCheckCOSCTExtends(ctxt, type);
16743 else
16744 ret = xmlSchemaCheckDerivationOKRestriction(ctxt, type);
16745 return (ret);
16749 * xmlSchemaCheckSRCCT:
16750 * @ctxt: the schema parser context
16751 * @type: the complex type definition
16753 * (3.4.3) Constraints on XML Representations of Complex Type Definitions:
16754 * Schema Representation Constraint:
16755 * Complex Type Definition Representation OK (src-ct)
16757 * Returns 0 if the constraints are satisfied, a positive
16758 * error code if not and -1 if an internal error occurred.
16760 static int
16761 xmlSchemaCheckSRCCT(xmlSchemaParserCtxtPtr ctxt,
16762 xmlSchemaTypePtr type)
16764 xmlSchemaTypePtr base;
16765 int ret = 0;
16768 * TODO: Adjust the error codes here, as I used
16769 * XML_SCHEMAP_SRC_CT_1 only yet.
16771 base = type->baseType;
16772 if (! WXS_HAS_SIMPLE_CONTENT(type)) {
16774 * 1 If the <complexContent> alternative is chosen, the type definition
16775 * `resolved` to by the `actual value` of the base [attribute]
16776 * must be a complex type definition;
16778 if (! WXS_IS_COMPLEX(base)) {
16779 xmlChar *str = NULL;
16780 xmlSchemaPCustomErr(ctxt,
16781 XML_SCHEMAP_SRC_CT_1,
16782 WXS_BASIC_CAST type, type->node,
16783 "If using <complexContent>, the base type is expected to be "
16784 "a complex type. The base type '%s' is a simple type",
16785 xmlSchemaFormatQName(&str, base->targetNamespace,
16786 base->name));
16787 FREE_AND_NULL(str)
16788 return (XML_SCHEMAP_SRC_CT_1);
16790 } else {
16792 * SPEC
16793 * 2 If the <simpleContent> alternative is chosen, all of the
16794 * following must be true:
16795 * 2.1 The type definition `resolved` to by the `actual value` of the
16796 * base [attribute] must be one of the following:
16798 if (WXS_IS_SIMPLE(base)) {
16799 if (WXS_IS_EXTENSION(type) == 0) {
16800 xmlChar *str = NULL;
16802 * 2.1.3 only if the <extension> alternative is also
16803 * chosen, a simple type definition.
16805 /* TODO: Change error code to ..._SRC_CT_2_1_3. */
16806 xmlSchemaPCustomErr(ctxt,
16807 XML_SCHEMAP_SRC_CT_1,
16808 WXS_BASIC_CAST type, NULL,
16809 "If using <simpleContent> and <restriction>, the base "
16810 "type must be a complex type. The base type '%s' is "
16811 "a simple type",
16812 xmlSchemaFormatQName(&str, base->targetNamespace,
16813 base->name));
16814 FREE_AND_NULL(str)
16815 return (XML_SCHEMAP_SRC_CT_1);
16817 } else {
16818 /* Base type is a complex type. */
16819 if ((base->contentType == XML_SCHEMA_CONTENT_SIMPLE) ||
16820 (base->contentType == XML_SCHEMA_CONTENT_BASIC)) {
16822 * 2.1.1 a complex type definition whose {content type} is a
16823 * simple type definition;
16824 * PASS
16826 if (base->contentTypeDef == NULL) {
16827 xmlSchemaPCustomErr(ctxt, XML_SCHEMAP_INTERNAL,
16828 WXS_BASIC_CAST type, NULL,
16829 "Internal error: xmlSchemaCheckSRCCT, "
16830 "'%s', base type has no content type",
16831 type->name);
16832 return (-1);
16834 } else if ((base->contentType == XML_SCHEMA_CONTENT_MIXED) &&
16835 (WXS_IS_RESTRICTION(type))) {
16838 * 2.1.2 only if the <restriction> alternative is also
16839 * chosen, a complex type definition whose {content type}
16840 * is mixed and a particle emptiable.
16842 if (! xmlSchemaIsParticleEmptiable(
16843 (xmlSchemaParticlePtr) base->subtypes)) {
16844 ret = XML_SCHEMAP_SRC_CT_1;
16845 } else
16847 * Attention: at this point the <simpleType> child is in
16848 * ->contentTypeDef (put there during parsing).
16850 if (type->contentTypeDef == NULL) {
16851 xmlChar *str = NULL;
16853 * 2.2 If clause 2.1.2 above is satisfied, then there
16854 * must be a <simpleType> among the [children] of
16855 * <restriction>.
16857 /* TODO: Change error code to ..._SRC_CT_2_2. */
16858 xmlSchemaPCustomErr(ctxt,
16859 XML_SCHEMAP_SRC_CT_1,
16860 WXS_BASIC_CAST type, NULL,
16861 "A <simpleType> is expected among the children "
16862 "of <restriction>, if <simpleContent> is used and "
16863 "the base type '%s' is a complex type",
16864 xmlSchemaFormatQName(&str, base->targetNamespace,
16865 base->name));
16866 FREE_AND_NULL(str)
16867 return (XML_SCHEMAP_SRC_CT_1);
16869 } else {
16870 ret = XML_SCHEMAP_SRC_CT_1;
16873 if (ret > 0) {
16874 xmlChar *str = NULL;
16875 if (WXS_IS_RESTRICTION(type)) {
16876 xmlSchemaPCustomErr(ctxt,
16877 XML_SCHEMAP_SRC_CT_1,
16878 WXS_BASIC_CAST type, NULL,
16879 "If <simpleContent> and <restriction> is used, the "
16880 "base type must be a simple type or a complex type with "
16881 "mixed content and particle emptiable. The base type "
16882 "'%s' is none of those",
16883 xmlSchemaFormatQName(&str, base->targetNamespace,
16884 base->name));
16885 } else {
16886 xmlSchemaPCustomErr(ctxt,
16887 XML_SCHEMAP_SRC_CT_1,
16888 WXS_BASIC_CAST type, NULL,
16889 "If <simpleContent> and <extension> is used, the "
16890 "base type must be a simple type. The base type '%s' "
16891 "is a complex type",
16892 xmlSchemaFormatQName(&str, base->targetNamespace,
16893 base->name));
16895 FREE_AND_NULL(str)
16899 * SPEC (3) "The corresponding complex type definition component must
16900 * satisfy the conditions set out in Constraints on Complex Type
16901 * Definition Schema Components ($3.4.6);"
16902 * NOTE (3) will be done in xmlSchemaTypeFixup().
16905 * SPEC (4) If clause 2.2.1 or clause 2.2.2 in the correspondence specification
16906 * above for {attribute wildcard} is satisfied, the intensional
16907 * intersection must be expressible, as defined in Attribute Wildcard
16908 * Intersection ($3.10.6).
16909 * NOTE (4) is done in xmlSchemaFixupTypeAttributeUses().
16911 return (ret);
16914 #ifdef ENABLE_PARTICLE_RESTRICTION
16916 * xmlSchemaCheckParticleRangeOK:
16917 * @ctxt: the schema parser context
16918 * @type: the complex type definition
16920 * (3.9.6) Constraints on Particle Schema Components
16921 * Schema Component Constraint:
16922 * Occurrence Range OK (range-ok)
16924 * STATUS: complete
16926 * Returns 0 if the constraints are satisfied, a positive
16927 * error code if not and -1 if an internal error occurred.
16929 static int
16930 xmlSchemaCheckParticleRangeOK(int rmin, int rmax,
16931 int bmin, int bmax)
16933 if (rmin < bmin)
16934 return (1);
16935 if ((bmax != UNBOUNDED) &&
16936 (rmax > bmax))
16937 return (1);
16938 return (0);
16942 * xmlSchemaCheckRCaseNameAndTypeOK:
16943 * @ctxt: the schema parser context
16944 * @r: the restricting element declaration particle
16945 * @b: the base element declaration particle
16947 * (3.9.6) Constraints on Particle Schema Components
16948 * Schema Component Constraint:
16949 * Particle Restriction OK (Elt:Elt -- NameAndTypeOK)
16950 * (rcase-NameAndTypeOK)
16952 * STATUS:
16953 * MISSING (3.2.3)
16954 * CLARIFY: (3.2.2)
16956 * Returns 0 if the constraints are satisfied, a positive
16957 * error code if not and -1 if an internal error occurred.
16959 static int
16960 xmlSchemaCheckRCaseNameAndTypeOK(xmlSchemaParserCtxtPtr ctxt,
16961 xmlSchemaParticlePtr r,
16962 xmlSchemaParticlePtr b)
16964 xmlSchemaElementPtr elemR, elemB;
16966 /* TODO: Error codes (rcase-NameAndTypeOK). */
16967 elemR = (xmlSchemaElementPtr) r->children;
16968 elemB = (xmlSchemaElementPtr) b->children;
16970 * SPEC (1) "The declarations' {name}s and {target namespace}s are
16971 * the same."
16973 if ((elemR != elemB) &&
16974 ((! xmlStrEqual(elemR->name, elemB->name)) ||
16975 (! xmlStrEqual(elemR->targetNamespace, elemB->targetNamespace))))
16976 return (1);
16978 * SPEC (2) "R's occurrence range is a valid restriction of B's
16979 * occurrence range as defined by Occurrence Range OK ($3.9.6)."
16981 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
16982 b->minOccurs, b->maxOccurs) != 0)
16983 return (1);
16985 * SPEC (3.1) "Both B's declaration's {scope} and R's declaration's
16986 * {scope} are global."
16988 if (elemR == elemB)
16989 return (0);
16991 * SPEC (3.2.1) "Either B's {nillable} is true or R's {nillable} is false."
16993 if (((elemB->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) &&
16994 (elemR->flags & XML_SCHEMAS_ELEM_NILLABLE))
16995 return (1);
16997 * SPEC (3.2.2) "either B's declaration's {value constraint} is absent,
16998 * or is not fixed, or R's declaration's {value constraint} is fixed
16999 * with the same value."
17001 if ((elemB->value != NULL) && (elemB->flags & XML_SCHEMAS_ELEM_FIXED) &&
17002 ((elemR->value == NULL) ||
17003 ((elemR->flags & XML_SCHEMAS_ELEM_FIXED) == 0) ||
17004 /* TODO: Equality of the initial value or normalized or canonical? */
17005 (! xmlStrEqual(elemR->value, elemB->value))))
17006 return (1);
17008 * TODO: SPEC (3.2.3) "R's declaration's {identity-constraint
17009 * definitions} is a subset of B's declaration's {identity-constraint
17010 * definitions}, if any."
17012 if (elemB->idcs != NULL) {
17013 /* TODO */
17016 * SPEC (3.2.4) "R's declaration's {disallowed substitutions} is a
17017 * superset of B's declaration's {disallowed substitutions}."
17019 if (((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) &&
17020 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) == 0)) ||
17021 ((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) &&
17022 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) == 0)) ||
17023 ((elemB->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION) &&
17024 ((elemR->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION) == 0)))
17025 return (1);
17027 * SPEC (3.2.5) "R's {type definition} is validly derived given
17028 * {extension, list, union} from B's {type definition}"
17030 * BADSPEC TODO: What's the point of adding "list" and "union" to the
17031 * set, if the corresponding constraints handle "restriction" and
17032 * "extension" only?
17036 int set = 0;
17038 set |= SUBSET_EXTENSION;
17039 set |= SUBSET_LIST;
17040 set |= SUBSET_UNION;
17041 if (xmlSchemaCheckCOSDerivedOK(ACTXT_CAST ctxt, elemR->subtypes,
17042 elemB->subtypes, set) != 0)
17043 return (1);
17045 return (0);
17049 * xmlSchemaCheckRCaseNSCompat:
17050 * @ctxt: the schema parser context
17051 * @r: the restricting element declaration particle
17052 * @b: the base wildcard particle
17054 * (3.9.6) Constraints on Particle Schema Components
17055 * Schema Component Constraint:
17056 * Particle Derivation OK (Elt:Any -- NSCompat)
17057 * (rcase-NSCompat)
17059 * STATUS: complete
17061 * Returns 0 if the constraints are satisfied, a positive
17062 * error code if not and -1 if an internal error occurred.
17064 static int
17065 xmlSchemaCheckRCaseNSCompat(xmlSchemaParserCtxtPtr ctxt,
17066 xmlSchemaParticlePtr r,
17067 xmlSchemaParticlePtr b)
17069 /* TODO:Error codes (rcase-NSCompat). */
17071 * SPEC "For an element declaration particle to be a `valid restriction`
17072 * of a wildcard particle all of the following must be true:"
17074 * SPEC (1) "The element declaration's {target namespace} is `valid`
17075 * with respect to the wildcard's {namespace constraint} as defined by
17076 * Wildcard allows Namespace Name ($3.10.4)."
17078 if (xmlSchemaCheckCVCWildcardNamespace((xmlSchemaWildcardPtr) b->children,
17079 ((xmlSchemaElementPtr) r->children)->targetNamespace) != 0)
17080 return (1);
17082 * SPEC (2) "R's occurrence range is a valid restriction of B's
17083 * occurrence range as defined by Occurrence Range OK ($3.9.6)."
17085 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
17086 b->minOccurs, b->maxOccurs) != 0)
17087 return (1);
17089 return (0);
17093 * xmlSchemaCheckRCaseRecurseAsIfGroup:
17094 * @ctxt: the schema parser context
17095 * @r: the restricting element declaration particle
17096 * @b: the base model group particle
17098 * (3.9.6) Constraints on Particle Schema Components
17099 * Schema Component Constraint:
17100 * Particle Derivation OK (Elt:All/Choice/Sequence -- RecurseAsIfGroup)
17101 * (rcase-RecurseAsIfGroup)
17103 * STATUS: TODO
17105 * Returns 0 if the constraints are satisfied, a positive
17106 * error code if not and -1 if an internal error occurred.
17108 static int
17109 xmlSchemaCheckRCaseRecurseAsIfGroup(xmlSchemaParserCtxtPtr ctxt,
17110 xmlSchemaParticlePtr r,
17111 xmlSchemaParticlePtr b)
17113 /* TODO: Error codes (rcase-RecurseAsIfGroup). */
17114 TODO
17115 return (0);
17119 * xmlSchemaCheckRCaseNSSubset:
17120 * @ctxt: the schema parser context
17121 * @r: the restricting wildcard particle
17122 * @b: the base wildcard particle
17124 * (3.9.6) Constraints on Particle Schema Components
17125 * Schema Component Constraint:
17126 * Particle Derivation OK (Any:Any -- NSSubset)
17127 * (rcase-NSSubset)
17129 * STATUS: complete
17131 * Returns 0 if the constraints are satisfied, a positive
17132 * error code if not and -1 if an internal error occurred.
17134 static int
17135 xmlSchemaCheckRCaseNSSubset(xmlSchemaParserCtxtPtr ctxt,
17136 xmlSchemaParticlePtr r,
17137 xmlSchemaParticlePtr b,
17138 int isAnyTypeBase)
17140 /* TODO: Error codes (rcase-NSSubset). */
17142 * SPEC (1) "R's occurrence range is a valid restriction of B's
17143 * occurrence range as defined by Occurrence Range OK ($3.9.6)."
17145 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
17146 b->minOccurs, b->maxOccurs))
17147 return (1);
17149 * SPEC (2) "R's {namespace constraint} must be an intensional subset
17150 * of B's {namespace constraint} as defined by Wildcard Subset ($3.10.6)."
17152 if (xmlSchemaCheckCOSNSSubset((xmlSchemaWildcardPtr) r->children,
17153 (xmlSchemaWildcardPtr) b->children))
17154 return (1);
17156 * SPEC (3) "Unless B is the content model wildcard of the `ur-type
17157 * definition`, R's {process contents} must be identical to or stronger
17158 * than B's {process contents}, where strict is stronger than lax is
17159 * stronger than skip."
17161 if (! isAnyTypeBase) {
17162 if ( ((xmlSchemaWildcardPtr) r->children)->processContents <
17163 ((xmlSchemaWildcardPtr) b->children)->processContents)
17164 return (1);
17167 return (0);
17171 * xmlSchemaCheckCOSParticleRestrict:
17172 * @ctxt: the schema parser context
17173 * @type: the complex type definition
17175 * (3.9.6) Constraints on Particle Schema Components
17176 * Schema Component Constraint:
17177 * Particle Valid (Restriction) (cos-particle-restrict)
17179 * STATUS: TODO
17181 * Returns 0 if the constraints are satisfied, a positive
17182 * error code if not and -1 if an internal error occurred.
17184 static int
17185 xmlSchemaCheckCOSParticleRestrict(xmlSchemaParserCtxtPtr ctxt,
17186 xmlSchemaParticlePtr r,
17187 xmlSchemaParticlePtr b)
17189 int ret = 0;
17191 /*part = WXS_TYPE_PARTICLE(type);
17192 basePart = WXS_TYPE_PARTICLE(base);
17195 TODO
17198 * SPEC (1) "They are the same particle."
17200 if (r == b)
17201 return (0);
17204 return (0);
17207 #if 0
17209 * xmlSchemaCheckRCaseNSRecurseCheckCardinality:
17210 * @ctxt: the schema parser context
17211 * @r: the model group particle
17212 * @b: the base wildcard particle
17214 * (3.9.6) Constraints on Particle Schema Components
17215 * Schema Component Constraint:
17216 * Particle Derivation OK (All/Choice/Sequence:Any --
17217 * NSRecurseCheckCardinality)
17218 * (rcase-NSRecurseCheckCardinality)
17220 * STATUS: TODO: subst-groups
17222 * Returns 0 if the constraints are satisfied, a positive
17223 * error code if not and -1 if an internal error occurred.
17225 static int
17226 xmlSchemaCheckRCaseNSRecurseCheckCardinality(xmlSchemaParserCtxtPtr ctxt,
17227 xmlSchemaParticlePtr r,
17228 xmlSchemaParticlePtr b)
17230 xmlSchemaParticlePtr part;
17231 /* TODO: Error codes (rcase-NSRecurseCheckCardinality). */
17232 if ((r->children == NULL) || (r->children->children == NULL))
17233 return (-1);
17235 * SPEC "For a group particle to be a `valid restriction` of a
17236 * wildcard particle..."
17238 * SPEC (1) "Every member of the {particles} of the group is a `valid
17239 * restriction` of the wildcard as defined by
17240 * Particle Valid (Restriction) ($3.9.6)."
17242 part = (xmlSchemaParticlePtr) r->children->children;
17243 do {
17244 if (xmlSchemaCheckCOSParticleRestrict(ctxt, part, b))
17245 return (1);
17246 part = (xmlSchemaParticlePtr) part->next;
17247 } while (part != NULL);
17249 * SPEC (2) "The effective total range of the group [...] is a
17250 * valid restriction of B's occurrence range as defined by
17251 * Occurrence Range OK ($3.9.6)."
17253 if (xmlSchemaCheckParticleRangeOK(
17254 xmlSchemaGetParticleTotalRangeMin(r),
17255 xmlSchemaGetParticleTotalRangeMax(r),
17256 b->minOccurs, b->maxOccurs) != 0)
17257 return (1);
17258 return (0);
17260 #endif
17263 * xmlSchemaCheckRCaseRecurse:
17264 * @ctxt: the schema parser context
17265 * @r: the <all> or <sequence> model group particle
17266 * @b: the base <all> or <sequence> model group particle
17268 * (3.9.6) Constraints on Particle Schema Components
17269 * Schema Component Constraint:
17270 * Particle Derivation OK (All:All,Sequence:Sequence --
17271 Recurse)
17272 * (rcase-Recurse)
17274 * STATUS: ?
17275 * TODO: subst-groups
17277 * Returns 0 if the constraints are satisfied, a positive
17278 * error code if not and -1 if an internal error occurred.
17280 static int
17281 xmlSchemaCheckRCaseRecurse(xmlSchemaParserCtxtPtr ctxt,
17282 xmlSchemaParticlePtr r,
17283 xmlSchemaParticlePtr b)
17285 /* xmlSchemaParticlePtr part; */
17286 /* TODO: Error codes (rcase-Recurse). */
17287 if ((r->children == NULL) || (b->children == NULL) ||
17288 (r->children->type != b->children->type))
17289 return (-1);
17291 * SPEC "For an all or sequence group particle to be a `valid
17292 * restriction` of another group particle with the same {compositor}..."
17294 * SPEC (1) "R's occurrence range is a valid restriction of B's
17295 * occurrence range as defined by Occurrence Range OK ($3.9.6)."
17297 if (xmlSchemaCheckParticleRangeOK(r->minOccurs, r->maxOccurs,
17298 b->minOccurs, b->maxOccurs))
17299 return (1);
17302 return (0);
17305 #endif
17307 #define FACET_RESTR_MUTUAL_ERR(fac1, fac2) \
17308 xmlSchemaPCustomErrExt(pctxt, \
17309 XML_SCHEMAP_INVALID_FACET_VALUE, \
17310 WXS_BASIC_CAST fac1, fac1->node, \
17311 "It is an error for both '%s' and '%s' to be specified on the "\
17312 "same type definition", \
17313 BAD_CAST xmlSchemaFacetTypeToString(fac1->type), \
17314 BAD_CAST xmlSchemaFacetTypeToString(fac2->type), NULL);
17316 #define FACET_RESTR_ERR(fac1, msg) \
17317 xmlSchemaPCustomErr(pctxt, \
17318 XML_SCHEMAP_INVALID_FACET_VALUE, \
17319 WXS_BASIC_CAST fac1, fac1->node, \
17320 msg, NULL);
17322 #define FACET_RESTR_FIXED_ERR(fac) \
17323 xmlSchemaPCustomErr(pctxt, \
17324 XML_SCHEMAP_INVALID_FACET_VALUE, \
17325 WXS_BASIC_CAST fac, fac->node, \
17326 "The base type's facet is 'fixed', thus the value must not " \
17327 "differ", NULL);
17329 static void
17330 xmlSchemaDeriveFacetErr(xmlSchemaParserCtxtPtr pctxt,
17331 xmlSchemaFacetPtr facet1,
17332 xmlSchemaFacetPtr facet2,
17333 int lessGreater,
17334 int orEqual,
17335 int ofBase)
17337 xmlChar *msg = NULL;
17339 msg = xmlStrdup(BAD_CAST "'");
17340 msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facet1->type));
17341 msg = xmlStrcat(msg, BAD_CAST "' has to be");
17342 if (lessGreater == 0)
17343 msg = xmlStrcat(msg, BAD_CAST " equal to");
17344 if (lessGreater == 1)
17345 msg = xmlStrcat(msg, BAD_CAST " greater than");
17346 else
17347 msg = xmlStrcat(msg, BAD_CAST " less than");
17349 if (orEqual)
17350 msg = xmlStrcat(msg, BAD_CAST " or equal to");
17351 msg = xmlStrcat(msg, BAD_CAST " '");
17352 msg = xmlStrcat(msg, xmlSchemaFacetTypeToString(facet2->type));
17353 if (ofBase)
17354 msg = xmlStrcat(msg, BAD_CAST "' of the base type");
17355 else
17356 msg = xmlStrcat(msg, BAD_CAST "'");
17358 xmlSchemaPCustomErr(pctxt,
17359 XML_SCHEMAP_INVALID_FACET_VALUE,
17360 WXS_BASIC_CAST facet1, NULL,
17361 (const char *) msg, NULL);
17363 if (msg != NULL)
17364 xmlFree(msg);
17368 * xmlSchemaDeriveAndValidateFacets:
17370 * Schema Component Constraint: Simple Type Restriction (Facets)
17371 * (st-restrict-facets)
17373 static int
17374 xmlSchemaDeriveAndValidateFacets(xmlSchemaParserCtxtPtr pctxt,
17375 xmlSchemaTypePtr type)
17377 xmlSchemaTypePtr base = type->baseType;
17378 xmlSchemaFacetLinkPtr link, cur, last = NULL;
17379 xmlSchemaFacetPtr facet, bfacet,
17380 flength = NULL, ftotdig = NULL, ffracdig = NULL,
17381 fmaxlen = NULL, fminlen = NULL, /* facets of the current type */
17382 fmininc = NULL, fmaxinc = NULL,
17383 fminexc = NULL, fmaxexc = NULL,
17384 bflength = NULL, bftotdig = NULL, bffracdig = NULL,
17385 bfmaxlen = NULL, bfminlen = NULL, /* facets of the base type */
17386 bfmininc = NULL, bfmaxinc = NULL,
17387 bfminexc = NULL, bfmaxexc = NULL;
17388 int res; /* err = 0, fixedErr; */
17391 * SPEC st-restrict-facets 1:
17392 * "The {variety} of R is the same as that of B."
17395 * SPEC st-restrict-facets 2:
17396 * "If {variety} is atomic, the {primitive type definition}
17397 * of R is the same as that of B."
17399 * NOTE: we leave 1 & 2 out for now, since this will be
17400 * satisfied by the derivation process.
17401 * CONSTRUCTION TODO: Maybe needed if using a construction API.
17404 * SPEC st-restrict-facets 3:
17405 * "The {facets} of R are the union of S and the {facets}
17406 * of B, eliminating duplicates. To eliminate duplicates,
17407 * when a facet of the same kind occurs in both S and the
17408 * {facets} of B, the one in the {facets} of B is not
17409 * included, with the exception of enumeration and pattern
17410 * facets, for which multiple occurrences with distinct values
17411 * are allowed."
17414 if ((type->facetSet == NULL) && (base->facetSet == NULL))
17415 return (0);
17417 last = type->facetSet;
17418 if (last != NULL)
17419 while (last->next != NULL)
17420 last = last->next;
17422 for (cur = type->facetSet; cur != NULL; cur = cur->next) {
17423 facet = cur->facet;
17424 switch (facet->type) {
17425 case XML_SCHEMA_FACET_LENGTH:
17426 flength = facet; break;
17427 case XML_SCHEMA_FACET_MINLENGTH:
17428 fminlen = facet; break;
17429 case XML_SCHEMA_FACET_MININCLUSIVE:
17430 fmininc = facet; break;
17431 case XML_SCHEMA_FACET_MINEXCLUSIVE:
17432 fminexc = facet; break;
17433 case XML_SCHEMA_FACET_MAXLENGTH:
17434 fmaxlen = facet; break;
17435 case XML_SCHEMA_FACET_MAXINCLUSIVE:
17436 fmaxinc = facet; break;
17437 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
17438 fmaxexc = facet; break;
17439 case XML_SCHEMA_FACET_TOTALDIGITS:
17440 ftotdig = facet; break;
17441 case XML_SCHEMA_FACET_FRACTIONDIGITS:
17442 ffracdig = facet; break;
17443 default:
17444 break;
17447 for (cur = base->facetSet; cur != NULL; cur = cur->next) {
17448 facet = cur->facet;
17449 switch (facet->type) {
17450 case XML_SCHEMA_FACET_LENGTH:
17451 bflength = facet; break;
17452 case XML_SCHEMA_FACET_MINLENGTH:
17453 bfminlen = facet; break;
17454 case XML_SCHEMA_FACET_MININCLUSIVE:
17455 bfmininc = facet; break;
17456 case XML_SCHEMA_FACET_MINEXCLUSIVE:
17457 bfminexc = facet; break;
17458 case XML_SCHEMA_FACET_MAXLENGTH:
17459 bfmaxlen = facet; break;
17460 case XML_SCHEMA_FACET_MAXINCLUSIVE:
17461 bfmaxinc = facet; break;
17462 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
17463 bfmaxexc = facet; break;
17464 case XML_SCHEMA_FACET_TOTALDIGITS:
17465 bftotdig = facet; break;
17466 case XML_SCHEMA_FACET_FRACTIONDIGITS:
17467 bffracdig = facet; break;
17468 default:
17469 break;
17473 * length and minLength or maxLength (2.2) + (3.2)
17475 if (flength && (fminlen || fmaxlen)) {
17476 FACET_RESTR_ERR(flength, "It is an error for both 'length' and "
17477 "either of 'minLength' or 'maxLength' to be specified on "
17478 "the same type definition")
17481 * Mutual exclusions in the same derivation step.
17483 if ((fmaxinc) && (fmaxexc)) {
17485 * SCC "maxInclusive and maxExclusive"
17487 FACET_RESTR_MUTUAL_ERR(fmaxinc, fmaxexc)
17489 if ((fmininc) && (fminexc)) {
17491 * SCC "minInclusive and minExclusive"
17493 FACET_RESTR_MUTUAL_ERR(fmininc, fminexc)
17496 if (flength && bflength) {
17498 * SCC "length valid restriction"
17499 * The values have to be equal.
17501 res = xmlSchemaCompareValues(flength->val, bflength->val);
17502 if (res == -2)
17503 goto internal_error;
17504 if (res != 0)
17505 xmlSchemaDeriveFacetErr(pctxt, flength, bflength, 0, 0, 1);
17506 if ((res != 0) && (bflength->fixed)) {
17507 FACET_RESTR_FIXED_ERR(flength)
17511 if (fminlen && bfminlen) {
17513 * SCC "minLength valid restriction"
17514 * minLength >= BASE minLength
17516 res = xmlSchemaCompareValues(fminlen->val, bfminlen->val);
17517 if (res == -2)
17518 goto internal_error;
17519 if (res == -1)
17520 xmlSchemaDeriveFacetErr(pctxt, fminlen, bfminlen, 1, 1, 1);
17521 if ((res != 0) && (bfminlen->fixed)) {
17522 FACET_RESTR_FIXED_ERR(fminlen)
17525 if (fmaxlen && bfmaxlen) {
17527 * SCC "maxLength valid restriction"
17528 * maxLength <= BASE minLength
17530 res = xmlSchemaCompareValues(fmaxlen->val, bfmaxlen->val);
17531 if (res == -2)
17532 goto internal_error;
17533 if (res == 1)
17534 xmlSchemaDeriveFacetErr(pctxt, fmaxlen, bfmaxlen, -1, 1, 1);
17535 if ((res != 0) && (bfmaxlen->fixed)) {
17536 FACET_RESTR_FIXED_ERR(fmaxlen)
17540 * SCC "length and minLength or maxLength"
17542 if (! flength)
17543 flength = bflength;
17544 if (flength) {
17545 if (! fminlen)
17546 fminlen = bfminlen;
17547 if (fminlen) {
17548 /* (1.1) length >= minLength */
17549 res = xmlSchemaCompareValues(flength->val, fminlen->val);
17550 if (res == -2)
17551 goto internal_error;
17552 if (res == -1)
17553 xmlSchemaDeriveFacetErr(pctxt, flength, fminlen, 1, 1, 0);
17555 if (! fmaxlen)
17556 fmaxlen = bfmaxlen;
17557 if (fmaxlen) {
17558 /* (2.1) length <= maxLength */
17559 res = xmlSchemaCompareValues(flength->val, fmaxlen->val);
17560 if (res == -2)
17561 goto internal_error;
17562 if (res == 1)
17563 xmlSchemaDeriveFacetErr(pctxt, flength, fmaxlen, -1, 1, 0);
17566 if (fmaxinc) {
17568 * "maxInclusive"
17570 if (fmininc) {
17571 /* SCC "maxInclusive >= minInclusive" */
17572 res = xmlSchemaCompareValues(fmaxinc->val, fmininc->val);
17573 if (res == -2)
17574 goto internal_error;
17575 if (res == -1) {
17576 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, fmininc, 1, 1, 0);
17580 * SCC "maxInclusive valid restriction"
17582 if (bfmaxinc) {
17583 /* maxInclusive <= BASE maxInclusive */
17584 res = xmlSchemaCompareValues(fmaxinc->val, bfmaxinc->val);
17585 if (res == -2)
17586 goto internal_error;
17587 if (res == 1)
17588 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmaxinc, -1, 1, 1);
17589 if ((res != 0) && (bfmaxinc->fixed)) {
17590 FACET_RESTR_FIXED_ERR(fmaxinc)
17593 if (bfmaxexc) {
17594 /* maxInclusive < BASE maxExclusive */
17595 res = xmlSchemaCompareValues(fmaxinc->val, bfmaxexc->val);
17596 if (res == -2)
17597 goto internal_error;
17598 if (res != -1) {
17599 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmaxexc, -1, 0, 1);
17602 if (bfmininc) {
17603 /* maxInclusive >= BASE minInclusive */
17604 res = xmlSchemaCompareValues(fmaxinc->val, bfmininc->val);
17605 if (res == -2)
17606 goto internal_error;
17607 if (res == -1) {
17608 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfmininc, 1, 1, 1);
17611 if (bfminexc) {
17612 /* maxInclusive > BASE minExclusive */
17613 res = xmlSchemaCompareValues(fmaxinc->val, bfminexc->val);
17614 if (res == -2)
17615 goto internal_error;
17616 if (res != 1) {
17617 xmlSchemaDeriveFacetErr(pctxt, fmaxinc, bfminexc, 1, 0, 1);
17621 if (fmaxexc) {
17623 * "maxExclusive >= minExclusive"
17625 if (fminexc) {
17626 res = xmlSchemaCompareValues(fmaxexc->val, fminexc->val);
17627 if (res == -2)
17628 goto internal_error;
17629 if (res == -1) {
17630 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, fminexc, 1, 1, 0);
17634 * "maxExclusive valid restriction"
17636 if (bfmaxexc) {
17637 /* maxExclusive <= BASE maxExclusive */
17638 res = xmlSchemaCompareValues(fmaxexc->val, bfmaxexc->val);
17639 if (res == -2)
17640 goto internal_error;
17641 if (res == 1) {
17642 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmaxexc, -1, 1, 1);
17644 if ((res != 0) && (bfmaxexc->fixed)) {
17645 FACET_RESTR_FIXED_ERR(fmaxexc)
17648 if (bfmaxinc) {
17649 /* maxExclusive <= BASE maxInclusive */
17650 res = xmlSchemaCompareValues(fmaxexc->val, bfmaxinc->val);
17651 if (res == -2)
17652 goto internal_error;
17653 if (res == 1) {
17654 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmaxinc, -1, 1, 1);
17657 if (bfmininc) {
17658 /* maxExclusive > BASE minInclusive */
17659 res = xmlSchemaCompareValues(fmaxexc->val, bfmininc->val);
17660 if (res == -2)
17661 goto internal_error;
17662 if (res != 1) {
17663 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfmininc, 1, 0, 1);
17666 if (bfminexc) {
17667 /* maxExclusive > BASE minExclusive */
17668 res = xmlSchemaCompareValues(fmaxexc->val, bfminexc->val);
17669 if (res == -2)
17670 goto internal_error;
17671 if (res != 1) {
17672 xmlSchemaDeriveFacetErr(pctxt, fmaxexc, bfminexc, 1, 0, 1);
17676 if (fminexc) {
17678 * "minExclusive < maxInclusive"
17680 if (fmaxinc) {
17681 res = xmlSchemaCompareValues(fminexc->val, fmaxinc->val);
17682 if (res == -2)
17683 goto internal_error;
17684 if (res != -1) {
17685 xmlSchemaDeriveFacetErr(pctxt, fminexc, fmaxinc, -1, 0, 0);
17689 * "minExclusive valid restriction"
17691 if (bfminexc) {
17692 /* minExclusive >= BASE minExclusive */
17693 res = xmlSchemaCompareValues(fminexc->val, bfminexc->val);
17694 if (res == -2)
17695 goto internal_error;
17696 if (res == -1) {
17697 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfminexc, 1, 1, 1);
17699 if ((res != 0) && (bfminexc->fixed)) {
17700 FACET_RESTR_FIXED_ERR(fminexc)
17703 if (bfmaxinc) {
17704 /* minExclusive <= BASE maxInclusive */
17705 res = xmlSchemaCompareValues(fminexc->val, bfmaxinc->val);
17706 if (res == -2)
17707 goto internal_error;
17708 if (res == 1) {
17709 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmaxinc, -1, 1, 1);
17712 if (bfmininc) {
17713 /* minExclusive >= BASE minInclusive */
17714 res = xmlSchemaCompareValues(fminexc->val, bfmininc->val);
17715 if (res == -2)
17716 goto internal_error;
17717 if (res == -1) {
17718 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmininc, 1, 1, 1);
17721 if (bfmaxexc) {
17722 /* minExclusive < BASE maxExclusive */
17723 res = xmlSchemaCompareValues(fminexc->val, bfmaxexc->val);
17724 if (res == -2)
17725 goto internal_error;
17726 if (res != -1) {
17727 xmlSchemaDeriveFacetErr(pctxt, fminexc, bfmaxexc, -1, 0, 1);
17731 if (fmininc) {
17733 * "minInclusive < maxExclusive"
17735 if (fmaxexc) {
17736 res = xmlSchemaCompareValues(fmininc->val, fmaxexc->val);
17737 if (res == -2)
17738 goto internal_error;
17739 if (res != -1) {
17740 xmlSchemaDeriveFacetErr(pctxt, fmininc, fmaxexc, -1, 0, 0);
17744 * "minExclusive valid restriction"
17746 if (bfmininc) {
17747 /* minInclusive >= BASE minInclusive */
17748 res = xmlSchemaCompareValues(fmininc->val, bfmininc->val);
17749 if (res == -2)
17750 goto internal_error;
17751 if (res == -1) {
17752 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmininc, 1, 1, 1);
17754 if ((res != 0) && (bfmininc->fixed)) {
17755 FACET_RESTR_FIXED_ERR(fmininc)
17758 if (bfmaxinc) {
17759 /* minInclusive <= BASE maxInclusive */
17760 res = xmlSchemaCompareValues(fmininc->val, bfmaxinc->val);
17761 if (res == -2)
17762 goto internal_error;
17763 if (res == 1) {
17764 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmaxinc, -1, 1, 1);
17767 if (bfminexc) {
17768 /* minInclusive > BASE minExclusive */
17769 res = xmlSchemaCompareValues(fmininc->val, bfminexc->val);
17770 if (res == -2)
17771 goto internal_error;
17772 if (res != 1)
17773 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfminexc, 1, 0, 1);
17775 if (bfmaxexc) {
17776 /* minInclusive < BASE maxExclusive */
17777 res = xmlSchemaCompareValues(fmininc->val, bfmaxexc->val);
17778 if (res == -2)
17779 goto internal_error;
17780 if (res != -1)
17781 xmlSchemaDeriveFacetErr(pctxt, fmininc, bfmaxexc, -1, 0, 1);
17784 if (ftotdig && bftotdig) {
17786 * SCC " totalDigits valid restriction"
17787 * totalDigits <= BASE totalDigits
17789 res = xmlSchemaCompareValues(ftotdig->val, bftotdig->val);
17790 if (res == -2)
17791 goto internal_error;
17792 if (res == 1)
17793 xmlSchemaDeriveFacetErr(pctxt, ftotdig, bftotdig,
17794 -1, 1, 1);
17795 if ((res != 0) && (bftotdig->fixed)) {
17796 FACET_RESTR_FIXED_ERR(ftotdig)
17799 if (ffracdig && bffracdig) {
17801 * SCC "fractionDigits valid restriction"
17802 * fractionDigits <= BASE fractionDigits
17804 res = xmlSchemaCompareValues(ffracdig->val, bffracdig->val);
17805 if (res == -2)
17806 goto internal_error;
17807 if (res == 1)
17808 xmlSchemaDeriveFacetErr(pctxt, ffracdig, bffracdig,
17809 -1, 1, 1);
17810 if ((res != 0) && (bffracdig->fixed)) {
17811 FACET_RESTR_FIXED_ERR(ffracdig)
17815 * SCC "fractionDigits less than or equal to totalDigits"
17817 if (! ftotdig)
17818 ftotdig = bftotdig;
17819 if (! ffracdig)
17820 ffracdig = bffracdig;
17821 if (ftotdig && ffracdig) {
17822 res = xmlSchemaCompareValues(ffracdig->val, ftotdig->val);
17823 if (res == -2)
17824 goto internal_error;
17825 if (res == 1)
17826 xmlSchemaDeriveFacetErr(pctxt, ffracdig, ftotdig,
17827 -1, 1, 0);
17830 * *Enumerations* won' be added here, since only the first set
17831 * of enumerations in the ancestor-or-self axis is used
17832 * for validation, plus we need to use the base type of those
17833 * enumerations for whitespace.
17835 * *Patterns*: won't be add here, since they are ORed at
17836 * type level and ANDed at ancestor level. This will
17837 * happen during validation by walking the base axis
17838 * of the type.
17840 for (cur = base->facetSet; cur != NULL; cur = cur->next) {
17841 bfacet = cur->facet;
17843 * Special handling of enumerations and patterns.
17844 * TODO: hmm, they should not appear in the set, so remove this.
17846 if ((bfacet->type == XML_SCHEMA_FACET_PATTERN) ||
17847 (bfacet->type == XML_SCHEMA_FACET_ENUMERATION))
17848 continue;
17850 * Search for a duplicate facet in the current type.
17852 link = type->facetSet;
17853 /* err = 0; */
17854 /* fixedErr = 0; */
17855 while (link != NULL) {
17856 facet = link->facet;
17857 if (facet->type == bfacet->type) {
17858 switch (facet->type) {
17859 case XML_SCHEMA_FACET_WHITESPACE:
17861 * The whitespace must be stronger.
17863 if (facet->whitespace < bfacet->whitespace) {
17864 FACET_RESTR_ERR(facet,
17865 "The 'whitespace' value has to be equal to "
17866 "or stronger than the 'whitespace' value of "
17867 "the base type")
17869 if ((bfacet->fixed) &&
17870 (facet->whitespace != bfacet->whitespace)) {
17871 FACET_RESTR_FIXED_ERR(facet)
17873 break;
17874 default:
17875 break;
17877 /* Duplicate found. */
17878 break;
17880 link = link->next;
17883 * If no duplicate was found: add the base types's facet
17884 * to the set.
17886 if (link == NULL) {
17887 link = (xmlSchemaFacetLinkPtr)
17888 xmlMalloc(sizeof(xmlSchemaFacetLink));
17889 if (link == NULL) {
17890 xmlSchemaPErrMemory(pctxt,
17891 "deriving facets, creating a facet link", NULL);
17892 return (-1);
17894 link->facet = cur->facet;
17895 link->next = NULL;
17896 if (last == NULL)
17897 type->facetSet = link;
17898 else
17899 last->next = link;
17900 last = link;
17905 return (0);
17906 internal_error:
17907 PERROR_INT("xmlSchemaDeriveAndValidateFacets",
17908 "an error occurred");
17909 return (-1);
17912 static int
17913 xmlSchemaFinishMemberTypeDefinitionsProperty(xmlSchemaParserCtxtPtr pctxt,
17914 xmlSchemaTypePtr type)
17916 xmlSchemaTypeLinkPtr link, lastLink, prevLink, subLink, newLink;
17918 * The actual value is then formed by replacing any union type
17919 * definition in the `explicit members` with the members of their
17920 * {member type definitions}, in order.
17922 * TODO: There's a bug entry at
17923 * "http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005JulSep/0287.html"
17924 * which indicates that we'll keep the union types the future.
17926 link = type->memberTypes;
17927 while (link != NULL) {
17929 if (WXS_IS_TYPE_NOT_FIXED(link->type))
17930 xmlSchemaTypeFixup(link->type, ACTXT_CAST pctxt);
17932 if (WXS_IS_UNION(link->type)) {
17933 subLink = xmlSchemaGetUnionSimpleTypeMemberTypes(link->type);
17934 if (subLink != NULL) {
17935 link->type = subLink->type;
17936 if (subLink->next != NULL) {
17937 lastLink = link->next;
17938 subLink = subLink->next;
17939 prevLink = link;
17940 while (subLink != NULL) {
17941 newLink = (xmlSchemaTypeLinkPtr)
17942 xmlMalloc(sizeof(xmlSchemaTypeLink));
17943 if (newLink == NULL) {
17944 xmlSchemaPErrMemory(pctxt, "allocating a type link",
17945 NULL);
17946 return (-1);
17948 newLink->type = subLink->type;
17949 prevLink->next = newLink;
17950 prevLink = newLink;
17951 newLink->next = lastLink;
17953 subLink = subLink->next;
17958 link = link->next;
17960 return (0);
17963 static void
17964 xmlSchemaTypeFixupOptimFacets(xmlSchemaTypePtr type)
17966 int has = 0, needVal = 0, normVal = 0;
17968 has = (type->baseType->flags & XML_SCHEMAS_TYPE_HAS_FACETS) ? 1 : 0;
17969 if (has) {
17970 needVal = (type->baseType->flags &
17971 XML_SCHEMAS_TYPE_FACETSNEEDVALUE) ? 1 : 0;
17972 normVal = (type->baseType->flags &
17973 XML_SCHEMAS_TYPE_NORMVALUENEEDED) ? 1 : 0;
17975 if (type->facets != NULL) {
17976 xmlSchemaFacetPtr fac;
17978 for (fac = type->facets; fac != NULL; fac = fac->next) {
17979 switch (fac->type) {
17980 case XML_SCHEMA_FACET_WHITESPACE:
17981 break;
17982 case XML_SCHEMA_FACET_PATTERN:
17983 normVal = 1;
17984 has = 1;
17985 break;
17986 case XML_SCHEMA_FACET_ENUMERATION:
17987 needVal = 1;
17988 normVal = 1;
17989 has = 1;
17990 break;
17991 default:
17992 has = 1;
17993 break;
17997 if (normVal)
17998 type->flags |= XML_SCHEMAS_TYPE_NORMVALUENEEDED;
17999 if (needVal)
18000 type->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
18001 if (has)
18002 type->flags |= XML_SCHEMAS_TYPE_HAS_FACETS;
18004 if (has && (! needVal) && WXS_IS_ATOMIC(type)) {
18005 xmlSchemaTypePtr prim = xmlSchemaGetPrimitiveType(type);
18007 * OPTIMIZE VAL TODO: Some facets need a computed value.
18009 if ((prim->builtInType != XML_SCHEMAS_ANYSIMPLETYPE) &&
18010 (prim->builtInType != XML_SCHEMAS_STRING)) {
18011 type->flags |= XML_SCHEMAS_TYPE_FACETSNEEDVALUE;
18016 static int
18017 xmlSchemaTypeFixupWhitespace(xmlSchemaTypePtr type)
18022 * Evaluate the whitespace-facet value.
18024 if (WXS_IS_LIST(type)) {
18025 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
18026 return (0);
18027 } else if (WXS_IS_UNION(type))
18028 return (0);
18030 if (type->facetSet != NULL) {
18031 xmlSchemaFacetLinkPtr lin;
18033 for (lin = type->facetSet; lin != NULL; lin = lin->next) {
18034 if (lin->facet->type == XML_SCHEMA_FACET_WHITESPACE) {
18035 switch (lin->facet->whitespace) {
18036 case XML_SCHEMAS_FACET_PRESERVE:
18037 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE;
18038 break;
18039 case XML_SCHEMAS_FACET_REPLACE:
18040 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_REPLACE;
18041 break;
18042 case XML_SCHEMAS_FACET_COLLAPSE:
18043 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
18044 break;
18045 default:
18046 return (-1);
18048 return (0);
18053 * For all `atomic` datatypes other than string (and types `derived`
18054 * by `restriction` from it) the value of whiteSpace is fixed to
18055 * collapse
18058 xmlSchemaTypePtr anc;
18060 for (anc = type->baseType; anc != NULL &&
18061 anc->builtInType != XML_SCHEMAS_ANYTYPE;
18062 anc = anc->baseType) {
18064 if (anc->type == XML_SCHEMA_TYPE_BASIC) {
18065 if (anc->builtInType == XML_SCHEMAS_NORMSTRING) {
18066 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_REPLACE;
18068 } else if ((anc->builtInType == XML_SCHEMAS_STRING) ||
18069 (anc->builtInType == XML_SCHEMAS_ANYSIMPLETYPE)) {
18070 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE;
18072 } else
18073 type->flags |= XML_SCHEMAS_TYPE_WHITESPACE_COLLAPSE;
18074 break;
18078 return (0);
18081 static int
18082 xmlSchemaFixupSimpleTypeStageOne(xmlSchemaParserCtxtPtr pctxt,
18083 xmlSchemaTypePtr type)
18085 if (type->type != XML_SCHEMA_TYPE_SIMPLE)
18086 return(0);
18087 if (! WXS_IS_TYPE_NOT_FIXED_1(type))
18088 return(0);
18089 type->flags |= XML_SCHEMAS_TYPE_FIXUP_1;
18091 if (WXS_IS_LIST(type)) {
18093 * Corresponds to <simpleType><list>...
18095 if (type->subtypes == NULL) {
18097 * This one is really needed, so get out.
18099 PERROR_INT("xmlSchemaFixupSimpleTypeStageOne",
18100 "list type has no item-type assigned");
18101 return(-1);
18103 } else if (WXS_IS_UNION(type)) {
18105 * Corresponds to <simpleType><union>...
18107 if (type->memberTypes == NULL) {
18109 * This one is really needed, so get out.
18111 PERROR_INT("xmlSchemaFixupSimpleTypeStageOne",
18112 "union type has no member-types assigned");
18113 return(-1);
18115 } else {
18117 * Corresponds to <simpleType><restriction>...
18119 if (type->baseType == NULL) {
18120 PERROR_INT("xmlSchemaFixupSimpleTypeStageOne",
18121 "type has no base-type assigned");
18122 return(-1);
18124 if (WXS_IS_TYPE_NOT_FIXED_1(type->baseType))
18125 if (xmlSchemaFixupSimpleTypeStageOne(pctxt, type->baseType) == -1)
18126 return(-1);
18128 * Variety
18129 * If the <restriction> alternative is chosen, then the
18130 * {variety} of the {base type definition}.
18132 if (WXS_IS_ATOMIC(type->baseType))
18133 type->flags |= XML_SCHEMAS_TYPE_VARIETY_ATOMIC;
18134 else if (WXS_IS_LIST(type->baseType)) {
18135 type->flags |= XML_SCHEMAS_TYPE_VARIETY_LIST;
18137 * Inherit the itemType.
18139 type->subtypes = type->baseType->subtypes;
18140 } else if (WXS_IS_UNION(type->baseType)) {
18141 type->flags |= XML_SCHEMAS_TYPE_VARIETY_UNION;
18143 * NOTE that we won't assign the memberTypes of the base,
18144 * since this will make trouble when freeing them; we will
18145 * use a lookup function to access them instead.
18149 return(0);
18152 #ifdef DEBUG_TYPE
18153 static void
18154 xmlSchemaDebugFixedType(xmlSchemaParserCtxtPtr pctxt,
18155 xmlSchemaTypePtr type)
18157 if (type->node != NULL) {
18158 xmlGenericError(xmlGenericErrorContext,
18159 "Type of %s : %s:%d :", name,
18160 type->node->doc->URL,
18161 xmlGetLineNo(type->node));
18162 } else {
18163 xmlGenericError(xmlGenericErrorContext, "Type of %s :", name);
18165 if ((WXS_IS_SIMPLE(type)) || (WXS_IS_COMPLEX(type))) {
18166 switch (type->contentType) {
18167 case XML_SCHEMA_CONTENT_SIMPLE:
18168 xmlGenericError(xmlGenericErrorContext, "simple\n");
18169 break;
18170 case XML_SCHEMA_CONTENT_ELEMENTS:
18171 xmlGenericError(xmlGenericErrorContext, "elements\n");
18172 break;
18173 case XML_SCHEMA_CONTENT_UNKNOWN:
18174 xmlGenericError(xmlGenericErrorContext, "unknown !!!\n");
18175 break;
18176 case XML_SCHEMA_CONTENT_EMPTY:
18177 xmlGenericError(xmlGenericErrorContext, "empty\n");
18178 break;
18179 case XML_SCHEMA_CONTENT_MIXED:
18180 if (xmlSchemaIsParticleEmptiable((xmlSchemaParticlePtr)
18181 type->subtypes))
18182 xmlGenericError(xmlGenericErrorContext,
18183 "mixed as emptiable particle\n");
18184 else
18185 xmlGenericError(xmlGenericErrorContext, "mixed\n");
18186 break;
18187 /* Removed, since not used. */
18189 case XML_SCHEMA_CONTENT_MIXED_OR_ELEMENTS:
18190 xmlGenericError(xmlGenericErrorContext, "mixed or elems\n");
18191 break;
18193 case XML_SCHEMA_CONTENT_BASIC:
18194 xmlGenericError(xmlGenericErrorContext, "basic\n");
18195 break;
18196 default:
18197 xmlGenericError(xmlGenericErrorContext,
18198 "not registered !!!\n");
18199 break;
18203 #endif
18206 * 3.14.6 Constraints on Simple Type Definition Schema Components
18208 static int
18209 xmlSchemaFixupSimpleTypeStageTwo(xmlSchemaParserCtxtPtr pctxt,
18210 xmlSchemaTypePtr type)
18212 int res, olderrs = pctxt->nberrors;
18214 if (type->type != XML_SCHEMA_TYPE_SIMPLE)
18215 return(-1);
18217 if (! WXS_IS_TYPE_NOT_FIXED(type))
18218 return(0);
18220 type->flags |= XML_SCHEMAS_TYPE_INTERNAL_RESOLVED;
18221 type->contentType = XML_SCHEMA_CONTENT_SIMPLE;
18223 if (type->baseType == NULL) {
18224 PERROR_INT("xmlSchemaFixupSimpleTypeStageTwo",
18225 "missing baseType");
18226 goto exit_failure;
18228 if (WXS_IS_TYPE_NOT_FIXED(type->baseType))
18229 xmlSchemaTypeFixup(type->baseType, ACTXT_CAST pctxt);
18231 * If a member type of a union is a union itself, we need to substitute
18232 * that member type for its member types.
18233 * NOTE that this might change in WXS 1.1; i.e. we will keep the union
18234 * types in WXS 1.1.
18236 if ((type->memberTypes != NULL) &&
18237 (xmlSchemaFinishMemberTypeDefinitionsProperty(pctxt, type) == -1))
18238 return(-1);
18240 * SPEC src-simple-type 1
18241 * "The corresponding simple type definition, if any, must satisfy
18242 * the conditions set out in Constraints on Simple Type Definition
18243 * Schema Components ($3.14.6)."
18246 * Schema Component Constraint: Simple Type Definition Properties Correct
18247 * (st-props-correct)
18249 res = xmlSchemaCheckSTPropsCorrect(pctxt, type);
18250 HFAILURE HERROR
18252 * Schema Component Constraint: Derivation Valid (Restriction, Simple)
18253 * (cos-st-restricts)
18255 res = xmlSchemaCheckCOSSTRestricts(pctxt, type);
18256 HFAILURE HERROR
18258 * TODO: Removed the error report, since it got annoying to get an
18259 * extra error report, if anything failed until now.
18260 * Enable this if needed.
18262 * xmlSchemaPErr(ctxt, type->node,
18263 * XML_SCHEMAP_SRC_SIMPLE_TYPE_1,
18264 * "Simple type '%s' does not satisfy the constraints "
18265 * "on simple type definitions.\n",
18266 * type->name, NULL);
18269 * Schema Component Constraint: Simple Type Restriction (Facets)
18270 * (st-restrict-facets)
18272 res = xmlSchemaCheckFacetValues(type, pctxt);
18273 HFAILURE HERROR
18274 if ((type->facetSet != NULL) ||
18275 (type->baseType->facetSet != NULL)) {
18276 res = xmlSchemaDeriveAndValidateFacets(pctxt, type);
18277 HFAILURE HERROR
18280 * Whitespace value.
18282 res = xmlSchemaTypeFixupWhitespace(type);
18283 HFAILURE HERROR
18284 xmlSchemaTypeFixupOptimFacets(type);
18286 exit_error:
18287 #ifdef DEBUG_TYPE
18288 xmlSchemaDebugFixedType(pctxt, type);
18289 #endif
18290 if (olderrs != pctxt->nberrors)
18291 return(pctxt->err);
18292 return(0);
18294 exit_failure:
18295 #ifdef DEBUG_TYPE
18296 xmlSchemaDebugFixedType(pctxt, type);
18297 #endif
18298 return(-1);
18301 static int
18302 xmlSchemaFixupComplexType(xmlSchemaParserCtxtPtr pctxt,
18303 xmlSchemaTypePtr type)
18305 int res = 0, olderrs = pctxt->nberrors;
18306 xmlSchemaTypePtr baseType = type->baseType;
18308 if (! WXS_IS_TYPE_NOT_FIXED(type))
18309 return(0);
18310 type->flags |= XML_SCHEMAS_TYPE_INTERNAL_RESOLVED;
18311 if (baseType == NULL) {
18312 PERROR_INT("xmlSchemaFixupComplexType",
18313 "missing baseType");
18314 goto exit_failure;
18317 * Fixup the base type.
18319 if (WXS_IS_TYPE_NOT_FIXED(baseType))
18320 xmlSchemaTypeFixup(baseType, ACTXT_CAST pctxt);
18321 if (baseType->flags & XML_SCHEMAS_TYPE_INTERNAL_INVALID) {
18323 * Skip fixup if the base type is invalid.
18324 * TODO: Generate a warning!
18326 return(0);
18329 * This basically checks if the base type can be derived.
18331 res = xmlSchemaCheckSRCCT(pctxt, type);
18332 HFAILURE HERROR
18334 * Fixup the content type.
18336 if (type->contentType == XML_SCHEMA_CONTENT_SIMPLE) {
18338 * Corresponds to <complexType><simpleContent>...
18340 if ((WXS_IS_COMPLEX(baseType)) &&
18341 (baseType->contentTypeDef != NULL) &&
18342 (WXS_IS_RESTRICTION(type))) {
18343 xmlSchemaTypePtr contentBase, content;
18344 #ifdef ENABLE_NAMED_LOCALS
18345 char buf[30];
18346 const xmlChar *tmpname;
18347 #endif
18349 * SPEC (1) If <restriction> + base type is <complexType>,
18350 * "whose own {content type} is a simple type..."
18352 if (type->contentTypeDef != NULL) {
18354 * SPEC (1.1) "the simple type definition corresponding to the
18355 * <simpleType> among the [children] of <restriction> if there
18356 * is one;"
18357 * Note that this "<simpleType> among the [children]" was put
18358 * into ->contentTypeDef during parsing.
18360 contentBase = type->contentTypeDef;
18361 type->contentTypeDef = NULL;
18362 } else {
18364 * (1.2) "...otherwise (<restriction> has no <simpleType>
18365 * among its [children]), the simple type definition which
18366 * is the {content type} of the ... base type."
18368 contentBase = baseType->contentTypeDef;
18371 * SPEC
18372 * "... a simple type definition which restricts the simple
18373 * type definition identified in clause 1.1 or clause 1.2
18374 * with a set of facet components"
18376 * Create the anonymous simple type, which will be the content
18377 * type of the complex type.
18379 #ifdef ENABLE_NAMED_LOCALS
18380 snprintf(buf, 29, "#scST%d", ++(pctxt->counter));
18381 tmpname = xmlDictLookup(pctxt->dict, BAD_CAST buf, -1);
18382 content = xmlSchemaAddType(pctxt, pctxt->schema,
18383 XML_SCHEMA_TYPE_SIMPLE, tmpname, type->targetNamespace,
18384 type->node, 0);
18385 #else
18386 content = xmlSchemaAddType(pctxt, pctxt->schema,
18387 XML_SCHEMA_TYPE_SIMPLE, NULL, type->targetNamespace,
18388 type->node, 0);
18389 #endif
18390 if (content == NULL)
18391 goto exit_failure;
18393 * We will use the same node as for the <complexType>
18394 * to have it somehow anchored in the schema doc.
18396 content->type = XML_SCHEMA_TYPE_SIMPLE;
18397 content->baseType = contentBase;
18399 * Move the facets, previously anchored on the
18400 * complexType during parsing.
18402 content->facets = type->facets;
18403 type->facets = NULL;
18404 content->facetSet = type->facetSet;
18405 type->facetSet = NULL;
18407 type->contentTypeDef = content;
18408 if (WXS_IS_TYPE_NOT_FIXED(contentBase))
18409 xmlSchemaTypeFixup(contentBase, ACTXT_CAST pctxt);
18411 * Fixup the newly created type. We don't need to check
18412 * for circularity here.
18414 res = xmlSchemaFixupSimpleTypeStageOne(pctxt, content);
18415 HFAILURE HERROR
18416 res = xmlSchemaFixupSimpleTypeStageTwo(pctxt, content);
18417 HFAILURE HERROR
18419 } else if ((WXS_IS_COMPLEX(baseType)) &&
18420 (baseType->contentType == XML_SCHEMA_CONTENT_MIXED) &&
18421 (WXS_IS_RESTRICTION(type))) {
18423 * SPEC (2) If <restriction> + base is a mixed <complexType> with
18424 * an emptiable particle, then a simple type definition which
18425 * restricts the <restriction>'s <simpleType> child.
18427 if ((type->contentTypeDef == NULL) ||
18428 (type->contentTypeDef->baseType == NULL)) {
18430 * TODO: Check if this ever happens.
18432 xmlSchemaPCustomErr(pctxt,
18433 XML_SCHEMAP_INTERNAL,
18434 WXS_BASIC_CAST type, NULL,
18435 "Internal error: xmlSchemaTypeFixup, "
18436 "complex type '%s': the <simpleContent><restriction> "
18437 "is missing a <simpleType> child, but was not caught "
18438 "by xmlSchemaCheckSRCCT()", type->name);
18439 goto exit_failure;
18441 } else if ((WXS_IS_COMPLEX(baseType)) && WXS_IS_EXTENSION(type)) {
18443 * SPEC (3) If <extension> + base is <complexType> with
18444 * <simpleType> content, "...then the {content type} of that
18445 * complex type definition"
18447 if (baseType->contentTypeDef == NULL) {
18449 * TODO: Check if this ever happens. xmlSchemaCheckSRCCT
18450 * should have caught this already.
18452 xmlSchemaPCustomErr(pctxt,
18453 XML_SCHEMAP_INTERNAL,
18454 WXS_BASIC_CAST type, NULL,
18455 "Internal error: xmlSchemaTypeFixup, "
18456 "complex type '%s': the <extension>ed base type is "
18457 "a complex type with no simple content type",
18458 type->name);
18459 goto exit_failure;
18461 type->contentTypeDef = baseType->contentTypeDef;
18462 } else if ((WXS_IS_SIMPLE(baseType)) && WXS_IS_EXTENSION(type)) {
18464 * SPEC (4) <extension> + base is <simpleType>
18465 * "... then that simple type definition"
18467 type->contentTypeDef = baseType;
18468 } else {
18470 * TODO: Check if this ever happens.
18472 xmlSchemaPCustomErr(pctxt,
18473 XML_SCHEMAP_INTERNAL,
18474 WXS_BASIC_CAST type, NULL,
18475 "Internal error: xmlSchemaTypeFixup, "
18476 "complex type '%s' with <simpleContent>: unhandled "
18477 "derivation case", type->name);
18478 goto exit_failure;
18480 } else {
18481 int dummySequence = 0;
18482 xmlSchemaParticlePtr particle =
18483 (xmlSchemaParticlePtr) type->subtypes;
18485 * Corresponds to <complexType><complexContent>...
18487 * NOTE that the effective mixed was already set during parsing of
18488 * <complexType> and <complexContent>; its flag value is
18489 * XML_SCHEMAS_TYPE_MIXED.
18491 * Compute the "effective content":
18492 * (2.1.1) + (2.1.2) + (2.1.3)
18494 if ((particle == NULL) ||
18495 ((particle->type == XML_SCHEMA_TYPE_PARTICLE) &&
18496 ((particle->children->type == XML_SCHEMA_TYPE_ALL) ||
18497 (particle->children->type == XML_SCHEMA_TYPE_SEQUENCE) ||
18498 ((particle->children->type == XML_SCHEMA_TYPE_CHOICE) &&
18499 (particle->minOccurs == 0))) &&
18500 ( ((xmlSchemaTreeItemPtr) particle->children)->children == NULL))) {
18501 if (type->flags & XML_SCHEMAS_TYPE_MIXED) {
18503 * SPEC (2.1.4) "If the `effective mixed` is true, then
18504 * a particle whose properties are as follows:..."
18506 * Empty sequence model group with
18507 * minOccurs/maxOccurs = 1 (i.e. a "particle emptiable").
18508 * NOTE that we sill assign it the <complexType> node to
18509 * somehow anchor it in the doc.
18511 if ((particle == NULL) ||
18512 (particle->children->type != XML_SCHEMA_TYPE_SEQUENCE)) {
18514 * Create the particle.
18516 particle = xmlSchemaAddParticle(pctxt,
18517 type->node, 1, 1);
18518 if (particle == NULL)
18519 goto exit_failure;
18521 * Create the model group.
18522 */ /* URGENT TODO: avoid adding to pending items. */
18523 particle->children = (xmlSchemaTreeItemPtr)
18524 xmlSchemaAddModelGroup(pctxt, pctxt->schema,
18525 XML_SCHEMA_TYPE_SEQUENCE, type->node);
18526 if (particle->children == NULL)
18527 goto exit_failure;
18529 type->subtypes = (xmlSchemaTypePtr) particle;
18531 dummySequence = 1;
18532 type->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
18533 } else {
18535 * SPEC (2.1.5) "otherwise empty"
18537 type->contentType = XML_SCHEMA_CONTENT_EMPTY;
18539 } else {
18541 * SPEC (2.2) "otherwise the particle corresponding to the
18542 * <all>, <choice>, <group> or <sequence> among the
18543 * [children]."
18545 type->contentType = XML_SCHEMA_CONTENT_ELEMENTS;
18548 * Compute the "content type".
18550 if (WXS_IS_RESTRICTION(type)) {
18552 * SPEC (3.1) "If <restriction>..."
18553 * (3.1.1) + (3.1.2) */
18554 if (type->contentType != XML_SCHEMA_CONTENT_EMPTY) {
18555 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
18556 type->contentType = XML_SCHEMA_CONTENT_MIXED;
18558 } else {
18560 * SPEC (3.2) "If <extension>..."
18562 if (type->contentType == XML_SCHEMA_CONTENT_EMPTY) {
18564 * SPEC (3.2.1)
18565 * "If the `effective content` is empty, then the
18566 * {content type} of the [...] base ..."
18568 type->contentType = baseType->contentType;
18569 type->subtypes = baseType->subtypes;
18571 * Fixes bug #347316:
18572 * This is the case when the base type has a simple
18573 * type definition as content.
18575 type->contentTypeDef = baseType->contentTypeDef;
18577 * NOTE that the effective mixed is ignored here.
18579 } else if (baseType->contentType == XML_SCHEMA_CONTENT_EMPTY) {
18581 * SPEC (3.2.2)
18583 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
18584 type->contentType = XML_SCHEMA_CONTENT_MIXED;
18585 } else {
18587 * SPEC (3.2.3)
18589 if (type->flags & XML_SCHEMAS_TYPE_MIXED)
18590 type->contentType = XML_SCHEMA_CONTENT_MIXED;
18592 * "A model group whose {compositor} is sequence and whose
18593 * {particles} are..."
18595 if ((WXS_TYPE_PARTICLE(type) != NULL) &&
18596 (WXS_TYPE_PARTICLE_TERM(type) != NULL) &&
18597 ((WXS_TYPE_PARTICLE_TERM(type))->type ==
18598 XML_SCHEMA_TYPE_ALL))
18601 * SPEC cos-all-limited (1)
18603 xmlSchemaCustomErr(ACTXT_CAST pctxt,
18604 /* TODO: error code */
18605 XML_SCHEMAP_COS_ALL_LIMITED,
18606 WXS_ITEM_NODE(type), NULL,
18607 "The type has an 'all' model group in its "
18608 "{content type} and thus cannot be derived from "
18609 "a non-empty type, since this would produce a "
18610 "'sequence' model group containing the 'all' "
18611 "model group; 'all' model groups are not "
18612 "allowed to appear inside other model groups",
18613 NULL, NULL);
18615 } else if ((WXS_TYPE_PARTICLE(baseType) != NULL) &&
18616 (WXS_TYPE_PARTICLE_TERM(baseType) != NULL) &&
18617 ((WXS_TYPE_PARTICLE_TERM(baseType))->type ==
18618 XML_SCHEMA_TYPE_ALL))
18621 * SPEC cos-all-limited (1)
18623 xmlSchemaCustomErr(ACTXT_CAST pctxt,
18624 /* TODO: error code */
18625 XML_SCHEMAP_COS_ALL_LIMITED,
18626 WXS_ITEM_NODE(type), NULL,
18627 "A type cannot be derived by extension from a type "
18628 "which has an 'all' model group in its "
18629 "{content type}, since this would produce a "
18630 "'sequence' model group containing the 'all' "
18631 "model group; 'all' model groups are not "
18632 "allowed to appear inside other model groups",
18633 NULL, NULL);
18635 } else if ((!dummySequence) && (baseType->subtypes != NULL)) {
18636 xmlSchemaTreeItemPtr effectiveContent =
18637 (xmlSchemaTreeItemPtr) type->subtypes;
18639 * Create the particle.
18641 particle = xmlSchemaAddParticle(pctxt,
18642 type->node, 1, 1);
18643 if (particle == NULL)
18644 goto exit_failure;
18646 * Create the "sequence" model group.
18648 particle->children = (xmlSchemaTreeItemPtr)
18649 xmlSchemaAddModelGroup(pctxt, pctxt->schema,
18650 XML_SCHEMA_TYPE_SEQUENCE, type->node);
18651 if (particle->children == NULL)
18652 goto exit_failure;
18653 WXS_TYPE_CONTENTTYPE(type) = (xmlSchemaTypePtr) particle;
18655 * SPEC "the particle of the {content type} of
18656 * the ... base ..."
18657 * Create a duplicate of the base type's particle
18658 * and assign its "term" to it.
18660 particle->children->children =
18661 (xmlSchemaTreeItemPtr) xmlSchemaAddParticle(pctxt,
18662 type->node,
18663 ((xmlSchemaParticlePtr) baseType->subtypes)->minOccurs,
18664 ((xmlSchemaParticlePtr) baseType->subtypes)->maxOccurs);
18665 if (particle->children->children == NULL)
18666 goto exit_failure;
18667 particle = (xmlSchemaParticlePtr)
18668 particle->children->children;
18669 particle->children =
18670 ((xmlSchemaParticlePtr) baseType->subtypes)->children;
18672 * SPEC "followed by the `effective content`."
18674 particle->next = effectiveContent;
18676 * This all will result in:
18677 * new-particle
18678 * --> new-sequence(
18679 * new-particle
18680 * --> base-model,
18681 * this-particle
18682 * --> this-model
18685 } else {
18687 * This is the case when there is already an empty
18688 * <sequence> with minOccurs==maxOccurs==1.
18689 * Just add the base types's content type.
18690 * NOTE that, although we miss to add an intermediate
18691 * <sequence>, this should produce no difference to
18692 * neither the regex compilation of the content model,
18693 * nor to the complex type constraints.
18695 particle->children->children =
18696 (xmlSchemaTreeItemPtr) baseType->subtypes;
18702 * Now fixup attribute uses:
18703 * - expand attr. group references
18704 * - intersect attribute wildcards
18705 * - inherit attribute uses of the base type
18706 * - inherit or union attr. wildcards if extending
18707 * - apply attr. use prohibitions if restricting
18709 res = xmlSchemaFixupTypeAttributeUses(pctxt, type);
18710 HFAILURE HERROR
18712 * Apply the complex type component constraints; this will not
18713 * check attributes, since this is done in
18714 * xmlSchemaFixupTypeAttributeUses().
18716 res = xmlSchemaCheckCTComponent(pctxt, type);
18717 HFAILURE HERROR
18719 #ifdef DEBUG_TYPE
18720 xmlSchemaDebugFixedType(pctxt, type);
18721 #endif
18722 if (olderrs != pctxt->nberrors)
18723 return(pctxt->err);
18724 else
18725 return(0);
18727 exit_error:
18728 type->flags |= XML_SCHEMAS_TYPE_INTERNAL_INVALID;
18729 #ifdef DEBUG_TYPE
18730 xmlSchemaDebugFixedType(pctxt, type);
18731 #endif
18732 return(pctxt->err);
18734 exit_failure:
18735 type->flags |= XML_SCHEMAS_TYPE_INTERNAL_INVALID;
18736 #ifdef DEBUG_TYPE
18737 xmlSchemaDebugFixedType(pctxt, type);
18738 #endif
18739 return(-1);
18744 * xmlSchemaTypeFixup:
18745 * @typeDecl: the schema type definition
18746 * @ctxt: the schema parser context
18748 * Fixes the content model of the type.
18749 * URGENT TODO: We need an int result!
18751 static int
18752 xmlSchemaTypeFixup(xmlSchemaTypePtr type,
18753 xmlSchemaAbstractCtxtPtr actxt)
18755 if (type == NULL)
18756 return(0);
18757 if (actxt->type != XML_SCHEMA_CTXT_PARSER) {
18758 AERROR_INT("xmlSchemaTypeFixup",
18759 "this function needs a parser context");
18760 return(-1);
18762 if (! WXS_IS_TYPE_NOT_FIXED(type))
18763 return(0);
18764 if (type->type == XML_SCHEMA_TYPE_COMPLEX)
18765 return(xmlSchemaFixupComplexType(PCTXT_CAST actxt, type));
18766 else if (type->type == XML_SCHEMA_TYPE_SIMPLE)
18767 return(xmlSchemaFixupSimpleTypeStageTwo(PCTXT_CAST actxt, type));
18768 return(0);
18772 * xmlSchemaCheckFacet:
18773 * @facet: the facet
18774 * @typeDecl: the schema type definition
18775 * @pctxt: the schema parser context or NULL
18776 * @name: the optional name of the type
18778 * Checks and computes the values of facets.
18780 * Returns 0 if valid, a positive error code if not valid and
18781 * -1 in case of an internal or API error.
18784 xmlSchemaCheckFacet(xmlSchemaFacetPtr facet,
18785 xmlSchemaTypePtr typeDecl,
18786 xmlSchemaParserCtxtPtr pctxt,
18787 const xmlChar * name ATTRIBUTE_UNUSED)
18789 int ret = 0, ctxtGiven;
18791 if ((facet == NULL) || (typeDecl == NULL))
18792 return(-1);
18794 * TODO: will the parser context be given if used from
18795 * the relaxNG module?
18797 if (pctxt == NULL)
18798 ctxtGiven = 0;
18799 else
18800 ctxtGiven = 1;
18802 switch (facet->type) {
18803 case XML_SCHEMA_FACET_MININCLUSIVE:
18804 case XML_SCHEMA_FACET_MINEXCLUSIVE:
18805 case XML_SCHEMA_FACET_MAXINCLUSIVE:
18806 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
18807 case XML_SCHEMA_FACET_ENUMERATION: {
18809 * Okay we need to validate the value
18810 * at that point.
18812 xmlSchemaTypePtr base;
18814 /* 4.3.5.5 Constraints on enumeration Schema Components
18815 * Schema Component Constraint: enumeration valid restriction
18816 * It is an `error` if any member of {value} is not in the
18817 * `value space` of {base type definition}.
18819 * minInclusive, maxInclusive, minExclusive, maxExclusive:
18820 * The value `must` be in the
18821 * `value space` of the `base type`.
18824 * This function is intended to deliver a compiled value
18825 * on the facet. In this implementation of XML Schemata the
18826 * type holding a facet, won't be a built-in type.
18827 * Thus to ensure that other API
18828 * calls (relaxng) do work, if the given type is a built-in
18829 * type, we will assume that the given built-in type *is
18830 * already* the base type.
18832 if (typeDecl->type != XML_SCHEMA_TYPE_BASIC) {
18833 base = typeDecl->baseType;
18834 if (base == NULL) {
18835 PERROR_INT("xmlSchemaCheckFacet",
18836 "a type user derived type has no base type");
18837 return (-1);
18839 } else
18840 base = typeDecl;
18842 if (! ctxtGiven) {
18844 * A context is needed if called from RelaxNG.
18846 pctxt = xmlSchemaNewParserCtxt("*");
18847 if (pctxt == NULL)
18848 return (-1);
18851 * NOTE: This call does not check the content nodes,
18852 * since they are not available:
18853 * facet->node is just the node holding the facet
18854 * definition, *not* the attribute holding the *value*
18855 * of the facet.
18857 ret = xmlSchemaVCheckCVCSimpleType(
18858 ACTXT_CAST pctxt, facet->node, base,
18859 facet->value, &(facet->val), 1, 1, 0);
18860 if (ret != 0) {
18861 if (ret < 0) {
18862 /* No error message for RelaxNG. */
18863 if (ctxtGiven) {
18864 xmlSchemaCustomErr(ACTXT_CAST pctxt,
18865 XML_SCHEMAP_INTERNAL, facet->node, NULL,
18866 "Internal error: xmlSchemaCheckFacet, "
18867 "failed to validate the value '%s' of the "
18868 "facet '%s' against the base type",
18869 facet->value, xmlSchemaFacetTypeToString(facet->type));
18871 goto internal_error;
18873 ret = XML_SCHEMAP_INVALID_FACET_VALUE;
18874 /* No error message for RelaxNG. */
18875 if (ctxtGiven) {
18876 xmlChar *str = NULL;
18878 xmlSchemaCustomErr(ACTXT_CAST pctxt,
18879 ret, facet->node, WXS_BASIC_CAST facet,
18880 "The value '%s' of the facet does not validate "
18881 "against the base type '%s'",
18882 facet->value,
18883 xmlSchemaFormatQName(&str,
18884 base->targetNamespace, base->name));
18885 FREE_AND_NULL(str);
18887 goto exit;
18888 } else if (facet->val == NULL) {
18889 if (ctxtGiven) {
18890 PERROR_INT("xmlSchemaCheckFacet",
18891 "value was not computed");
18893 TODO
18895 break;
18897 case XML_SCHEMA_FACET_PATTERN:
18898 facet->regexp = xmlRegexpCompile(facet->value);
18899 if (facet->regexp == NULL) {
18900 ret = XML_SCHEMAP_REGEXP_INVALID;
18901 /* No error message for RelaxNG. */
18902 if (ctxtGiven) {
18903 xmlSchemaCustomErr(ACTXT_CAST pctxt,
18904 ret, facet->node, WXS_BASIC_CAST typeDecl,
18905 "The value '%s' of the facet 'pattern' is not a "
18906 "valid regular expression",
18907 facet->value, NULL);
18910 break;
18911 case XML_SCHEMA_FACET_TOTALDIGITS:
18912 case XML_SCHEMA_FACET_FRACTIONDIGITS:
18913 case XML_SCHEMA_FACET_LENGTH:
18914 case XML_SCHEMA_FACET_MAXLENGTH:
18915 case XML_SCHEMA_FACET_MINLENGTH:
18917 if (facet->type == XML_SCHEMA_FACET_TOTALDIGITS) {
18918 ret = xmlSchemaValidatePredefinedType(
18919 xmlSchemaGetBuiltInType(XML_SCHEMAS_PINTEGER),
18920 facet->value, &(facet->val));
18921 } else {
18922 ret = xmlSchemaValidatePredefinedType(
18923 xmlSchemaGetBuiltInType(XML_SCHEMAS_NNINTEGER),
18924 facet->value, &(facet->val));
18926 if (ret != 0) {
18927 if (ret < 0) {
18928 /* No error message for RelaxNG. */
18929 if (ctxtGiven) {
18930 PERROR_INT("xmlSchemaCheckFacet",
18931 "validating facet value");
18933 goto internal_error;
18935 ret = XML_SCHEMAP_INVALID_FACET_VALUE;
18936 /* No error message for RelaxNG. */
18937 if (ctxtGiven) {
18938 /* error code */
18939 xmlSchemaCustomErr4(ACTXT_CAST pctxt,
18940 ret, facet->node, WXS_BASIC_CAST typeDecl,
18941 "The value '%s' of the facet '%s' is not a valid '%s'",
18942 facet->value,
18943 xmlSchemaFacetTypeToString(facet->type),
18944 (facet->type != XML_SCHEMA_FACET_TOTALDIGITS) ?
18945 BAD_CAST "nonNegativeInteger" :
18946 BAD_CAST "positiveInteger",
18947 NULL);
18950 break;
18952 case XML_SCHEMA_FACET_WHITESPACE:{
18953 if (xmlStrEqual(facet->value, BAD_CAST "preserve")) {
18954 facet->whitespace = XML_SCHEMAS_FACET_PRESERVE;
18955 } else if (xmlStrEqual(facet->value, BAD_CAST "replace")) {
18956 facet->whitespace = XML_SCHEMAS_FACET_REPLACE;
18957 } else if (xmlStrEqual(facet->value, BAD_CAST "collapse")) {
18958 facet->whitespace = XML_SCHEMAS_FACET_COLLAPSE;
18959 } else {
18960 ret = XML_SCHEMAP_INVALID_FACET_VALUE;
18961 /* No error message for RelaxNG. */
18962 if (ctxtGiven) {
18963 /* error was previously: XML_SCHEMAP_INVALID_WHITE_SPACE */
18964 xmlSchemaCustomErr(ACTXT_CAST pctxt,
18965 ret, facet->node, WXS_BASIC_CAST typeDecl,
18966 "The value '%s' of the facet 'whitespace' is not "
18967 "valid", facet->value, NULL);
18971 default:
18972 break;
18974 exit:
18975 if ((! ctxtGiven) && (pctxt != NULL))
18976 xmlSchemaFreeParserCtxt(pctxt);
18977 return (ret);
18978 internal_error:
18979 if ((! ctxtGiven) && (pctxt != NULL))
18980 xmlSchemaFreeParserCtxt(pctxt);
18981 return (-1);
18985 * xmlSchemaCheckFacetValues:
18986 * @typeDecl: the schema type definition
18987 * @ctxt: the schema parser context
18989 * Checks the default values types, especially for facets
18991 static int
18992 xmlSchemaCheckFacetValues(xmlSchemaTypePtr typeDecl,
18993 xmlSchemaParserCtxtPtr pctxt)
18995 int res, olderrs = pctxt->nberrors;
18996 const xmlChar *name = typeDecl->name;
18998 * NOTE: It is intended to use the facets list, instead
18999 * of facetSet.
19001 if (typeDecl->facets != NULL) {
19002 xmlSchemaFacetPtr facet = typeDecl->facets;
19005 * Temporarily assign the "schema" to the validation context
19006 * of the parser context. This is needed for NOTATION validation.
19008 if (pctxt->vctxt == NULL) {
19009 if (xmlSchemaCreateVCtxtOnPCtxt(pctxt) == -1)
19010 return(-1);
19012 pctxt->vctxt->schema = pctxt->schema;
19013 while (facet != NULL) {
19014 res = xmlSchemaCheckFacet(facet, typeDecl, pctxt, name);
19015 HFAILURE
19016 facet = facet->next;
19018 pctxt->vctxt->schema = NULL;
19020 if (olderrs != pctxt->nberrors)
19021 return(pctxt->err);
19022 return(0);
19023 exit_failure:
19024 return(-1);
19028 * xmlSchemaGetCircModelGrDefRef:
19029 * @ctxtMGroup: the searched model group
19030 * @selfMGroup: the second searched model group
19031 * @particle: the first particle
19033 * This one is intended to be used by
19034 * xmlSchemaCheckGroupDefCircular only.
19036 * Returns the particle with the circular model group definition reference,
19037 * otherwise NULL.
19039 static xmlSchemaTreeItemPtr
19040 xmlSchemaGetCircModelGrDefRef(xmlSchemaModelGroupDefPtr groupDef,
19041 xmlSchemaTreeItemPtr particle)
19043 xmlSchemaTreeItemPtr circ = NULL;
19044 xmlSchemaTreeItemPtr term;
19045 xmlSchemaModelGroupDefPtr gdef;
19047 for (; particle != NULL; particle = particle->next) {
19048 term = particle->children;
19049 if (term == NULL)
19050 continue;
19051 switch (term->type) {
19052 case XML_SCHEMA_TYPE_GROUP:
19053 gdef = (xmlSchemaModelGroupDefPtr) term;
19054 if (gdef == groupDef)
19055 return (particle);
19057 * Mark this model group definition to avoid infinite
19058 * recursion on circular references not yet examined.
19060 if (gdef->flags & XML_SCHEMA_MODEL_GROUP_DEF_MARKED)
19061 continue;
19062 if (gdef->children != NULL) {
19063 gdef->flags |= XML_SCHEMA_MODEL_GROUP_DEF_MARKED;
19064 circ = xmlSchemaGetCircModelGrDefRef(groupDef,
19065 gdef->children->children);
19066 gdef->flags ^= XML_SCHEMA_MODEL_GROUP_DEF_MARKED;
19067 if (circ != NULL)
19068 return (circ);
19070 break;
19071 case XML_SCHEMA_TYPE_SEQUENCE:
19072 case XML_SCHEMA_TYPE_CHOICE:
19073 case XML_SCHEMA_TYPE_ALL:
19074 circ = xmlSchemaGetCircModelGrDefRef(groupDef, term->children);
19075 if (circ != NULL)
19076 return (circ);
19077 break;
19078 default:
19079 break;
19082 return (NULL);
19086 * xmlSchemaCheckGroupDefCircular:
19087 * @item: the model group definition
19088 * @ctxt: the parser context
19089 * @name: the name
19091 * Checks for circular references to model group definitions.
19093 static void
19094 xmlSchemaCheckGroupDefCircular(xmlSchemaModelGroupDefPtr item,
19095 xmlSchemaParserCtxtPtr ctxt)
19098 * Schema Component Constraint: Model Group Correct
19099 * 2 Circular groups are disallowed. That is, within the {particles}
19100 * of a group there must not be at any depth a particle whose {term}
19101 * is the group itself.
19103 if ((item == NULL) ||
19104 (item->type != XML_SCHEMA_TYPE_GROUP) ||
19105 (item->children == NULL))
19106 return;
19108 xmlSchemaTreeItemPtr circ;
19110 circ = xmlSchemaGetCircModelGrDefRef(item, item->children->children);
19111 if (circ != NULL) {
19112 xmlChar *str = NULL;
19114 * TODO: The error report is not adequate: this constraint
19115 * is defined for model groups but not definitions, but since
19116 * there cannot be any circular model groups without a model group
19117 * definition (if not using a construction API), we check those
19118 * definitions only.
19120 xmlSchemaPCustomErr(ctxt,
19121 XML_SCHEMAP_MG_PROPS_CORRECT_2,
19122 NULL, WXS_ITEM_NODE(circ),
19123 "Circular reference to the model group definition '%s' "
19124 "defined", xmlSchemaFormatQName(&str,
19125 item->targetNamespace, item->name));
19126 FREE_AND_NULL(str)
19128 * NOTE: We will cut the reference to avoid further
19129 * confusion of the processor. This is a fatal error.
19131 circ->children = NULL;
19137 * xmlSchemaModelGroupToModelGroupDefFixup:
19138 * @ctxt: the parser context
19139 * @mg: the model group
19141 * Assigns the model group of model group definitions to the "term"
19142 * of the referencing particle.
19143 * In xmlSchemaResolveModelGroupParticleReferences the model group
19144 * definitions were assigned to the "term", since needed for the
19145 * circularity check.
19147 * Schema Component Constraint:
19148 * All Group Limited (cos-all-limited) (1.2)
19150 static void
19151 xmlSchemaModelGroupToModelGroupDefFixup(
19152 xmlSchemaParserCtxtPtr ctxt ATTRIBUTE_UNUSED,
19153 xmlSchemaModelGroupPtr mg)
19155 xmlSchemaParticlePtr particle = WXS_MODELGROUP_PARTICLE(mg);
19157 while (particle != NULL) {
19158 if ((WXS_PARTICLE_TERM(particle) == NULL) ||
19159 ((WXS_PARTICLE_TERM(particle))->type !=
19160 XML_SCHEMA_TYPE_GROUP))
19162 particle = WXS_PTC_CAST particle->next;
19163 continue;
19165 if (WXS_MODELGROUPDEF_MODEL(WXS_PARTICLE_TERM(particle)) == NULL) {
19167 * TODO: Remove the particle.
19169 WXS_PARTICLE_TERM(particle) = NULL;
19170 particle = WXS_PTC_CAST particle->next;
19171 continue;
19174 * Assign the model group to the {term} of the particle.
19176 WXS_PARTICLE_TERM(particle) =
19177 WXS_TREE_CAST WXS_MODELGROUPDEF_MODEL(WXS_PARTICLE_TERM(particle));
19179 particle = WXS_PTC_CAST particle->next;
19184 * xmlSchemaCheckAttrGroupCircularRecur:
19185 * @ctxtGr: the searched attribute group
19186 * @attr: the current attribute list to be processed
19188 * This one is intended to be used by
19189 * xmlSchemaCheckAttrGroupCircular only.
19191 * Returns the circular attribute group reference, otherwise NULL.
19193 static xmlSchemaQNameRefPtr
19194 xmlSchemaCheckAttrGroupCircularRecur(xmlSchemaAttributeGroupPtr ctxtGr,
19195 xmlSchemaItemListPtr list)
19197 xmlSchemaAttributeGroupPtr gr;
19198 xmlSchemaQNameRefPtr ref, circ;
19199 int i;
19201 * We will search for an attribute group reference which
19202 * references the context attribute group.
19204 for (i = 0; i < list->nbItems; i++) {
19205 ref = list->items[i];
19206 if ((ref->type == XML_SCHEMA_EXTRA_QNAMEREF) &&
19207 (ref->itemType == XML_SCHEMA_TYPE_ATTRIBUTEGROUP) &&
19208 (ref->item != NULL))
19210 gr = WXS_ATTR_GROUP_CAST ref->item;
19211 if (gr == ctxtGr)
19212 return(ref);
19213 if (gr->flags & XML_SCHEMAS_ATTRGROUP_MARKED)
19214 continue;
19216 * Mark as visited to avoid infinite recursion on
19217 * circular references not yet examined.
19219 if ((gr->attrUses) &&
19220 (gr->flags & XML_SCHEMAS_ATTRGROUP_HAS_REFS))
19222 gr->flags |= XML_SCHEMAS_ATTRGROUP_MARKED;
19223 circ = xmlSchemaCheckAttrGroupCircularRecur(ctxtGr,
19224 (xmlSchemaItemListPtr) gr->attrUses);
19225 gr->flags ^= XML_SCHEMAS_ATTRGROUP_MARKED;
19226 if (circ != NULL)
19227 return (circ);
19232 return (NULL);
19236 * xmlSchemaCheckAttrGroupCircular:
19237 * attrGr: the attribute group definition
19238 * @ctxt: the parser context
19239 * @name: the name
19241 * Checks for circular references of attribute groups.
19243 static int
19244 xmlSchemaCheckAttrGroupCircular(xmlSchemaAttributeGroupPtr attrGr,
19245 xmlSchemaParserCtxtPtr ctxt)
19248 * Schema Representation Constraint:
19249 * Attribute Group Definition Representation OK
19250 * 3 Circular group reference is disallowed outside <redefine>.
19251 * That is, unless this element information item's parent is
19252 * <redefine>, then among the [children], if any, there must
19253 * not be an <attributeGroup> with ref [attribute] which resolves
19254 * to the component corresponding to this <attributeGroup>. Indirect
19255 * circularity is also ruled out. That is, when QName resolution
19256 * (Schema Document) ($3.15.3) is applied to a `QName` arising from
19257 * any <attributeGroup>s with a ref [attribute] among the [children],
19258 * it must not be the case that a `QName` is encountered at any depth
19259 * which resolves to the component corresponding to this <attributeGroup>.
19261 if (attrGr->attrUses == NULL)
19262 return(0);
19263 else if ((attrGr->flags & XML_SCHEMAS_ATTRGROUP_HAS_REFS) == 0)
19264 return(0);
19265 else {
19266 xmlSchemaQNameRefPtr circ;
19268 circ = xmlSchemaCheckAttrGroupCircularRecur(attrGr,
19269 (xmlSchemaItemListPtr) attrGr->attrUses);
19270 if (circ != NULL) {
19271 xmlChar *str = NULL;
19273 * TODO: Report the referenced attr group as QName.
19275 xmlSchemaPCustomErr(ctxt,
19276 XML_SCHEMAP_SRC_ATTRIBUTE_GROUP_3,
19277 NULL, WXS_ITEM_NODE(WXS_BASIC_CAST circ),
19278 "Circular reference to the attribute group '%s' "
19279 "defined", xmlSchemaGetComponentQName(&str, attrGr));
19280 FREE_AND_NULL(str);
19282 * NOTE: We will cut the reference to avoid further
19283 * confusion of the processor.
19284 * BADSPEC TODO: The spec should define how to process in this case.
19286 circ->item = NULL;
19287 return(ctxt->err);
19290 return(0);
19293 static int
19294 xmlSchemaAttributeGroupExpandRefs(xmlSchemaParserCtxtPtr pctxt,
19295 xmlSchemaAttributeGroupPtr attrGr);
19298 * xmlSchemaExpandAttributeGroupRefs:
19299 * @pctxt: the parser context
19300 * @node: the node of the component holding the attribute uses
19301 * @completeWild: the intersected wildcard to be returned
19302 * @list: the attribute uses
19304 * Substitutes contained attribute group references
19305 * for their attribute uses. Wildcards are intersected.
19306 * Attribute use prohibitions are removed from the list
19307 * and returned via the @prohibs list.
19308 * Pointlessness of attr. prohibs, if a matching attr. decl
19309 * is existent a well, are checked.
19311 static int
19312 xmlSchemaExpandAttributeGroupRefs(xmlSchemaParserCtxtPtr pctxt,
19313 xmlSchemaBasicItemPtr item,
19314 xmlSchemaWildcardPtr *completeWild,
19315 xmlSchemaItemListPtr list,
19316 xmlSchemaItemListPtr prohibs)
19318 xmlSchemaAttributeGroupPtr gr;
19319 xmlSchemaAttributeUsePtr use;
19320 xmlSchemaItemListPtr sublist;
19321 int i, j;
19322 int created = (*completeWild == NULL) ? 0 : 1;
19324 if (prohibs)
19325 prohibs->nbItems = 0;
19327 for (i = 0; i < list->nbItems; i++) {
19328 use = list->items[i];
19330 if (use->type == XML_SCHEMA_EXTRA_ATTR_USE_PROHIB) {
19331 if (prohibs == NULL) {
19332 PERROR_INT("xmlSchemaExpandAttributeGroupRefs",
19333 "unexpected attr prohibition found");
19334 return(-1);
19337 * Remove from attribute uses.
19339 if (xmlSchemaItemListRemove(list, i) == -1)
19340 return(-1);
19341 i--;
19343 * Note that duplicate prohibitions were already
19344 * handled at parsing time.
19347 * Add to list of prohibitions.
19349 xmlSchemaItemListAddSize(prohibs, 2, use);
19350 continue;
19352 if ((use->type == XML_SCHEMA_EXTRA_QNAMEREF) &&
19353 ((WXS_QNAME_CAST use)->itemType == XML_SCHEMA_TYPE_ATTRIBUTEGROUP))
19355 if ((WXS_QNAME_CAST use)->item == NULL)
19356 return(-1);
19357 gr = WXS_ATTR_GROUP_CAST (WXS_QNAME_CAST use)->item;
19359 * Expand the referenced attr. group.
19360 * TODO: remove this, this is done in a previous step, so
19361 * already done here.
19363 if ((gr->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED) == 0) {
19364 if (xmlSchemaAttributeGroupExpandRefs(pctxt, gr) == -1)
19365 return(-1);
19368 * Build the 'complete' wildcard; i.e. intersect multiple
19369 * wildcards.
19371 if (gr->attributeWildcard != NULL) {
19372 if (*completeWild == NULL) {
19373 *completeWild = gr->attributeWildcard;
19374 } else {
19375 if (! created) {
19376 xmlSchemaWildcardPtr tmpWild;
19379 * Copy the first encountered wildcard as context,
19380 * except for the annotation.
19382 * Although the complete wildcard might not correspond
19383 * to any node in the schema, we will anchor it on
19384 * the node of the owner component.
19386 tmpWild = xmlSchemaAddWildcard(pctxt, pctxt->schema,
19387 XML_SCHEMA_TYPE_ANY_ATTRIBUTE,
19388 WXS_ITEM_NODE(item));
19389 if (tmpWild == NULL)
19390 return(-1);
19391 if (xmlSchemaCloneWildcardNsConstraints(pctxt,
19392 tmpWild, *completeWild) == -1)
19393 return (-1);
19394 tmpWild->processContents = (*completeWild)->processContents;
19395 *completeWild = tmpWild;
19396 created = 1;
19399 if (xmlSchemaIntersectWildcards(pctxt, *completeWild,
19400 gr->attributeWildcard) == -1)
19401 return(-1);
19405 * Just remove the reference if the referenced group does not
19406 * contain any attribute uses.
19408 sublist = ((xmlSchemaItemListPtr) gr->attrUses);
19409 if ((sublist == NULL) || sublist->nbItems == 0) {
19410 if (xmlSchemaItemListRemove(list, i) == -1)
19411 return(-1);
19412 i--;
19413 continue;
19416 * Add the attribute uses.
19418 list->items[i] = sublist->items[0];
19419 if (sublist->nbItems != 1) {
19420 for (j = 1; j < sublist->nbItems; j++) {
19421 i++;
19422 if (xmlSchemaItemListInsert(list,
19423 sublist->items[j], i) == -1)
19424 return(-1);
19431 * Handle pointless prohibitions of declared attributes.
19433 if (prohibs && (prohibs->nbItems != 0) && (list->nbItems != 0)) {
19434 xmlSchemaAttributeUseProhibPtr prohib;
19436 for (i = prohibs->nbItems -1; i >= 0; i--) {
19437 prohib = prohibs->items[i];
19438 for (j = 0; j < list->nbItems; j++) {
19439 use = list->items[j];
19441 if ((prohib->name == WXS_ATTRUSE_DECL_NAME(use)) &&
19442 (prohib->targetNamespace == WXS_ATTRUSE_DECL_TNS(use)))
19444 xmlChar *str = NULL;
19446 xmlSchemaCustomWarning(ACTXT_CAST pctxt,
19447 XML_SCHEMAP_WARN_ATTR_POINTLESS_PROH,
19448 prohib->node, NULL,
19449 "Skipping pointless attribute use prohibition "
19450 "'%s', since a corresponding attribute use "
19451 "exists already in the type definition",
19452 xmlSchemaFormatQName(&str,
19453 prohib->targetNamespace, prohib->name),
19454 NULL, NULL);
19455 FREE_AND_NULL(str);
19457 * Remove the prohibition.
19459 if (xmlSchemaItemListRemove(prohibs, i) == -1)
19460 return(-1);
19461 break;
19466 return(0);
19470 * xmlSchemaAttributeGroupExpandRefs:
19471 * @pctxt: the parser context
19472 * @attrGr: the attribute group definition
19474 * Computation of:
19475 * {attribute uses} property
19476 * {attribute wildcard} property
19478 * Substitutes contained attribute group references
19479 * for their attribute uses. Wildcards are intersected.
19481 static int
19482 xmlSchemaAttributeGroupExpandRefs(xmlSchemaParserCtxtPtr pctxt,
19483 xmlSchemaAttributeGroupPtr attrGr)
19485 if ((attrGr->attrUses == NULL) ||
19486 (attrGr->flags & XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED))
19487 return(0);
19489 attrGr->flags |= XML_SCHEMAS_ATTRGROUP_WILDCARD_BUILDED;
19490 if (xmlSchemaExpandAttributeGroupRefs(pctxt, WXS_BASIC_CAST attrGr,
19491 &(attrGr->attributeWildcard), attrGr->attrUses, NULL) == -1)
19492 return(-1);
19493 return(0);
19497 * xmlSchemaAttributeGroupExpandRefs:
19498 * @pctxt: the parser context
19499 * @attrGr: the attribute group definition
19501 * Substitutes contained attribute group references
19502 * for their attribute uses. Wildcards are intersected.
19504 * Schema Component Constraint:
19505 * Attribute Group Definition Properties Correct (ag-props-correct)
19507 static int
19508 xmlSchemaCheckAGPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
19509 xmlSchemaAttributeGroupPtr attrGr)
19512 * SPEC ag-props-correct
19513 * (1) "The values of the properties of an attribute group definition
19514 * must be as described in the property tableau in The Attribute
19515 * Group Definition Schema Component ($3.6.1), modulo the impact of
19516 * Missing Sub-components ($5.3);"
19519 if ((attrGr->attrUses != NULL) &&
19520 (WXS_LIST_CAST attrGr->attrUses)->nbItems > 1)
19522 xmlSchemaItemListPtr uses = WXS_LIST_CAST attrGr->attrUses;
19523 xmlSchemaAttributeUsePtr use, tmp;
19524 int i, j, hasId = 0;
19526 for (i = uses->nbItems -1; i >= 0; i--) {
19527 use = uses->items[i];
19529 * SPEC ag-props-correct
19530 * (2) "Two distinct members of the {attribute uses} must not have
19531 * {attribute declaration}s both of whose {name}s match and whose
19532 * {target namespace}s are identical."
19534 if (i > 0) {
19535 for (j = i -1; j >= 0; j--) {
19536 tmp = uses->items[j];
19537 if ((WXS_ATTRUSE_DECL_NAME(use) ==
19538 WXS_ATTRUSE_DECL_NAME(tmp)) &&
19539 (WXS_ATTRUSE_DECL_TNS(use) ==
19540 WXS_ATTRUSE_DECL_TNS(tmp)))
19542 xmlChar *str = NULL;
19544 xmlSchemaCustomErr(ACTXT_CAST pctxt,
19545 XML_SCHEMAP_AG_PROPS_CORRECT,
19546 attrGr->node, WXS_BASIC_CAST attrGr,
19547 "Duplicate %s",
19548 xmlSchemaGetComponentDesignation(&str, use),
19549 NULL);
19550 FREE_AND_NULL(str);
19552 * Remove the duplicate.
19554 if (xmlSchemaItemListRemove(uses, i) == -1)
19555 return(-1);
19556 goto next_use;
19561 * SPEC ag-props-correct
19562 * (3) "Two distinct members of the {attribute uses} must not have
19563 * {attribute declaration}s both of whose {type definition}s are or
19564 * are derived from ID."
19565 * TODO: Does 'derived' include member-types of unions?
19567 if (WXS_ATTRUSE_TYPEDEF(use) != NULL) {
19568 if (xmlSchemaIsDerivedFromBuiltInType(
19569 WXS_ATTRUSE_TYPEDEF(use), XML_SCHEMAS_ID))
19571 if (hasId) {
19572 xmlChar *str = NULL;
19574 xmlSchemaCustomErr(ACTXT_CAST pctxt,
19575 XML_SCHEMAP_AG_PROPS_CORRECT,
19576 attrGr->node, WXS_BASIC_CAST attrGr,
19577 "There must not exist more than one attribute "
19578 "declaration of type 'xs:ID' "
19579 "(or derived from 'xs:ID'). The %s violates this "
19580 "constraint",
19581 xmlSchemaGetComponentDesignation(&str, use),
19582 NULL);
19583 FREE_AND_NULL(str);
19584 if (xmlSchemaItemListRemove(uses, i) == -1)
19585 return(-1);
19587 hasId = 1;
19590 next_use: {}
19593 return(0);
19597 * xmlSchemaResolveAttrGroupReferences:
19598 * @attrgrpDecl: the schema attribute definition
19599 * @ctxt: the schema parser context
19600 * @name: the attribute name
19602 * Resolves references to attribute group definitions.
19604 static int
19605 xmlSchemaResolveAttrGroupReferences(xmlSchemaQNameRefPtr ref,
19606 xmlSchemaParserCtxtPtr ctxt)
19608 xmlSchemaAttributeGroupPtr group;
19610 if (ref->item != NULL)
19611 return(0);
19612 group = xmlSchemaGetAttributeGroup(ctxt->schema,
19613 ref->name,
19614 ref->targetNamespace);
19615 if (group == NULL) {
19616 xmlSchemaPResCompAttrErr(ctxt,
19617 XML_SCHEMAP_SRC_RESOLVE,
19618 NULL, ref->node,
19619 "ref", ref->name, ref->targetNamespace,
19620 ref->itemType, NULL);
19621 return(ctxt->err);
19623 ref->item = WXS_BASIC_CAST group;
19624 return(0);
19628 * xmlSchemaCheckAttrPropsCorrect:
19629 * @item: an schema attribute declaration/use
19630 * @ctxt: a schema parser context
19631 * @name: the name of the attribute
19634 * Schema Component Constraint:
19635 * Attribute Declaration Properties Correct (a-props-correct)
19637 * Validates the value constraints of an attribute declaration/use.
19638 * NOTE that this needs the simple type definitions to be already
19639 * built and checked.
19641 static int
19642 xmlSchemaCheckAttrPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
19643 xmlSchemaAttributePtr attr)
19647 * SPEC a-props-correct (1)
19648 * "The values of the properties of an attribute declaration must
19649 * be as described in the property tableau in The Attribute
19650 * Declaration Schema Component ($3.2.1), modulo the impact of
19651 * Missing Sub-components ($5.3)."
19654 if (WXS_ATTR_TYPEDEF(attr) == NULL)
19655 return(0);
19657 if (attr->defValue != NULL) {
19658 int ret;
19661 * SPEC a-props-correct (3)
19662 * "If the {type definition} is or is derived from ID then there
19663 * must not be a {value constraint}."
19665 if (xmlSchemaIsDerivedFromBuiltInType(
19666 WXS_ATTR_TYPEDEF(attr), XML_SCHEMAS_ID))
19668 xmlSchemaCustomErr(ACTXT_CAST pctxt,
19669 XML_SCHEMAP_A_PROPS_CORRECT_3,
19670 NULL, WXS_BASIC_CAST attr,
19671 "Value constraints are not allowed if the type definition "
19672 "is or is derived from xs:ID",
19673 NULL, NULL);
19674 return(pctxt->err);
19677 * SPEC a-props-correct (2)
19678 * "if there is a {value constraint}, the canonical lexical
19679 * representation of its value must be `valid` with respect
19680 * to the {type definition} as defined in String Valid ($3.14.4)."
19681 * TODO: Don't care about the *canonical* stuff here, this requirement
19682 * will be removed in WXS 1.1 anyway.
19684 ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST pctxt,
19685 attr->node, WXS_ATTR_TYPEDEF(attr),
19686 attr->defValue, &(attr->defVal),
19687 1, 1, 0);
19688 if (ret != 0) {
19689 if (ret < 0) {
19690 PERROR_INT("xmlSchemaCheckAttrPropsCorrect",
19691 "calling xmlSchemaVCheckCVCSimpleType()");
19692 return(-1);
19694 xmlSchemaCustomErr(ACTXT_CAST pctxt,
19695 XML_SCHEMAP_A_PROPS_CORRECT_2,
19696 NULL, WXS_BASIC_CAST attr,
19697 "The value of the value constraint is not valid",
19698 NULL, NULL);
19699 return(pctxt->err);
19703 return(0);
19706 static xmlSchemaElementPtr
19707 xmlSchemaCheckSubstGroupCircular(xmlSchemaElementPtr elemDecl,
19708 xmlSchemaElementPtr ancestor)
19710 xmlSchemaElementPtr ret;
19712 if (WXS_SUBST_HEAD(ancestor) == NULL)
19713 return (NULL);
19714 if (WXS_SUBST_HEAD(ancestor) == elemDecl)
19715 return (ancestor);
19717 if (WXS_SUBST_HEAD(ancestor)->flags & XML_SCHEMAS_ELEM_CIRCULAR)
19718 return (NULL);
19719 WXS_SUBST_HEAD(ancestor)->flags |= XML_SCHEMAS_ELEM_CIRCULAR;
19720 ret = xmlSchemaCheckSubstGroupCircular(elemDecl,
19721 WXS_SUBST_HEAD(ancestor));
19722 WXS_SUBST_HEAD(ancestor)->flags ^= XML_SCHEMAS_ELEM_CIRCULAR;
19724 return (ret);
19728 * xmlSchemaCheckElemPropsCorrect:
19729 * @ctxt: a schema parser context
19730 * @decl: the element declaration
19731 * @name: the name of the attribute
19733 * Schema Component Constraint:
19734 * Element Declaration Properties Correct (e-props-correct)
19736 * STATUS:
19737 * missing: (6)
19739 static int
19740 xmlSchemaCheckElemPropsCorrect(xmlSchemaParserCtxtPtr pctxt,
19741 xmlSchemaElementPtr elemDecl)
19743 int ret = 0;
19744 xmlSchemaTypePtr typeDef = WXS_ELEM_TYPEDEF(elemDecl);
19746 * SPEC (1) "The values of the properties of an element declaration
19747 * must be as described in the property tableau in The Element
19748 * Declaration Schema Component ($3.3.1), modulo the impact of Missing
19749 * Sub-components ($5.3)."
19751 if (WXS_SUBST_HEAD(elemDecl) != NULL) {
19752 xmlSchemaElementPtr head = WXS_SUBST_HEAD(elemDecl), circ;
19754 xmlSchemaCheckElementDeclComponent(head, pctxt);
19756 * SPEC (3) "If there is a non-`absent` {substitution group
19757 * affiliation}, then {scope} must be global."
19759 if ((elemDecl->flags & XML_SCHEMAS_ELEM_GLOBAL) == 0) {
19760 xmlSchemaPCustomErr(pctxt,
19761 XML_SCHEMAP_E_PROPS_CORRECT_3,
19762 WXS_BASIC_CAST elemDecl, NULL,
19763 "Only global element declarations can have a "
19764 "substitution group affiliation", NULL);
19765 ret = XML_SCHEMAP_E_PROPS_CORRECT_3;
19768 * TODO: SPEC (6) "Circular substitution groups are disallowed.
19769 * That is, it must not be possible to return to an element declaration
19770 * by repeatedly following the {substitution group affiliation}
19771 * property."
19773 if (head == elemDecl)
19774 circ = head;
19775 else if (WXS_SUBST_HEAD(head) != NULL)
19776 circ = xmlSchemaCheckSubstGroupCircular(head, head);
19777 else
19778 circ = NULL;
19779 if (circ != NULL) {
19780 xmlChar *strA = NULL, *strB = NULL;
19782 xmlSchemaPCustomErrExt(pctxt,
19783 XML_SCHEMAP_E_PROPS_CORRECT_6,
19784 WXS_BASIC_CAST circ, NULL,
19785 "The element declaration '%s' defines a circular "
19786 "substitution group to element declaration '%s'",
19787 xmlSchemaGetComponentQName(&strA, circ),
19788 xmlSchemaGetComponentQName(&strB, head),
19789 NULL);
19790 FREE_AND_NULL(strA)
19791 FREE_AND_NULL(strB)
19792 ret = XML_SCHEMAP_E_PROPS_CORRECT_6;
19795 * SPEC (4) "If there is a {substitution group affiliation},
19796 * the {type definition}
19797 * of the element declaration must be validly derived from the {type
19798 * definition} of the {substitution group affiliation}, given the value
19799 * of the {substitution group exclusions} of the {substitution group
19800 * affiliation}, as defined in Type Derivation OK (Complex) ($3.4.6)
19801 * (if the {type definition} is complex) or as defined in
19802 * Type Derivation OK (Simple) ($3.14.6) (if the {type definition} is
19803 * simple)."
19805 * NOTE: {substitution group exclusions} means the values of the
19806 * attribute "final".
19809 if (typeDef != WXS_ELEM_TYPEDEF(WXS_SUBST_HEAD(elemDecl))) {
19810 int set = 0;
19812 if (head->flags & XML_SCHEMAS_ELEM_FINAL_EXTENSION)
19813 set |= SUBSET_EXTENSION;
19814 if (head->flags & XML_SCHEMAS_ELEM_FINAL_RESTRICTION)
19815 set |= SUBSET_RESTRICTION;
19817 if (xmlSchemaCheckCOSDerivedOK(ACTXT_CAST pctxt, typeDef,
19818 WXS_ELEM_TYPEDEF(head), set) != 0) {
19819 xmlChar *strA = NULL, *strB = NULL, *strC = NULL;
19821 ret = XML_SCHEMAP_E_PROPS_CORRECT_4;
19822 xmlSchemaPCustomErrExt(pctxt,
19823 XML_SCHEMAP_E_PROPS_CORRECT_4,
19824 WXS_BASIC_CAST elemDecl, NULL,
19825 "The type definition '%s' was "
19826 "either rejected by the substitution group "
19827 "affiliation '%s', or not validly derived from its type "
19828 "definition '%s'",
19829 xmlSchemaGetComponentQName(&strA, typeDef),
19830 xmlSchemaGetComponentQName(&strB, head),
19831 xmlSchemaGetComponentQName(&strC, WXS_ELEM_TYPEDEF(head)));
19832 FREE_AND_NULL(strA)
19833 FREE_AND_NULL(strB)
19834 FREE_AND_NULL(strC)
19839 * SPEC (5) "If the {type definition} or {type definition}'s
19840 * {content type}
19841 * is or is derived from ID then there must not be a {value constraint}.
19842 * Note: The use of ID as a type definition for elements goes beyond
19843 * XML 1.0, and should be avoided if backwards compatibility is desired"
19845 if ((elemDecl->value != NULL) &&
19846 ((WXS_IS_SIMPLE(typeDef) &&
19847 xmlSchemaIsDerivedFromBuiltInType(typeDef, XML_SCHEMAS_ID)) ||
19848 (WXS_IS_COMPLEX(typeDef) &&
19849 WXS_HAS_SIMPLE_CONTENT(typeDef) &&
19850 xmlSchemaIsDerivedFromBuiltInType(typeDef->contentTypeDef,
19851 XML_SCHEMAS_ID)))) {
19853 ret = XML_SCHEMAP_E_PROPS_CORRECT_5;
19854 xmlSchemaPCustomErr(pctxt,
19855 XML_SCHEMAP_E_PROPS_CORRECT_5,
19856 WXS_BASIC_CAST elemDecl, NULL,
19857 "The type definition (or type definition's content type) is or "
19858 "is derived from ID; value constraints are not allowed in "
19859 "conjunction with such a type definition", NULL);
19860 } else if (elemDecl->value != NULL) {
19861 int vcret;
19862 xmlNodePtr node = NULL;
19865 * SPEC (2) "If there is a {value constraint}, the canonical lexical
19866 * representation of its value must be `valid` with respect to the
19867 * {type definition} as defined in Element Default Valid (Immediate)
19868 * ($3.3.6)."
19870 if (typeDef == NULL) {
19871 xmlSchemaPErr(pctxt, elemDecl->node,
19872 XML_SCHEMAP_INTERNAL,
19873 "Internal error: xmlSchemaCheckElemPropsCorrect, "
19874 "type is missing... skipping validation of "
19875 "the value constraint", NULL, NULL);
19876 return (-1);
19878 if (elemDecl->node != NULL) {
19879 if (elemDecl->flags & XML_SCHEMAS_ELEM_FIXED)
19880 node = (xmlNodePtr) xmlHasProp(elemDecl->node,
19881 BAD_CAST "fixed");
19882 else
19883 node = (xmlNodePtr) xmlHasProp(elemDecl->node,
19884 BAD_CAST "default");
19886 vcret = xmlSchemaParseCheckCOSValidDefault(pctxt, node,
19887 typeDef, elemDecl->value, &(elemDecl->defVal));
19888 if (vcret != 0) {
19889 if (vcret < 0) {
19890 PERROR_INT("xmlSchemaElemCheckValConstr",
19891 "failed to validate the value constraint of an "
19892 "element declaration");
19893 return (-1);
19895 return (vcret);
19899 return (ret);
19903 * xmlSchemaCheckElemSubstGroup:
19904 * @ctxt: a schema parser context
19905 * @decl: the element declaration
19906 * @name: the name of the attribute
19908 * Schema Component Constraint:
19909 * Substitution Group (cos-equiv-class)
19911 * In Libxml2 the subst. groups will be precomputed, in terms of that
19912 * a list will be built for each subst. group head, holding all direct
19913 * referents to this head.
19914 * NOTE that this function needs:
19915 * 1. circular subst. groups to be checked beforehand
19916 * 2. the declaration's type to be derived from the head's type
19918 * STATUS:
19921 static void
19922 xmlSchemaCheckElemSubstGroup(xmlSchemaParserCtxtPtr ctxt,
19923 xmlSchemaElementPtr elemDecl)
19925 if ((WXS_SUBST_HEAD(elemDecl) == NULL) ||
19926 /* SPEC (1) "Its {abstract} is false." */
19927 (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT))
19928 return;
19930 xmlSchemaElementPtr head;
19931 xmlSchemaTypePtr headType, type;
19932 int set, methSet;
19934 * SPEC (2) "It is validly substitutable for HEAD subject to HEAD's
19935 * {disallowed substitutions} as the blocking constraint, as defined in
19936 * Substitution Group OK (Transitive) ($3.3.6)."
19938 for (head = WXS_SUBST_HEAD(elemDecl); head != NULL;
19939 head = WXS_SUBST_HEAD(head)) {
19940 set = 0;
19941 methSet = 0;
19943 * The blocking constraints.
19945 if (head->flags & XML_SCHEMAS_ELEM_BLOCK_SUBSTITUTION)
19946 continue;
19947 headType = head->subtypes;
19948 type = elemDecl->subtypes;
19949 if (headType == type)
19950 goto add_member;
19951 if (head->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION)
19952 set |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
19953 if (head->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION)
19954 set |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
19956 * SPEC: Substitution Group OK (Transitive) (2.3)
19957 * "The set of all {derivation method}s involved in the
19958 * derivation of D's {type definition} from C's {type definition}
19959 * does not intersect with the union of the blocking constraint,
19960 * C's {prohibited substitutions} (if C is complex, otherwise the
19961 * empty set) and the {prohibited substitutions} (respectively the
19962 * empty set) of any intermediate {type definition}s in the
19963 * derivation of D's {type definition} from C's {type definition}."
19966 * OPTIMIZE TODO: Optimize this a bit, since, if traversing the
19967 * subst.head axis, the methSet does not need to be computed for
19968 * the full depth over and over.
19971 * The set of all {derivation method}s involved in the derivation
19973 while ((type != NULL) && (type != headType) &&
19974 (type != type->baseType)) {
19975 if ((WXS_IS_EXTENSION(type)) &&
19976 ((methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
19977 methSet |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
19979 if (WXS_IS_RESTRICTION(type) &&
19980 ((methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
19981 methSet |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
19983 type = type->baseType;
19986 * The {prohibited substitutions} of all intermediate types +
19987 * the head's type.
19989 type = elemDecl->subtypes->baseType;
19990 while (type != NULL) {
19991 if (WXS_IS_COMPLEX(type)) {
19992 if ((type->flags &
19993 XML_SCHEMAS_TYPE_BLOCK_EXTENSION) &&
19994 ((set & XML_SCHEMAS_TYPE_BLOCK_EXTENSION) == 0))
19995 set |= XML_SCHEMAS_TYPE_BLOCK_EXTENSION;
19996 if ((type->flags &
19997 XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) &&
19998 ((set & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) == 0))
19999 set |= XML_SCHEMAS_TYPE_BLOCK_RESTRICTION;
20000 } else
20001 break;
20002 if (type == headType)
20003 break;
20004 type = type->baseType;
20006 if ((set != 0) &&
20007 (((set & XML_SCHEMAS_TYPE_BLOCK_EXTENSION) &&
20008 (methSet & XML_SCHEMAS_TYPE_BLOCK_EXTENSION)) ||
20009 ((set & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION) &&
20010 (methSet & XML_SCHEMAS_TYPE_BLOCK_RESTRICTION)))) {
20011 continue;
20013 add_member:
20014 xmlSchemaAddElementSubstitutionMember(ctxt, head, elemDecl);
20015 if ((head->flags & XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD) == 0)
20016 head->flags |= XML_SCHEMAS_ELEM_SUBST_GROUP_HEAD;
20021 #ifdef WXS_ELEM_DECL_CONS_ENABLED /* enable when finished */
20023 * xmlSchemaCheckElementDeclComponent
20024 * @pctxt: the schema parser context
20025 * @ctxtComponent: the context component (an element declaration)
20026 * @ctxtParticle: the first particle of the context component
20027 * @searchParticle: the element declaration particle to be analysed
20029 * Schema Component Constraint: Element Declarations Consistent
20031 static int
20032 xmlSchemaCheckElementDeclConsistent(xmlSchemaParserCtxtPtr pctxt,
20033 xmlSchemaBasicItemPtr ctxtComponent,
20034 xmlSchemaParticlePtr ctxtParticle,
20035 xmlSchemaParticlePtr searchParticle,
20036 xmlSchemaParticlePtr curParticle,
20037 int search)
20039 return(0);
20041 int ret = 0;
20042 xmlSchemaParticlePtr cur = curParticle;
20043 if (curParticle == NULL) {
20044 return(0);
20046 if (WXS_PARTICLE_TERM(curParticle) == NULL) {
20048 * Just return in this case. A missing "term" of the particle
20049 * might arise due to an invalid "term" component.
20051 return(0);
20053 while (cur != NULL) {
20054 switch (WXS_PARTICLE_TERM(cur)->type) {
20055 case XML_SCHEMA_TYPE_ANY:
20056 break;
20057 case XML_SCHEMA_TYPE_ELEMENT:
20058 if (search == 0) {
20059 ret = xmlSchemaCheckElementDeclConsistent(pctxt,
20060 ctxtComponent, ctxtParticle, cur, ctxtParticle, 1);
20061 if (ret != 0)
20062 return(ret);
20063 } else {
20064 xmlSchemaElementPtr elem =
20065 WXS_ELEM_CAST(WXS_PARTICLE_TERM(cur));
20067 * SPEC Element Declarations Consistent:
20068 * "If the {particles} contains, either directly,
20069 * indirectly (that is, within the {particles} of a
20070 * contained model group, recursively) or `implicitly`
20071 * two or more element declaration particles with
20072 * the same {name} and {target namespace}, then
20073 * all their type definitions must be the same
20074 * top-level definition [...]"
20076 if (xmlStrEqual(WXS_PARTICLE_TERM_AS_ELEM(cur)->name,
20077 WXS_PARTICLE_TERM_AS_ELEM(searchParticle)->name) &&
20078 xmlStrEqual(WXS_PARTICLE_TERM_AS_ELEM(cur)->targetNamespace,
20079 WXS_PARTICLE_TERM_AS_ELEM(searchParticle)->targetNamespace))
20081 xmlChar *strA = NULL, *strB = NULL;
20083 xmlSchemaCustomErr(ACTXT_CAST pctxt,
20084 /* TODO: error code */
20085 XML_SCHEMAP_COS_NONAMBIG,
20086 WXS_ITEM_NODE(cur), NULL,
20087 "In the content model of %s, there are multiple "
20088 "element declarations for '%s' with different "
20089 "type definitions",
20090 xmlSchemaGetComponentDesignation(&strA,
20091 ctxtComponent),
20092 xmlSchemaFormatQName(&strB,
20093 WXS_PARTICLE_TERM_AS_ELEM(cur)->targetNamespace,
20094 WXS_PARTICLE_TERM_AS_ELEM(cur)->name));
20095 FREE_AND_NULL(strA);
20096 FREE_AND_NULL(strB);
20097 return(XML_SCHEMAP_COS_NONAMBIG);
20100 break;
20101 case XML_SCHEMA_TYPE_SEQUENCE: {
20102 break;
20104 case XML_SCHEMA_TYPE_CHOICE:{
20106 xmlSchemaTreeItemPtr sub;
20108 sub = WXS_PARTICLE_TERM(particle)->children; (xmlSchemaParticlePtr)
20109 while (sub != NULL) {
20110 ret = xmlSchemaCheckElementDeclConsistent(pctxt, ctxtComponent,
20111 ctxtParticle, ctxtElem);
20112 if (ret != 0)
20113 return(ret);
20114 sub = sub->next;
20117 break;
20119 case XML_SCHEMA_TYPE_ALL:
20120 break;
20121 case XML_SCHEMA_TYPE_GROUP:
20122 break;
20123 default:
20124 xmlSchemaInternalErr2(ACTXT_CAST pctxt,
20125 "xmlSchemaCheckElementDeclConsistent",
20126 "found unexpected term of type '%s' in content model",
20127 WXS_ITEM_TYPE_NAME(WXS_PARTICLE_TERM(cur)), NULL);
20128 return(-1);
20130 cur = (xmlSchemaParticlePtr) cur->next;
20133 exit:
20134 return(ret);
20136 #endif
20139 * xmlSchemaCheckElementDeclComponent
20140 * @item: an schema element declaration/particle
20141 * @ctxt: a schema parser context
20142 * @name: the name of the attribute
20144 * Validates the value constraints of an element declaration.
20145 * Adds substitution group members.
20147 static void
20148 xmlSchemaCheckElementDeclComponent(xmlSchemaElementPtr elemDecl,
20149 xmlSchemaParserCtxtPtr ctxt)
20151 if (elemDecl == NULL)
20152 return;
20153 if (elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_CHECKED)
20154 return;
20155 elemDecl->flags |= XML_SCHEMAS_ELEM_INTERNAL_CHECKED;
20156 if (xmlSchemaCheckElemPropsCorrect(ctxt, elemDecl) == 0) {
20158 * Adds substitution group members.
20160 xmlSchemaCheckElemSubstGroup(ctxt, elemDecl);
20165 * xmlSchemaResolveModelGroupParticleReferences:
20166 * @particle: a particle component
20167 * @ctxt: a parser context
20169 * Resolves references of a model group's {particles} to
20170 * model group definitions and to element declarations.
20172 static void
20173 xmlSchemaResolveModelGroupParticleReferences(
20174 xmlSchemaParserCtxtPtr ctxt,
20175 xmlSchemaModelGroupPtr mg)
20177 xmlSchemaParticlePtr particle = WXS_MODELGROUP_PARTICLE(mg);
20178 xmlSchemaQNameRefPtr ref;
20179 xmlSchemaBasicItemPtr refItem;
20182 * URGENT TODO: Test this.
20184 while (particle != NULL) {
20185 if ((WXS_PARTICLE_TERM(particle) == NULL) ||
20186 ((WXS_PARTICLE_TERM(particle))->type !=
20187 XML_SCHEMA_EXTRA_QNAMEREF))
20189 goto next_particle;
20191 ref = WXS_QNAME_CAST WXS_PARTICLE_TERM(particle);
20193 * Resolve the reference.
20194 * NULL the {term} by default.
20196 particle->children = NULL;
20198 refItem = xmlSchemaGetNamedComponent(ctxt->schema,
20199 ref->itemType, ref->name, ref->targetNamespace);
20200 if (refItem == NULL) {
20201 xmlSchemaPResCompAttrErr(ctxt, XML_SCHEMAP_SRC_RESOLVE,
20202 NULL, WXS_ITEM_NODE(particle), "ref", ref->name,
20203 ref->targetNamespace, ref->itemType, NULL);
20204 /* TODO: remove the particle. */
20205 goto next_particle;
20207 if (refItem->type == XML_SCHEMA_TYPE_GROUP) {
20208 if (WXS_MODELGROUPDEF_MODEL(refItem) == NULL)
20209 /* TODO: remove the particle. */
20210 goto next_particle;
20212 * NOTE that we will assign the model group definition
20213 * itself to the "term" of the particle. This will ease
20214 * the check for circular model group definitions. After
20215 * that the "term" will be assigned the model group of the
20216 * model group definition.
20218 if ((WXS_MODELGROUPDEF_MODEL(refItem))->type ==
20219 XML_SCHEMA_TYPE_ALL) {
20221 * SPEC cos-all-limited (1)
20222 * SPEC cos-all-limited (1.2)
20223 * "It appears only as the value of one or both of the
20224 * following properties:"
20225 * (1.1) "the {model group} property of a model group
20226 * definition."
20227 * (1.2) "the {term} property of a particle [... of] the "
20228 * {content type} of a complex type definition."
20230 xmlSchemaCustomErr(ACTXT_CAST ctxt,
20231 /* TODO: error code */
20232 XML_SCHEMAP_COS_ALL_LIMITED,
20233 WXS_ITEM_NODE(particle), NULL,
20234 "A model group definition is referenced, but "
20235 "it contains an 'all' model group, which "
20236 "cannot be contained by model groups",
20237 NULL, NULL);
20238 /* TODO: remove the particle. */
20239 goto next_particle;
20241 particle->children = (xmlSchemaTreeItemPtr) refItem;
20242 } else {
20244 * TODO: Are referenced element declarations the only
20245 * other components we expect here?
20247 particle->children = (xmlSchemaTreeItemPtr) refItem;
20249 next_particle:
20250 particle = WXS_PTC_CAST particle->next;
20254 static int
20255 xmlSchemaAreValuesEqual(xmlSchemaValPtr x,
20256 xmlSchemaValPtr y)
20258 xmlSchemaTypePtr tx, ty, ptx, pty;
20259 int ret;
20261 while (x != NULL) {
20262 /* Same types. */
20263 tx = xmlSchemaGetBuiltInType(xmlSchemaGetValType(x));
20264 ty = xmlSchemaGetBuiltInType(xmlSchemaGetValType(y));
20265 ptx = xmlSchemaGetPrimitiveType(tx);
20266 pty = xmlSchemaGetPrimitiveType(ty);
20268 * (1) if a datatype T' is `derived` by `restriction` from an
20269 * atomic datatype T then the `value space` of T' is a subset of
20270 * the `value space` of T. */
20272 * (2) if datatypes T' and T'' are `derived` by `restriction`
20273 * from a common atomic ancestor T then the `value space`s of T'
20274 * and T'' may overlap.
20276 if (ptx != pty)
20277 return(0);
20279 * We assume computed values to be normalized, so do a fast
20280 * string comparison for string based types.
20282 if ((ptx->builtInType == XML_SCHEMAS_STRING) ||
20283 WXS_IS_ANY_SIMPLE_TYPE(ptx)) {
20284 if (! xmlStrEqual(
20285 xmlSchemaValueGetAsString(x),
20286 xmlSchemaValueGetAsString(y)))
20287 return (0);
20288 } else {
20289 ret = xmlSchemaCompareValuesWhtsp(
20290 x, XML_SCHEMA_WHITESPACE_PRESERVE,
20291 y, XML_SCHEMA_WHITESPACE_PRESERVE);
20292 if (ret == -2)
20293 return(-1);
20294 if (ret != 0)
20295 return(0);
20298 * Lists.
20300 x = xmlSchemaValueGetNext(x);
20301 if (x != NULL) {
20302 y = xmlSchemaValueGetNext(y);
20303 if (y == NULL)
20304 return (0);
20305 } else if (xmlSchemaValueGetNext(y) != NULL)
20306 return (0);
20307 else
20308 return (1);
20310 return (0);
20314 * xmlSchemaResolveAttrUseReferences:
20315 * @item: an attribute use
20316 * @ctxt: a parser context
20318 * Resolves the referenced attribute declaration.
20320 static int
20321 xmlSchemaResolveAttrUseReferences(xmlSchemaAttributeUsePtr ause,
20322 xmlSchemaParserCtxtPtr ctxt)
20324 if ((ctxt == NULL) || (ause == NULL))
20325 return(-1);
20326 if ((ause->attrDecl == NULL) ||
20327 (ause->attrDecl->type != XML_SCHEMA_EXTRA_QNAMEREF))
20328 return(0);
20331 xmlSchemaQNameRefPtr ref = WXS_QNAME_CAST ause->attrDecl;
20334 * TODO: Evaluate, what errors could occur if the declaration is not
20335 * found.
20337 ause->attrDecl = xmlSchemaGetAttributeDecl(ctxt->schema,
20338 ref->name, ref->targetNamespace);
20339 if (ause->attrDecl == NULL) {
20340 xmlSchemaPResCompAttrErr(ctxt,
20341 XML_SCHEMAP_SRC_RESOLVE,
20342 WXS_BASIC_CAST ause, ause->node,
20343 "ref", ref->name, ref->targetNamespace,
20344 XML_SCHEMA_TYPE_ATTRIBUTE, NULL);
20345 return(ctxt->err);;
20348 return(0);
20352 * xmlSchemaCheckAttrUsePropsCorrect:
20353 * @ctxt: a parser context
20354 * @use: an attribute use
20356 * Schema Component Constraint:
20357 * Attribute Use Correct (au-props-correct)
20360 static int
20361 xmlSchemaCheckAttrUsePropsCorrect(xmlSchemaParserCtxtPtr ctxt,
20362 xmlSchemaAttributeUsePtr use)
20364 if ((ctxt == NULL) || (use == NULL))
20365 return(-1);
20366 if ((use->defValue == NULL) || (WXS_ATTRUSE_DECL(use) == NULL) ||
20367 ((WXS_ATTRUSE_DECL(use))->type != XML_SCHEMA_TYPE_ATTRIBUTE))
20368 return(0);
20371 * SPEC au-props-correct (1)
20372 * "The values of the properties of an attribute use must be as
20373 * described in the property tableau in The Attribute Use Schema
20374 * Component ($3.5.1), modulo the impact of Missing
20375 * Sub-components ($5.3)."
20378 if (((WXS_ATTRUSE_DECL(use))->defValue != NULL) &&
20379 ((WXS_ATTRUSE_DECL(use))->flags & XML_SCHEMAS_ATTR_FIXED) &&
20380 ((use->flags & XML_SCHEMA_ATTR_USE_FIXED) == 0))
20382 xmlSchemaPCustomErr(ctxt,
20383 XML_SCHEMAP_AU_PROPS_CORRECT_2,
20384 WXS_BASIC_CAST use, NULL,
20385 "The attribute declaration has a 'fixed' value constraint "
20386 ", thus the attribute use must also have a 'fixed' value "
20387 "constraint",
20388 NULL);
20389 return(ctxt->err);
20392 * Compute and check the value constraint's value.
20394 if ((use->defVal != NULL) && (WXS_ATTRUSE_TYPEDEF(use) != NULL)) {
20395 int ret;
20397 * TODO: The spec seems to be missing a check of the
20398 * value constraint of the attribute use. We will do it here.
20401 * SPEC a-props-correct (3)
20403 if (xmlSchemaIsDerivedFromBuiltInType(
20404 WXS_ATTRUSE_TYPEDEF(use), XML_SCHEMAS_ID))
20406 xmlSchemaCustomErr(ACTXT_CAST ctxt,
20407 XML_SCHEMAP_AU_PROPS_CORRECT,
20408 NULL, WXS_BASIC_CAST use,
20409 "Value constraints are not allowed if the type definition "
20410 "is or is derived from xs:ID",
20411 NULL, NULL);
20412 return(ctxt->err);
20415 ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST ctxt,
20416 use->node, WXS_ATTRUSE_TYPEDEF(use),
20417 use->defValue, &(use->defVal),
20418 1, 1, 0);
20419 if (ret != 0) {
20420 if (ret < 0) {
20421 PERROR_INT2("xmlSchemaCheckAttrUsePropsCorrect",
20422 "calling xmlSchemaVCheckCVCSimpleType()");
20423 return(-1);
20425 xmlSchemaCustomErr(ACTXT_CAST ctxt,
20426 XML_SCHEMAP_AU_PROPS_CORRECT,
20427 NULL, WXS_BASIC_CAST use,
20428 "The value of the value constraint is not valid",
20429 NULL, NULL);
20430 return(ctxt->err);
20434 * SPEC au-props-correct (2)
20435 * "If the {attribute declaration} has a fixed
20436 * {value constraint}, then if the attribute use itself has a
20437 * {value constraint}, it must also be fixed and its value must match
20438 * that of the {attribute declaration}'s {value constraint}."
20440 if (((WXS_ATTRUSE_DECL(use))->defVal != NULL) &&
20441 (((WXS_ATTRUSE_DECL(use))->flags & XML_SCHEMA_ATTR_USE_FIXED) == 0))
20443 if (! xmlSchemaAreValuesEqual(use->defVal,
20444 (WXS_ATTRUSE_DECL(use))->defVal))
20446 xmlSchemaPCustomErr(ctxt,
20447 XML_SCHEMAP_AU_PROPS_CORRECT_2,
20448 WXS_BASIC_CAST use, NULL,
20449 "The 'fixed' value constraint of the attribute use "
20450 "must match the attribute declaration's value "
20451 "constraint '%s'",
20452 (WXS_ATTRUSE_DECL(use))->defValue);
20454 return(ctxt->err);
20456 return(0);
20463 * xmlSchemaResolveAttrTypeReferences:
20464 * @item: an attribute declaration
20465 * @ctxt: a parser context
20467 * Resolves the referenced type definition component.
20469 static int
20470 xmlSchemaResolveAttrTypeReferences(xmlSchemaAttributePtr item,
20471 xmlSchemaParserCtxtPtr ctxt)
20474 * The simple type definition corresponding to the <simpleType> element
20475 * information item in the [children], if present, otherwise the simple
20476 * type definition `resolved` to by the `actual value` of the type
20477 * [attribute], if present, otherwise the `simple ur-type definition`.
20479 if (item->flags & XML_SCHEMAS_ATTR_INTERNAL_RESOLVED)
20480 return(0);
20481 item->flags |= XML_SCHEMAS_ATTR_INTERNAL_RESOLVED;
20482 if (item->subtypes != NULL)
20483 return(0);
20484 if (item->typeName != NULL) {
20485 xmlSchemaTypePtr type;
20487 type = xmlSchemaGetType(ctxt->schema, item->typeName,
20488 item->typeNs);
20489 if ((type == NULL) || (! WXS_IS_SIMPLE(type))) {
20490 xmlSchemaPResCompAttrErr(ctxt,
20491 XML_SCHEMAP_SRC_RESOLVE,
20492 WXS_BASIC_CAST item, item->node,
20493 "type", item->typeName, item->typeNs,
20494 XML_SCHEMA_TYPE_SIMPLE, NULL);
20495 return(ctxt->err);
20496 } else
20497 item->subtypes = type;
20499 } else {
20501 * The type defaults to the xs:anySimpleType.
20503 item->subtypes = xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYSIMPLETYPE);
20505 return(0);
20509 * xmlSchemaResolveIDCKeyReferences:
20510 * @idc: the identity-constraint definition
20511 * @ctxt: the schema parser context
20512 * @name: the attribute name
20514 * Resolve keyRef references to key/unique IDCs.
20515 * Schema Component Constraint:
20516 * Identity-constraint Definition Properties Correct (c-props-correct)
20518 static int
20519 xmlSchemaResolveIDCKeyReferences(xmlSchemaIDCPtr idc,
20520 xmlSchemaParserCtxtPtr pctxt)
20522 if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF)
20523 return(0);
20524 if (idc->ref->name != NULL) {
20525 idc->ref->item = (xmlSchemaBasicItemPtr)
20526 xmlSchemaGetIDC(pctxt->schema, idc->ref->name,
20527 idc->ref->targetNamespace);
20528 if (idc->ref->item == NULL) {
20530 * TODO: It is actually not an error to fail to resolve
20531 * at this stage. BUT we need to be that strict!
20533 xmlSchemaPResCompAttrErr(pctxt,
20534 XML_SCHEMAP_SRC_RESOLVE,
20535 WXS_BASIC_CAST idc, idc->node,
20536 "refer", idc->ref->name,
20537 idc->ref->targetNamespace,
20538 XML_SCHEMA_TYPE_IDC_KEY, NULL);
20539 return(pctxt->err);
20540 } else if (idc->ref->item->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
20542 * SPEC c-props-correct (1)
20544 xmlSchemaCustomErr(ACTXT_CAST pctxt,
20545 XML_SCHEMAP_C_PROPS_CORRECT,
20546 NULL, WXS_BASIC_CAST idc,
20547 "The keyref references a keyref",
20548 NULL, NULL);
20549 idc->ref->item = NULL;
20550 return(pctxt->err);
20551 } else {
20552 if (idc->nbFields !=
20553 ((xmlSchemaIDCPtr) idc->ref->item)->nbFields) {
20554 xmlChar *str = NULL;
20555 xmlSchemaIDCPtr refer;
20557 refer = (xmlSchemaIDCPtr) idc->ref->item;
20559 * SPEC c-props-correct(2)
20560 * "If the {identity-constraint category} is keyref,
20561 * the cardinality of the {fields} must equal that of
20562 * the {fields} of the {referenced key}.
20564 xmlSchemaCustomErr(ACTXT_CAST pctxt,
20565 XML_SCHEMAP_C_PROPS_CORRECT,
20566 NULL, WXS_BASIC_CAST idc,
20567 "The cardinality of the keyref differs from the "
20568 "cardinality of the referenced key/unique '%s'",
20569 xmlSchemaFormatQName(&str, refer->targetNamespace,
20570 refer->name),
20571 NULL);
20572 FREE_AND_NULL(str)
20573 return(pctxt->err);
20577 return(0);
20580 static int
20581 xmlSchemaResolveAttrUseProhibReferences(xmlSchemaAttributeUseProhibPtr prohib,
20582 xmlSchemaParserCtxtPtr pctxt)
20584 if (xmlSchemaGetAttributeDecl(pctxt->schema, prohib->name,
20585 prohib->targetNamespace) == NULL) {
20587 xmlSchemaPResCompAttrErr(pctxt,
20588 XML_SCHEMAP_SRC_RESOLVE,
20589 NULL, prohib->node,
20590 "ref", prohib->name, prohib->targetNamespace,
20591 XML_SCHEMA_TYPE_ATTRIBUTE, NULL);
20592 return(XML_SCHEMAP_SRC_RESOLVE);
20594 return(0);
20597 #define WXS_REDEFINED_TYPE(c) \
20598 (((xmlSchemaTypePtr) item)->flags & XML_SCHEMAS_TYPE_REDEFINED)
20600 #define WXS_REDEFINED_MODEL_GROUP_DEF(c) \
20601 (((xmlSchemaModelGroupDefPtr) item)->flags & XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED)
20603 #define WXS_REDEFINED_ATTR_GROUP(c) \
20604 (((xmlSchemaAttributeGroupPtr) item)->flags & XML_SCHEMAS_ATTRGROUP_REDEFINED)
20606 static int
20607 xmlSchemaCheckSRCRedefineFirst(xmlSchemaParserCtxtPtr pctxt)
20609 int err = 0;
20610 xmlSchemaRedefPtr redef = WXS_CONSTRUCTOR(pctxt)->redefs;
20611 xmlSchemaBasicItemPtr prev, item;
20612 int wasRedefined;
20614 if (redef == NULL)
20615 return(0);
20617 do {
20618 item = redef->item;
20620 * First try to locate the redefined component in the
20621 * schema graph starting with the redefined schema.
20622 * NOTE: According to this schema bug entry:
20623 * http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005OctDec/0019.html
20624 * it's not clear if the referenced component needs to originate
20625 * from the <redefine>d schema _document_ or the schema; the latter
20626 * would include all imported and included sub-schemas of the
20627 * <redefine>d schema. Currently the latter approach is used.
20628 * SUPPLEMENT: It seems that the WG moves towards the latter
20629 * approach, so we are doing it right.
20632 prev = xmlSchemaFindRedefCompInGraph(
20633 redef->targetBucket, item->type,
20634 redef->refName, redef->refTargetNs);
20635 if (prev == NULL) {
20636 xmlChar *str = NULL;
20637 xmlNodePtr node;
20640 * SPEC src-redefine:
20641 * (6.2.1) "The `actual value` of its own name attribute plus
20642 * target namespace must successfully `resolve` to a model
20643 * group definition in I."
20644 * (7.2.1) "The `actual value` of its own name attribute plus
20645 * target namespace must successfully `resolve` to an attribute
20646 * group definition in I."
20649 * Note that, if we are redefining with the use of references
20650 * to components, the spec assumes the src-resolve to be used;
20651 * but this won't assure that we search only *inside* the
20652 * redefined schema.
20654 if (redef->reference)
20655 node = WXS_ITEM_NODE(redef->reference);
20656 else
20657 node = WXS_ITEM_NODE(item);
20658 xmlSchemaCustomErr(ACTXT_CAST pctxt,
20660 * TODO: error code.
20661 * Probably XML_SCHEMAP_SRC_RESOLVE, if this is using the
20662 * reference kind.
20664 XML_SCHEMAP_SRC_REDEFINE, node, NULL,
20665 "The %s '%s' to be redefined could not be found in "
20666 "the redefined schema",
20667 WXS_ITEM_TYPE_NAME(item),
20668 xmlSchemaFormatQName(&str, redef->refTargetNs,
20669 redef->refName));
20670 FREE_AND_NULL(str);
20671 err = pctxt->err;
20672 redef = redef->next;
20673 continue;
20676 * TODO: Obtaining and setting the redefinition state is really
20677 * clumsy.
20679 wasRedefined = 0;
20680 switch (item->type) {
20681 case XML_SCHEMA_TYPE_COMPLEX:
20682 case XML_SCHEMA_TYPE_SIMPLE:
20683 if ((WXS_TYPE_CAST prev)->flags &
20684 XML_SCHEMAS_TYPE_REDEFINED)
20686 wasRedefined = 1;
20687 break;
20689 /* Mark it as redefined. */
20690 (WXS_TYPE_CAST prev)->flags |= XML_SCHEMAS_TYPE_REDEFINED;
20692 * Assign the redefined type to the
20693 * base type of the redefining type.
20694 * TODO: How
20696 ((xmlSchemaTypePtr) item)->baseType =
20697 (xmlSchemaTypePtr) prev;
20698 break;
20699 case XML_SCHEMA_TYPE_GROUP:
20700 if ((WXS_MODEL_GROUPDEF_CAST prev)->flags &
20701 XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED)
20703 wasRedefined = 1;
20704 break;
20706 /* Mark it as redefined. */
20707 (WXS_MODEL_GROUPDEF_CAST prev)->flags |=
20708 XML_SCHEMA_MODEL_GROUP_DEF_REDEFINED;
20709 if (redef->reference != NULL) {
20711 * Overwrite the QName-reference with the
20712 * referenced model group def.
20714 (WXS_PTC_CAST redef->reference)->children =
20715 WXS_TREE_CAST prev;
20717 redef->target = prev;
20718 break;
20719 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20720 if ((WXS_ATTR_GROUP_CAST prev)->flags &
20721 XML_SCHEMAS_ATTRGROUP_REDEFINED)
20723 wasRedefined = 1;
20724 break;
20726 (WXS_ATTR_GROUP_CAST prev)->flags |=
20727 XML_SCHEMAS_ATTRGROUP_REDEFINED;
20728 if (redef->reference != NULL) {
20730 * Assign the redefined attribute group to the
20731 * QName-reference component.
20732 * This is the easy case, since we will just
20733 * expand the redefined group.
20735 (WXS_QNAME_CAST redef->reference)->item = prev;
20736 redef->target = NULL;
20737 } else {
20739 * This is the complicated case: we need
20740 * to apply src-redefine (7.2.2) at a later
20741 * stage, i.e. when attribute group references
20742 * have been expanded and simple types have
20743 * been fixed.
20745 redef->target = prev;
20747 break;
20748 default:
20749 PERROR_INT("xmlSchemaResolveRedefReferences",
20750 "Unexpected redefined component type");
20751 return(-1);
20753 if (wasRedefined) {
20754 xmlChar *str = NULL;
20755 xmlNodePtr node;
20757 if (redef->reference)
20758 node = WXS_ITEM_NODE(redef->reference);
20759 else
20760 node = WXS_ITEM_NODE(redef->item);
20762 xmlSchemaCustomErr(ACTXT_CAST pctxt,
20763 /* TODO: error code. */
20764 XML_SCHEMAP_SRC_REDEFINE,
20765 node, NULL,
20766 "The referenced %s was already redefined. Multiple "
20767 "redefinition of the same component is not supported",
20768 xmlSchemaGetComponentDesignation(&str, prev),
20769 NULL);
20770 FREE_AND_NULL(str)
20771 err = pctxt->err;
20772 redef = redef->next;
20773 continue;
20775 redef = redef->next;
20776 } while (redef != NULL);
20778 return(err);
20781 static int
20782 xmlSchemaCheckSRCRedefineSecond(xmlSchemaParserCtxtPtr pctxt)
20784 int err = 0;
20785 xmlSchemaRedefPtr redef = WXS_CONSTRUCTOR(pctxt)->redefs;
20786 xmlSchemaBasicItemPtr item;
20788 if (redef == NULL)
20789 return(0);
20791 do {
20792 if (redef->target == NULL) {
20793 redef = redef->next;
20794 continue;
20796 item = redef->item;
20798 switch (item->type) {
20799 case XML_SCHEMA_TYPE_SIMPLE:
20800 case XML_SCHEMA_TYPE_COMPLEX:
20802 * Since the spec wants the {name} of the redefined
20803 * type to be 'absent', we'll NULL it.
20805 (WXS_TYPE_CAST redef->target)->name = NULL;
20808 * TODO: Seems like there's nothing more to do. The normal
20809 * inheritance mechanism is used. But not 100% sure.
20811 break;
20812 case XML_SCHEMA_TYPE_GROUP:
20814 * URGENT TODO:
20815 * SPEC src-redefine:
20816 * (6.2.2) "The {model group} of the model group definition
20817 * which corresponds to it per XML Representation of Model
20818 * Group Definition Schema Components ($3.7.2) must be a
20819 * `valid restriction` of the {model group} of that model
20820 * group definition in I, as defined in Particle Valid
20821 * (Restriction) ($3.9.6)."
20823 break;
20824 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20826 * SPEC src-redefine:
20827 * (7.2.2) "The {attribute uses} and {attribute wildcard} of
20828 * the attribute group definition which corresponds to it
20829 * per XML Representation of Attribute Group Definition Schema
20830 * Components ($3.6.2) must be `valid restrictions` of the
20831 * {attribute uses} and {attribute wildcard} of that attribute
20832 * group definition in I, as defined in clause 2, clause 3 and
20833 * clause 4 of Derivation Valid (Restriction, Complex)
20834 * ($3.4.6) (where references to the base type definition are
20835 * understood as references to the attribute group definition
20836 * in I)."
20838 err = xmlSchemaCheckDerivationOKRestriction2to4(pctxt,
20839 XML_SCHEMA_ACTION_REDEFINE,
20840 item, redef->target,
20841 (WXS_ATTR_GROUP_CAST item)->attrUses,
20842 (WXS_ATTR_GROUP_CAST redef->target)->attrUses,
20843 (WXS_ATTR_GROUP_CAST item)->attributeWildcard,
20844 (WXS_ATTR_GROUP_CAST redef->target)->attributeWildcard);
20845 if (err == -1)
20846 return(-1);
20847 break;
20848 default:
20849 break;
20851 redef = redef->next;
20852 } while (redef != NULL);
20853 return(0);
20857 static int
20858 xmlSchemaAddComponents(xmlSchemaParserCtxtPtr pctxt,
20859 xmlSchemaBucketPtr bucket)
20861 xmlSchemaBasicItemPtr item;
20862 int err;
20863 xmlHashTablePtr *table;
20864 const xmlChar *name;
20865 int i;
20867 #define WXS_GET_GLOBAL_HASH(c, slot) { \
20868 if (WXS_IS_BUCKET_IMPMAIN((c)->type)) \
20869 table = &(WXS_IMPBUCKET((c))->schema->slot); \
20870 else \
20871 table = &(WXS_INCBUCKET((c))->ownerImport->schema->slot); }
20874 * Add global components to the schema's hash tables.
20875 * This is the place where duplicate components will be
20876 * detected.
20877 * TODO: I think normally we should support imports of the
20878 * same namespace from multiple locations. We don't do currently,
20879 * but if we do then according to:
20880 * http://www.w3.org/Bugs/Public/show_bug.cgi?id=2224
20881 * we would need, if imported directly, to import redefined
20882 * components as well to be able to catch clashing components.
20883 * (I hope I'll still know what this means after some months :-()
20885 if (bucket == NULL)
20886 return(-1);
20887 if (bucket->flags & XML_SCHEMA_BUCKET_COMPS_ADDED)
20888 return(0);
20889 bucket->flags |= XML_SCHEMA_BUCKET_COMPS_ADDED;
20891 for (i = 0; i < bucket->globals->nbItems; i++) {
20892 item = bucket->globals->items[i];
20893 table = NULL;
20894 switch (item->type) {
20895 case XML_SCHEMA_TYPE_COMPLEX:
20896 case XML_SCHEMA_TYPE_SIMPLE:
20897 if (WXS_REDEFINED_TYPE(item))
20898 continue;
20899 name = (WXS_TYPE_CAST item)->name;
20900 WXS_GET_GLOBAL_HASH(bucket, typeDecl)
20901 break;
20902 case XML_SCHEMA_TYPE_ELEMENT:
20903 name = (WXS_ELEM_CAST item)->name;
20904 WXS_GET_GLOBAL_HASH(bucket, elemDecl)
20905 break;
20906 case XML_SCHEMA_TYPE_ATTRIBUTE:
20907 name = (WXS_ATTR_CAST item)->name;
20908 WXS_GET_GLOBAL_HASH(bucket, attrDecl)
20909 break;
20910 case XML_SCHEMA_TYPE_GROUP:
20911 if (WXS_REDEFINED_MODEL_GROUP_DEF(item))
20912 continue;
20913 name = (WXS_MODEL_GROUPDEF_CAST item)->name;
20914 WXS_GET_GLOBAL_HASH(bucket, groupDecl)
20915 break;
20916 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
20917 if (WXS_REDEFINED_ATTR_GROUP(item))
20918 continue;
20919 name = (WXS_ATTR_GROUP_CAST item)->name;
20920 WXS_GET_GLOBAL_HASH(bucket, attrgrpDecl)
20921 break;
20922 case XML_SCHEMA_TYPE_IDC_KEY:
20923 case XML_SCHEMA_TYPE_IDC_UNIQUE:
20924 case XML_SCHEMA_TYPE_IDC_KEYREF:
20925 name = (WXS_IDC_CAST item)->name;
20926 WXS_GET_GLOBAL_HASH(bucket, idcDef)
20927 break;
20928 case XML_SCHEMA_TYPE_NOTATION:
20929 name = ((xmlSchemaNotationPtr) item)->name;
20930 WXS_GET_GLOBAL_HASH(bucket, notaDecl)
20931 break;
20932 default:
20933 PERROR_INT("xmlSchemaAddComponents",
20934 "Unexpected global component type");
20935 continue;
20937 if (*table == NULL) {
20938 *table = xmlHashCreateDict(10, pctxt->dict);
20939 if (*table == NULL) {
20940 PERROR_INT("xmlSchemaAddComponents",
20941 "failed to create a component hash table");
20942 return(-1);
20945 err = xmlHashAddEntry(*table, name, item);
20946 if (err != 0) {
20947 xmlChar *str = NULL;
20949 xmlSchemaCustomErr(ACTXT_CAST pctxt,
20950 XML_SCHEMAP_REDEFINED_TYPE,
20951 WXS_ITEM_NODE(item),
20952 WXS_BASIC_CAST item,
20953 "A global %s '%s' does already exist",
20954 WXS_ITEM_TYPE_NAME(item),
20955 xmlSchemaGetComponentQName(&str, item));
20956 FREE_AND_NULL(str);
20960 * Process imported/included schemas.
20962 if (bucket->relations != NULL) {
20963 xmlSchemaSchemaRelationPtr rel = bucket->relations;
20964 do {
20965 if ((rel->bucket != NULL) &&
20966 ((rel->bucket->flags & XML_SCHEMA_BUCKET_COMPS_ADDED) == 0)) {
20967 if (xmlSchemaAddComponents(pctxt, rel->bucket) == -1)
20968 return(-1);
20970 rel = rel->next;
20971 } while (rel != NULL);
20973 return(0);
20976 static int
20977 xmlSchemaFixupComponents(xmlSchemaParserCtxtPtr pctxt,
20978 xmlSchemaBucketPtr rootBucket)
20980 xmlSchemaConstructionCtxtPtr con = pctxt->constructor;
20981 xmlSchemaTreeItemPtr item, *items;
20982 int nbItems, i, ret = 0;
20983 xmlSchemaBucketPtr oldbucket = con->bucket;
20984 xmlSchemaElementPtr elemDecl;
20986 #define FIXHFAILURE if (pctxt->err == XML_SCHEMAP_INTERNAL) goto exit_failure;
20988 if ((con->pending == NULL) ||
20989 (con->pending->nbItems == 0))
20990 return(0);
20993 * Since xmlSchemaFixupComplexType() will create new particles
20994 * (local components), and those particle components need a bucket
20995 * on the constructor, we'll assure here that the constructor has
20996 * a bucket.
20997 * TODO: Think about storing locals _only_ on the main bucket.
20999 if (con->bucket == NULL)
21000 con->bucket = rootBucket;
21002 /* TODO:
21003 * SPEC (src-redefine):
21004 * (6.2) "If it has no such self-reference, then all of the
21005 * following must be true:"
21007 * (6.2.2) The {model group} of the model group definition which
21008 * corresponds to it per XML Representation of Model Group
21009 * Definition Schema Components ($3.7.2) must be a `valid
21010 * restriction` of the {model group} of that model group definition
21011 * in I, as defined in Particle Valid (Restriction) ($3.9.6)."
21013 xmlSchemaCheckSRCRedefineFirst(pctxt);
21016 * Add global components to the schemata's hash tables.
21018 xmlSchemaAddComponents(pctxt, rootBucket);
21020 pctxt->ctxtType = NULL;
21021 items = (xmlSchemaTreeItemPtr *) con->pending->items;
21022 nbItems = con->pending->nbItems;
21024 * Now that we have parsed *all* the schema document(s) and converted
21025 * them to schema components, we can resolve references, apply component
21026 * constraints, create the FSA from the content model, etc.
21029 * Resolve references of..
21031 * 1. element declarations:
21032 * - the type definition
21033 * - the substitution group affiliation
21034 * 2. simple/complex types:
21035 * - the base type definition
21036 * - the memberTypes of union types
21037 * - the itemType of list types
21038 * 3. attributes declarations and attribute uses:
21039 * - the type definition
21040 * - if an attribute use, then the attribute declaration
21041 * 4. attribute group references:
21042 * - the attribute group definition
21043 * 5. particles:
21044 * - the term of the particle (e.g. a model group)
21045 * 6. IDC key-references:
21046 * - the referenced IDC 'key' or 'unique' definition
21047 * 7. Attribute prohibitions which had a "ref" attribute.
21049 for (i = 0; i < nbItems; i++) {
21050 item = items[i];
21051 switch (item->type) {
21052 case XML_SCHEMA_TYPE_ELEMENT:
21053 xmlSchemaResolveElementReferences(
21054 (xmlSchemaElementPtr) item, pctxt);
21055 FIXHFAILURE;
21056 break;
21057 case XML_SCHEMA_TYPE_COMPLEX:
21058 case XML_SCHEMA_TYPE_SIMPLE:
21059 xmlSchemaResolveTypeReferences(
21060 (xmlSchemaTypePtr) item, pctxt);
21061 FIXHFAILURE;
21062 break;
21063 case XML_SCHEMA_TYPE_ATTRIBUTE:
21064 xmlSchemaResolveAttrTypeReferences(
21065 (xmlSchemaAttributePtr) item, pctxt);
21066 FIXHFAILURE;
21067 break;
21068 case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
21069 xmlSchemaResolveAttrUseReferences(
21070 (xmlSchemaAttributeUsePtr) item, pctxt);
21071 FIXHFAILURE;
21072 break;
21073 case XML_SCHEMA_EXTRA_QNAMEREF:
21074 if ((WXS_QNAME_CAST item)->itemType ==
21075 XML_SCHEMA_TYPE_ATTRIBUTEGROUP)
21077 xmlSchemaResolveAttrGroupReferences(
21078 WXS_QNAME_CAST item, pctxt);
21080 FIXHFAILURE;
21081 break;
21082 case XML_SCHEMA_TYPE_SEQUENCE:
21083 case XML_SCHEMA_TYPE_CHOICE:
21084 case XML_SCHEMA_TYPE_ALL:
21085 xmlSchemaResolveModelGroupParticleReferences(pctxt,
21086 WXS_MODEL_GROUP_CAST item);
21087 FIXHFAILURE;
21088 break;
21089 case XML_SCHEMA_TYPE_IDC_KEY:
21090 case XML_SCHEMA_TYPE_IDC_UNIQUE:
21091 case XML_SCHEMA_TYPE_IDC_KEYREF:
21092 xmlSchemaResolveIDCKeyReferences(
21093 (xmlSchemaIDCPtr) item, pctxt);
21094 FIXHFAILURE;
21095 break;
21096 case XML_SCHEMA_EXTRA_ATTR_USE_PROHIB:
21098 * Handle attribute prohibition which had a
21099 * "ref" attribute.
21101 xmlSchemaResolveAttrUseProhibReferences(
21102 WXS_ATTR_PROHIB_CAST item, pctxt);
21103 FIXHFAILURE;
21104 break;
21105 default:
21106 break;
21109 if (pctxt->nberrors != 0)
21110 goto exit_error;
21113 * Now that all references are resolved we
21114 * can check for circularity of...
21115 * 1. the base axis of type definitions
21116 * 2. nested model group definitions
21117 * 3. nested attribute group definitions
21118 * TODO: check for circular substitution groups.
21120 for (i = 0; i < nbItems; i++) {
21121 item = items[i];
21123 * Let's better stop on the first error here.
21125 switch (item->type) {
21126 case XML_SCHEMA_TYPE_COMPLEX:
21127 case XML_SCHEMA_TYPE_SIMPLE:
21128 xmlSchemaCheckTypeDefCircular(
21129 (xmlSchemaTypePtr) item, pctxt);
21130 FIXHFAILURE;
21131 if (pctxt->nberrors != 0)
21132 goto exit_error;
21133 break;
21134 case XML_SCHEMA_TYPE_GROUP:
21135 xmlSchemaCheckGroupDefCircular(
21136 (xmlSchemaModelGroupDefPtr) item, pctxt);
21137 FIXHFAILURE;
21138 if (pctxt->nberrors != 0)
21139 goto exit_error;
21140 break;
21141 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
21142 xmlSchemaCheckAttrGroupCircular(
21143 (xmlSchemaAttributeGroupPtr) item, pctxt);
21144 FIXHFAILURE;
21145 if (pctxt->nberrors != 0)
21146 goto exit_error;
21147 break;
21148 default:
21149 break;
21152 if (pctxt->nberrors != 0)
21153 goto exit_error;
21155 * Model group definition references:
21156 * Such a reference is reflected by a particle at the component
21157 * level. Until now the 'term' of such particles pointed
21158 * to the model group definition; this was done, in order to
21159 * ease circularity checks. Now we need to set the 'term' of
21160 * such particles to the model group of the model group definition.
21162 for (i = 0; i < nbItems; i++) {
21163 item = items[i];
21164 switch (item->type) {
21165 case XML_SCHEMA_TYPE_SEQUENCE:
21166 case XML_SCHEMA_TYPE_CHOICE:
21167 xmlSchemaModelGroupToModelGroupDefFixup(pctxt,
21168 WXS_MODEL_GROUP_CAST item);
21169 break;
21170 default:
21171 break;
21174 if (pctxt->nberrors != 0)
21175 goto exit_error;
21177 * Expand attribute group references of attribute group definitions.
21179 for (i = 0; i < nbItems; i++) {
21180 item = items[i];
21181 switch (item->type) {
21182 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
21183 if ((! WXS_ATTR_GROUP_EXPANDED(item)) &&
21184 WXS_ATTR_GROUP_HAS_REFS(item))
21186 xmlSchemaAttributeGroupExpandRefs(pctxt,
21187 WXS_ATTR_GROUP_CAST item);
21188 FIXHFAILURE;
21190 break;
21191 default:
21192 break;
21195 if (pctxt->nberrors != 0)
21196 goto exit_error;
21198 * First compute the variety of simple types. This is needed as
21199 * a separate step, since otherwise we won't be able to detect
21200 * circular union types in all cases.
21202 for (i = 0; i < nbItems; i++) {
21203 item = items[i];
21204 switch (item->type) {
21205 case XML_SCHEMA_TYPE_SIMPLE:
21206 if (WXS_IS_TYPE_NOT_FIXED_1((xmlSchemaTypePtr) item)) {
21207 xmlSchemaFixupSimpleTypeStageOne(pctxt,
21208 (xmlSchemaTypePtr) item);
21209 FIXHFAILURE;
21211 break;
21212 default:
21213 break;
21216 if (pctxt->nberrors != 0)
21217 goto exit_error;
21219 * Detect circular union types. Note that this needs the variety to
21220 * be already computed.
21222 for (i = 0; i < nbItems; i++) {
21223 item = items[i];
21224 switch (item->type) {
21225 case XML_SCHEMA_TYPE_SIMPLE:
21226 if (((xmlSchemaTypePtr) item)->memberTypes != NULL) {
21227 xmlSchemaCheckUnionTypeDefCircular(pctxt,
21228 (xmlSchemaTypePtr) item);
21229 FIXHFAILURE;
21231 break;
21232 default:
21233 break;
21236 if (pctxt->nberrors != 0)
21237 goto exit_error;
21240 * Do the complete type fixup for simple types.
21242 for (i = 0; i < nbItems; i++) {
21243 item = items[i];
21244 switch (item->type) {
21245 case XML_SCHEMA_TYPE_SIMPLE:
21246 if (WXS_IS_TYPE_NOT_FIXED(WXS_TYPE_CAST item)) {
21247 xmlSchemaFixupSimpleTypeStageTwo(pctxt, WXS_TYPE_CAST item);
21248 FIXHFAILURE;
21250 break;
21251 default:
21252 break;
21255 if (pctxt->nberrors != 0)
21256 goto exit_error;
21258 * At this point we need build and check all simple types.
21261 * Apply constraints for attribute declarations.
21263 for (i = 0; i < nbItems; i++) {
21264 item = items[i];
21265 switch (item->type) {
21266 case XML_SCHEMA_TYPE_ATTRIBUTE:
21267 xmlSchemaCheckAttrPropsCorrect(pctxt, WXS_ATTR_CAST item);
21268 FIXHFAILURE;
21269 break;
21270 default:
21271 break;
21274 if (pctxt->nberrors != 0)
21275 goto exit_error;
21277 * Apply constraints for attribute uses.
21279 for (i = 0; i < nbItems; i++) {
21280 item = items[i];
21281 switch (item->type) {
21282 case XML_SCHEMA_TYPE_ATTRIBUTE_USE:
21283 if (((xmlSchemaAttributeUsePtr)item)->defValue != NULL) {
21284 xmlSchemaCheckAttrUsePropsCorrect(pctxt,
21285 WXS_ATTR_USE_CAST item);
21286 FIXHFAILURE;
21288 break;
21289 default:
21290 break;
21293 if (pctxt->nberrors != 0)
21294 goto exit_error;
21297 * Apply constraints for attribute group definitions.
21299 for (i = 0; i < nbItems; i++) {
21300 item = items[i];
21301 switch (item->type) {
21302 case XML_SCHEMA_TYPE_ATTRIBUTEGROUP:
21303 if (( (WXS_ATTR_GROUP_CAST item)->attrUses != NULL) &&
21304 ( (WXS_LIST_CAST (WXS_ATTR_GROUP_CAST item)->attrUses)->nbItems > 1))
21306 xmlSchemaCheckAGPropsCorrect(pctxt, WXS_ATTR_GROUP_CAST item);
21307 FIXHFAILURE;
21309 break;
21310 default:
21311 break;
21314 if (pctxt->nberrors != 0)
21315 goto exit_error;
21318 * Apply constraints for redefinitions.
21320 if (WXS_CONSTRUCTOR(pctxt)->redefs != NULL)
21321 xmlSchemaCheckSRCRedefineSecond(pctxt);
21322 if (pctxt->nberrors != 0)
21323 goto exit_error;
21326 * Complex types are built and checked.
21328 for (i = 0; i < nbItems; i++) {
21329 item = con->pending->items[i];
21330 switch (item->type) {
21331 case XML_SCHEMA_TYPE_COMPLEX:
21332 if (WXS_IS_TYPE_NOT_FIXED(WXS_TYPE_CAST item)) {
21333 xmlSchemaFixupComplexType(pctxt, WXS_TYPE_CAST item);
21334 FIXHFAILURE;
21336 break;
21337 default:
21338 break;
21341 if (pctxt->nberrors != 0)
21342 goto exit_error;
21345 * The list could have changed, since xmlSchemaFixupComplexType()
21346 * will create particles and model groups in some cases.
21348 items = (xmlSchemaTreeItemPtr *) con->pending->items;
21349 nbItems = con->pending->nbItems;
21352 * Apply some constraints for element declarations.
21354 for (i = 0; i < nbItems; i++) {
21355 item = items[i];
21356 switch (item->type) {
21357 case XML_SCHEMA_TYPE_ELEMENT:
21358 elemDecl = (xmlSchemaElementPtr) item;
21360 if ((elemDecl->flags & XML_SCHEMAS_ELEM_INTERNAL_CHECKED) == 0)
21362 xmlSchemaCheckElementDeclComponent(
21363 (xmlSchemaElementPtr) elemDecl, pctxt);
21364 FIXHFAILURE;
21367 #ifdef WXS_ELEM_DECL_CONS_ENABLED
21369 * Schema Component Constraint: Element Declarations Consistent
21370 * Apply this constraint to local types of element declarations.
21372 if ((WXS_ELEM_TYPEDEF(elemDecl) != NULL) &&
21373 (WXS_IS_COMPLEX(WXS_ELEM_TYPEDEF(elemDecl))) &&
21374 (WXS_TYPE_IS_LOCAL(WXS_ELEM_TYPEDEF(elemDecl))))
21376 xmlSchemaCheckElementDeclConsistent(pctxt,
21377 WXS_BASIC_CAST elemDecl,
21378 WXS_TYPE_PARTICLE(WXS_ELEM_TYPEDEF(elemDecl)),
21379 NULL, NULL, 0);
21381 #endif
21382 break;
21383 default:
21384 break;
21387 if (pctxt->nberrors != 0)
21388 goto exit_error;
21391 * Finally we can build the automaton from the content model of
21392 * complex types.
21395 for (i = 0; i < nbItems; i++) {
21396 item = items[i];
21397 switch (item->type) {
21398 case XML_SCHEMA_TYPE_COMPLEX:
21399 xmlSchemaBuildContentModel((xmlSchemaTypePtr) item, pctxt);
21400 /* FIXHFAILURE; */
21401 break;
21402 default:
21403 break;
21406 if (pctxt->nberrors != 0)
21407 goto exit_error;
21409 * URGENT TODO: cos-element-consistent
21411 goto exit;
21413 exit_error:
21414 ret = pctxt->err;
21415 goto exit;
21417 exit_failure:
21418 ret = -1;
21420 exit:
21422 * Reset the constructor. This is needed for XSI acquisition, since
21423 * those items will be processed over and over again for every XSI
21424 * if not cleared here.
21426 con->bucket = oldbucket;
21427 con->pending->nbItems = 0;
21428 if (con->substGroups != NULL) {
21429 xmlHashFree(con->substGroups, xmlSchemaSubstGroupFreeEntry);
21430 con->substGroups = NULL;
21432 if (con->redefs != NULL) {
21433 xmlSchemaRedefListFree(con->redefs);
21434 con->redefs = NULL;
21436 return(ret);
21439 * xmlSchemaParse:
21440 * @ctxt: a schema validation context
21442 * parse a schema definition resource and build an internal
21443 * XML Schema structure which can be used to validate instances.
21445 * Returns the internal XML Schema structure built from the resource or
21446 * NULL in case of error
21448 xmlSchemaPtr
21449 xmlSchemaParse(xmlSchemaParserCtxtPtr ctxt)
21451 xmlSchemaPtr mainSchema = NULL;
21452 xmlSchemaBucketPtr bucket = NULL;
21453 int res;
21456 * This one is used if the schema to be parsed was specified via
21457 * the API; i.e. not automatically by the validated instance document.
21460 if (xmlSchemaInitTypes() < 0)
21461 return (NULL);
21463 if (ctxt == NULL)
21464 return (NULL);
21466 /* TODO: Init the context. Is this all we need?*/
21467 ctxt->nberrors = 0;
21468 ctxt->err = 0;
21469 ctxt->counter = 0;
21471 /* Create the *main* schema. */
21472 mainSchema = xmlSchemaNewSchema(ctxt);
21473 if (mainSchema == NULL)
21474 goto exit_failure;
21476 * Create the schema constructor.
21478 if (ctxt->constructor == NULL) {
21479 ctxt->constructor = xmlSchemaConstructionCtxtCreate(ctxt->dict);
21480 if (ctxt->constructor == NULL)
21481 goto exit_failure;
21482 /* Take ownership of the constructor to be able to free it. */
21483 ctxt->ownsConstructor = 1;
21485 ctxt->constructor->mainSchema = mainSchema;
21487 * Locate and add the schema document.
21489 res = xmlSchemaAddSchemaDoc(ctxt, XML_SCHEMA_SCHEMA_MAIN,
21490 ctxt->URL, ctxt->doc, ctxt->buffer, ctxt->size, NULL,
21491 NULL, NULL, &bucket);
21492 if (res == -1)
21493 goto exit_failure;
21494 if (res != 0)
21495 goto exit;
21497 if (bucket == NULL) {
21498 /* TODO: Error code, actually we failed to *locate* the schema. */
21499 if (ctxt->URL)
21500 xmlSchemaCustomErr(ACTXT_CAST ctxt, XML_SCHEMAP_FAILED_LOAD,
21501 NULL, NULL,
21502 "Failed to locate the main schema resource at '%s'",
21503 ctxt->URL, NULL);
21504 else
21505 xmlSchemaCustomErr(ACTXT_CAST ctxt, XML_SCHEMAP_FAILED_LOAD,
21506 NULL, NULL,
21507 "Failed to locate the main schema resource",
21508 NULL, NULL);
21509 goto exit;
21511 /* Then do the parsing for good. */
21512 if (xmlSchemaParseNewDocWithContext(ctxt, mainSchema, bucket) == -1)
21513 goto exit_failure;
21514 if (ctxt->nberrors != 0)
21515 goto exit;
21517 mainSchema->doc = bucket->doc;
21518 mainSchema->preserve = ctxt->preserve;
21520 ctxt->schema = mainSchema;
21522 if (xmlSchemaFixupComponents(ctxt, WXS_CONSTRUCTOR(ctxt)->mainBucket) == -1)
21523 goto exit_failure;
21526 * TODO: This is not nice, since we cannot distinguish from the
21527 * result if there was an internal error or not.
21529 exit:
21530 if (ctxt->nberrors != 0) {
21531 if (mainSchema) {
21532 xmlSchemaFree(mainSchema);
21533 mainSchema = NULL;
21535 if (ctxt->constructor) {
21536 xmlSchemaConstructionCtxtFree(ctxt->constructor);
21537 ctxt->constructor = NULL;
21538 ctxt->ownsConstructor = 0;
21541 ctxt->schema = NULL;
21542 return(mainSchema);
21543 exit_failure:
21545 * Quite verbose, but should catch internal errors, which were
21546 * not communicated.
21548 if (mainSchema) {
21549 xmlSchemaFree(mainSchema);
21550 mainSchema = NULL;
21552 if (ctxt->constructor) {
21553 xmlSchemaConstructionCtxtFree(ctxt->constructor);
21554 ctxt->constructor = NULL;
21555 ctxt->ownsConstructor = 0;
21557 PERROR_INT2("xmlSchemaParse",
21558 "An internal error occurred");
21559 ctxt->schema = NULL;
21560 return(NULL);
21564 * xmlSchemaSetParserErrors:
21565 * @ctxt: a schema validation context
21566 * @err: the error callback
21567 * @warn: the warning callback
21568 * @ctx: contextual data for the callbacks
21570 * Set the callback functions used to handle errors for a validation context
21572 void
21573 xmlSchemaSetParserErrors(xmlSchemaParserCtxtPtr ctxt,
21574 xmlSchemaValidityErrorFunc err,
21575 xmlSchemaValidityWarningFunc warn, void *ctx)
21577 if (ctxt == NULL)
21578 return;
21579 ctxt->error = err;
21580 ctxt->warning = warn;
21581 ctxt->errCtxt = ctx;
21582 if (ctxt->vctxt != NULL)
21583 xmlSchemaSetValidErrors(ctxt->vctxt, err, warn, ctx);
21587 * xmlSchemaSetParserStructuredErrors:
21588 * @ctxt: a schema parser context
21589 * @serror: the structured error function
21590 * @ctx: the functions context
21592 * Set the structured error callback
21594 void
21595 xmlSchemaSetParserStructuredErrors(xmlSchemaParserCtxtPtr ctxt,
21596 xmlStructuredErrorFunc serror,
21597 void *ctx)
21599 if (ctxt == NULL)
21600 return;
21601 ctxt->serror = serror;
21602 ctxt->errCtxt = ctx;
21603 if (ctxt->vctxt != NULL)
21604 xmlSchemaSetValidStructuredErrors(ctxt->vctxt, serror, ctx);
21608 * xmlSchemaGetParserErrors:
21609 * @ctxt: a XMl-Schema parser context
21610 * @err: the error callback result
21611 * @warn: the warning callback result
21612 * @ctx: contextual data for the callbacks result
21614 * Get the callback information used to handle errors for a parser context
21616 * Returns -1 in case of failure, 0 otherwise
21619 xmlSchemaGetParserErrors(xmlSchemaParserCtxtPtr ctxt,
21620 xmlSchemaValidityErrorFunc * err,
21621 xmlSchemaValidityWarningFunc * warn, void **ctx)
21623 if (ctxt == NULL)
21624 return(-1);
21625 if (err != NULL)
21626 *err = ctxt->error;
21627 if (warn != NULL)
21628 *warn = ctxt->warning;
21629 if (ctx != NULL)
21630 *ctx = ctxt->errCtxt;
21631 return(0);
21635 * xmlSchemaFacetTypeToString:
21636 * @type: the facet type
21638 * Convert the xmlSchemaTypeType to a char string.
21640 * Returns the char string representation of the facet type if the
21641 * type is a facet and an "Internal Error" string otherwise.
21643 static const xmlChar *
21644 xmlSchemaFacetTypeToString(xmlSchemaTypeType type)
21646 switch (type) {
21647 case XML_SCHEMA_FACET_PATTERN:
21648 return (BAD_CAST "pattern");
21649 case XML_SCHEMA_FACET_MAXEXCLUSIVE:
21650 return (BAD_CAST "maxExclusive");
21651 case XML_SCHEMA_FACET_MAXINCLUSIVE:
21652 return (BAD_CAST "maxInclusive");
21653 case XML_SCHEMA_FACET_MINEXCLUSIVE:
21654 return (BAD_CAST "minExclusive");
21655 case XML_SCHEMA_FACET_MININCLUSIVE:
21656 return (BAD_CAST "minInclusive");
21657 case XML_SCHEMA_FACET_WHITESPACE:
21658 return (BAD_CAST "whiteSpace");
21659 case XML_SCHEMA_FACET_ENUMERATION:
21660 return (BAD_CAST "enumeration");
21661 case XML_SCHEMA_FACET_LENGTH:
21662 return (BAD_CAST "length");
21663 case XML_SCHEMA_FACET_MAXLENGTH:
21664 return (BAD_CAST "maxLength");
21665 case XML_SCHEMA_FACET_MINLENGTH:
21666 return (BAD_CAST "minLength");
21667 case XML_SCHEMA_FACET_TOTALDIGITS:
21668 return (BAD_CAST "totalDigits");
21669 case XML_SCHEMA_FACET_FRACTIONDIGITS:
21670 return (BAD_CAST "fractionDigits");
21671 default:
21672 break;
21674 return (BAD_CAST "Internal Error");
21677 static xmlSchemaWhitespaceValueType
21678 xmlSchemaGetWhiteSpaceFacetValue(xmlSchemaTypePtr type)
21681 * The normalization type can be changed only for types which are derived
21682 * from xsd:string.
21684 if (type->type == XML_SCHEMA_TYPE_BASIC) {
21686 * Note that we assume a whitespace of preserve for anySimpleType.
21688 if ((type->builtInType == XML_SCHEMAS_STRING) ||
21689 (type->builtInType == XML_SCHEMAS_ANYSIMPLETYPE))
21690 return(XML_SCHEMA_WHITESPACE_PRESERVE);
21691 else if (type->builtInType == XML_SCHEMAS_NORMSTRING)
21692 return(XML_SCHEMA_WHITESPACE_REPLACE);
21693 else {
21695 * For all `atomic` datatypes other than string (and types `derived`
21696 * by `restriction` from it) the value of whiteSpace is fixed to
21697 * collapse
21698 * Note that this includes built-in list datatypes.
21700 return(XML_SCHEMA_WHITESPACE_COLLAPSE);
21702 } else if (WXS_IS_LIST(type)) {
21704 * For list types the facet "whiteSpace" is fixed to "collapse".
21706 return (XML_SCHEMA_WHITESPACE_COLLAPSE);
21707 } else if (WXS_IS_UNION(type)) {
21708 return (XML_SCHEMA_WHITESPACE_UNKNOWN);
21709 } else if (WXS_IS_ATOMIC(type)) {
21710 if (type->flags & XML_SCHEMAS_TYPE_WHITESPACE_PRESERVE)
21711 return (XML_SCHEMA_WHITESPACE_PRESERVE);
21712 else if (type->flags & XML_SCHEMAS_TYPE_WHITESPACE_REPLACE)
21713 return (XML_SCHEMA_WHITESPACE_REPLACE);
21714 else
21715 return (XML_SCHEMA_WHITESPACE_COLLAPSE);
21717 return (-1);
21720 /************************************************************************
21722 * Simple type validation *
21724 ************************************************************************/
21727 /************************************************************************
21729 * DOM Validation code *
21731 ************************************************************************/
21734 * xmlSchemaAssembleByLocation:
21735 * @pctxt: a schema parser context
21736 * @vctxt: a schema validation context
21737 * @schema: the existing schema
21738 * @node: the node that fired the assembling
21739 * @nsName: the namespace name of the new schema
21740 * @location: the location of the schema
21742 * Expands an existing schema by an additional schema.
21744 * Returns 0 if the new schema is correct, a positive error code
21745 * number otherwise and -1 in case of an internal or API error.
21747 static int
21748 xmlSchemaAssembleByLocation(xmlSchemaValidCtxtPtr vctxt,
21749 xmlSchemaPtr schema,
21750 xmlNodePtr node,
21751 const xmlChar *nsName,
21752 const xmlChar *location)
21754 int ret = 0;
21755 xmlSchemaParserCtxtPtr pctxt;
21756 xmlSchemaBucketPtr bucket = NULL;
21758 if ((vctxt == NULL) || (schema == NULL))
21759 return (-1);
21761 if (vctxt->pctxt == NULL) {
21762 VERROR_INT("xmlSchemaAssembleByLocation",
21763 "no parser context available");
21764 return(-1);
21766 pctxt = vctxt->pctxt;
21767 if (pctxt->constructor == NULL) {
21768 PERROR_INT("xmlSchemaAssembleByLocation",
21769 "no constructor");
21770 return(-1);
21773 * Acquire the schema document.
21775 location = xmlSchemaBuildAbsoluteURI(pctxt->dict,
21776 location, node);
21778 * Note that we pass XML_SCHEMA_SCHEMA_IMPORT here;
21779 * the process will automatically change this to
21780 * XML_SCHEMA_SCHEMA_MAIN if it is the first schema document.
21782 ret = xmlSchemaAddSchemaDoc(pctxt, XML_SCHEMA_SCHEMA_IMPORT,
21783 location, NULL, NULL, 0, node, NULL, nsName,
21784 &bucket);
21785 if (ret != 0)
21786 return(ret);
21787 if (bucket == NULL) {
21789 * Generate a warning that the document could not be located.
21791 xmlSchemaCustomWarning(ACTXT_CAST vctxt, XML_SCHEMAV_MISC,
21792 node, NULL,
21793 "The document at location '%s' could not be acquired",
21794 location, NULL, NULL);
21795 return(ret);
21798 * The first located schema will be handled as if all other
21799 * schemas imported by XSI were imported by this first schema.
21801 if ((bucket != NULL) &&
21802 (WXS_CONSTRUCTOR(pctxt)->bucket == NULL))
21803 WXS_CONSTRUCTOR(pctxt)->bucket = bucket;
21805 * TODO: Is this handled like an import? I.e. is it not an error
21806 * if the schema cannot be located?
21808 if ((bucket == NULL) || (! CAN_PARSE_SCHEMA(bucket)))
21809 return(0);
21811 * We will reuse the parser context for every schema imported
21812 * directly via XSI. So reset the context.
21814 pctxt->nberrors = 0;
21815 pctxt->err = 0;
21816 pctxt->doc = bucket->doc;
21818 ret = xmlSchemaParseNewDocWithContext(pctxt, schema, bucket);
21819 if (ret == -1) {
21820 pctxt->doc = NULL;
21821 goto exit_failure;
21823 /* Paranoid error channelling. */
21824 if ((ret == 0) && (pctxt->nberrors != 0))
21825 ret = pctxt->err;
21826 if (pctxt->nberrors == 0) {
21828 * Only bother to fixup pending components, if there was
21829 * no error yet.
21830 * For every XSI acquired schema (and its sub-schemata) we will
21831 * fixup the components.
21833 xmlSchemaFixupComponents(pctxt, bucket);
21834 ret = pctxt->err;
21836 * Not nice, but we need somehow to channel the schema parser
21837 * error to the validation context.
21839 if ((ret != 0) && (vctxt->err == 0))
21840 vctxt->err = ret;
21841 vctxt->nberrors += pctxt->nberrors;
21842 } else {
21843 /* Add to validation error sum. */
21844 vctxt->nberrors += pctxt->nberrors;
21846 pctxt->doc = NULL;
21847 return(ret);
21848 exit_failure:
21849 pctxt->doc = NULL;
21850 return (-1);
21853 static xmlSchemaAttrInfoPtr
21854 xmlSchemaGetMetaAttrInfo(xmlSchemaValidCtxtPtr vctxt,
21855 int metaType)
21857 if (vctxt->nbAttrInfos == 0)
21858 return (NULL);
21860 int i;
21861 xmlSchemaAttrInfoPtr iattr;
21863 for (i = 0; i < vctxt->nbAttrInfos; i++) {
21864 iattr = vctxt->attrInfos[i];
21865 if (iattr->metaType == metaType)
21866 return (iattr);
21870 return (NULL);
21874 * xmlSchemaAssembleByXSI:
21875 * @vctxt: a schema validation context
21877 * Expands an existing schema by an additional schema using
21878 * the xsi:schemaLocation or xsi:noNamespaceSchemaLocation attribute
21879 * of an instance. If xsi:noNamespaceSchemaLocation is used, @noNamespace
21880 * must be set to 1.
21882 * Returns 0 if the new schema is correct, a positive error code
21883 * number otherwise and -1 in case of an internal or API error.
21885 static int
21886 xmlSchemaAssembleByXSI(xmlSchemaValidCtxtPtr vctxt)
21888 const xmlChar *cur, *end;
21889 const xmlChar *nsname = NULL, *location;
21890 int ret = 0;
21891 xmlSchemaAttrInfoPtr iattr;
21894 * Parse the value; we will assume an even number of values
21895 * to be given (this is how Xerces and XSV work).
21897 * URGENT TODO: !! This needs to work for both
21898 * @noNamespaceSchemaLocation AND @schemaLocation on the same
21899 * element !!
21901 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
21902 XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC);
21903 if (iattr == NULL)
21904 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
21905 XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC);
21906 if (iattr == NULL)
21907 return (0);
21908 cur = iattr->value;
21909 do {
21911 * TODO: Move the string parsing mechanism away from here.
21913 if (iattr->metaType == XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC) {
21915 * Get the namespace name.
21917 while (IS_BLANK_CH(*cur))
21918 cur++;
21919 end = cur;
21920 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
21921 end++;
21922 if (end == cur)
21923 break;
21924 /* TODO: Don't use the schema's dict. */
21925 nsname = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
21926 cur = end;
21929 * Get the URI.
21931 while (IS_BLANK_CH(*cur))
21932 cur++;
21933 end = cur;
21934 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
21935 end++;
21936 if (end == cur) {
21937 if (iattr->metaType ==
21938 XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC)
21941 * If using @schemaLocation then tuples are expected.
21942 * I.e. the namespace name *and* the document's URI.
21944 xmlSchemaCustomWarning(ACTXT_CAST vctxt, XML_SCHEMAV_MISC,
21945 iattr->node, NULL,
21946 "The value must consist of tuples: the target namespace "
21947 "name and the document's URI", NULL, NULL, NULL);
21949 break;
21951 /* TODO: Don't use the schema's dict. */
21952 location = xmlDictLookup(vctxt->schema->dict, cur, end - cur);
21953 cur = end;
21954 ret = xmlSchemaAssembleByLocation(vctxt, vctxt->schema,
21955 iattr->node, nsname, location);
21956 if (ret == -1) {
21957 VERROR_INT("xmlSchemaAssembleByXSI",
21958 "assembling schemata");
21959 return (-1);
21961 } while (*cur != 0);
21962 return (ret);
21965 static const xmlChar *
21966 xmlSchemaLookupNamespace(xmlSchemaValidCtxtPtr vctxt,
21967 const xmlChar *prefix)
21969 if (vctxt->sax != NULL) {
21970 int i, j;
21971 xmlSchemaNodeInfoPtr inode;
21973 for (i = vctxt->depth; i >= 0; i--) {
21974 if (vctxt->elemInfos[i]->nbNsBindings != 0) {
21975 inode = vctxt->elemInfos[i];
21976 for (j = 0; j < inode->nbNsBindings * 2; j += 2) {
21977 if (((prefix == NULL) &&
21978 (inode->nsBindings[j] == NULL)) ||
21979 ((prefix != NULL) && xmlStrEqual(prefix,
21980 inode->nsBindings[j]))) {
21983 * Note that the namespace bindings are already
21984 * in a string dict.
21986 return (inode->nsBindings[j+1]);
21991 return (NULL);
21992 #ifdef LIBXML_READER_ENABLED
21993 } else if (vctxt->reader != NULL) {
21994 xmlChar *nsName;
21996 nsName = xmlTextReaderLookupNamespace(vctxt->reader, prefix);
21997 if (nsName != NULL) {
21998 const xmlChar *ret;
22000 ret = xmlDictLookup(vctxt->dict, nsName, -1);
22001 xmlFree(nsName);
22002 return (ret);
22003 } else
22004 return (NULL);
22005 #endif
22006 } else {
22007 xmlNsPtr ns;
22009 if ((vctxt->inode->node == NULL) ||
22010 (vctxt->inode->node->doc == NULL)) {
22011 VERROR_INT("xmlSchemaLookupNamespace",
22012 "no node or node's doc available");
22013 return (NULL);
22015 ns = xmlSearchNs(vctxt->inode->node->doc,
22016 vctxt->inode->node, prefix);
22017 if (ns != NULL)
22018 return (ns->href);
22019 return (NULL);
22024 * This one works on the schema of the validation context.
22026 static int
22027 xmlSchemaValidateNotation(xmlSchemaValidCtxtPtr vctxt,
22028 xmlSchemaPtr schema,
22029 xmlNodePtr node,
22030 const xmlChar *value,
22031 xmlSchemaValPtr *val,
22032 int valNeeded)
22034 int ret;
22036 if (vctxt && (vctxt->schema == NULL)) {
22037 VERROR_INT("xmlSchemaValidateNotation",
22038 "a schema is needed on the validation context");
22039 return (-1);
22041 ret = xmlValidateQName(value, 1);
22042 if (ret != 0)
22043 return (ret);
22045 xmlChar *localName = NULL;
22046 xmlChar *prefix = NULL;
22048 localName = xmlSplitQName2(value, &prefix);
22049 if (prefix != NULL) {
22050 const xmlChar *nsName = NULL;
22052 if (vctxt != NULL)
22053 nsName = xmlSchemaLookupNamespace(vctxt, BAD_CAST prefix);
22054 else if (node != NULL) {
22055 xmlNsPtr ns = xmlSearchNs(node->doc, node, prefix);
22056 if (ns != NULL)
22057 nsName = ns->href;
22058 } else {
22059 xmlFree(prefix);
22060 xmlFree(localName);
22061 return (1);
22063 if (nsName == NULL) {
22064 xmlFree(prefix);
22065 xmlFree(localName);
22066 return (1);
22068 if (xmlSchemaGetNotation(schema, localName, nsName) != NULL) {
22069 if ((valNeeded) && (val != NULL)) {
22070 (*val) = xmlSchemaNewNOTATIONValue(xmlStrdup(localName),
22071 xmlStrdup(nsName));
22072 if (*val == NULL)
22073 ret = -1;
22075 } else
22076 ret = 1;
22077 xmlFree(prefix);
22078 xmlFree(localName);
22079 } else {
22080 if (xmlSchemaGetNotation(schema, value, NULL) != NULL) {
22081 if (valNeeded && (val != NULL)) {
22082 (*val) = xmlSchemaNewNOTATIONValue(
22083 BAD_CAST xmlStrdup(value), NULL);
22084 if (*val == NULL)
22085 ret = -1;
22087 } else
22088 return (1);
22091 return (ret);
22094 static int
22095 xmlSchemaVAddNodeQName(xmlSchemaValidCtxtPtr vctxt,
22096 const xmlChar* lname,
22097 const xmlChar* nsname)
22099 int i;
22101 lname = xmlDictLookup(vctxt->dict, lname, -1);
22102 if (lname == NULL)
22103 return(-1);
22104 if (nsname != NULL) {
22105 nsname = xmlDictLookup(vctxt->dict, nsname, -1);
22106 if (nsname == NULL)
22107 return(-1);
22109 for (i = 0; i < vctxt->nodeQNames->nbItems; i += 2) {
22110 if ((vctxt->nodeQNames->items [i] == lname) &&
22111 (vctxt->nodeQNames->items[i +1] == nsname))
22112 /* Already there */
22113 return(i);
22115 /* Add new entry. */
22116 i = vctxt->nodeQNames->nbItems;
22117 xmlSchemaItemListAdd(vctxt->nodeQNames, (void *) lname);
22118 xmlSchemaItemListAdd(vctxt->nodeQNames, (void *) nsname);
22119 return(i);
22122 /************************************************************************
22124 * Validation of identity-constraints (IDC) *
22126 ************************************************************************/
22129 * xmlSchemaAugmentIDC:
22130 * @idcDef: the IDC definition
22132 * Creates an augmented IDC definition item.
22134 * Returns the item, or NULL on internal errors.
22136 static void
22137 xmlSchemaAugmentIDC(void *payload, void *data,
22138 const xmlChar *name ATTRIBUTE_UNUSED)
22140 xmlSchemaIDCPtr idcDef = (xmlSchemaIDCPtr) payload;
22141 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) data;
22142 xmlSchemaIDCAugPtr aidc;
22144 aidc = (xmlSchemaIDCAugPtr) xmlMalloc(sizeof(xmlSchemaIDCAug));
22145 if (aidc == NULL) {
22146 xmlSchemaVErrMemory(vctxt,
22147 "xmlSchemaAugmentIDC: allocating an augmented IDC definition",
22148 NULL);
22149 return;
22151 aidc->keyrefDepth = -1;
22152 aidc->def = idcDef;
22153 aidc->next = NULL;
22154 if (vctxt->aidcs == NULL)
22155 vctxt->aidcs = aidc;
22156 else {
22157 aidc->next = vctxt->aidcs;
22158 vctxt->aidcs = aidc;
22161 * Save if we have keyrefs at all.
22163 if ((vctxt->hasKeyrefs == 0) &&
22164 (idcDef->type == XML_SCHEMA_TYPE_IDC_KEYREF))
22165 vctxt->hasKeyrefs = 1;
22169 * xmlSchemaAugmentImportedIDC:
22170 * @imported: the imported schema
22172 * Creates an augmented IDC definition for the imported schema.
22174 static void
22175 xmlSchemaAugmentImportedIDC(void *payload, void *data,
22176 const xmlChar *name ATTRIBUTE_UNUSED) {
22177 xmlSchemaImportPtr imported = (xmlSchemaImportPtr) payload;
22178 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) data;
22179 if (imported->schema->idcDef != NULL) {
22180 xmlHashScan(imported->schema->idcDef, xmlSchemaAugmentIDC, vctxt);
22185 * xmlSchemaIDCNewBinding:
22186 * @idcDef: the IDC definition of this binding
22188 * Creates a new IDC binding.
22190 * Returns the new IDC binding, NULL on internal errors.
22192 static xmlSchemaPSVIIDCBindingPtr
22193 xmlSchemaIDCNewBinding(xmlSchemaIDCPtr idcDef)
22195 xmlSchemaPSVIIDCBindingPtr ret;
22197 ret = (xmlSchemaPSVIIDCBindingPtr) xmlMalloc(
22198 sizeof(xmlSchemaPSVIIDCBinding));
22199 if (ret == NULL) {
22200 xmlSchemaVErrMemory(NULL,
22201 "allocating a PSVI IDC binding item", NULL);
22202 return (NULL);
22204 memset(ret, 0, sizeof(xmlSchemaPSVIIDCBinding));
22205 ret->definition = idcDef;
22206 return (ret);
22210 * xmlSchemaIDCStoreNodeTableItem:
22211 * @vctxt: the WXS validation context
22212 * @item: the IDC node table item
22214 * The validation context is used to store IDC node table items.
22215 * They are stored to avoid copying them if IDC node-tables are merged
22216 * with corresponding parent IDC node-tables (bubbling).
22218 * Returns 0 if succeeded, -1 on internal errors.
22220 static int
22221 xmlSchemaIDCStoreNodeTableItem(xmlSchemaValidCtxtPtr vctxt,
22222 xmlSchemaPSVIIDCNodePtr item)
22225 * Add to global list.
22227 if (vctxt->idcNodes == NULL) {
22228 vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
22229 xmlMalloc(20 * sizeof(xmlSchemaPSVIIDCNodePtr));
22230 if (vctxt->idcNodes == NULL) {
22231 xmlSchemaVErrMemory(vctxt,
22232 "allocating the IDC node table item list", NULL);
22233 return (-1);
22235 vctxt->sizeIdcNodes = 20;
22236 } else if (vctxt->sizeIdcNodes <= vctxt->nbIdcNodes) {
22237 vctxt->sizeIdcNodes *= 2;
22238 vctxt->idcNodes = (xmlSchemaPSVIIDCNodePtr *)
22239 xmlRealloc(vctxt->idcNodes, vctxt->sizeIdcNodes *
22240 sizeof(xmlSchemaPSVIIDCNodePtr));
22241 if (vctxt->idcNodes == NULL) {
22242 xmlSchemaVErrMemory(vctxt,
22243 "re-allocating the IDC node table item list", NULL);
22244 return (-1);
22247 vctxt->idcNodes[vctxt->nbIdcNodes++] = item;
22249 return (0);
22253 * xmlSchemaIDCStoreKey:
22254 * @vctxt: the WXS validation context
22255 * @item: the IDC key
22257 * The validation context is used to store an IDC key.
22259 * Returns 0 if succeeded, -1 on internal errors.
22261 static int
22262 xmlSchemaIDCStoreKey(xmlSchemaValidCtxtPtr vctxt,
22263 xmlSchemaPSVIIDCKeyPtr key)
22266 * Add to global list.
22268 if (vctxt->idcKeys == NULL) {
22269 vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
22270 xmlMalloc(40 * sizeof(xmlSchemaPSVIIDCKeyPtr));
22271 if (vctxt->idcKeys == NULL) {
22272 xmlSchemaVErrMemory(vctxt,
22273 "allocating the IDC key storage list", NULL);
22274 return (-1);
22276 vctxt->sizeIdcKeys = 40;
22277 } else if (vctxt->sizeIdcKeys <= vctxt->nbIdcKeys) {
22278 vctxt->sizeIdcKeys *= 2;
22279 vctxt->idcKeys = (xmlSchemaPSVIIDCKeyPtr *)
22280 xmlRealloc(vctxt->idcKeys, vctxt->sizeIdcKeys *
22281 sizeof(xmlSchemaPSVIIDCKeyPtr));
22282 if (vctxt->idcKeys == NULL) {
22283 xmlSchemaVErrMemory(vctxt,
22284 "re-allocating the IDC key storage list", NULL);
22285 return (-1);
22288 vctxt->idcKeys[vctxt->nbIdcKeys++] = key;
22290 return (0);
22294 * xmlSchemaIDCAppendNodeTableItem:
22295 * @bind: the IDC binding
22296 * @ntItem: the node-table item
22298 * Appends the IDC node-table item to the binding.
22300 * Returns 0 on success and -1 on internal errors.
22302 static int
22303 xmlSchemaIDCAppendNodeTableItem(xmlSchemaPSVIIDCBindingPtr bind,
22304 xmlSchemaPSVIIDCNodePtr ntItem)
22306 if (bind->nodeTable == NULL) {
22307 bind->sizeNodes = 10;
22308 bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
22309 xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr));
22310 if (bind->nodeTable == NULL) {
22311 xmlSchemaVErrMemory(NULL,
22312 "allocating an array of IDC node-table items", NULL);
22313 return(-1);
22315 } else if (bind->sizeNodes <= bind->nbNodes) {
22316 bind->sizeNodes *= 2;
22317 bind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
22318 xmlRealloc(bind->nodeTable, bind->sizeNodes *
22319 sizeof(xmlSchemaPSVIIDCNodePtr));
22320 if (bind->nodeTable == NULL) {
22321 xmlSchemaVErrMemory(NULL,
22322 "re-allocating an array of IDC node-table items", NULL);
22323 return(-1);
22326 bind->nodeTable[bind->nbNodes++] = ntItem;
22327 return(0);
22331 * xmlSchemaIDCAcquireBinding:
22332 * @vctxt: the WXS validation context
22333 * @matcher: the IDC matcher
22335 * Looks up an PSVI IDC binding, for the IDC definition and
22336 * of the given matcher. If none found, a new one is created
22337 * and added to the IDC table.
22339 * Returns an IDC binding or NULL on internal errors.
22341 static xmlSchemaPSVIIDCBindingPtr
22342 xmlSchemaIDCAcquireBinding(xmlSchemaValidCtxtPtr vctxt,
22343 xmlSchemaIDCMatcherPtr matcher)
22345 xmlSchemaNodeInfoPtr ielem;
22347 ielem = vctxt->elemInfos[matcher->depth];
22349 if (ielem->idcTable == NULL) {
22350 ielem->idcTable = xmlSchemaIDCNewBinding(matcher->aidc->def);
22351 if (ielem->idcTable == NULL)
22352 return (NULL);
22353 return(ielem->idcTable);
22354 } else {
22355 xmlSchemaPSVIIDCBindingPtr bind = NULL;
22357 bind = ielem->idcTable;
22358 do {
22359 if (bind->definition == matcher->aidc->def)
22360 return(bind);
22361 if (bind->next == NULL) {
22362 bind->next = xmlSchemaIDCNewBinding(matcher->aidc->def);
22363 if (bind->next == NULL)
22364 return (NULL);
22365 return(bind->next);
22367 bind = bind->next;
22368 } while (bind != NULL);
22370 return (NULL);
22373 static xmlSchemaItemListPtr
22374 xmlSchemaIDCAcquireTargetList(xmlSchemaValidCtxtPtr vctxt ATTRIBUTE_UNUSED,
22375 xmlSchemaIDCMatcherPtr matcher)
22377 if (matcher->targets == NULL)
22378 matcher->targets = xmlSchemaItemListCreate();
22379 return(matcher->targets);
22383 * xmlSchemaIDCFreeKey:
22384 * @key: the IDC key
22386 * Frees an IDC key together with its compiled value.
22388 static void
22389 xmlSchemaIDCFreeKey(xmlSchemaPSVIIDCKeyPtr key)
22391 if (key->val != NULL)
22392 xmlSchemaFreeValue(key->val);
22393 xmlFree(key);
22397 * xmlSchemaIDCFreeBinding:
22399 * Frees an IDC binding. Note that the node table-items
22400 * are not freed.
22402 static void
22403 xmlSchemaIDCFreeBinding(xmlSchemaPSVIIDCBindingPtr bind)
22405 if (bind->nodeTable != NULL)
22406 xmlFree(bind->nodeTable);
22407 if (bind->dupls != NULL)
22408 xmlSchemaItemListFree(bind->dupls);
22409 xmlFree(bind);
22413 * xmlSchemaIDCFreeIDCTable:
22414 * @bind: the first IDC binding in the list
22416 * Frees an IDC table, i.e. all the IDC bindings in the list.
22418 static void
22419 xmlSchemaIDCFreeIDCTable(xmlSchemaPSVIIDCBindingPtr bind)
22421 xmlSchemaPSVIIDCBindingPtr prev;
22423 while (bind != NULL) {
22424 prev = bind;
22425 bind = bind->next;
22426 xmlSchemaIDCFreeBinding(prev);
22430 static void
22431 xmlFreeIDCHashEntry (void *payload, const xmlChar *name ATTRIBUTE_UNUSED)
22433 xmlIDCHashEntryPtr e = payload, n;
22434 while (e) {
22435 n = e->next;
22436 xmlFree(e);
22437 e = n;
22442 * xmlSchemaIDCFreeMatcherList:
22443 * @matcher: the first IDC matcher in the list
22445 * Frees a list of IDC matchers.
22447 static void
22448 xmlSchemaIDCFreeMatcherList(xmlSchemaIDCMatcherPtr matcher)
22450 xmlSchemaIDCMatcherPtr next;
22452 while (matcher != NULL) {
22453 next = matcher->next;
22454 if (matcher->keySeqs != NULL) {
22455 int i;
22456 for (i = 0; i < matcher->sizeKeySeqs; i++)
22457 if (matcher->keySeqs[i] != NULL)
22458 xmlFree(matcher->keySeqs[i]);
22459 xmlFree(matcher->keySeqs);
22461 if (matcher->targets != NULL) {
22462 if (matcher->idcType == XML_SCHEMA_TYPE_IDC_KEYREF) {
22463 int i;
22464 xmlSchemaPSVIIDCNodePtr idcNode;
22466 * Node-table items for keyrefs are not stored globally
22467 * to the validation context, since they are not bubbled.
22468 * We need to free them here.
22470 for (i = 0; i < matcher->targets->nbItems; i++) {
22471 idcNode =
22472 (xmlSchemaPSVIIDCNodePtr) matcher->targets->items[i];
22473 xmlFree(idcNode->keys);
22474 xmlFree(idcNode);
22477 xmlSchemaItemListFree(matcher->targets);
22479 if (matcher->htab != NULL)
22480 xmlHashFree(matcher->htab, xmlFreeIDCHashEntry);
22481 xmlFree(matcher);
22482 matcher = next;
22487 * xmlSchemaIDCReleaseMatcherList:
22488 * @vctxt: the WXS validation context
22489 * @matcher: the first IDC matcher in the list
22491 * Caches a list of IDC matchers for reuse.
22493 static void
22494 xmlSchemaIDCReleaseMatcherList(xmlSchemaValidCtxtPtr vctxt,
22495 xmlSchemaIDCMatcherPtr matcher)
22497 xmlSchemaIDCMatcherPtr next;
22499 while (matcher != NULL) {
22500 next = matcher->next;
22501 if (matcher->keySeqs != NULL) {
22502 int i;
22504 * Don't free the array, but only the content.
22506 for (i = 0; i < matcher->sizeKeySeqs; i++)
22507 if (matcher->keySeqs[i] != NULL) {
22508 xmlFree(matcher->keySeqs[i]);
22509 matcher->keySeqs[i] = NULL;
22512 if (matcher->targets) {
22513 if (matcher->idcType == XML_SCHEMA_TYPE_IDC_KEYREF) {
22514 int i;
22515 xmlSchemaPSVIIDCNodePtr idcNode;
22517 * Node-table items for keyrefs are not stored globally
22518 * to the validation context, since they are not bubbled.
22519 * We need to free them here.
22521 for (i = 0; i < matcher->targets->nbItems; i++) {
22522 idcNode =
22523 (xmlSchemaPSVIIDCNodePtr) matcher->targets->items[i];
22524 xmlFree(idcNode->keys);
22525 xmlFree(idcNode);
22528 xmlSchemaItemListFree(matcher->targets);
22529 matcher->targets = NULL;
22531 if (matcher->htab != NULL) {
22532 xmlHashFree(matcher->htab, xmlFreeIDCHashEntry);
22533 matcher->htab = NULL;
22535 matcher->next = NULL;
22537 * Cache the matcher.
22539 if (vctxt->idcMatcherCache != NULL)
22540 matcher->nextCached = vctxt->idcMatcherCache;
22541 vctxt->idcMatcherCache = matcher;
22543 matcher = next;
22548 * xmlSchemaIDCAddStateObject:
22549 * @vctxt: the WXS validation context
22550 * @matcher: the IDC matcher
22551 * @sel: the XPath information
22552 * @parent: the parent "selector" state object if any
22553 * @type: "selector" or "field"
22555 * Creates/reuses and activates state objects for the given
22556 * XPath information; if the XPath expression consists of unions,
22557 * multiple state objects are created for every unioned expression.
22559 * Returns 0 on success and -1 on internal errors.
22561 static int
22562 xmlSchemaIDCAddStateObject(xmlSchemaValidCtxtPtr vctxt,
22563 xmlSchemaIDCMatcherPtr matcher,
22564 xmlSchemaIDCSelectPtr sel,
22565 int type)
22567 xmlSchemaIDCStateObjPtr sto;
22570 * Reuse the state objects from the pool.
22572 if (vctxt->xpathStatePool != NULL) {
22573 sto = vctxt->xpathStatePool;
22574 vctxt->xpathStatePool = sto->next;
22575 sto->next = NULL;
22576 } else {
22578 * Create a new state object.
22580 sto = (xmlSchemaIDCStateObjPtr) xmlMalloc(sizeof(xmlSchemaIDCStateObj));
22581 if (sto == NULL) {
22582 xmlSchemaVErrMemory(NULL,
22583 "allocating an IDC state object", NULL);
22584 return (-1);
22586 memset(sto, 0, sizeof(xmlSchemaIDCStateObj));
22589 * Add to global list.
22591 if (vctxt->xpathStates != NULL)
22592 sto->next = vctxt->xpathStates;
22593 vctxt->xpathStates = sto;
22596 * Free the old xpath validation context.
22598 if (sto->xpathCtxt != NULL)
22599 xmlFreeStreamCtxt((xmlStreamCtxtPtr) sto->xpathCtxt);
22602 * Create a new XPath (pattern) validation context.
22604 sto->xpathCtxt = (void *) xmlPatternGetStreamCtxt(
22605 (xmlPatternPtr) sel->xpathComp);
22606 if (sto->xpathCtxt == NULL) {
22607 VERROR_INT("xmlSchemaIDCAddStateObject",
22608 "failed to create an XPath validation context");
22609 return (-1);
22611 sto->type = type;
22612 sto->depth = vctxt->depth;
22613 sto->matcher = matcher;
22614 sto->sel = sel;
22615 sto->nbHistory = 0;
22617 #ifdef DEBUG_IDC
22618 xmlGenericError(xmlGenericErrorContext, "IDC: STO push '%s'\n",
22619 sto->sel->xpath);
22620 #endif
22621 return (0);
22625 * xmlSchemaXPathEvaluate:
22626 * @vctxt: the WXS validation context
22627 * @nodeType: the nodeType of the current node
22629 * Evaluates all active XPath state objects.
22631 * Returns the number of IC "field" state objects which resolved to
22632 * this node, 0 if none resolved and -1 on internal errors.
22634 static int
22635 xmlSchemaXPathEvaluate(xmlSchemaValidCtxtPtr vctxt,
22636 xmlElementType nodeType)
22638 xmlSchemaIDCStateObjPtr sto, head = NULL, first;
22639 int res, resolved = 0, depth = vctxt->depth;
22641 if (vctxt->xpathStates == NULL)
22642 return (0);
22644 if (nodeType == XML_ATTRIBUTE_NODE)
22645 depth++;
22646 #ifdef DEBUG_IDC
22648 xmlChar *str = NULL;
22649 xmlGenericError(xmlGenericErrorContext,
22650 "IDC: EVAL on %s, depth %d, type %d\n",
22651 xmlSchemaFormatQName(&str, vctxt->inode->nsName,
22652 vctxt->inode->localName), depth, nodeType);
22653 FREE_AND_NULL(str)
22655 #endif
22657 * Process all active XPath state objects.
22659 first = vctxt->xpathStates;
22660 sto = first;
22661 while (sto != head) {
22662 #ifdef DEBUG_IDC
22663 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR)
22664 xmlGenericError(xmlGenericErrorContext, "IDC: ['%s'] selector '%s'\n",
22665 sto->matcher->aidc->def->name, sto->sel->xpath);
22666 else
22667 xmlGenericError(xmlGenericErrorContext, "IDC: ['%s'] field '%s'\n",
22668 sto->matcher->aidc->def->name, sto->sel->xpath);
22669 #endif
22670 if (nodeType == XML_ELEMENT_NODE)
22671 res = xmlStreamPush((xmlStreamCtxtPtr) sto->xpathCtxt,
22672 vctxt->inode->localName, vctxt->inode->nsName);
22673 else
22674 res = xmlStreamPushAttr((xmlStreamCtxtPtr) sto->xpathCtxt,
22675 vctxt->inode->localName, vctxt->inode->nsName);
22677 if (res == -1) {
22678 VERROR_INT("xmlSchemaXPathEvaluate",
22679 "calling xmlStreamPush()");
22680 return (-1);
22682 if (res == 0)
22683 goto next_sto;
22685 * Full match.
22687 #ifdef DEBUG_IDC
22688 xmlGenericError(xmlGenericErrorContext, "IDC: "
22689 "MATCH\n");
22690 #endif
22692 * Register a match in the state object history.
22694 if (sto->history == NULL) {
22695 sto->history = (int *) xmlMalloc(5 * sizeof(int));
22696 if (sto->history == NULL) {
22697 xmlSchemaVErrMemory(NULL,
22698 "allocating the state object history", NULL);
22699 return(-1);
22701 sto->sizeHistory = 5;
22702 } else if (sto->sizeHistory <= sto->nbHistory) {
22703 sto->sizeHistory *= 2;
22704 sto->history = (int *) xmlRealloc(sto->history,
22705 sto->sizeHistory * sizeof(int));
22706 if (sto->history == NULL) {
22707 xmlSchemaVErrMemory(NULL,
22708 "re-allocating the state object history", NULL);
22709 return(-1);
22712 sto->history[sto->nbHistory++] = depth;
22714 #ifdef DEBUG_IDC
22715 xmlGenericError(xmlGenericErrorContext, "IDC: push match '%d'\n",
22716 vctxt->depth);
22717 #endif
22719 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
22720 xmlSchemaIDCSelectPtr sel;
22722 * Activate state objects for the IDC fields of
22723 * the IDC selector.
22725 #ifdef DEBUG_IDC
22726 xmlGenericError(xmlGenericErrorContext, "IDC: "
22727 "activating field states\n");
22728 #endif
22729 sel = sto->matcher->aidc->def->fields;
22730 while (sel != NULL) {
22731 if (xmlSchemaIDCAddStateObject(vctxt, sto->matcher,
22732 sel, XPATH_STATE_OBJ_TYPE_IDC_FIELD) == -1)
22733 return (-1);
22734 sel = sel->next;
22736 } else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
22738 * An IDC key node was found by the IDC field.
22740 #ifdef DEBUG_IDC
22741 xmlGenericError(xmlGenericErrorContext,
22742 "IDC: key found\n");
22743 #endif
22745 * Notify that the character value of this node is
22746 * needed.
22748 if (resolved == 0) {
22749 if ((vctxt->inode->flags &
22750 XML_SCHEMA_NODE_INFO_VALUE_NEEDED) == 0)
22751 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_VALUE_NEEDED;
22753 resolved++;
22755 next_sto:
22756 if (sto->next == NULL) {
22758 * Evaluate field state objects created on this node as well.
22760 head = first;
22761 sto = vctxt->xpathStates;
22762 } else
22763 sto = sto->next;
22765 return (resolved);
22768 static const xmlChar *
22769 xmlSchemaFormatIDCKeySequence_1(xmlSchemaValidCtxtPtr vctxt,
22770 xmlChar **buf,
22771 xmlSchemaPSVIIDCKeyPtr *seq,
22772 int count, int for_hash)
22774 int i, res;
22775 xmlChar *value = NULL;
22777 *buf = xmlStrdup(BAD_CAST "[");
22778 for (i = 0; i < count; i++) {
22779 *buf = xmlStrcat(*buf, BAD_CAST "'");
22780 if (!for_hash)
22781 res = xmlSchemaGetCanonValueWhtspExt(seq[i]->val,
22782 xmlSchemaGetWhiteSpaceFacetValue(seq[i]->type),
22783 &value);
22784 else {
22785 res = xmlSchemaGetCanonValueHash(seq[i]->val, &value);
22787 if (res == 0)
22788 *buf = xmlStrcat(*buf, BAD_CAST value);
22789 else {
22790 VERROR_INT("xmlSchemaFormatIDCKeySequence",
22791 "failed to compute a canonical value");
22792 *buf = xmlStrcat(*buf, BAD_CAST "???");
22794 if (i < count -1)
22795 *buf = xmlStrcat(*buf, BAD_CAST "', ");
22796 else
22797 *buf = xmlStrcat(*buf, BAD_CAST "'");
22798 if (value != NULL) {
22799 xmlFree(value);
22800 value = NULL;
22803 *buf = xmlStrcat(*buf, BAD_CAST "]");
22805 return (BAD_CAST *buf);
22808 static const xmlChar *
22809 xmlSchemaFormatIDCKeySequence(xmlSchemaValidCtxtPtr vctxt,
22810 xmlChar **buf,
22811 xmlSchemaPSVIIDCKeyPtr *seq,
22812 int count)
22814 return xmlSchemaFormatIDCKeySequence_1(vctxt, buf, seq, count, 0);
22817 static const xmlChar *
22818 xmlSchemaHashKeySequence(xmlSchemaValidCtxtPtr vctxt,
22819 xmlChar **buf,
22820 xmlSchemaPSVIIDCKeyPtr *seq,
22821 int count)
22823 return xmlSchemaFormatIDCKeySequence_1(vctxt, buf, seq, count, 1);
22827 * xmlSchemaXPathPop:
22828 * @vctxt: the WXS validation context
22830 * Pops all XPath states.
22832 * Returns 0 on success and -1 on internal errors.
22834 static int
22835 xmlSchemaXPathPop(xmlSchemaValidCtxtPtr vctxt)
22837 xmlSchemaIDCStateObjPtr sto;
22838 int res;
22840 if (vctxt->xpathStates == NULL)
22841 return(0);
22842 sto = vctxt->xpathStates;
22843 do {
22844 res = xmlStreamPop((xmlStreamCtxtPtr) sto->xpathCtxt);
22845 if (res == -1)
22846 return (-1);
22847 sto = sto->next;
22848 } while (sto != NULL);
22849 return(0);
22853 * xmlSchemaXPathProcessHistory:
22854 * @vctxt: the WXS validation context
22855 * @type: the simple/complex type of the current node if any at all
22856 * @val: the precompiled value
22858 * Processes and pops the history items of the IDC state objects.
22859 * IDC key-sequences are validated/created on IDC bindings.
22861 * Returns 0 on success and -1 on internal errors.
22863 static int
22864 xmlSchemaXPathProcessHistory(xmlSchemaValidCtxtPtr vctxt,
22865 int depth)
22867 xmlSchemaIDCStateObjPtr sto, nextsto;
22868 int res, matchDepth;
22869 xmlSchemaPSVIIDCKeyPtr key = NULL;
22870 xmlSchemaTypePtr type = vctxt->inode->typeDef, simpleType = NULL;
22872 if (vctxt->xpathStates == NULL)
22873 return (0);
22874 sto = vctxt->xpathStates;
22876 #ifdef DEBUG_IDC
22878 xmlChar *str = NULL;
22879 xmlGenericError(xmlGenericErrorContext,
22880 "IDC: BACK on %s, depth %d\n",
22881 xmlSchemaFormatQName(&str, vctxt->inode->nsName,
22882 vctxt->inode->localName), vctxt->depth);
22883 FREE_AND_NULL(str)
22885 #endif
22887 * Evaluate the state objects.
22889 while (sto != NULL) {
22890 res = xmlStreamPop((xmlStreamCtxtPtr) sto->xpathCtxt);
22891 if (res == -1) {
22892 VERROR_INT("xmlSchemaXPathProcessHistory",
22893 "calling xmlStreamPop()");
22894 return (-1);
22896 #ifdef DEBUG_IDC
22897 xmlGenericError(xmlGenericErrorContext, "IDC: stream pop '%s'\n",
22898 sto->sel->xpath);
22899 #endif
22900 if (sto->nbHistory == 0)
22901 goto deregister_check;
22903 matchDepth = sto->history[sto->nbHistory -1];
22906 * Only matches at the current depth are of interest.
22908 if (matchDepth != depth) {
22909 sto = sto->next;
22910 continue;
22912 if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_FIELD) {
22914 * NOTE: According to
22915 * http://www.w3.org/Bugs/Public/show_bug.cgi?id=2198
22916 * ... the simple-content of complex types is also allowed.
22919 if (WXS_IS_COMPLEX(type)) {
22920 if (WXS_HAS_SIMPLE_CONTENT(type)) {
22922 * Sanity check for complex types with simple content.
22924 simpleType = type->contentTypeDef;
22925 if (simpleType == NULL) {
22926 VERROR_INT("xmlSchemaXPathProcessHistory",
22927 "field resolves to a CT with simple content "
22928 "but the CT is missing the ST definition");
22929 return (-1);
22931 } else
22932 simpleType = NULL;
22933 } else
22934 simpleType = type;
22935 if (simpleType == NULL) {
22936 xmlChar *str = NULL;
22939 * Not qualified if the field resolves to a node of non
22940 * simple type.
22942 xmlSchemaCustomErr(ACTXT_CAST vctxt,
22943 XML_SCHEMAV_CVC_IDC, NULL,
22944 WXS_BASIC_CAST sto->matcher->aidc->def,
22945 "The XPath '%s' of a field of %s does evaluate to a node of "
22946 "non-simple type",
22947 sto->sel->xpath,
22948 xmlSchemaGetIDCDesignation(&str, sto->matcher->aidc->def));
22949 FREE_AND_NULL(str);
22950 sto->nbHistory--;
22951 goto deregister_check;
22954 if ((key == NULL) && (vctxt->inode->val == NULL)) {
22956 * Failed to provide the normalized value; maybe
22957 * the value was invalid.
22959 VERROR(XML_SCHEMAV_CVC_IDC,
22960 WXS_BASIC_CAST sto->matcher->aidc->def,
22961 "Warning: No precomputed value available, the value "
22962 "was either invalid or something strange happened");
22963 sto->nbHistory--;
22964 goto deregister_check;
22965 } else {
22966 xmlSchemaIDCMatcherPtr matcher = sto->matcher;
22967 xmlSchemaPSVIIDCKeyPtr *keySeq;
22968 int pos, idx;
22971 * The key will be anchored on the matcher's list of
22972 * key-sequences. The position in this list is determined
22973 * by the target node's depth relative to the matcher's
22974 * depth of creation (i.e. the depth of the scope element).
22976 * Element Depth Pos List-entries
22977 * <scope> 0 NULL
22978 * <bar> 1 NULL
22979 * <target/> 2 2 target
22980 * <bar>
22981 * </scope>
22983 * The size of the list is only dependent on the depth of
22984 * the tree.
22985 * An entry will be NULLed in selector_leave, i.e. when
22986 * we hit the target's
22988 pos = sto->depth - matcher->depth;
22989 idx = sto->sel->index;
22992 * Create/grow the array of key-sequences.
22994 if (matcher->keySeqs == NULL) {
22995 if (pos > 9)
22996 matcher->sizeKeySeqs = pos * 2;
22997 else
22998 matcher->sizeKeySeqs = 10;
22999 matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
23000 xmlMalloc(matcher->sizeKeySeqs *
23001 sizeof(xmlSchemaPSVIIDCKeyPtr *));
23002 if (matcher->keySeqs == NULL) {
23003 xmlSchemaVErrMemory(NULL,
23004 "allocating an array of key-sequences",
23005 NULL);
23006 return(-1);
23008 memset(matcher->keySeqs, 0,
23009 matcher->sizeKeySeqs *
23010 sizeof(xmlSchemaPSVIIDCKeyPtr *));
23011 } else if (pos >= matcher->sizeKeySeqs) {
23012 int i = matcher->sizeKeySeqs;
23014 matcher->sizeKeySeqs *= 2;
23015 matcher->keySeqs = (xmlSchemaPSVIIDCKeyPtr **)
23016 xmlRealloc(matcher->keySeqs,
23017 matcher->sizeKeySeqs *
23018 sizeof(xmlSchemaPSVIIDCKeyPtr *));
23019 if (matcher->keySeqs == NULL) {
23020 xmlSchemaVErrMemory(NULL,
23021 "reallocating an array of key-sequences",
23022 NULL);
23023 return (-1);
23026 * The array needs to be NULLed.
23027 * TODO: Use memset?
23029 for (; i < matcher->sizeKeySeqs; i++)
23030 matcher->keySeqs[i] = NULL;
23034 * Get/create the key-sequence.
23036 keySeq = matcher->keySeqs[pos];
23037 if (keySeq == NULL) {
23038 goto create_sequence;
23039 } else if (keySeq[idx] != NULL) {
23040 xmlChar *str = NULL;
23042 * cvc-identity-constraint:
23043 * 3 For each node in the `target node set` all
23044 * of the {fields}, with that node as the context
23045 * node, evaluate to either an empty node-set or
23046 * a node-set with exactly one member, which must
23047 * have a simple type.
23049 * The key was already set; report an error.
23051 xmlSchemaCustomErr(ACTXT_CAST vctxt,
23052 XML_SCHEMAV_CVC_IDC, NULL,
23053 WXS_BASIC_CAST matcher->aidc->def,
23054 "The XPath '%s' of a field of %s evaluates to a "
23055 "node-set with more than one member",
23056 sto->sel->xpath,
23057 xmlSchemaGetIDCDesignation(&str, matcher->aidc->def));
23058 FREE_AND_NULL(str);
23059 sto->nbHistory--;
23060 goto deregister_check;
23061 } else
23062 goto create_key;
23064 create_sequence:
23066 * Create a key-sequence.
23068 keySeq = (xmlSchemaPSVIIDCKeyPtr *) xmlMalloc(
23069 matcher->aidc->def->nbFields *
23070 sizeof(xmlSchemaPSVIIDCKeyPtr));
23071 if (keySeq == NULL) {
23072 xmlSchemaVErrMemory(NULL,
23073 "allocating an IDC key-sequence", NULL);
23074 return(-1);
23076 memset(keySeq, 0, matcher->aidc->def->nbFields *
23077 sizeof(xmlSchemaPSVIIDCKeyPtr));
23078 matcher->keySeqs[pos] = keySeq;
23079 create_key:
23081 * Create a key once per node only.
23083 if (key == NULL) {
23084 key = (xmlSchemaPSVIIDCKeyPtr) xmlMalloc(
23085 sizeof(xmlSchemaPSVIIDCKey));
23086 if (key == NULL) {
23087 xmlSchemaVErrMemory(NULL,
23088 "allocating a IDC key", NULL);
23089 xmlFree(keySeq);
23090 matcher->keySeqs[pos] = NULL;
23091 return(-1);
23094 * Consume the compiled value.
23096 key->type = simpleType;
23097 key->val = vctxt->inode->val;
23098 vctxt->inode->val = NULL;
23100 * Store the key in a global list.
23102 if (xmlSchemaIDCStoreKey(vctxt, key) == -1) {
23103 xmlSchemaIDCFreeKey(key);
23104 return (-1);
23107 keySeq[idx] = key;
23109 } else if (sto->type == XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) {
23111 xmlSchemaPSVIIDCKeyPtr **keySeq = NULL;
23112 /* xmlSchemaPSVIIDCBindingPtr bind; */
23113 xmlSchemaPSVIIDCNodePtr ntItem;
23114 xmlSchemaIDCMatcherPtr matcher;
23115 xmlSchemaIDCPtr idc;
23116 xmlSchemaItemListPtr targets;
23117 int pos, i, j, nbKeys;
23119 * Here we have the following scenario:
23120 * An IDC 'selector' state object resolved to a target node,
23121 * during the time this target node was in the
23122 * ancestor-or-self axis, the 'field' state object(s) looked
23123 * out for matching nodes to create a key-sequence for this
23124 * target node. Now we are back to this target node and need
23125 * to put the key-sequence, together with the target node
23126 * itself, into the node-table of the corresponding IDC
23127 * binding.
23129 matcher = sto->matcher;
23130 idc = matcher->aidc->def;
23131 nbKeys = idc->nbFields;
23132 pos = depth - matcher->depth;
23134 * Check if the matcher has any key-sequences at all, plus
23135 * if it has a key-sequence for the current target node.
23137 if ((matcher->keySeqs == NULL) ||
23138 (matcher->sizeKeySeqs <= pos)) {
23139 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
23140 goto selector_key_error;
23141 else
23142 goto selector_leave;
23145 keySeq = &(matcher->keySeqs[pos]);
23146 if (*keySeq == NULL) {
23147 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY)
23148 goto selector_key_error;
23149 else
23150 goto selector_leave;
23153 for (i = 0; i < nbKeys; i++) {
23154 if ((*keySeq)[i] == NULL) {
23156 * Not qualified, if not all fields did resolve.
23158 if (idc->type == XML_SCHEMA_TYPE_IDC_KEY) {
23160 * All fields of a "key" IDC must resolve.
23162 goto selector_key_error;
23164 goto selector_leave;
23168 * All fields did resolve.
23172 * 4.1 If the {identity-constraint category} is unique(/key),
23173 * then no two members of the `qualified node set` have
23174 * `key-sequences` whose members are pairwise equal, as
23175 * defined by Equal in [XML Schemas: Datatypes].
23177 * Get the IDC binding from the matcher and check for
23178 * duplicate key-sequences.
23180 #if 0
23181 bind = xmlSchemaIDCAcquireBinding(vctxt, matcher);
23182 #endif
23183 targets = xmlSchemaIDCAcquireTargetList(vctxt, matcher);
23184 if ((idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) &&
23185 (targets->nbItems != 0)) {
23186 xmlSchemaPSVIIDCKeyPtr ckey, bkey, *bkeySeq;
23187 xmlIDCHashEntryPtr e;
23189 res = 0;
23191 if (!matcher->htab)
23192 e = NULL;
23193 else {
23194 xmlChar *value = NULL;
23195 xmlSchemaHashKeySequence(vctxt, &value, *keySeq, nbKeys);
23196 e = xmlHashLookup(matcher->htab, value);
23197 FREE_AND_NULL(value);
23201 * Compare the key-sequences, key by key.
23203 for (;e; e = e->next) {
23204 bkeySeq =
23205 ((xmlSchemaPSVIIDCNodePtr) targets->items[e->index])->keys;
23206 for (j = 0; j < nbKeys; j++) {
23207 ckey = (*keySeq)[j];
23208 bkey = bkeySeq[j];
23209 res = xmlSchemaAreValuesEqual(ckey->val, bkey->val);
23210 if (res == -1) {
23211 return (-1);
23212 } else if (res == 0) {
23214 * One of the keys differs, so the key-sequence
23215 * won't be equal; get out.
23217 break;
23220 if (res == 1) {
23222 * Duplicate key-sequence found.
23224 break;
23227 if (e) {
23228 xmlChar *str = NULL, *strB = NULL;
23230 * TODO: Try to report the key-sequence.
23232 xmlSchemaCustomErr(ACTXT_CAST vctxt,
23233 XML_SCHEMAV_CVC_IDC, NULL,
23234 WXS_BASIC_CAST idc,
23235 "Duplicate key-sequence %s in %s",
23236 xmlSchemaFormatIDCKeySequence(vctxt, &str,
23237 (*keySeq), nbKeys),
23238 xmlSchemaGetIDCDesignation(&strB, idc));
23239 FREE_AND_NULL(str);
23240 FREE_AND_NULL(strB);
23241 goto selector_leave;
23245 * Add a node-table item to the IDC binding.
23247 ntItem = (xmlSchemaPSVIIDCNodePtr) xmlMalloc(
23248 sizeof(xmlSchemaPSVIIDCNode));
23249 if (ntItem == NULL) {
23250 xmlSchemaVErrMemory(NULL,
23251 "allocating an IDC node-table item", NULL);
23252 xmlFree(*keySeq);
23253 *keySeq = NULL;
23254 return(-1);
23256 memset(ntItem, 0, sizeof(xmlSchemaPSVIIDCNode));
23259 * Store the node-table item in a global list.
23261 if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) {
23262 if (xmlSchemaIDCStoreNodeTableItem(vctxt, ntItem) == -1) {
23263 xmlFree(ntItem);
23264 xmlFree(*keySeq);
23265 *keySeq = NULL;
23266 return (-1);
23268 ntItem->nodeQNameID = -1;
23269 } else {
23271 * Save a cached QName for this node on the IDC node, to be
23272 * able to report it, even if the node is not saved.
23274 ntItem->nodeQNameID = xmlSchemaVAddNodeQName(vctxt,
23275 vctxt->inode->localName, vctxt->inode->nsName);
23276 if (ntItem->nodeQNameID == -1) {
23277 xmlFree(ntItem);
23278 xmlFree(*keySeq);
23279 *keySeq = NULL;
23280 return (-1);
23284 * Init the node-table item: Save the node, position and
23285 * consume the key-sequence.
23287 ntItem->node = vctxt->node;
23288 ntItem->nodeLine = vctxt->inode->nodeLine;
23289 ntItem->keys = *keySeq;
23290 *keySeq = NULL;
23291 #if 0
23292 if (xmlSchemaIDCAppendNodeTableItem(bind, ntItem) == -1)
23293 #endif
23294 if (xmlSchemaItemListAdd(targets, ntItem) == -1) {
23295 if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
23297 * Free the item, since keyref items won't be
23298 * put on a global list.
23300 xmlFree(ntItem->keys);
23301 xmlFree(ntItem);
23303 return (-1);
23305 if (idc->type != XML_SCHEMA_TYPE_IDC_KEYREF) {
23306 xmlChar *value = NULL;
23307 xmlIDCHashEntryPtr r, e;
23308 if (!matcher->htab)
23309 matcher->htab = xmlHashCreate(4);
23310 xmlSchemaHashKeySequence(vctxt, &value, ntItem->keys, nbKeys);
23311 e = xmlMalloc(sizeof *e);
23312 e->index = targets->nbItems - 1;
23313 r = xmlHashLookup(matcher->htab, value);
23314 if (r) {
23315 e->next = r->next;
23316 r->next = e;
23317 } else {
23318 e->next = NULL;
23319 xmlHashAddEntry(matcher->htab, value, e);
23321 FREE_AND_NULL(value);
23324 goto selector_leave;
23325 selector_key_error:
23327 xmlChar *str = NULL;
23329 * 4.2.1 (KEY) The `target node set` and the
23330 * `qualified node set` are equal, that is, every
23331 * member of the `target node set` is also a member
23332 * of the `qualified node set` and vice versa.
23334 xmlSchemaCustomErr(ACTXT_CAST vctxt,
23335 XML_SCHEMAV_CVC_IDC, NULL,
23336 WXS_BASIC_CAST idc,
23337 "Not all fields of %s evaluate to a node",
23338 xmlSchemaGetIDCDesignation(&str, idc), NULL);
23339 FREE_AND_NULL(str);
23341 selector_leave:
23343 * Free the key-sequence if not added to the IDC table.
23345 if ((keySeq != NULL) && (*keySeq != NULL)) {
23346 xmlFree(*keySeq);
23347 *keySeq = NULL;
23349 } /* if selector */
23351 sto->nbHistory--;
23353 deregister_check:
23355 * Deregister state objects if they reach the depth of creation.
23357 if ((sto->nbHistory == 0) && (sto->depth == depth)) {
23358 #ifdef DEBUG_IDC
23359 xmlGenericError(xmlGenericErrorContext, "IDC: STO pop '%s'\n",
23360 sto->sel->xpath);
23361 #endif
23362 if (vctxt->xpathStates != sto) {
23363 VERROR_INT("xmlSchemaXPathProcessHistory",
23364 "The state object to be removed is not the first "
23365 "in the list");
23367 nextsto = sto->next;
23369 * Unlink from the list of active XPath state objects.
23371 vctxt->xpathStates = sto->next;
23372 sto->next = vctxt->xpathStatePool;
23374 * Link it to the pool of reusable state objects.
23376 vctxt->xpathStatePool = sto;
23377 sto = nextsto;
23378 } else
23379 sto = sto->next;
23380 } /* while (sto != NULL) */
23381 return (0);
23385 * xmlSchemaIDCRegisterMatchers:
23386 * @vctxt: the WXS validation context
23387 * @elemDecl: the element declaration
23389 * Creates helper objects to evaluate IDC selectors/fields
23390 * successively.
23392 * Returns 0 if OK and -1 on internal errors.
23394 static int
23395 xmlSchemaIDCRegisterMatchers(xmlSchemaValidCtxtPtr vctxt,
23396 xmlSchemaElementPtr elemDecl)
23398 xmlSchemaIDCMatcherPtr matcher, last = NULL;
23399 xmlSchemaIDCPtr idc, refIdc;
23400 xmlSchemaIDCAugPtr aidc;
23402 idc = (xmlSchemaIDCPtr) elemDecl->idcs;
23403 if (idc == NULL)
23404 return (0);
23406 #ifdef DEBUG_IDC
23408 xmlChar *str = NULL;
23409 xmlGenericError(xmlGenericErrorContext,
23410 "IDC: REGISTER on %s, depth %d\n",
23411 (char *) xmlSchemaFormatQName(&str, vctxt->inode->nsName,
23412 vctxt->inode->localName), vctxt->depth);
23413 FREE_AND_NULL(str)
23415 #endif
23416 if (vctxt->inode->idcMatchers != NULL) {
23417 VERROR_INT("xmlSchemaIDCRegisterMatchers",
23418 "The chain of IDC matchers is expected to be empty");
23419 return (-1);
23421 do {
23422 if (idc->type == XML_SCHEMA_TYPE_IDC_KEYREF) {
23424 * Since IDCs bubbles are expensive we need to know the
23425 * depth at which the bubbles should stop; this will be
23426 * the depth of the top-most keyref IDC. If no keyref
23427 * references a key/unique IDC, the keyrefDepth will
23428 * be -1, indicating that no bubbles are needed.
23430 refIdc = (xmlSchemaIDCPtr) idc->ref->item;
23431 if (refIdc != NULL) {
23433 * Remember that we have keyrefs on this node.
23435 vctxt->inode->hasKeyrefs = 1;
23437 * Lookup the referenced augmented IDC info.
23439 aidc = vctxt->aidcs;
23440 while (aidc != NULL) {
23441 if (aidc->def == refIdc)
23442 break;
23443 aidc = aidc->next;
23445 if (aidc == NULL) {
23446 VERROR_INT("xmlSchemaIDCRegisterMatchers",
23447 "Could not find an augmented IDC item for an IDC "
23448 "definition");
23449 return (-1);
23451 if ((aidc->keyrefDepth == -1) ||
23452 (vctxt->depth < aidc->keyrefDepth))
23453 aidc->keyrefDepth = vctxt->depth;
23457 * Lookup the augmented IDC item for the IDC definition.
23459 aidc = vctxt->aidcs;
23460 while (aidc != NULL) {
23461 if (aidc->def == idc)
23462 break;
23463 aidc = aidc->next;
23465 if (aidc == NULL) {
23466 VERROR_INT("xmlSchemaIDCRegisterMatchers",
23467 "Could not find an augmented IDC item for an IDC definition");
23468 return (-1);
23471 * Create an IDC matcher for every IDC definition.
23473 if (vctxt->idcMatcherCache != NULL) {
23475 * Reuse a cached matcher.
23477 matcher = vctxt->idcMatcherCache;
23478 vctxt->idcMatcherCache = matcher->nextCached;
23479 matcher->nextCached = NULL;
23480 } else {
23481 matcher = (xmlSchemaIDCMatcherPtr)
23482 xmlMalloc(sizeof(xmlSchemaIDCMatcher));
23483 if (matcher == NULL) {
23484 xmlSchemaVErrMemory(vctxt,
23485 "allocating an IDC matcher", NULL);
23486 return (-1);
23488 memset(matcher, 0, sizeof(xmlSchemaIDCMatcher));
23490 if (last == NULL)
23491 vctxt->inode->idcMatchers = matcher;
23492 else
23493 last->next = matcher;
23494 last = matcher;
23496 matcher->type = IDC_MATCHER;
23497 matcher->depth = vctxt->depth;
23498 matcher->aidc = aidc;
23499 matcher->idcType = aidc->def->type;
23500 #ifdef DEBUG_IDC
23501 xmlGenericError(xmlGenericErrorContext, "IDC: register matcher\n");
23502 #endif
23504 * Init the automaton state object.
23506 if (xmlSchemaIDCAddStateObject(vctxt, matcher,
23507 idc->selector, XPATH_STATE_OBJ_TYPE_IDC_SELECTOR) == -1)
23508 return (-1);
23510 idc = idc->next;
23511 } while (idc != NULL);
23512 return (0);
23515 static int
23516 xmlSchemaIDCFillNodeTables(xmlSchemaValidCtxtPtr vctxt,
23517 xmlSchemaNodeInfoPtr ielem)
23519 xmlSchemaPSVIIDCBindingPtr bind;
23520 int res, i, j, k, nbTargets, nbFields, nbDupls, nbNodeTable;
23521 xmlSchemaPSVIIDCKeyPtr *keys, *ntkeys;
23522 xmlSchemaPSVIIDCNodePtr *targets, *dupls;
23524 xmlSchemaIDCMatcherPtr matcher = ielem->idcMatchers;
23525 /* vctxt->createIDCNodeTables */
23526 while (matcher != NULL) {
23528 * Skip keyref IDCs and empty IDC target-lists.
23530 if ((matcher->aidc->def->type == XML_SCHEMA_TYPE_IDC_KEYREF) ||
23531 WXS_ILIST_IS_EMPTY(matcher->targets))
23533 matcher = matcher->next;
23534 continue;
23537 * If we _want_ the IDC node-table to be created in any case
23538 * then do so. Otherwise create them only if keyrefs need them.
23540 if ((! vctxt->createIDCNodeTables) &&
23541 ((matcher->aidc->keyrefDepth == -1) ||
23542 (matcher->aidc->keyrefDepth > vctxt->depth)))
23544 matcher = matcher->next;
23545 continue;
23548 * Get/create the IDC binding on this element for the IDC definition.
23550 bind = xmlSchemaIDCAcquireBinding(vctxt, matcher);
23551 if (bind == NULL)
23552 goto internal_error;
23554 if (! WXS_ILIST_IS_EMPTY(bind->dupls)) {
23555 dupls = (xmlSchemaPSVIIDCNodePtr *) bind->dupls->items;
23556 nbDupls = bind->dupls->nbItems;
23557 } else {
23558 dupls = NULL;
23559 nbDupls = 0;
23561 if (bind->nodeTable != NULL) {
23562 nbNodeTable = bind->nbNodes;
23563 } else {
23564 nbNodeTable = 0;
23567 if ((nbNodeTable == 0) && (nbDupls == 0)) {
23569 * Transfer all IDC target-nodes to the IDC node-table.
23571 bind->nodeTable =
23572 (xmlSchemaPSVIIDCNodePtr *) matcher->targets->items;
23573 bind->sizeNodes = matcher->targets->sizeItems;
23574 bind->nbNodes = matcher->targets->nbItems;
23576 matcher->targets->items = NULL;
23577 matcher->targets->sizeItems = 0;
23578 matcher->targets->nbItems = 0;
23579 if (matcher->htab) {
23580 xmlHashFree(matcher->htab, xmlFreeIDCHashEntry);
23581 matcher->htab = NULL;
23583 } else {
23585 * Compare the key-sequences and add to the IDC node-table.
23587 nbTargets = matcher->targets->nbItems;
23588 targets = (xmlSchemaPSVIIDCNodePtr *) matcher->targets->items;
23589 nbFields = matcher->aidc->def->nbFields;
23590 i = 0;
23591 do {
23592 keys = targets[i]->keys;
23593 if (nbDupls) {
23595 * Search in already found duplicates first.
23597 j = 0;
23598 do {
23599 if (nbFields == 1) {
23600 res = xmlSchemaAreValuesEqual(keys[0]->val,
23601 dupls[j]->keys[0]->val);
23602 if (res == -1)
23603 goto internal_error;
23604 if (res == 1) {
23606 * Equal key-sequence.
23608 goto next_target;
23610 } else {
23611 res = 0;
23612 ntkeys = dupls[j]->keys;
23613 for (k = 0; k < nbFields; k++) {
23614 res = xmlSchemaAreValuesEqual(keys[k]->val,
23615 ntkeys[k]->val);
23616 if (res == -1)
23617 goto internal_error;
23618 if (res == 0) {
23620 * One of the keys differs.
23622 break;
23625 if (res == 1) {
23627 * Equal key-sequence found.
23629 goto next_target;
23632 j++;
23633 } while (j < nbDupls);
23635 if (nbNodeTable) {
23636 j = 0;
23637 do {
23638 if (nbFields == 1) {
23639 res = xmlSchemaAreValuesEqual(keys[0]->val,
23640 bind->nodeTable[j]->keys[0]->val);
23641 if (res == -1)
23642 goto internal_error;
23643 if (res == 0) {
23645 * The key-sequence differs.
23647 goto next_node_table_entry;
23649 } else {
23650 res = 0;
23651 ntkeys = bind->nodeTable[j]->keys;
23652 for (k = 0; k < nbFields; k++) {
23653 res = xmlSchemaAreValuesEqual(keys[k]->val,
23654 ntkeys[k]->val);
23655 if (res == -1)
23656 goto internal_error;
23657 if (res == 0) {
23659 * One of the keys differs.
23661 goto next_node_table_entry;
23666 * Add the duplicate to the list of duplicates.
23668 if (bind->dupls == NULL) {
23669 bind->dupls = xmlSchemaItemListCreate();
23670 if (bind->dupls == NULL)
23671 goto internal_error;
23673 if (xmlSchemaItemListAdd(bind->dupls, bind->nodeTable[j]) == -1)
23674 goto internal_error;
23676 * Remove the duplicate entry from the IDC node-table.
23678 bind->nodeTable[j] = bind->nodeTable[bind->nbNodes -1];
23679 bind->nbNodes--;
23681 goto next_target;
23683 next_node_table_entry:
23684 j++;
23685 } while (j < nbNodeTable);
23688 * If everything is fine, then add the IDC target-node to
23689 * the IDC node-table.
23691 if (xmlSchemaIDCAppendNodeTableItem(bind, targets[i]) == -1)
23692 goto internal_error;
23694 next_target:
23695 i++;
23696 } while (i < nbTargets);
23698 matcher = matcher->next;
23700 return(0);
23702 internal_error:
23703 return(-1);
23707 * xmlSchemaBubbleIDCNodeTables:
23708 * @depth: the current tree depth
23710 * Merges IDC bindings of an element at @depth into the corresponding IDC
23711 * bindings of its parent element. If a duplicate note-table entry is found,
23712 * both, the parent node-table entry and child entry are discarded from the
23713 * node-table of the parent.
23715 * Returns 0 if OK and -1 on internal errors.
23717 static int
23718 xmlSchemaBubbleIDCNodeTables(xmlSchemaValidCtxtPtr vctxt)
23720 xmlSchemaPSVIIDCBindingPtr bind; /* IDC bindings of the current node. */
23721 xmlSchemaPSVIIDCBindingPtr *parTable, parBind = NULL; /* parent IDC bindings. */
23722 xmlSchemaPSVIIDCNodePtr node, parNode = NULL, *dupls, *parNodes; /* node-table entries. */
23723 xmlSchemaIDCAugPtr aidc;
23724 int i, j, k, ret = 0, nbFields, oldNum, oldDupls;
23726 bind = vctxt->inode->idcTable;
23727 if (bind == NULL) {
23728 /* Fine, no table, no bubbles. */
23729 return (0);
23732 parTable = &(vctxt->elemInfos[vctxt->depth -1]->idcTable);
23734 * Walk all bindings; create new or add to existing bindings.
23735 * Remove duplicate key-sequences.
23737 while (bind != NULL) {
23739 if ((bind->nbNodes == 0) && WXS_ILIST_IS_EMPTY(bind->dupls))
23740 goto next_binding;
23742 * Check if the key/unique IDC table needs to be bubbled.
23744 if (! vctxt->createIDCNodeTables) {
23745 aidc = vctxt->aidcs;
23746 do {
23747 if (aidc->def == bind->definition) {
23748 if ((aidc->keyrefDepth == -1) ||
23749 (aidc->keyrefDepth >= vctxt->depth)) {
23750 goto next_binding;
23752 break;
23754 aidc = aidc->next;
23755 } while (aidc != NULL);
23758 if (parTable != NULL)
23759 parBind = *parTable;
23761 * Search a matching parent binding for the
23762 * IDC definition.
23764 while (parBind != NULL) {
23765 if (parBind->definition == bind->definition)
23766 break;
23767 parBind = parBind->next;
23770 if (parBind != NULL) {
23772 * Compare every node-table entry of the child node,
23773 * i.e. the key-sequence within, ...
23775 oldNum = parBind->nbNodes; /* Skip newly added items. */
23777 if (! WXS_ILIST_IS_EMPTY(parBind->dupls)) {
23778 oldDupls = parBind->dupls->nbItems;
23779 dupls = (xmlSchemaPSVIIDCNodePtr *) parBind->dupls->items;
23780 } else {
23781 dupls = NULL;
23782 oldDupls = 0;
23785 parNodes = parBind->nodeTable;
23786 nbFields = bind->definition->nbFields;
23788 for (i = 0; i < bind->nbNodes; i++) {
23789 node = bind->nodeTable[i];
23790 if (node == NULL)
23791 continue;
23793 * ...with every key-sequence of the parent node, already
23794 * evaluated to be a duplicate key-sequence.
23796 if (oldDupls) {
23797 j = 0;
23798 while (j < oldDupls) {
23799 if (nbFields == 1) {
23800 ret = xmlSchemaAreValuesEqual(
23801 node->keys[0]->val,
23802 dupls[j]->keys[0]->val);
23803 if (ret == -1)
23804 goto internal_error;
23805 if (ret == 0) {
23806 j++;
23807 continue;
23809 } else {
23810 parNode = dupls[j];
23811 for (k = 0; k < nbFields; k++) {
23812 ret = xmlSchemaAreValuesEqual(
23813 node->keys[k]->val,
23814 parNode->keys[k]->val);
23815 if (ret == -1)
23816 goto internal_error;
23817 if (ret == 0)
23818 break;
23821 if (ret == 1)
23822 /* Duplicate found. */
23823 break;
23824 j++;
23826 if (j != oldDupls) {
23827 /* Duplicate found. Skip this entry. */
23828 continue;
23832 * ... and with every key-sequence of the parent node.
23834 if (oldNum) {
23835 j = 0;
23836 while (j < oldNum) {
23837 parNode = parNodes[j];
23838 if (nbFields == 1) {
23839 ret = xmlSchemaAreValuesEqual(
23840 node->keys[0]->val,
23841 parNode->keys[0]->val);
23842 if (ret == -1)
23843 goto internal_error;
23844 if (ret == 0) {
23845 j++;
23846 continue;
23848 } else {
23849 for (k = 0; k < nbFields; k++) {
23850 ret = xmlSchemaAreValuesEqual(
23851 node->keys[k]->val,
23852 parNode->keys[k]->val);
23853 if (ret == -1)
23854 goto internal_error;
23855 if (ret == 0)
23856 break;
23859 if (ret == 1)
23860 /* Duplicate found. */
23861 break;
23862 j++;
23864 if (j != oldNum) {
23866 * Handle duplicates. Move the duplicate in
23867 * the parent's node-table to the list of
23868 * duplicates.
23870 oldNum--;
23871 parBind->nbNodes--;
23873 * Move last old item to pos of duplicate.
23875 parNodes[j] = parNodes[oldNum];
23877 if (parBind->nbNodes != oldNum) {
23879 * If new items exist, move last new item to
23880 * last of old items.
23882 parNodes[oldNum] =
23883 parNodes[parBind->nbNodes];
23885 if (parBind->dupls == NULL) {
23886 parBind->dupls = xmlSchemaItemListCreate();
23887 if (parBind->dupls == NULL)
23888 goto internal_error;
23890 xmlSchemaItemListAdd(parBind->dupls, parNode);
23891 } else {
23893 * Add the node-table entry (node and key-sequence) of
23894 * the child node to the node table of the parent node.
23896 if (parBind->nodeTable == NULL) {
23897 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
23898 xmlMalloc(10 * sizeof(xmlSchemaPSVIIDCNodePtr));
23899 if (parBind->nodeTable == NULL) {
23900 xmlSchemaVErrMemory(NULL,
23901 "allocating IDC list of node-table items", NULL);
23902 goto internal_error;
23904 parBind->sizeNodes = 1;
23905 } else if (parBind->nbNodes >= parBind->sizeNodes) {
23906 parBind->sizeNodes *= 2;
23907 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
23908 xmlRealloc(parBind->nodeTable, parBind->sizeNodes *
23909 sizeof(xmlSchemaPSVIIDCNodePtr));
23910 if (parBind->nodeTable == NULL) {
23911 xmlSchemaVErrMemory(NULL,
23912 "re-allocating IDC list of node-table items", NULL);
23913 goto internal_error;
23916 parNodes = parBind->nodeTable;
23918 * Append the new node-table entry to the 'new node-table
23919 * entries' section.
23921 parNodes[parBind->nbNodes++] = node;
23927 } else {
23929 * No binding for the IDC was found: create a new one and
23930 * copy all node-tables.
23932 parBind = xmlSchemaIDCNewBinding(bind->definition);
23933 if (parBind == NULL)
23934 goto internal_error;
23937 * TODO: Hmm, how to optimize the initial number of
23938 * allocated entries?
23940 if (bind->nbNodes != 0) {
23942 * Add all IDC node-table entries.
23944 if (! vctxt->psviExposeIDCNodeTables) {
23946 * Just move the entries.
23947 * NOTE: this is quite save here, since
23948 * all the keyref lookups have already been
23949 * performed.
23951 parBind->nodeTable = bind->nodeTable;
23952 bind->nodeTable = NULL;
23953 parBind->sizeNodes = bind->sizeNodes;
23954 bind->sizeNodes = 0;
23955 parBind->nbNodes = bind->nbNodes;
23956 bind->nbNodes = 0;
23957 } else {
23959 * Copy the entries.
23961 parBind->nodeTable = (xmlSchemaPSVIIDCNodePtr *)
23962 xmlMalloc(bind->nbNodes *
23963 sizeof(xmlSchemaPSVIIDCNodePtr));
23964 if (parBind->nodeTable == NULL) {
23965 xmlSchemaVErrMemory(NULL,
23966 "allocating an array of IDC node-table "
23967 "items", NULL);
23968 xmlSchemaIDCFreeBinding(parBind);
23969 goto internal_error;
23971 parBind->sizeNodes = bind->nbNodes;
23972 parBind->nbNodes = bind->nbNodes;
23973 memcpy(parBind->nodeTable, bind->nodeTable,
23974 bind->nbNodes * sizeof(xmlSchemaPSVIIDCNodePtr));
23977 if (bind->dupls) {
23979 * Move the duplicates.
23981 if (parBind->dupls != NULL)
23982 xmlSchemaItemListFree(parBind->dupls);
23983 parBind->dupls = bind->dupls;
23984 bind->dupls = NULL;
23986 if (parTable != NULL) {
23987 if (*parTable == NULL)
23988 *parTable = parBind;
23989 else {
23990 parBind->next = *parTable;
23991 *parTable = parBind;
23996 next_binding:
23997 bind = bind->next;
23999 return (0);
24001 internal_error:
24002 return(-1);
24006 * xmlSchemaCheckCVCIDCKeyRef:
24007 * @vctxt: the WXS validation context
24008 * @elemDecl: the element declaration
24010 * Check the cvc-idc-keyref constraints.
24012 static int
24013 xmlSchemaCheckCVCIDCKeyRef(xmlSchemaValidCtxtPtr vctxt)
24015 xmlSchemaIDCMatcherPtr matcher;
24016 xmlSchemaPSVIIDCBindingPtr bind;
24018 matcher = vctxt->inode->idcMatchers;
24020 * Find a keyref.
24022 while (matcher != NULL) {
24023 if ((matcher->idcType == XML_SCHEMA_TYPE_IDC_KEYREF) &&
24024 matcher->targets &&
24025 matcher->targets->nbItems)
24027 int i, j, k, res, nbFields, hasDupls;
24028 xmlSchemaPSVIIDCKeyPtr *refKeys, *keys;
24029 xmlSchemaPSVIIDCNodePtr refNode = NULL;
24030 xmlHashTablePtr table = NULL;
24032 nbFields = matcher->aidc->def->nbFields;
24035 * Find the IDC node-table for the referenced IDC key/unique.
24037 bind = vctxt->inode->idcTable;
24038 while (bind != NULL) {
24039 if ((xmlSchemaIDCPtr) matcher->aidc->def->ref->item ==
24040 bind->definition)
24041 break;
24042 bind = bind->next;
24044 hasDupls = (bind && bind->dupls && bind->dupls->nbItems) ? 1 : 0;
24046 * Search for a matching key-sequences.
24048 if (bind) {
24049 table = xmlHashCreate(bind->nbNodes * 2);
24050 for (j = 0; j < bind->nbNodes; j++) {
24051 xmlChar *value;
24052 xmlIDCHashEntryPtr r, e;
24053 keys = bind->nodeTable[j]->keys;
24054 xmlSchemaHashKeySequence(vctxt, &value, keys, nbFields);
24055 e = xmlMalloc(sizeof *e);
24056 e->index = j;
24057 r = xmlHashLookup(table, value);
24058 if (r) {
24059 e->next = r->next;
24060 r->next = e;
24061 } else {
24062 e->next = NULL;
24063 xmlHashAddEntry(table, value, e);
24065 FREE_AND_NULL(value);
24068 for (i = 0; i < matcher->targets->nbItems; i++) {
24069 res = 0;
24070 refNode = matcher->targets->items[i];
24071 if (bind != NULL) {
24072 xmlChar *value;
24073 xmlIDCHashEntryPtr e;
24074 refKeys = refNode->keys;
24075 xmlSchemaHashKeySequence(vctxt, &value, refKeys, nbFields);
24076 e = xmlHashLookup(table, value);
24077 FREE_AND_NULL(value);
24078 res = 0;
24079 for (;e; e = e->next) {
24080 keys = bind->nodeTable[e->index]->keys;
24081 for (k = 0; k < nbFields; k++) {
24082 res = xmlSchemaAreValuesEqual(keys[k]->val,
24083 refKeys[k]->val);
24084 if (res == 0)
24085 break;
24086 else if (res == -1) {
24087 return (-1);
24090 if (res == 1) {
24092 * Match found.
24094 break;
24097 if ((res == 0) && hasDupls) {
24099 * Search in duplicates
24101 for (j = 0; j < bind->dupls->nbItems; j++) {
24102 keys = ((xmlSchemaPSVIIDCNodePtr)
24103 bind->dupls->items[j])->keys;
24104 for (k = 0; k < nbFields; k++) {
24105 res = xmlSchemaAreValuesEqual(keys[k]->val,
24106 refKeys[k]->val);
24107 if (res == 0)
24108 break;
24109 else if (res == -1) {
24110 return (-1);
24113 if (res == 1) {
24115 * Match in duplicates found.
24117 xmlChar *str = NULL, *strB = NULL;
24118 xmlSchemaKeyrefErr(vctxt,
24119 XML_SCHEMAV_CVC_IDC, refNode,
24120 (xmlSchemaTypePtr) matcher->aidc->def,
24121 "More than one match found for "
24122 "key-sequence %s of keyref '%s'",
24123 xmlSchemaFormatIDCKeySequence(vctxt, &str,
24124 refNode->keys, nbFields),
24125 xmlSchemaGetComponentQName(&strB,
24126 matcher->aidc->def));
24127 FREE_AND_NULL(str);
24128 FREE_AND_NULL(strB);
24129 break;
24135 if (res == 0) {
24136 xmlChar *str = NULL, *strB = NULL;
24137 xmlSchemaKeyrefErr(vctxt,
24138 XML_SCHEMAV_CVC_IDC, refNode,
24139 (xmlSchemaTypePtr) matcher->aidc->def,
24140 "No match found for key-sequence %s of keyref '%s'",
24141 xmlSchemaFormatIDCKeySequence(vctxt, &str,
24142 refNode->keys, nbFields),
24143 xmlSchemaGetComponentQName(&strB, matcher->aidc->def));
24144 FREE_AND_NULL(str);
24145 FREE_AND_NULL(strB);
24148 if (table) {
24149 xmlHashFree(table, xmlFreeIDCHashEntry);
24152 matcher = matcher->next;
24154 /* TODO: Return an error if any error encountered. */
24155 return (0);
24158 /************************************************************************
24160 * XML Reader validation code *
24162 ************************************************************************/
24164 static xmlSchemaAttrInfoPtr
24165 xmlSchemaGetFreshAttrInfo(xmlSchemaValidCtxtPtr vctxt)
24167 xmlSchemaAttrInfoPtr iattr;
24169 * Grow/create list of attribute infos.
24171 if (vctxt->attrInfos == NULL) {
24172 vctxt->attrInfos = (xmlSchemaAttrInfoPtr *)
24173 xmlMalloc(sizeof(xmlSchemaAttrInfoPtr));
24174 vctxt->sizeAttrInfos = 1;
24175 if (vctxt->attrInfos == NULL) {
24176 xmlSchemaVErrMemory(vctxt,
24177 "allocating attribute info list", NULL);
24178 return (NULL);
24180 } else if (vctxt->sizeAttrInfos <= vctxt->nbAttrInfos) {
24181 vctxt->sizeAttrInfos++;
24182 vctxt->attrInfos = (xmlSchemaAttrInfoPtr *)
24183 xmlRealloc(vctxt->attrInfos,
24184 vctxt->sizeAttrInfos * sizeof(xmlSchemaAttrInfoPtr));
24185 if (vctxt->attrInfos == NULL) {
24186 xmlSchemaVErrMemory(vctxt,
24187 "re-allocating attribute info list", NULL);
24188 return (NULL);
24190 } else {
24191 iattr = vctxt->attrInfos[vctxt->nbAttrInfos++];
24192 if (iattr->localName != NULL) {
24193 VERROR_INT("xmlSchemaGetFreshAttrInfo",
24194 "attr info not cleared");
24195 return (NULL);
24197 iattr->nodeType = XML_ATTRIBUTE_NODE;
24198 return (iattr);
24201 * Create an attribute info.
24203 iattr = (xmlSchemaAttrInfoPtr)
24204 xmlMalloc(sizeof(xmlSchemaAttrInfo));
24205 if (iattr == NULL) {
24206 xmlSchemaVErrMemory(vctxt, "creating new attribute info", NULL);
24207 return (NULL);
24209 memset(iattr, 0, sizeof(xmlSchemaAttrInfo));
24210 iattr->nodeType = XML_ATTRIBUTE_NODE;
24211 vctxt->attrInfos[vctxt->nbAttrInfos++] = iattr;
24213 return (iattr);
24216 static int
24217 xmlSchemaValidatorPushAttribute(xmlSchemaValidCtxtPtr vctxt,
24218 xmlNodePtr attrNode,
24219 int nodeLine,
24220 const xmlChar *localName,
24221 const xmlChar *nsName,
24222 int ownedNames,
24223 xmlChar *value,
24224 int ownedValue)
24226 xmlSchemaAttrInfoPtr attr;
24228 attr = xmlSchemaGetFreshAttrInfo(vctxt);
24229 if (attr == NULL) {
24230 VERROR_INT("xmlSchemaPushAttribute",
24231 "calling xmlSchemaGetFreshAttrInfo()");
24232 return (-1);
24234 attr->node = attrNode;
24235 attr->nodeLine = nodeLine;
24236 attr->state = XML_SCHEMAS_ATTR_UNKNOWN;
24237 attr->localName = localName;
24238 attr->nsName = nsName;
24239 if (ownedNames)
24240 attr->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES;
24242 * Evaluate if it's an XSI attribute.
24244 if (nsName != NULL) {
24245 if (xmlStrEqual(localName, BAD_CAST "nil")) {
24246 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
24247 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_NIL;
24249 } else if (xmlStrEqual(localName, BAD_CAST "type")) {
24250 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
24251 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_TYPE;
24253 } else if (xmlStrEqual(localName, BAD_CAST "schemaLocation")) {
24254 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
24255 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_SCHEMA_LOC;
24257 } else if (xmlStrEqual(localName, BAD_CAST "noNamespaceSchemaLocation")) {
24258 if (xmlStrEqual(attr->nsName, xmlSchemaInstanceNs)) {
24259 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XSI_NO_NS_SCHEMA_LOC;
24261 } else if (xmlStrEqual(attr->nsName, xmlNamespaceNs)) {
24262 attr->metaType = XML_SCHEMA_ATTR_INFO_META_XMLNS;
24265 attr->value = value;
24266 if (ownedValue)
24267 attr->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
24268 if (attr->metaType != 0)
24269 attr->state = XML_SCHEMAS_ATTR_META;
24270 return (0);
24274 * xmlSchemaClearElemInfo:
24275 * @vctxt: the WXS validation context
24276 * @ielem: the element information item
24278 static void
24279 xmlSchemaClearElemInfo(xmlSchemaValidCtxtPtr vctxt,
24280 xmlSchemaNodeInfoPtr ielem)
24282 ielem->hasKeyrefs = 0;
24283 ielem->appliedXPath = 0;
24284 if (ielem->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES) {
24285 FREE_AND_NULL(ielem->localName);
24286 FREE_AND_NULL(ielem->nsName);
24287 } else {
24288 ielem->localName = NULL;
24289 ielem->nsName = NULL;
24291 if (ielem->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
24292 FREE_AND_NULL(ielem->value);
24293 } else {
24294 ielem->value = NULL;
24296 if (ielem->val != NULL) {
24298 * PSVI TODO: Be careful not to free it when the value is
24299 * exposed via PSVI.
24301 xmlSchemaFreeValue(ielem->val);
24302 ielem->val = NULL;
24304 if (ielem->idcMatchers != NULL) {
24306 * REVISIT OPTIMIZE TODO: Use a pool of IDC matchers.
24307 * Does it work?
24309 xmlSchemaIDCReleaseMatcherList(vctxt, ielem->idcMatchers);
24310 #if 0
24311 xmlSchemaIDCFreeMatcherList(ielem->idcMatchers);
24312 #endif
24313 ielem->idcMatchers = NULL;
24315 if (ielem->idcTable != NULL) {
24317 * OPTIMIZE TODO: Use a pool of IDC tables??.
24319 xmlSchemaIDCFreeIDCTable(ielem->idcTable);
24320 ielem->idcTable = NULL;
24322 if (ielem->regexCtxt != NULL) {
24323 xmlRegFreeExecCtxt(ielem->regexCtxt);
24324 ielem->regexCtxt = NULL;
24326 if (ielem->nsBindings != NULL) {
24327 xmlFree((xmlChar **)ielem->nsBindings);
24328 ielem->nsBindings = NULL;
24329 ielem->nbNsBindings = 0;
24330 ielem->sizeNsBindings = 0;
24335 * xmlSchemaGetFreshElemInfo:
24336 * @vctxt: the schema validation context
24338 * Creates/reuses and initializes the element info item for
24339 * the current tree depth.
24341 * Returns the element info item or NULL on API or internal errors.
24343 static xmlSchemaNodeInfoPtr
24344 xmlSchemaGetFreshElemInfo(xmlSchemaValidCtxtPtr vctxt)
24346 xmlSchemaNodeInfoPtr info = NULL;
24348 if (vctxt->depth > vctxt->sizeElemInfos) {
24349 VERROR_INT("xmlSchemaGetFreshElemInfo",
24350 "inconsistent depth encountered");
24351 return (NULL);
24353 if (vctxt->elemInfos == NULL) {
24354 vctxt->elemInfos = (xmlSchemaNodeInfoPtr *)
24355 xmlMalloc(10 * sizeof(xmlSchemaNodeInfoPtr));
24356 if (vctxt->elemInfos == NULL) {
24357 xmlSchemaVErrMemory(vctxt,
24358 "allocating the element info array", NULL);
24359 return (NULL);
24361 memset(vctxt->elemInfos, 0, 10 * sizeof(xmlSchemaNodeInfoPtr));
24362 vctxt->sizeElemInfos = 10;
24363 } else if (vctxt->sizeElemInfos <= vctxt->depth) {
24364 int i = vctxt->sizeElemInfos;
24366 vctxt->sizeElemInfos *= 2;
24367 vctxt->elemInfos = (xmlSchemaNodeInfoPtr *)
24368 xmlRealloc(vctxt->elemInfos, vctxt->sizeElemInfos *
24369 sizeof(xmlSchemaNodeInfoPtr));
24370 if (vctxt->elemInfos == NULL) {
24371 xmlSchemaVErrMemory(vctxt,
24372 "re-allocating the element info array", NULL);
24373 return (NULL);
24376 * We need the new memory to be NULLed.
24377 * TODO: Use memset instead?
24379 for (; i < vctxt->sizeElemInfos; i++)
24380 vctxt->elemInfos[i] = NULL;
24381 } else
24382 info = vctxt->elemInfos[vctxt->depth];
24384 if (info == NULL) {
24385 info = (xmlSchemaNodeInfoPtr)
24386 xmlMalloc(sizeof(xmlSchemaNodeInfo));
24387 if (info == NULL) {
24388 xmlSchemaVErrMemory(vctxt,
24389 "allocating an element info", NULL);
24390 return (NULL);
24392 vctxt->elemInfos[vctxt->depth] = info;
24393 } else {
24394 if (info->localName != NULL) {
24395 VERROR_INT("xmlSchemaGetFreshElemInfo",
24396 "elem info has not been cleared");
24397 return (NULL);
24400 memset(info, 0, sizeof(xmlSchemaNodeInfo));
24401 info->nodeType = XML_ELEMENT_NODE;
24402 info->depth = vctxt->depth;
24404 return (info);
24407 #define ACTIVATE_ATTRIBUTE(item) vctxt->inode = (xmlSchemaNodeInfoPtr) item;
24408 #define ACTIVATE_ELEM vctxt->inode = vctxt->elemInfos[vctxt->depth];
24409 #define ACTIVATE_PARENT_ELEM vctxt->inode = vctxt->elemInfos[vctxt->depth -1];
24411 static int
24412 xmlSchemaValidateFacets(xmlSchemaAbstractCtxtPtr actxt,
24413 xmlNodePtr node,
24414 xmlSchemaTypePtr type,
24415 xmlSchemaValType valType,
24416 const xmlChar * value,
24417 xmlSchemaValPtr val,
24418 unsigned long length,
24419 int fireErrors)
24421 int ret, error = 0, found;
24423 xmlSchemaTypePtr tmpType;
24424 xmlSchemaFacetLinkPtr facetLink;
24425 xmlSchemaFacetPtr facet;
24426 unsigned long len = 0;
24427 xmlSchemaWhitespaceValueType ws;
24430 * In Libxml2, derived built-in types have currently no explicit facets.
24432 if (type->type == XML_SCHEMA_TYPE_BASIC)
24433 return (0);
24436 * NOTE: Do not jump away, if the facetSet of the given type is
24437 * empty: until now, "pattern" and "enumeration" facets of the
24438 * *base types* need to be checked as well.
24440 if (type->facetSet == NULL)
24441 goto pattern_and_enum;
24443 if (! WXS_IS_ATOMIC(type)) {
24444 if (WXS_IS_LIST(type))
24445 goto WXS_IS_LIST;
24446 else
24447 goto pattern_and_enum;
24451 * Whitespace handling is only of importance for string-based
24452 * types.
24454 tmpType = xmlSchemaGetPrimitiveType(type);
24455 if ((tmpType->builtInType == XML_SCHEMAS_STRING) ||
24456 WXS_IS_ANY_SIMPLE_TYPE(tmpType)) {
24457 ws = xmlSchemaGetWhiteSpaceFacetValue(type);
24458 } else
24459 ws = XML_SCHEMA_WHITESPACE_COLLAPSE;
24462 * If the value was not computed (for string or
24463 * anySimpleType based types), then use the provided
24464 * type.
24466 if (val != NULL)
24467 valType = xmlSchemaGetValType(val);
24469 ret = 0;
24470 for (facetLink = type->facetSet; facetLink != NULL;
24471 facetLink = facetLink->next) {
24473 * Skip the pattern "whiteSpace": it is used to
24474 * format the character content beforehand.
24476 switch (facetLink->facet->type) {
24477 case XML_SCHEMA_FACET_WHITESPACE:
24478 case XML_SCHEMA_FACET_PATTERN:
24479 case XML_SCHEMA_FACET_ENUMERATION:
24480 continue;
24481 case XML_SCHEMA_FACET_LENGTH:
24482 case XML_SCHEMA_FACET_MINLENGTH:
24483 case XML_SCHEMA_FACET_MAXLENGTH:
24484 ret = xmlSchemaValidateLengthFacetWhtsp(facetLink->facet,
24485 valType, value, val, &len, ws);
24486 break;
24487 default:
24488 ret = xmlSchemaValidateFacetWhtsp(facetLink->facet, ws,
24489 valType, value, val, ws);
24490 break;
24492 if (ret < 0) {
24493 AERROR_INT("xmlSchemaValidateFacets",
24494 "validating against a atomic type facet");
24495 return (-1);
24496 } else if (ret > 0) {
24497 if (fireErrors)
24498 xmlSchemaFacetErr(actxt, ret, node,
24499 value, len, type, facetLink->facet, NULL, NULL, NULL);
24500 else
24501 return (ret);
24502 if (error == 0)
24503 error = ret;
24505 ret = 0;
24508 WXS_IS_LIST:
24509 if (! WXS_IS_LIST(type))
24510 goto pattern_and_enum;
24512 * "length", "minLength" and "maxLength" of list types.
24514 ret = 0;
24515 for (facetLink = type->facetSet; facetLink != NULL;
24516 facetLink = facetLink->next) {
24518 switch (facetLink->facet->type) {
24519 case XML_SCHEMA_FACET_LENGTH:
24520 case XML_SCHEMA_FACET_MINLENGTH:
24521 case XML_SCHEMA_FACET_MAXLENGTH:
24522 ret = xmlSchemaValidateListSimpleTypeFacet(facetLink->facet,
24523 value, length, NULL);
24524 break;
24525 default:
24526 continue;
24528 if (ret < 0) {
24529 AERROR_INT("xmlSchemaValidateFacets",
24530 "validating against a list type facet");
24531 return (-1);
24532 } else if (ret > 0) {
24533 if (fireErrors)
24534 xmlSchemaFacetErr(actxt, ret, node,
24535 value, length, type, facetLink->facet, NULL, NULL, NULL);
24536 else
24537 return (ret);
24538 if (error == 0)
24539 error = ret;
24541 ret = 0;
24544 pattern_and_enum:
24545 found = 0;
24547 * Process enumerations. Facet values are in the value space
24548 * of the defining type's base type. This seems to be a bug in the
24549 * XML Schema 1.0 spec. Use the whitespace type of the base type.
24550 * Only the first set of enumerations in the ancestor-or-self axis
24551 * is used for validation.
24553 ret = 0;
24554 tmpType = type;
24555 do {
24556 for (facet = tmpType->facets; facet != NULL; facet = facet->next) {
24557 if (facet->type != XML_SCHEMA_FACET_ENUMERATION)
24558 continue;
24559 found = 1;
24560 ret = xmlSchemaAreValuesEqual(facet->val, val);
24561 if (ret == 1)
24562 break;
24563 else if (ret < 0) {
24564 AERROR_INT("xmlSchemaValidateFacets",
24565 "validating against an enumeration facet");
24566 return (-1);
24569 if (ret != 0)
24570 break;
24572 * Break on the first set of enumerations. Any additional
24573 * enumerations which might be existent on the ancestors
24574 * of the current type are restricted by this set; thus
24575 * *must* *not* be taken into account.
24577 if (found)
24578 break;
24579 tmpType = tmpType->baseType;
24580 } while ((tmpType != NULL) &&
24581 (tmpType->type != XML_SCHEMA_TYPE_BASIC));
24582 if (found && (ret == 0)) {
24583 ret = XML_SCHEMAV_CVC_ENUMERATION_VALID;
24584 if (fireErrors) {
24585 xmlSchemaFacetErr(actxt, ret, node,
24586 value, 0, type, NULL, NULL, NULL, NULL);
24587 } else
24588 return (ret);
24589 if (error == 0)
24590 error = ret;
24594 * Process patters. Pattern facets are ORed at type level
24595 * and ANDed if derived. Walk the base type axis.
24597 tmpType = type;
24598 facet = NULL;
24599 do {
24600 found = 0;
24601 for (facetLink = tmpType->facetSet; facetLink != NULL;
24602 facetLink = facetLink->next) {
24603 if (facetLink->facet->type != XML_SCHEMA_FACET_PATTERN)
24604 continue;
24605 found = 1;
24607 * NOTE that for patterns, @value needs to be the
24608 * normalized value.
24610 ret = xmlRegexpExec(facetLink->facet->regexp, value);
24611 if (ret == 1)
24612 break;
24613 else if (ret < 0) {
24614 AERROR_INT("xmlSchemaValidateFacets",
24615 "validating against a pattern facet");
24616 return (-1);
24617 } else {
24619 * Save the last non-validating facet.
24621 facet = facetLink->facet;
24624 if (found && (ret != 1)) {
24625 ret = XML_SCHEMAV_CVC_PATTERN_VALID;
24626 if (fireErrors) {
24627 xmlSchemaFacetErr(actxt, ret, node,
24628 value, 0, type, facet, NULL, NULL, NULL);
24629 } else
24630 return (ret);
24631 if (error == 0)
24632 error = ret;
24633 break;
24635 tmpType = tmpType->baseType;
24636 } while ((tmpType != NULL) && (tmpType->type != XML_SCHEMA_TYPE_BASIC));
24638 return (error);
24641 static xmlChar *
24642 xmlSchemaNormalizeValue(xmlSchemaTypePtr type,
24643 const xmlChar *value)
24645 switch (xmlSchemaGetWhiteSpaceFacetValue(type)) {
24646 case XML_SCHEMA_WHITESPACE_COLLAPSE:
24647 return (xmlSchemaCollapseString(value));
24648 case XML_SCHEMA_WHITESPACE_REPLACE:
24649 return (xmlSchemaWhiteSpaceReplace(value));
24650 default:
24651 return (NULL);
24655 static int
24656 xmlSchemaValidateQName(xmlSchemaValidCtxtPtr vctxt,
24657 const xmlChar *value,
24658 xmlSchemaValPtr *val,
24659 int valNeeded)
24661 int ret;
24662 xmlChar *stripped;
24663 const xmlChar *nsName;
24664 xmlChar *local, *prefix = NULL;
24666 ret = xmlValidateQName(value, 1);
24667 if (ret != 0) {
24668 if (ret == -1) {
24669 VERROR_INT("xmlSchemaValidateQName",
24670 "calling xmlValidateQName()");
24671 return (-1);
24673 return( XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1);
24676 * NOTE: xmlSplitQName2 will always return a duplicated
24677 * strings.
24679 /* TODO: Export and use xmlSchemaStrip instead */
24680 stripped = xmlSchemaCollapseString(value);
24681 local = xmlSplitQName2(stripped ? stripped : value, &prefix);
24682 xmlFree(stripped);
24683 if (local == NULL)
24684 local = xmlStrdup(value);
24686 * OPTIMIZE TODO: Use flags for:
24687 * - is there any namespace binding?
24688 * - is there a default namespace?
24690 nsName = xmlSchemaLookupNamespace(vctxt, prefix);
24692 if (prefix != NULL) {
24693 xmlFree(prefix);
24695 * A namespace must be found if the prefix is
24696 * NOT NULL.
24698 if (nsName == NULL) {
24699 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
24700 xmlSchemaCustomErr(ACTXT_CAST vctxt, ret, NULL,
24701 WXS_BASIC_CAST xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
24702 "The QName value '%s' has no "
24703 "corresponding namespace declaration in "
24704 "scope", value, NULL);
24705 if (local != NULL)
24706 xmlFree(local);
24707 return (ret);
24710 if (valNeeded && val) {
24711 if (nsName != NULL)
24712 *val = xmlSchemaNewQNameValue(
24713 BAD_CAST xmlStrdup(nsName), BAD_CAST local);
24714 else
24715 *val = xmlSchemaNewQNameValue(NULL,
24716 BAD_CAST local);
24717 } else
24718 xmlFree(local);
24719 return (0);
24723 * cvc-simple-type
24725 static int
24726 xmlSchemaVCheckCVCSimpleType(xmlSchemaAbstractCtxtPtr actxt,
24727 xmlNodePtr node,
24728 xmlSchemaTypePtr type,
24729 const xmlChar *value,
24730 xmlSchemaValPtr *retVal,
24731 int fireErrors,
24732 int normalize,
24733 int isNormalized)
24735 int ret = 0, valNeeded = (retVal) ? 1 : 0;
24736 xmlSchemaValPtr val = NULL;
24737 /* xmlSchemaWhitespaceValueType ws; */
24738 xmlChar *normValue = NULL;
24740 #define NORMALIZE(atype) \
24741 if ((! isNormalized) && \
24742 (normalize || (type->flags & XML_SCHEMAS_TYPE_NORMVALUENEEDED))) { \
24743 normValue = xmlSchemaNormalizeValue(atype, value); \
24744 if (normValue != NULL) \
24745 value = normValue; \
24746 isNormalized = 1; \
24749 if ((retVal != NULL) && (*retVal != NULL)) {
24750 xmlSchemaFreeValue(*retVal);
24751 *retVal = NULL;
24754 * 3.14.4 Simple Type Definition Validation Rules
24755 * Validation Rule: String Valid
24758 * 1 It is schema-valid with respect to that definition as defined
24759 * by Datatype Valid in [XML Schemas: Datatypes].
24762 * 2.1 If The definition is ENTITY or is validly derived from ENTITY given
24763 * the empty set, as defined in Type Derivation OK (Simple) ($3.14.6), then
24764 * the string must be a `declared entity name`.
24767 * 2.2 If The definition is ENTITIES or is validly derived from ENTITIES
24768 * given the empty set, as defined in Type Derivation OK (Simple) ($3.14.6),
24769 * then every whitespace-delimited substring of the string must be a `declared
24770 * entity name`.
24773 * 2.3 otherwise no further condition applies.
24775 if ((! valNeeded) && (type->flags & XML_SCHEMAS_TYPE_FACETSNEEDVALUE))
24776 valNeeded = 1;
24777 if (value == NULL)
24778 value = BAD_CAST "";
24779 if (WXS_IS_ANY_SIMPLE_TYPE(type) || WXS_IS_ATOMIC(type)) {
24780 xmlSchemaTypePtr biType; /* The built-in type. */
24782 * SPEC (1.2.1) "if {variety} is `atomic` then the string must `match`
24783 * a literal in the `lexical space` of {base type definition}"
24786 * Whitespace-normalize.
24788 NORMALIZE(type);
24789 if (type->type != XML_SCHEMA_TYPE_BASIC) {
24791 * Get the built-in type.
24793 biType = type->baseType;
24794 while ((biType != NULL) &&
24795 (biType->type != XML_SCHEMA_TYPE_BASIC))
24796 biType = biType->baseType;
24798 if (biType == NULL) {
24799 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24800 "could not get the built-in type");
24801 goto internal_error;
24803 } else
24804 biType = type;
24806 * NOTATIONs need to be processed here, since they need
24807 * to lookup in the hashtable of NOTATION declarations of the schema.
24809 if (actxt->type == XML_SCHEMA_CTXT_VALIDATOR) {
24810 switch (biType->builtInType) {
24811 case XML_SCHEMAS_NOTATION:
24812 ret = xmlSchemaValidateNotation(
24813 (xmlSchemaValidCtxtPtr) actxt,
24814 ((xmlSchemaValidCtxtPtr) actxt)->schema,
24815 NULL, value, &val, valNeeded);
24816 break;
24817 case XML_SCHEMAS_QNAME:
24818 ret = xmlSchemaValidateQName((xmlSchemaValidCtxtPtr) actxt,
24819 value, &val, valNeeded);
24820 break;
24821 default:
24822 /* ws = xmlSchemaGetWhiteSpaceFacetValue(type); */
24823 if (valNeeded)
24824 ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24825 value, &val, node);
24826 else
24827 ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24828 value, NULL, node);
24829 break;
24831 } else if (actxt->type == XML_SCHEMA_CTXT_PARSER) {
24832 switch (biType->builtInType) {
24833 case XML_SCHEMAS_NOTATION:
24834 ret = xmlSchemaValidateNotation(NULL,
24835 ((xmlSchemaParserCtxtPtr) actxt)->schema, node,
24836 value, &val, valNeeded);
24837 break;
24838 default:
24839 /* ws = xmlSchemaGetWhiteSpaceFacetValue(type); */
24840 if (valNeeded)
24841 ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24842 value, &val, node);
24843 else
24844 ret = xmlSchemaValPredefTypeNodeNoNorm(biType,
24845 value, NULL, node);
24846 break;
24848 } else {
24850 * Validation via a public API is not implemented yet.
24852 TODO
24853 goto internal_error;
24855 if (ret != 0) {
24856 if (ret < 0) {
24857 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24858 "validating against a built-in type");
24859 goto internal_error;
24861 if (WXS_IS_LIST(type))
24862 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24863 else
24864 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
24866 if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
24868 * Check facets.
24870 ret = xmlSchemaValidateFacets(actxt, node, type,
24871 (xmlSchemaValType) biType->builtInType, value, val,
24872 0, fireErrors);
24873 if (ret != 0) {
24874 if (ret < 0) {
24875 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24876 "validating facets of atomic simple type");
24877 goto internal_error;
24879 if (WXS_IS_LIST(type))
24880 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24881 else
24882 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1;
24885 else if (fireErrors && (ret > 0))
24886 xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
24887 } else if (WXS_IS_LIST(type)) {
24889 xmlSchemaTypePtr itemType;
24890 const xmlChar *cur, *end;
24891 xmlChar *tmpValue = NULL;
24892 unsigned long len = 0;
24893 xmlSchemaValPtr prevVal = NULL, curVal = NULL;
24894 /* 1.2.2 if {variety} is `list` then the string must be a sequence
24895 * of white space separated tokens, each of which `match`es a literal
24896 * in the `lexical space` of {item type definition}
24899 * Note that XML_SCHEMAS_TYPE_NORMVALUENEEDED will be set if
24900 * the list type has an enum or pattern facet.
24902 NORMALIZE(type);
24904 * VAL TODO: Optimize validation of empty values.
24905 * VAL TODO: We do not have computed values for lists.
24907 itemType = WXS_LIST_ITEMTYPE(type);
24908 cur = value;
24909 do {
24910 while (IS_BLANK_CH(*cur))
24911 cur++;
24912 end = cur;
24913 while ((*end != 0) && (!(IS_BLANK_CH(*end))))
24914 end++;
24915 if (end == cur)
24916 break;
24917 tmpValue = xmlStrndup(cur, end - cur);
24918 len++;
24920 if (valNeeded)
24921 ret = xmlSchemaVCheckCVCSimpleType(actxt, node, itemType,
24922 tmpValue, &curVal, fireErrors, 0, 1);
24923 else
24924 ret = xmlSchemaVCheckCVCSimpleType(actxt, node, itemType,
24925 tmpValue, NULL, fireErrors, 0, 1);
24926 FREE_AND_NULL(tmpValue);
24927 if (curVal != NULL) {
24929 * Add to list of computed values.
24931 if (val == NULL)
24932 val = curVal;
24933 else
24934 xmlSchemaValueAppend(prevVal, curVal);
24935 prevVal = curVal;
24936 curVal = NULL;
24938 if (ret != 0) {
24939 if (ret < 0) {
24940 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24941 "validating an item of list simple type");
24942 goto internal_error;
24944 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24945 break;
24947 cur = end;
24948 } while (*cur != 0);
24949 FREE_AND_NULL(tmpValue);
24950 if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
24952 * Apply facets (pattern, enumeration).
24954 ret = xmlSchemaValidateFacets(actxt, node, type,
24955 XML_SCHEMAS_UNKNOWN, value, val,
24956 len, fireErrors);
24957 if (ret != 0) {
24958 if (ret < 0) {
24959 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24960 "validating facets of list simple type");
24961 goto internal_error;
24963 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_2;
24966 if (fireErrors && (ret > 0)) {
24968 * Report the normalized value.
24970 normalize = 1;
24971 NORMALIZE(type);
24972 xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
24974 } else if (WXS_IS_UNION(type)) {
24975 xmlSchemaTypeLinkPtr memberLink;
24977 * TODO: For all datatypes `derived` by `union` whiteSpace does
24978 * not apply directly; however, the normalization behavior of `union`
24979 * types is controlled by the value of whiteSpace on that one of the
24980 * `memberTypes` against which the `union` is successfully validated.
24982 * This means that the value is normalized by the first validating
24983 * member type, then the facets of the union type are applied. This
24984 * needs changing of the value!
24988 * 1.2.3 if {variety} is `union` then the string must `match` a
24989 * literal in the `lexical space` of at least one member of
24990 * {member type definitions}
24992 memberLink = xmlSchemaGetUnionSimpleTypeMemberTypes(type);
24993 if (memberLink == NULL) {
24994 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
24995 "union simple type has no member types");
24996 goto internal_error;
24999 * Always normalize union type values, since we currently
25000 * cannot store the whitespace information with the value
25001 * itself; otherwise a later value-comparison would be
25002 * not possible.
25004 while (memberLink != NULL) {
25005 if (valNeeded)
25006 ret = xmlSchemaVCheckCVCSimpleType(actxt, node,
25007 memberLink->type, value, &val, 0, 1, 0);
25008 else
25009 ret = xmlSchemaVCheckCVCSimpleType(actxt, node,
25010 memberLink->type, value, NULL, 0, 1, 0);
25011 if (ret <= 0)
25012 break;
25013 memberLink = memberLink->next;
25015 if (ret != 0) {
25016 if (ret < 0) {
25017 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
25018 "validating members of union simple type");
25019 goto internal_error;
25021 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
25024 * Apply facets (pattern, enumeration).
25026 if ((ret == 0) && (type->flags & XML_SCHEMAS_TYPE_HAS_FACETS)) {
25028 * The normalization behavior of `union` types is controlled by
25029 * the value of whiteSpace on that one of the `memberTypes`
25030 * against which the `union` is successfully validated.
25032 NORMALIZE(memberLink->type);
25033 ret = xmlSchemaValidateFacets(actxt, node, type,
25034 XML_SCHEMAS_UNKNOWN, value, val,
25035 0, fireErrors);
25036 if (ret != 0) {
25037 if (ret < 0) {
25038 AERROR_INT("xmlSchemaVCheckCVCSimpleType",
25039 "validating facets of union simple type");
25040 goto internal_error;
25042 ret = XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_3;
25045 if (fireErrors && (ret > 0))
25046 xmlSchemaSimpleTypeErr(actxt, ret, node, value, type, 1);
25049 if (normValue != NULL)
25050 xmlFree(normValue);
25051 if (ret == 0) {
25052 if (retVal != NULL)
25053 *retVal = val;
25054 else if (val != NULL)
25055 xmlSchemaFreeValue(val);
25056 } else if (val != NULL)
25057 xmlSchemaFreeValue(val);
25058 return (ret);
25059 internal_error:
25060 if (normValue != NULL)
25061 xmlFree(normValue);
25062 if (val != NULL)
25063 xmlSchemaFreeValue(val);
25064 return (-1);
25067 static int
25068 xmlSchemaVExpandQName(xmlSchemaValidCtxtPtr vctxt,
25069 const xmlChar *value,
25070 const xmlChar **nsName,
25071 const xmlChar **localName)
25073 int ret = 0;
25075 if ((nsName == NULL) || (localName == NULL))
25076 return (-1);
25077 *nsName = NULL;
25078 *localName = NULL;
25080 ret = xmlValidateQName(value, 1);
25081 if (ret == -1)
25082 return (-1);
25083 if (ret > 0) {
25084 xmlSchemaSimpleTypeErr(ACTXT_CAST vctxt,
25085 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1, NULL,
25086 value, xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME), 1);
25087 return (1);
25090 xmlChar *local = NULL;
25091 xmlChar *prefix;
25094 * NOTE: xmlSplitQName2 will return a duplicated
25095 * string.
25097 local = xmlSplitQName2(value, &prefix);
25098 if (local == NULL)
25099 *localName = xmlDictLookup(vctxt->dict, value, -1);
25100 else {
25101 *localName = xmlDictLookup(vctxt->dict, local, -1);
25102 xmlFree(local);
25105 *nsName = xmlSchemaLookupNamespace(vctxt, prefix);
25107 if (prefix != NULL) {
25108 xmlFree(prefix);
25110 * A namespace must be found if the prefix is NOT NULL.
25112 if (*nsName == NULL) {
25113 xmlSchemaCustomErr(ACTXT_CAST vctxt,
25114 XML_SCHEMAV_CVC_DATATYPE_VALID_1_2_1, NULL,
25115 WXS_BASIC_CAST xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
25116 "The QName value '%s' has no "
25117 "corresponding namespace declaration in scope",
25118 value, NULL);
25119 return (2);
25123 return (0);
25126 static int
25127 xmlSchemaProcessXSIType(xmlSchemaValidCtxtPtr vctxt,
25128 xmlSchemaAttrInfoPtr iattr,
25129 xmlSchemaTypePtr *localType,
25130 xmlSchemaElementPtr elemDecl)
25132 int ret = 0;
25134 * cvc-elt (3.3.4) : (4)
25135 * AND
25136 * Schema-Validity Assessment (Element) (cvc-assess-elt)
25137 * (1.2.1.2.1) - (1.2.1.2.4)
25138 * Handle 'xsi:type'.
25140 if (localType == NULL)
25141 return (-1);
25142 *localType = NULL;
25143 if (iattr == NULL)
25144 return (0);
25145 else {
25146 const xmlChar *nsName = NULL, *local = NULL;
25148 * TODO: We should report a *warning* that the type was overridden
25149 * by the instance.
25151 ACTIVATE_ATTRIBUTE(iattr);
25153 * (cvc-elt) (3.3.4) : (4.1)
25154 * (cvc-assess-elt) (1.2.1.2.2)
25156 ret = xmlSchemaVExpandQName(vctxt, iattr->value,
25157 &nsName, &local);
25158 if (ret != 0) {
25159 if (ret < 0) {
25160 VERROR_INT("xmlSchemaValidateElementByDeclaration",
25161 "calling xmlSchemaQNameExpand() to validate the "
25162 "attribute 'xsi:type'");
25163 goto internal_error;
25165 goto exit;
25168 * (cvc-elt) (3.3.4) : (4.2)
25169 * (cvc-assess-elt) (1.2.1.2.3)
25171 *localType = xmlSchemaGetType(vctxt->schema, local, nsName);
25172 if (*localType == NULL) {
25173 xmlChar *str = NULL;
25175 xmlSchemaCustomErr(ACTXT_CAST vctxt,
25176 XML_SCHEMAV_CVC_ELT_4_2, NULL,
25177 WXS_BASIC_CAST xmlSchemaGetBuiltInType(XML_SCHEMAS_QNAME),
25178 "The QName value '%s' of the xsi:type attribute does not "
25179 "resolve to a type definition",
25180 xmlSchemaFormatQName(&str, nsName, local), NULL);
25181 FREE_AND_NULL(str);
25182 ret = vctxt->err;
25183 goto exit;
25185 if (elemDecl != NULL) {
25186 int set = 0;
25189 * SPEC cvc-elt (3.3.4) : (4.3) (Type Derivation OK)
25190 * "The `local type definition` must be validly
25191 * derived from the {type definition} given the union of
25192 * the {disallowed substitutions} and the {type definition}'s
25193 * {prohibited substitutions}, as defined in
25194 * Type Derivation OK (Complex) ($3.4.6)
25195 * (if it is a complex type definition),
25196 * or given {disallowed substitutions} as defined in Type
25197 * Derivation OK (Simple) ($3.14.6) (if it is a simple type
25198 * definition)."
25200 * {disallowed substitutions}: the "block" on the element decl.
25201 * {prohibited substitutions}: the "block" on the type def.
25204 * OPTIMIZE TODO: We could map types already evaluated
25205 * to be validly derived from other types to avoid checking
25206 * this over and over for the same types.
25208 if ((elemDecl->flags & XML_SCHEMAS_ELEM_BLOCK_EXTENSION) ||
25209 (elemDecl->subtypes->flags &
25210 XML_SCHEMAS_TYPE_BLOCK_EXTENSION))
25211 set |= SUBSET_EXTENSION;
25213 if ((elemDecl->flags & XML_SCHEMAS_ELEM_BLOCK_RESTRICTION) ||
25214 (elemDecl->subtypes->flags &
25215 XML_SCHEMAS_TYPE_BLOCK_RESTRICTION))
25216 set |= SUBSET_RESTRICTION;
25219 * REMOVED and CHANGED since this produced a parser context
25220 * which adds to the string dict of the schema. So this would
25221 * change the schema and we don't want this. We don't need
25222 * the parser context anymore.
25224 * if ((vctxt->pctxt == NULL) &&
25225 * (xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1))
25226 * return (-1);
25229 if (xmlSchemaCheckCOSDerivedOK(ACTXT_CAST vctxt, *localType,
25230 elemDecl->subtypes, set) != 0) {
25231 xmlChar *str = NULL;
25233 xmlSchemaCustomErr(ACTXT_CAST vctxt,
25234 XML_SCHEMAV_CVC_ELT_4_3, NULL, NULL,
25235 "The type definition '%s', specified by xsi:type, is "
25236 "blocked or not validly derived from the type definition "
25237 "of the element declaration",
25238 xmlSchemaFormatQName(&str,
25239 (*localType)->targetNamespace,
25240 (*localType)->name),
25241 NULL);
25242 FREE_AND_NULL(str);
25243 ret = vctxt->err;
25244 *localType = NULL;
25248 exit:
25249 ACTIVATE_ELEM;
25250 return (ret);
25251 internal_error:
25252 ACTIVATE_ELEM;
25253 return (-1);
25256 static int
25257 xmlSchemaValidateElemDecl(xmlSchemaValidCtxtPtr vctxt)
25259 xmlSchemaElementPtr elemDecl = vctxt->inode->decl;
25260 xmlSchemaTypePtr actualType;
25263 * cvc-elt (3.3.4) : 1
25265 if (elemDecl == NULL) {
25266 VERROR(XML_SCHEMAV_CVC_ELT_1, NULL,
25267 "No matching declaration available");
25268 return (vctxt->err);
25270 actualType = WXS_ELEM_TYPEDEF(elemDecl);
25272 * cvc-elt (3.3.4) : 2
25274 if (elemDecl->flags & XML_SCHEMAS_ELEM_ABSTRACT) {
25275 VERROR(XML_SCHEMAV_CVC_ELT_2, NULL,
25276 "The element declaration is abstract");
25277 return (vctxt->err);
25279 if (actualType == NULL) {
25280 VERROR(XML_SCHEMAV_CVC_TYPE_1, NULL,
25281 "The type definition is absent");
25282 return (XML_SCHEMAV_CVC_TYPE_1);
25284 if (vctxt->nbAttrInfos != 0) {
25285 int ret;
25286 xmlSchemaAttrInfoPtr iattr;
25288 * cvc-elt (3.3.4) : 3
25289 * Handle 'xsi:nil'.
25291 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
25292 XML_SCHEMA_ATTR_INFO_META_XSI_NIL);
25293 if (iattr) {
25294 ACTIVATE_ATTRIBUTE(iattr);
25296 * Validate the value.
25298 ret = xmlSchemaVCheckCVCSimpleType(
25299 ACTXT_CAST vctxt, NULL,
25300 xmlSchemaGetBuiltInType(XML_SCHEMAS_BOOLEAN),
25301 iattr->value, &(iattr->val), 1, 0, 0);
25302 ACTIVATE_ELEM;
25303 if (ret < 0) {
25304 VERROR_INT("xmlSchemaValidateElemDecl",
25305 "calling xmlSchemaVCheckCVCSimpleType() to "
25306 "validate the attribute 'xsi:nil'");
25307 return (-1);
25309 if (ret == 0) {
25310 if ((elemDecl->flags & XML_SCHEMAS_ELEM_NILLABLE) == 0) {
25312 * cvc-elt (3.3.4) : 3.1
25314 VERROR(XML_SCHEMAV_CVC_ELT_3_1, NULL,
25315 "The element is not 'nillable'");
25316 /* Does not return an error on purpose. */
25317 } else {
25318 if (xmlSchemaValueGetAsBoolean(iattr->val)) {
25320 * cvc-elt (3.3.4) : 3.2.2
25322 if ((elemDecl->flags & XML_SCHEMAS_ELEM_FIXED) &&
25323 (elemDecl->value != NULL)) {
25324 VERROR(XML_SCHEMAV_CVC_ELT_3_2_2, NULL,
25325 "The element cannot be 'nilled' because "
25326 "there is a fixed value constraint defined "
25327 "for it");
25328 /* Does not return an error on purpose. */
25329 } else
25330 vctxt->inode->flags |=
25331 XML_SCHEMA_ELEM_INFO_NILLED;
25337 * cvc-elt (3.3.4) : 4
25338 * Handle 'xsi:type'.
25340 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
25341 XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
25342 if (iattr) {
25343 xmlSchemaTypePtr localType = NULL;
25345 ret = xmlSchemaProcessXSIType(vctxt, iattr, &localType,
25346 elemDecl);
25347 if (ret != 0) {
25348 if (ret == -1) {
25349 VERROR_INT("xmlSchemaValidateElemDecl",
25350 "calling xmlSchemaProcessXSIType() to "
25351 "process the attribute 'xsi:type'");
25352 return (-1);
25354 /* Does not return an error on purpose. */
25356 if (localType != NULL) {
25357 vctxt->inode->flags |= XML_SCHEMA_ELEM_INFO_LOCAL_TYPE;
25358 actualType = localType;
25363 * IDC: Register identity-constraint XPath matchers.
25365 if ((elemDecl->idcs != NULL) &&
25366 (xmlSchemaIDCRegisterMatchers(vctxt, elemDecl) == -1))
25367 return (-1);
25369 * No actual type definition.
25371 if (actualType == NULL) {
25372 VERROR(XML_SCHEMAV_CVC_TYPE_1, NULL,
25373 "The type definition is absent");
25374 return (XML_SCHEMAV_CVC_TYPE_1);
25377 * Remember the actual type definition.
25379 vctxt->inode->typeDef = actualType;
25381 return (0);
25384 static int
25385 xmlSchemaVAttributesSimple(xmlSchemaValidCtxtPtr vctxt)
25387 xmlSchemaAttrInfoPtr iattr;
25388 int ret = 0, i;
25391 * SPEC cvc-type (3.1.1)
25392 * "The attributes of must be empty, excepting those whose namespace
25393 * name is identical to http://www.w3.org/2001/XMLSchema-instance and
25394 * whose local name is one of type, nil, schemaLocation or
25395 * noNamespaceSchemaLocation."
25397 if (vctxt->nbAttrInfos == 0)
25398 return (0);
25399 for (i = 0; i < vctxt->nbAttrInfos; i++) {
25400 iattr = vctxt->attrInfos[i];
25401 if (! iattr->metaType) {
25402 ACTIVATE_ATTRIBUTE(iattr)
25403 xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt,
25404 XML_SCHEMAV_CVC_TYPE_3_1_1, iattr, NULL);
25405 ret = XML_SCHEMAV_CVC_TYPE_3_1_1;
25408 ACTIVATE_ELEM
25409 return (ret);
25413 * Cleanup currently used attribute infos.
25415 static void
25416 xmlSchemaClearAttrInfos(xmlSchemaValidCtxtPtr vctxt)
25418 int i;
25419 xmlSchemaAttrInfoPtr attr;
25421 if (vctxt->nbAttrInfos == 0)
25422 return;
25423 for (i = 0; i < vctxt->nbAttrInfos; i++) {
25424 attr = vctxt->attrInfos[i];
25425 if (attr->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES) {
25426 if (attr->localName != NULL)
25427 xmlFree((xmlChar *) attr->localName);
25428 if (attr->nsName != NULL)
25429 xmlFree((xmlChar *) attr->nsName);
25431 if (attr->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
25432 if (attr->value != NULL)
25433 xmlFree((xmlChar *) attr->value);
25435 if (attr->val != NULL) {
25436 xmlSchemaFreeValue(attr->val);
25437 attr->val = NULL;
25439 memset(attr, 0, sizeof(xmlSchemaAttrInfo));
25441 vctxt->nbAttrInfos = 0;
25445 * 3.4.4 Complex Type Definition Validation Rules
25446 * Element Locally Valid (Complex Type) (cvc-complex-type)
25447 * 3.2.4 Attribute Declaration Validation Rules
25448 * Validation Rule: Attribute Locally Valid (cvc-attribute)
25449 * Attribute Locally Valid (Use) (cvc-au)
25451 * Only "assessed" attribute information items will be visible to
25452 * IDCs. I.e. not "lax" (without declaration) and "skip" wild attributes.
25454 static int
25455 xmlSchemaVAttributesComplex(xmlSchemaValidCtxtPtr vctxt)
25457 xmlSchemaTypePtr type = vctxt->inode->typeDef;
25458 xmlSchemaItemListPtr attrUseList;
25459 xmlSchemaAttributeUsePtr attrUse = NULL;
25460 xmlSchemaAttributePtr attrDecl = NULL;
25461 xmlSchemaAttrInfoPtr iattr, tmpiattr;
25462 int i, j, found, nbAttrs, nbUses;
25463 int xpathRes = 0, res, wildIDs = 0, fixed;
25464 xmlNodePtr defAttrOwnerElem = NULL;
25467 * SPEC (cvc-attribute)
25468 * (1) "The declaration must not be `absent` (see Missing
25469 * Sub-components ($5.3) for how this can fail to be
25470 * the case)."
25471 * (2) "Its {type definition} must not be absent."
25473 * NOTE (1) + (2): This is not handled here, since we currently do not
25474 * allow validation against schemas which have missing sub-components.
25476 * SPEC (cvc-complex-type)
25477 * (3) "For each attribute information item in the element information
25478 * item's [attributes] excepting those whose [namespace name] is
25479 * identical to http://www.w3.org/2001/XMLSchema-instance and whose
25480 * [local name] is one of type, nil, schemaLocation or
25481 * noNamespaceSchemaLocation, the appropriate case among the following
25482 * must be true:
25485 attrUseList = (xmlSchemaItemListPtr) type->attrUses;
25487 * @nbAttrs is the number of attributes present in the instance.
25489 nbAttrs = vctxt->nbAttrInfos;
25490 if (attrUseList != NULL)
25491 nbUses = attrUseList->nbItems;
25492 else
25493 nbUses = 0;
25494 for (i = 0; i < nbUses; i++) {
25495 found = 0;
25496 attrUse = attrUseList->items[i];
25497 attrDecl = WXS_ATTRUSE_DECL(attrUse);
25498 for (j = 0; j < nbAttrs; j++) {
25499 iattr = vctxt->attrInfos[j];
25501 * SPEC (cvc-complex-type) (3)
25502 * Skip meta attributes.
25504 if (iattr->metaType)
25505 continue;
25506 if (iattr->localName[0] != attrDecl->name[0])
25507 continue;
25508 if (!xmlStrEqual(iattr->localName, attrDecl->name))
25509 continue;
25510 if (!xmlStrEqual(iattr->nsName, attrDecl->targetNamespace))
25511 continue;
25512 found = 1;
25514 * SPEC (cvc-complex-type)
25515 * (3.1) "If there is among the {attribute uses} an attribute
25516 * use with an {attribute declaration} whose {name} matches
25517 * the attribute information item's [local name] and whose
25518 * {target namespace} is identical to the attribute information
25519 * item's [namespace name] (where an `absent` {target namespace}
25520 * is taken to be identical to a [namespace name] with no value),
25521 * then the attribute information must be `valid` with respect
25522 * to that attribute use as per Attribute Locally Valid (Use)
25523 * ($3.5.4). In this case the {attribute declaration} of that
25524 * attribute use is the `context-determined declaration` for the
25525 * attribute information item with respect to Schema-Validity
25526 * Assessment (Attribute) ($3.2.4) and
25527 * Assessment Outcome (Attribute) ($3.2.5).
25529 iattr->state = XML_SCHEMAS_ATTR_ASSESSED;
25530 iattr->use = attrUse;
25532 * Context-determined declaration.
25534 iattr->decl = attrDecl;
25535 iattr->typeDef = attrDecl->subtypes;
25536 break;
25539 if (found)
25540 continue;
25542 if (attrUse->occurs == XML_SCHEMAS_ATTR_USE_REQUIRED) {
25544 * Handle non-existent, required attributes.
25546 * SPEC (cvc-complex-type)
25547 * (4) "The {attribute declaration} of each attribute use in
25548 * the {attribute uses} whose {required} is true matches one
25549 * of the attribute information items in the element information
25550 * item's [attributes] as per clause 3.1 above."
25552 tmpiattr = xmlSchemaGetFreshAttrInfo(vctxt);
25553 if (tmpiattr == NULL) {
25554 VERROR_INT(
25555 "xmlSchemaVAttributesComplex",
25556 "calling xmlSchemaGetFreshAttrInfo()");
25557 return (-1);
25559 tmpiattr->state = XML_SCHEMAS_ATTR_ERR_MISSING;
25560 tmpiattr->use = attrUse;
25561 tmpiattr->decl = attrDecl;
25562 } else if ((attrUse->occurs == XML_SCHEMAS_ATTR_USE_OPTIONAL) &&
25563 ((attrUse->defValue != NULL) ||
25564 (attrDecl->defValue != NULL))) {
25566 * Handle non-existent, optional, default/fixed attributes.
25568 tmpiattr = xmlSchemaGetFreshAttrInfo(vctxt);
25569 if (tmpiattr == NULL) {
25570 VERROR_INT(
25571 "xmlSchemaVAttributesComplex",
25572 "calling xmlSchemaGetFreshAttrInfo()");
25573 return (-1);
25575 tmpiattr->state = XML_SCHEMAS_ATTR_DEFAULT;
25576 tmpiattr->use = attrUse;
25577 tmpiattr->decl = attrDecl;
25578 tmpiattr->typeDef = attrDecl->subtypes;
25579 tmpiattr->localName = attrDecl->name;
25580 tmpiattr->nsName = attrDecl->targetNamespace;
25584 if (vctxt->nbAttrInfos == 0)
25585 return (0);
25587 * Validate against the wildcard.
25589 if (type->attributeWildcard != NULL) {
25591 * SPEC (cvc-complex-type)
25592 * (3.2.1) "There must be an {attribute wildcard}."
25594 for (i = 0; i < nbAttrs; i++) {
25595 iattr = vctxt->attrInfos[i];
25597 * SPEC (cvc-complex-type) (3)
25598 * Skip meta attributes.
25600 if (iattr->state != XML_SCHEMAS_ATTR_UNKNOWN)
25601 continue;
25603 * SPEC (cvc-complex-type)
25604 * (3.2.2) "The attribute information item must be `valid` with
25605 * respect to it as defined in Item Valid (Wildcard) ($3.10.4)."
25607 * SPEC Item Valid (Wildcard) (cvc-wildcard)
25608 * "... its [namespace name] must be `valid` with respect to
25609 * the wildcard constraint, as defined in Wildcard allows
25610 * Namespace Name ($3.10.4)."
25612 if (xmlSchemaCheckCVCWildcardNamespace(type->attributeWildcard,
25613 iattr->nsName) == 0) {
25615 * Handle processContents.
25617 * SPEC (cvc-wildcard):
25618 * processContents | context-determined declaration:
25619 * "strict" "mustFind"
25620 * "lax" "none"
25621 * "skip" "skip"
25623 if (type->attributeWildcard->processContents ==
25624 XML_SCHEMAS_ANY_SKIP) {
25626 * context-determined declaration = "skip"
25628 * SPEC PSVI Assessment Outcome (Attribute)
25629 * [validity] = "notKnown"
25630 * [validation attempted] = "none"
25632 iattr->state = XML_SCHEMAS_ATTR_WILD_SKIP;
25633 continue;
25636 * Find an attribute declaration.
25638 iattr->decl = xmlSchemaGetAttributeDecl(vctxt->schema,
25639 iattr->localName, iattr->nsName);
25640 if (iattr->decl != NULL) {
25641 iattr->state = XML_SCHEMAS_ATTR_ASSESSED;
25643 * SPEC (cvc-complex-type)
25644 * (5) "Let [Definition:] the wild IDs be the set of
25645 * all attribute information item to which clause 3.2
25646 * applied and whose `validation` resulted in a
25647 * `context-determined declaration` of mustFind or no
25648 * `context-determined declaration` at all, and whose
25649 * [local name] and [namespace name] resolve (as
25650 * defined by QName resolution (Instance) ($3.15.4)) to
25651 * an attribute declaration whose {type definition} is
25652 * or is derived from ID. Then all of the following
25653 * must be true:"
25655 iattr->typeDef = WXS_ATTR_TYPEDEF(iattr->decl);
25656 if (xmlSchemaIsDerivedFromBuiltInType(
25657 iattr->typeDef, XML_SCHEMAS_ID)) {
25659 * SPEC (5.1) "There must be no more than one
25660 * item in `wild IDs`."
25662 if (wildIDs != 0) {
25663 /* VAL TODO */
25664 iattr->state = XML_SCHEMAS_ATTR_ERR_WILD_DUPLICATE_ID;
25665 TODO
25666 continue;
25668 wildIDs++;
25670 * SPEC (cvc-complex-type)
25671 * (5.2) "If `wild IDs` is non-empty, there must not
25672 * be any attribute uses among the {attribute uses}
25673 * whose {attribute declaration}'s {type definition}
25674 * is or is derived from ID."
25676 if (attrUseList != NULL) {
25677 for (j = 0; j < attrUseList->nbItems; j++) {
25678 if (xmlSchemaIsDerivedFromBuiltInType(
25679 WXS_ATTRUSE_TYPEDEF(attrUseList->items[j]),
25680 XML_SCHEMAS_ID)) {
25681 /* URGENT VAL TODO: implement */
25682 iattr->state = XML_SCHEMAS_ATTR_ERR_WILD_AND_USE_ID;
25683 TODO
25684 break;
25689 } else if (type->attributeWildcard->processContents ==
25690 XML_SCHEMAS_ANY_LAX) {
25691 iattr->state = XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL;
25693 * SPEC PSVI Assessment Outcome (Attribute)
25694 * [validity] = "notKnown"
25695 * [validation attempted] = "none"
25697 } else {
25698 iattr->state = XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL;
25704 if (vctxt->nbAttrInfos == 0)
25705 return (0);
25708 * Get the owner element; needed for creation of default attributes.
25709 * This fixes bug #341337, reported by David Grohmann.
25711 if (vctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) {
25712 xmlSchemaNodeInfoPtr ielem = vctxt->elemInfos[vctxt->depth];
25713 if (ielem && ielem->node && ielem->node->doc)
25714 defAttrOwnerElem = ielem->node;
25717 * Validate values, create default attributes, evaluate IDCs.
25719 for (i = 0; i < vctxt->nbAttrInfos; i++) {
25720 iattr = vctxt->attrInfos[i];
25722 * VAL TODO: Note that we won't try to resolve IDCs to
25723 * "lax" and "skip" validated attributes. Check what to
25724 * do in this case.
25726 if ((iattr->state != XML_SCHEMAS_ATTR_ASSESSED) &&
25727 (iattr->state != XML_SCHEMAS_ATTR_DEFAULT))
25728 continue;
25730 * VAL TODO: What to do if the type definition is missing?
25732 if (iattr->typeDef == NULL) {
25733 iattr->state = XML_SCHEMAS_ATTR_ERR_NO_TYPE;
25734 continue;
25737 ACTIVATE_ATTRIBUTE(iattr);
25738 fixed = 0;
25739 xpathRes = 0;
25741 if (vctxt->xpathStates != NULL) {
25743 * Evaluate IDCs.
25745 xpathRes = xmlSchemaXPathEvaluate(vctxt,
25746 XML_ATTRIBUTE_NODE);
25747 if (xpathRes == -1) {
25748 VERROR_INT("xmlSchemaVAttributesComplex",
25749 "calling xmlSchemaXPathEvaluate()");
25750 goto internal_error;
25754 if (iattr->state == XML_SCHEMAS_ATTR_DEFAULT) {
25756 * Default/fixed attributes.
25757 * We need the value only if we need to resolve IDCs or
25758 * will create default attributes.
25760 if ((xpathRes) || (defAttrOwnerElem)) {
25761 if (iattr->use->defValue != NULL) {
25762 iattr->value = (xmlChar *) iattr->use->defValue;
25763 iattr->val = iattr->use->defVal;
25764 } else {
25765 iattr->value = (xmlChar *) iattr->decl->defValue;
25766 iattr->val = iattr->decl->defVal;
25769 * IDCs will consume the precomputed default value,
25770 * so we need to clone it.
25772 if (iattr->val == NULL) {
25773 VERROR_INT("xmlSchemaVAttributesComplex",
25774 "default/fixed value on an attribute use was "
25775 "not precomputed");
25776 goto internal_error;
25778 iattr->val = xmlSchemaCopyValue(iattr->val);
25779 if (iattr->val == NULL) {
25780 VERROR_INT("xmlSchemaVAttributesComplex",
25781 "calling xmlSchemaCopyValue()");
25782 goto internal_error;
25786 * PSVI: Add the default attribute to the current element.
25787 * VAL TODO: Should we use the *normalized* value? This currently
25788 * uses the *initial* value.
25791 if (defAttrOwnerElem) {
25792 xmlChar *normValue;
25793 const xmlChar *value;
25795 value = iattr->value;
25797 * Normalize the value.
25799 normValue = xmlSchemaNormalizeValue(iattr->typeDef,
25800 iattr->value);
25801 if (normValue != NULL)
25802 value = BAD_CAST normValue;
25804 if (iattr->nsName == NULL) {
25805 if (xmlNewProp(defAttrOwnerElem,
25806 iattr->localName, value) == NULL) {
25807 VERROR_INT("xmlSchemaVAttributesComplex",
25808 "calling xmlNewProp()");
25809 if (normValue != NULL)
25810 xmlFree(normValue);
25811 goto internal_error;
25813 } else {
25814 xmlNsPtr ns;
25816 ns = xmlSearchNsByHref(defAttrOwnerElem->doc,
25817 defAttrOwnerElem, iattr->nsName);
25818 if (ns == NULL) {
25819 xmlChar prefix[12];
25820 int counter = 0;
25823 * Create a namespace declaration on the validation
25824 * root node if no namespace declaration is in scope.
25826 do {
25827 snprintf((char *) prefix, 12, "p%d", counter++);
25828 ns = xmlSearchNs(defAttrOwnerElem->doc,
25829 defAttrOwnerElem, BAD_CAST prefix);
25830 if (counter > 1000) {
25831 VERROR_INT(
25832 "xmlSchemaVAttributesComplex",
25833 "could not compute a ns prefix for a "
25834 "default/fixed attribute");
25835 if (normValue != NULL)
25836 xmlFree(normValue);
25837 goto internal_error;
25839 } while (ns != NULL);
25840 ns = xmlNewNs(vctxt->validationRoot,
25841 iattr->nsName, BAD_CAST prefix);
25844 * TODO:
25845 * http://lists.w3.org/Archives/Public/www-xml-schema-comments/2005JulSep/0406.html
25846 * If we have QNames: do we need to ensure there's a
25847 * prefix defined for the QName?
25849 xmlNewNsProp(defAttrOwnerElem, ns, iattr->localName, value);
25851 if (normValue != NULL)
25852 xmlFree(normValue);
25855 * Go directly to IDC evaluation.
25857 goto eval_idcs;
25860 * Validate the value.
25862 if (vctxt->value != NULL) {
25864 * Free last computed value; just for safety reasons.
25866 xmlSchemaFreeValue(vctxt->value);
25867 vctxt->value = NULL;
25870 * Note that the attribute *use* can be unavailable, if
25871 * the attribute was a wild attribute.
25873 if ((iattr->decl->flags & XML_SCHEMAS_ATTR_FIXED) ||
25874 ((iattr->use != NULL) &&
25875 (iattr->use->flags & XML_SCHEMAS_ATTR_FIXED)))
25876 fixed = 1;
25877 else
25878 fixed = 0;
25880 * SPEC (cvc-attribute)
25881 * (3) "The item's `normalized value` must be locally `valid`
25882 * with respect to that {type definition} as per
25883 * String Valid ($3.14.4)."
25885 * VAL TODO: Do we already have the
25886 * "normalized attribute value" here?
25888 if (xpathRes || fixed) {
25889 iattr->flags |= XML_SCHEMA_NODE_INFO_VALUE_NEEDED;
25891 * Request a computed value.
25893 res = xmlSchemaVCheckCVCSimpleType(
25894 ACTXT_CAST vctxt,
25895 iattr->node, iattr->typeDef, iattr->value, &(iattr->val),
25896 1, 1, 0);
25897 } else {
25898 res = xmlSchemaVCheckCVCSimpleType(
25899 ACTXT_CAST vctxt,
25900 iattr->node, iattr->typeDef, iattr->value, NULL,
25901 1, 0, 0);
25904 if (res != 0) {
25905 if (res == -1) {
25906 VERROR_INT("xmlSchemaVAttributesComplex",
25907 "calling xmlSchemaStreamValidateSimpleTypeValue()");
25908 goto internal_error;
25910 iattr->state = XML_SCHEMAS_ATTR_INVALID_VALUE;
25912 * SPEC PSVI Assessment Outcome (Attribute)
25913 * [validity] = "invalid"
25915 goto eval_idcs;
25918 if (fixed) {
25920 * SPEC Attribute Locally Valid (Use) (cvc-au)
25921 * "For an attribute information item to be `valid`
25922 * with respect to an attribute use its *normalized*
25923 * value must match the *canonical* lexical
25924 * representation of the attribute use's {value
25925 * constraint}value, if it is present and fixed."
25927 * VAL TODO: The requirement for the *canonical* value
25928 * will be removed in XML Schema 1.1.
25931 * SPEC Attribute Locally Valid (cvc-attribute)
25932 * (4) "The item's *actual* value must match the *value* of
25933 * the {value constraint}, if it is present and fixed."
25935 if (iattr->val == NULL) {
25936 /* VAL TODO: A value was not precomputed. */
25937 TODO
25938 goto eval_idcs;
25940 if ((iattr->use != NULL) &&
25941 (iattr->use->defValue != NULL)) {
25942 if (iattr->use->defVal == NULL) {
25943 /* VAL TODO: A default value was not precomputed. */
25944 TODO
25945 goto eval_idcs;
25947 iattr->vcValue = iattr->use->defValue;
25949 if (xmlSchemaCompareValuesWhtsp(attr->val,
25950 (xmlSchemaWhitespaceValueType) ws,
25951 attr->use->defVal,
25952 (xmlSchemaWhitespaceValueType) ws) != 0) {
25954 if (! xmlSchemaAreValuesEqual(iattr->val, iattr->use->defVal))
25955 iattr->state = XML_SCHEMAS_ATTR_ERR_FIXED_VALUE;
25956 } else {
25957 if (iattr->decl->defVal == NULL) {
25958 /* VAL TODO: A default value was not precomputed. */
25959 TODO
25960 goto eval_idcs;
25962 iattr->vcValue = iattr->decl->defValue;
25964 if (xmlSchemaCompareValuesWhtsp(attr->val,
25965 (xmlSchemaWhitespaceValueType) ws,
25966 attrDecl->defVal,
25967 (xmlSchemaWhitespaceValueType) ws) != 0) {
25969 if (! xmlSchemaAreValuesEqual(iattr->val, iattr->decl->defVal))
25970 iattr->state = XML_SCHEMAS_ATTR_ERR_FIXED_VALUE;
25973 * [validity] = "valid"
25976 eval_idcs:
25978 * Evaluate IDCs.
25980 if (xpathRes) {
25981 if (xmlSchemaXPathProcessHistory(vctxt,
25982 vctxt->depth +1) == -1) {
25983 VERROR_INT("xmlSchemaVAttributesComplex",
25984 "calling xmlSchemaXPathEvaluate()");
25985 goto internal_error;
25987 } else if (vctxt->xpathStates != NULL)
25988 xmlSchemaXPathPop(vctxt);
25992 * Report errors.
25994 for (i = 0; i < vctxt->nbAttrInfos; i++) {
25995 iattr = vctxt->attrInfos[i];
25996 if ((iattr->state == XML_SCHEMAS_ATTR_META) ||
25997 (iattr->state == XML_SCHEMAS_ATTR_ASSESSED) ||
25998 (iattr->state == XML_SCHEMAS_ATTR_WILD_SKIP) ||
25999 (iattr->state == XML_SCHEMAS_ATTR_WILD_LAX_NO_DECL))
26000 continue;
26001 ACTIVATE_ATTRIBUTE(iattr);
26002 switch (iattr->state) {
26003 case XML_SCHEMAS_ATTR_ERR_MISSING: {
26004 xmlChar *str = NULL;
26005 ACTIVATE_ELEM;
26006 xmlSchemaCustomErr(ACTXT_CAST vctxt,
26007 XML_SCHEMAV_CVC_COMPLEX_TYPE_4, NULL, NULL,
26008 "The attribute '%s' is required but missing",
26009 xmlSchemaFormatQName(&str,
26010 iattr->decl->targetNamespace,
26011 iattr->decl->name),
26012 NULL);
26013 FREE_AND_NULL(str)
26014 break;
26016 case XML_SCHEMAS_ATTR_ERR_NO_TYPE:
26017 VERROR(XML_SCHEMAV_CVC_ATTRIBUTE_2, NULL,
26018 "The type definition is absent");
26019 break;
26020 case XML_SCHEMAS_ATTR_ERR_FIXED_VALUE:
26021 xmlSchemaCustomErr(ACTXT_CAST vctxt,
26022 XML_SCHEMAV_CVC_AU, NULL, NULL,
26023 "The value '%s' does not match the fixed "
26024 "value constraint '%s'",
26025 iattr->value, iattr->vcValue);
26026 break;
26027 case XML_SCHEMAS_ATTR_ERR_WILD_STRICT_NO_DECL:
26028 VERROR(XML_SCHEMAV_CVC_WILDCARD, NULL,
26029 "No matching global attribute declaration available, but "
26030 "demanded by the strict wildcard");
26031 break;
26032 case XML_SCHEMAS_ATTR_UNKNOWN:
26033 if (iattr->metaType)
26034 break;
26036 * MAYBE VAL TODO: One might report different error messages
26037 * for the following errors.
26039 if (type->attributeWildcard == NULL) {
26040 xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt,
26041 XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_1, iattr, NULL);
26042 } else {
26043 xmlSchemaIllegalAttrErr(ACTXT_CAST vctxt,
26044 XML_SCHEMAV_CVC_COMPLEX_TYPE_3_2_2, iattr, NULL);
26046 break;
26047 default:
26048 break;
26052 ACTIVATE_ELEM;
26053 return (0);
26054 internal_error:
26055 ACTIVATE_ELEM;
26056 return (-1);
26059 static int
26060 xmlSchemaValidateElemWildcard(xmlSchemaValidCtxtPtr vctxt,
26061 int *skip)
26063 xmlSchemaWildcardPtr wild = (xmlSchemaWildcardPtr) vctxt->inode->decl;
26065 * The namespace of the element was already identified to be
26066 * matching the wildcard.
26068 if ((skip == NULL) || (wild == NULL) ||
26069 (wild->type != XML_SCHEMA_TYPE_ANY)) {
26070 VERROR_INT("xmlSchemaValidateElemWildcard",
26071 "bad arguments");
26072 return (-1);
26074 *skip = 0;
26075 if (wild->processContents == XML_SCHEMAS_ANY_SKIP) {
26077 * URGENT VAL TODO: Either we need to position the stream to the
26078 * next sibling, or walk the whole subtree.
26080 *skip = 1;
26081 return (0);
26084 xmlSchemaElementPtr decl = NULL;
26086 decl = xmlSchemaGetElem(vctxt->schema,
26087 vctxt->inode->localName, vctxt->inode->nsName);
26088 if (decl != NULL) {
26089 vctxt->inode->decl = decl;
26090 return (0);
26093 if (wild->processContents == XML_SCHEMAS_ANY_STRICT) {
26094 /* VAL TODO: Change to proper error code. */
26095 VERROR(XML_SCHEMAV_CVC_ELT_1, NULL, /* WXS_BASIC_CAST wild */
26096 "No matching global element declaration available, but "
26097 "demanded by the strict wildcard");
26098 return (vctxt->err);
26100 if (vctxt->nbAttrInfos != 0) {
26101 xmlSchemaAttrInfoPtr iattr;
26103 * SPEC Validation Rule: Schema-Validity Assessment (Element)
26104 * (1.2.1.2.1) - (1.2.1.2.3 )
26106 * Use the xsi:type attribute for the type definition.
26108 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
26109 XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
26110 if (iattr != NULL) {
26111 if (xmlSchemaProcessXSIType(vctxt, iattr,
26112 &(vctxt->inode->typeDef), NULL) == -1) {
26113 VERROR_INT("xmlSchemaValidateElemWildcard",
26114 "calling xmlSchemaProcessXSIType() to "
26115 "process the attribute 'xsi:nil'");
26116 return (-1);
26119 * Don't return an error on purpose.
26121 return (0);
26125 * SPEC Validation Rule: Schema-Validity Assessment (Element)
26127 * Fallback to "anyType".
26129 vctxt->inode->typeDef =
26130 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
26131 return (0);
26135 * xmlSchemaCheckCOSValidDefault:
26137 * This will be called if: not nilled, no content and a default/fixed
26138 * value is provided.
26141 static int
26142 xmlSchemaCheckCOSValidDefault(xmlSchemaValidCtxtPtr vctxt,
26143 const xmlChar *value,
26144 xmlSchemaValPtr *val)
26146 int ret = 0;
26147 xmlSchemaNodeInfoPtr inode = vctxt->inode;
26150 * cos-valid-default:
26151 * Schema Component Constraint: Element Default Valid (Immediate)
26152 * For a string to be a valid default with respect to a type
26153 * definition the appropriate case among the following must be true:
26155 if WXS_IS_COMPLEX(inode->typeDef) {
26157 * Complex type.
26159 * SPEC (2.1) "its {content type} must be a simple type definition
26160 * or mixed."
26161 * SPEC (2.2.2) "If the {content type} is mixed, then the {content
26162 * type}'s particle must be `emptiable` as defined by
26163 * Particle Emptiable ($3.9.6)."
26165 if ((! WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) &&
26166 ((! WXS_HAS_MIXED_CONTENT(inode->typeDef)) ||
26167 (! WXS_EMPTIABLE(inode->typeDef)))) {
26168 ret = XML_SCHEMAP_COS_VALID_DEFAULT_2_1;
26169 /* NOTE that this covers (2.2.2) as well. */
26170 VERROR(ret, NULL,
26171 "For a string to be a valid default, the type definition "
26172 "must be a simple type or a complex type with simple content "
26173 "or mixed content and a particle emptiable");
26174 return(ret);
26178 * 1 If the type definition is a simple type definition, then the string
26179 * must be `valid` with respect to that definition as defined by String
26180 * Valid ($3.14.4).
26182 * AND
26184 * 2.2.1 If the {content type} is a simple type definition, then the
26185 * string must be `valid` with respect to that simple type definition
26186 * as defined by String Valid ($3.14.4).
26188 if (WXS_IS_SIMPLE(inode->typeDef)) {
26190 ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST vctxt,
26191 NULL, inode->typeDef, value, val, 1, 1, 0);
26193 } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
26195 ret = xmlSchemaVCheckCVCSimpleType(ACTXT_CAST vctxt,
26196 NULL, inode->typeDef->contentTypeDef, value, val, 1, 1, 0);
26198 if (ret < 0) {
26199 VERROR_INT("xmlSchemaCheckCOSValidDefault",
26200 "calling xmlSchemaVCheckCVCSimpleType()");
26202 return (ret);
26205 static void
26206 xmlSchemaVContentModelCallback(xmlRegExecCtxtPtr exec ATTRIBUTE_UNUSED,
26207 const xmlChar * name ATTRIBUTE_UNUSED,
26208 void *transdata, void *inputdata)
26210 xmlSchemaElementPtr item = (xmlSchemaElementPtr) transdata;
26211 xmlSchemaNodeInfoPtr inode = (xmlSchemaNodeInfoPtr) inputdata;
26212 inode->decl = item;
26213 #ifdef DEBUG_CONTENT
26215 xmlChar *str = NULL;
26217 if (item->type == XML_SCHEMA_TYPE_ELEMENT) {
26218 xmlGenericError(xmlGenericErrorContext,
26219 "AUTOMATON callback for '%s' [declaration]\n",
26220 xmlSchemaFormatQName(&str,
26221 inode->localName, inode->nsName));
26222 } else {
26223 xmlGenericError(xmlGenericErrorContext,
26224 "AUTOMATON callback for '%s' [wildcard]\n",
26225 xmlSchemaFormatQName(&str,
26226 inode->localName, inode->nsName));
26229 FREE_AND_NULL(str)
26231 #endif
26234 static int
26235 xmlSchemaValidatorPushElem(xmlSchemaValidCtxtPtr vctxt)
26237 vctxt->inode = xmlSchemaGetFreshElemInfo(vctxt);
26238 if (vctxt->inode == NULL) {
26239 VERROR_INT("xmlSchemaValidatorPushElem",
26240 "calling xmlSchemaGetFreshElemInfo()");
26241 return (-1);
26243 vctxt->nbAttrInfos = 0;
26244 return (0);
26247 static int
26248 xmlSchemaVCheckINodeDataType(xmlSchemaValidCtxtPtr vctxt,
26249 xmlSchemaNodeInfoPtr inode,
26250 xmlSchemaTypePtr type,
26251 const xmlChar *value)
26253 if (inode->flags & XML_SCHEMA_NODE_INFO_VALUE_NEEDED)
26254 return (xmlSchemaVCheckCVCSimpleType(
26255 ACTXT_CAST vctxt, NULL,
26256 type, value, &(inode->val), 1, 1, 0));
26257 else
26258 return (xmlSchemaVCheckCVCSimpleType(
26259 ACTXT_CAST vctxt, NULL,
26260 type, value, NULL, 1, 0, 0));
26266 * Process END of element.
26268 static int
26269 xmlSchemaValidatorPopElem(xmlSchemaValidCtxtPtr vctxt)
26271 int ret = 0;
26272 xmlSchemaNodeInfoPtr inode = vctxt->inode;
26274 if (vctxt->nbAttrInfos != 0)
26275 xmlSchemaClearAttrInfos(vctxt);
26276 if (inode->flags & XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED) {
26278 * This element was not expected;
26279 * we will not validate child elements of broken parents.
26280 * Skip validation of all content of the parent.
26282 vctxt->skipDepth = vctxt->depth -1;
26283 goto end_elem;
26285 if ((inode->typeDef == NULL) ||
26286 (inode->flags & XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE)) {
26288 * 1. the type definition might be missing if the element was
26289 * error prone
26290 * 2. it might be abstract.
26292 goto end_elem;
26295 * Check the content model.
26297 if ((inode->typeDef->contentType == XML_SCHEMA_CONTENT_MIXED) ||
26298 (inode->typeDef->contentType == XML_SCHEMA_CONTENT_ELEMENTS)) {
26301 * Workaround for "anyType".
26303 if (inode->typeDef->builtInType == XML_SCHEMAS_ANYTYPE)
26304 goto character_content;
26306 if ((inode->flags & XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT) == 0) {
26307 xmlChar *values[10];
26308 int terminal, nbval = 10, nbneg;
26310 if (inode->regexCtxt == NULL) {
26312 * Create the regex context.
26314 inode->regexCtxt =
26315 xmlRegNewExecCtxt(inode->typeDef->contModel,
26316 xmlSchemaVContentModelCallback, vctxt);
26317 if (inode->regexCtxt == NULL) {
26318 VERROR_INT("xmlSchemaValidatorPopElem",
26319 "failed to create a regex context");
26320 goto internal_error;
26322 #ifdef DEBUG_AUTOMATA
26323 xmlGenericError(xmlGenericErrorContext,
26324 "AUTOMATON create on '%s'\n", inode->localName);
26325 #endif
26329 * Do not check further content if the node has been nilled
26331 if (INODE_NILLED(inode)) {
26332 ret = 0;
26333 #ifdef DEBUG_AUTOMATA
26334 xmlGenericError(xmlGenericErrorContext,
26335 "AUTOMATON succeeded on nilled '%s'\n",
26336 inode->localName);
26337 #endif
26338 goto skip_nilled;
26342 * Get hold of the still expected content, since a further
26343 * call to xmlRegExecPushString() will lose this information.
26345 xmlRegExecNextValues(inode->regexCtxt,
26346 &nbval, &nbneg, &values[0], &terminal);
26347 ret = xmlRegExecPushString(inode->regexCtxt, NULL, NULL);
26348 if ((ret<0) || ((ret==0) && (!INODE_NILLED(inode)))) {
26350 * Still missing something.
26352 ret = 1;
26353 inode->flags |=
26354 XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT;
26355 xmlSchemaComplexTypeErr(ACTXT_CAST vctxt,
26356 XML_SCHEMAV_ELEMENT_CONTENT, NULL, NULL,
26357 "Missing child element(s)",
26358 nbval, nbneg, values);
26359 #ifdef DEBUG_AUTOMATA
26360 xmlGenericError(xmlGenericErrorContext,
26361 "AUTOMATON missing ERROR on '%s'\n",
26362 inode->localName);
26363 #endif
26364 } else {
26366 * Content model is satisfied.
26368 ret = 0;
26369 #ifdef DEBUG_AUTOMATA
26370 xmlGenericError(xmlGenericErrorContext,
26371 "AUTOMATON succeeded on '%s'\n",
26372 inode->localName);
26373 #endif
26379 skip_nilled:
26381 if (inode->typeDef->contentType == XML_SCHEMA_CONTENT_ELEMENTS)
26382 goto end_elem;
26384 character_content:
26386 if (vctxt->value != NULL) {
26387 xmlSchemaFreeValue(vctxt->value);
26388 vctxt->value = NULL;
26391 * Check character content.
26393 if (inode->decl == NULL) {
26395 * Speedup if no declaration exists.
26397 if (WXS_IS_SIMPLE(inode->typeDef)) {
26398 ret = xmlSchemaVCheckINodeDataType(vctxt,
26399 inode, inode->typeDef, inode->value);
26400 } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
26401 ret = xmlSchemaVCheckINodeDataType(vctxt,
26402 inode, inode->typeDef->contentTypeDef,
26403 inode->value);
26405 if (ret < 0) {
26406 VERROR_INT("xmlSchemaValidatorPopElem",
26407 "calling xmlSchemaVCheckCVCSimpleType()");
26408 goto internal_error;
26410 goto end_elem;
26413 * cvc-elt (3.3.4) : 5
26414 * The appropriate case among the following must be true:
26417 * cvc-elt (3.3.4) : 5.1
26418 * If the declaration has a {value constraint},
26419 * the item has neither element nor character [children] and
26420 * clause 3.2 has not applied, then all of the following must be true:
26422 if ((inode->decl->value != NULL) &&
26423 (inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY) &&
26424 (! INODE_NILLED(inode))) {
26426 * cvc-elt (3.3.4) : 5.1.1
26427 * If the `actual type definition` is a `local type definition`
26428 * then the canonical lexical representation of the {value constraint}
26429 * value must be a valid default for the `actual type definition` as
26430 * defined in Element Default Valid (Immediate) ($3.3.6).
26433 * NOTE: 'local' above means types acquired by xsi:type.
26434 * NOTE: Although the *canonical* value is stated, it is not
26435 * relevant if canonical or not. Additionally XML Schema 1.1
26436 * will removed this requirement as well.
26438 if (inode->flags & XML_SCHEMA_ELEM_INFO_LOCAL_TYPE) {
26440 ret = xmlSchemaCheckCOSValidDefault(vctxt,
26441 inode->decl->value, &(inode->val));
26442 if (ret != 0) {
26443 if (ret < 0) {
26444 VERROR_INT("xmlSchemaValidatorPopElem",
26445 "calling xmlSchemaCheckCOSValidDefault()");
26446 goto internal_error;
26448 goto end_elem;
26451 * Stop here, to avoid redundant validation of the value
26452 * (see following).
26454 goto default_psvi;
26457 * cvc-elt (3.3.4) : 5.1.2
26458 * The element information item with the canonical lexical
26459 * representation of the {value constraint} value used as its
26460 * `normalized value` must be `valid` with respect to the
26461 * `actual type definition` as defined by Element Locally Valid (Type)
26462 * ($3.3.4).
26464 if (WXS_IS_SIMPLE(inode->typeDef)) {
26465 ret = xmlSchemaVCheckINodeDataType(vctxt,
26466 inode, inode->typeDef, inode->decl->value);
26467 } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
26468 ret = xmlSchemaVCheckINodeDataType(vctxt,
26469 inode, inode->typeDef->contentTypeDef,
26470 inode->decl->value);
26472 if (ret != 0) {
26473 if (ret < 0) {
26474 VERROR_INT("xmlSchemaValidatorPopElem",
26475 "calling xmlSchemaVCheckCVCSimpleType()");
26476 goto internal_error;
26478 goto end_elem;
26481 default_psvi:
26483 * PSVI: Create a text node on the instance element.
26485 if ((vctxt->options & XML_SCHEMA_VAL_VC_I_CREATE) &&
26486 (inode->node != NULL)) {
26487 xmlNodePtr textChild;
26488 xmlChar *normValue;
26490 * VAL TODO: Normalize the value.
26492 normValue = xmlSchemaNormalizeValue(inode->typeDef,
26493 inode->decl->value);
26494 if (normValue != NULL) {
26495 textChild = xmlNewDocText(inode->node->doc,
26496 BAD_CAST normValue);
26497 xmlFree(normValue);
26498 } else
26499 textChild = xmlNewDocText(inode->node->doc,
26500 inode->decl->value);
26501 if (textChild == NULL) {
26502 VERROR_INT("xmlSchemaValidatorPopElem",
26503 "calling xmlNewDocText()");
26504 goto internal_error;
26505 } else
26506 xmlAddChild(inode->node, textChild);
26509 } else if (! INODE_NILLED(inode)) {
26511 * 5.2.1 The element information item must be `valid` with respect
26512 * to the `actual type definition` as defined by Element Locally
26513 * Valid (Type) ($3.3.4).
26515 if (WXS_IS_SIMPLE(inode->typeDef)) {
26517 * SPEC (cvc-type) (3.1)
26518 * "If the type definition is a simple type definition, ..."
26519 * (3.1.3) "If clause 3.2 of Element Locally Valid
26520 * (Element) ($3.3.4) did not apply, then the `normalized value`
26521 * must be `valid` with respect to the type definition as defined
26522 * by String Valid ($3.14.4).
26524 ret = xmlSchemaVCheckINodeDataType(vctxt,
26525 inode, inode->typeDef, inode->value);
26526 } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
26528 * SPEC (cvc-type) (3.2) "If the type definition is a complex type
26529 * definition, then the element information item must be
26530 * `valid` with respect to the type definition as per
26531 * Element Locally Valid (Complex Type) ($3.4.4);"
26533 * SPEC (cvc-complex-type) (2.2)
26534 * "If the {content type} is a simple type definition, ...
26535 * the `normalized value` of the element information item is
26536 * `valid` with respect to that simple type definition as
26537 * defined by String Valid ($3.14.4)."
26539 ret = xmlSchemaVCheckINodeDataType(vctxt,
26540 inode, inode->typeDef->contentTypeDef, inode->value);
26542 if (ret != 0) {
26543 if (ret < 0) {
26544 VERROR_INT("xmlSchemaValidatorPopElem",
26545 "calling xmlSchemaVCheckCVCSimpleType()");
26546 goto internal_error;
26548 goto end_elem;
26551 * 5.2.2 If there is a fixed {value constraint} and clause 3.2 has
26552 * not applied, all of the following must be true:
26554 if ((inode->decl->value != NULL) &&
26555 (inode->decl->flags & XML_SCHEMAS_ELEM_FIXED)) {
26558 * TODO: We will need a computed value, when comparison is
26559 * done on computed values.
26562 * 5.2.2.1 The element information item must have no element
26563 * information item [children].
26565 if (inode->flags &
26566 XML_SCHEMA_ELEM_INFO_HAS_ELEM_CONTENT) {
26567 ret = XML_SCHEMAV_CVC_ELT_5_2_2_1;
26568 VERROR(ret, NULL,
26569 "The content must not contain element nodes since "
26570 "there is a fixed value constraint");
26571 goto end_elem;
26572 } else {
26574 * 5.2.2.2 The appropriate case among the following must
26575 * be true:
26577 if (WXS_HAS_MIXED_CONTENT(inode->typeDef)) {
26579 * 5.2.2.2.1 If the {content type} of the `actual type
26580 * definition` is mixed, then the *initial value* of the
26581 * item must match the canonical lexical representation
26582 * of the {value constraint} value.
26584 * ... the *initial value* of an element information
26585 * item is the string composed of, in order, the
26586 * [character code] of each character information item in
26587 * the [children] of that element information item.
26589 if (! xmlStrEqual(inode->value, inode->decl->value)){
26591 * VAL TODO: Report invalid & expected values as well.
26592 * VAL TODO: Implement the canonical stuff.
26594 ret = XML_SCHEMAV_CVC_ELT_5_2_2_2_1;
26595 xmlSchemaCustomErr(ACTXT_CAST vctxt,
26596 ret, NULL, NULL,
26597 "The initial value '%s' does not match the fixed "
26598 "value constraint '%s'",
26599 inode->value, inode->decl->value);
26600 goto end_elem;
26602 } else if (WXS_HAS_SIMPLE_CONTENT(inode->typeDef)) {
26604 * 5.2.2.2.2 If the {content type} of the `actual type
26605 * definition` is a simple type definition, then the
26606 * *actual value* of the item must match the canonical
26607 * lexical representation of the {value constraint} value.
26610 * VAL TODO: *actual value* is the normalized value, impl.
26611 * this.
26612 * VAL TODO: Report invalid & expected values as well.
26613 * VAL TODO: Implement a comparison with the computed values.
26615 if (! xmlStrEqual(inode->value,
26616 inode->decl->value)) {
26617 ret = XML_SCHEMAV_CVC_ELT_5_2_2_2_2;
26618 xmlSchemaCustomErr(ACTXT_CAST vctxt,
26619 ret, NULL, NULL,
26620 "The actual value '%s' does not match the fixed "
26621 "value constraint '%s'",
26622 inode->value,
26623 inode->decl->value);
26624 goto end_elem;
26631 end_elem:
26632 if (vctxt->depth < 0) {
26633 /* TODO: raise error? */
26634 return (0);
26636 if (vctxt->depth == vctxt->skipDepth)
26637 vctxt->skipDepth = -1;
26639 * Evaluate the history of XPath state objects.
26641 if (inode->appliedXPath &&
26642 (xmlSchemaXPathProcessHistory(vctxt, vctxt->depth) == -1))
26643 goto internal_error;
26645 * MAYBE TODO:
26646 * SPEC (6) "The element information item must be `valid` with
26647 * respect to each of the {identity-constraint definitions} as per
26648 * Identity-constraint Satisfied ($3.11.4)."
26651 * PSVI TODO: If we expose IDC node-tables via PSVI then the tables
26652 * need to be built in any case.
26653 * We will currently build IDC node-tables and bubble them only if
26654 * keyrefs do exist.
26658 * Add the current IDC target-nodes to the IDC node-tables.
26660 if ((inode->idcMatchers != NULL) &&
26661 (vctxt->hasKeyrefs || vctxt->createIDCNodeTables))
26663 if (xmlSchemaIDCFillNodeTables(vctxt, inode) == -1)
26664 goto internal_error;
26667 * Validate IDC keyrefs.
26669 if (vctxt->inode->hasKeyrefs)
26670 if (xmlSchemaCheckCVCIDCKeyRef(vctxt) == -1)
26671 goto internal_error;
26673 * Merge/free the IDC table.
26675 if (inode->idcTable != NULL) {
26676 #ifdef DEBUG_IDC_NODE_TABLE
26677 xmlSchemaDebugDumpIDCTable(stdout,
26678 inode->nsName,
26679 inode->localName,
26680 inode->idcTable);
26681 #endif
26682 if ((vctxt->depth > 0) &&
26683 (vctxt->hasKeyrefs || vctxt->createIDCNodeTables))
26686 * Merge the IDC node table with the table of the parent node.
26688 if (xmlSchemaBubbleIDCNodeTables(vctxt) == -1)
26689 goto internal_error;
26693 * Clear the current ielem.
26694 * VAL TODO: Don't free the PSVI IDC tables if they are
26695 * requested for the PSVI.
26697 xmlSchemaClearElemInfo(vctxt, inode);
26699 * Skip further processing if we are on the validation root.
26701 if (vctxt->depth == 0) {
26702 vctxt->depth--;
26703 vctxt->inode = NULL;
26704 return (0);
26707 * Reset the keyrefDepth if needed.
26709 if (vctxt->aidcs != NULL) {
26710 xmlSchemaIDCAugPtr aidc = vctxt->aidcs;
26711 do {
26712 if (aidc->keyrefDepth == vctxt->depth) {
26714 * A 'keyrefDepth' of a key/unique IDC matches the current
26715 * depth, this means that we are leaving the scope of the
26716 * top-most keyref IDC which refers to this IDC.
26718 aidc->keyrefDepth = -1;
26720 aidc = aidc->next;
26721 } while (aidc != NULL);
26723 vctxt->depth--;
26724 vctxt->inode = vctxt->elemInfos[vctxt->depth];
26726 * VAL TODO: 7 If the element information item is the `validation root`, it must be
26727 * `valid` per Validation Root Valid (ID/IDREF) ($3.3.4).
26729 return (ret);
26731 internal_error:
26732 vctxt->err = -1;
26733 return (-1);
26737 * 3.4.4 Complex Type Definition Validation Rules
26738 * Validation Rule: Element Locally Valid (Complex Type) (cvc-complex-type)
26740 static int
26741 xmlSchemaValidateChildElem(xmlSchemaValidCtxtPtr vctxt)
26743 xmlSchemaNodeInfoPtr pielem;
26744 xmlSchemaTypePtr ptype;
26745 int ret = 0;
26747 if (vctxt->depth <= 0) {
26748 VERROR_INT("xmlSchemaValidateChildElem",
26749 "not intended for the validation root");
26750 return (-1);
26752 pielem = vctxt->elemInfos[vctxt->depth -1];
26753 if (pielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
26754 pielem->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
26756 * Handle 'nilled' elements.
26758 if (INODE_NILLED(pielem)) {
26760 * SPEC (cvc-elt) (3.3.4) : (3.2.1)
26762 ACTIVATE_PARENT_ELEM;
26763 ret = XML_SCHEMAV_CVC_ELT_3_2_1;
26764 VERROR(ret, NULL,
26765 "Neither character nor element content is allowed, "
26766 "because the element was 'nilled'");
26767 ACTIVATE_ELEM;
26768 goto unexpected_elem;
26771 ptype = pielem->typeDef;
26773 if (ptype->builtInType == XML_SCHEMAS_ANYTYPE) {
26775 * Workaround for "anyType": we have currently no content model
26776 * assigned for "anyType", so handle it explicitly.
26777 * "anyType" has an unbounded, lax "any" wildcard.
26779 vctxt->inode->decl = xmlSchemaGetElem(vctxt->schema,
26780 vctxt->inode->localName,
26781 vctxt->inode->nsName);
26783 if (vctxt->inode->decl == NULL) {
26784 xmlSchemaAttrInfoPtr iattr;
26786 * Process "xsi:type".
26787 * SPEC (cvc-assess-elt) (1.2.1.2.1) - (1.2.1.2.3)
26789 iattr = xmlSchemaGetMetaAttrInfo(vctxt,
26790 XML_SCHEMA_ATTR_INFO_META_XSI_TYPE);
26791 if (iattr != NULL) {
26792 ret = xmlSchemaProcessXSIType(vctxt, iattr,
26793 &(vctxt->inode->typeDef), NULL);
26794 if (ret != 0) {
26795 if (ret == -1) {
26796 VERROR_INT("xmlSchemaValidateChildElem",
26797 "calling xmlSchemaProcessXSIType() to "
26798 "process the attribute 'xsi:nil'");
26799 return (-1);
26801 return (ret);
26803 } else {
26805 * Fallback to "anyType".
26807 * SPEC (cvc-assess-elt)
26808 * "If the item cannot be `strictly assessed`, [...]
26809 * an element information item's schema validity may be laxly
26810 * assessed if its `context-determined declaration` is not
26811 * skip by `validating` with respect to the `ur-type
26812 * definition` as per Element Locally Valid (Type) ($3.3.4)."
26814 vctxt->inode->typeDef =
26815 xmlSchemaGetBuiltInType(XML_SCHEMAS_ANYTYPE);
26818 return (0);
26821 switch (ptype->contentType) {
26822 case XML_SCHEMA_CONTENT_EMPTY:
26824 * SPEC (2.1) "If the {content type} is empty, then the
26825 * element information item has no character or element
26826 * information item [children]."
26828 ACTIVATE_PARENT_ELEM
26829 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1;
26830 VERROR(ret, NULL,
26831 "Element content is not allowed, "
26832 "because the content type is empty");
26833 ACTIVATE_ELEM
26834 goto unexpected_elem;
26835 break;
26837 case XML_SCHEMA_CONTENT_MIXED:
26838 case XML_SCHEMA_CONTENT_ELEMENTS: {
26839 xmlRegExecCtxtPtr regexCtxt;
26840 xmlChar *values[10];
26841 int terminal, nbval = 10, nbneg;
26843 /* VAL TODO: Optimized "anyType" validation.*/
26845 if (ptype->contModel == NULL) {
26846 VERROR_INT("xmlSchemaValidateChildElem",
26847 "type has elem content but no content model");
26848 return (-1);
26851 * Safety belt for evaluation if the cont. model was already
26852 * examined to be invalid.
26854 if (pielem->flags & XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT) {
26855 VERROR_INT("xmlSchemaValidateChildElem",
26856 "validating elem, but elem content is already invalid");
26857 return (-1);
26860 regexCtxt = pielem->regexCtxt;
26861 if (regexCtxt == NULL) {
26863 * Create the regex context.
26865 regexCtxt = xmlRegNewExecCtxt(ptype->contModel,
26866 xmlSchemaVContentModelCallback, vctxt);
26867 if (regexCtxt == NULL) {
26868 VERROR_INT("xmlSchemaValidateChildElem",
26869 "failed to create a regex context");
26870 return (-1);
26872 pielem->regexCtxt = regexCtxt;
26873 #ifdef DEBUG_AUTOMATA
26874 xmlGenericError(xmlGenericErrorContext, "AUTOMATA create on '%s'\n",
26875 pielem->localName);
26876 #endif
26880 * SPEC (2.4) "If the {content type} is element-only or mixed,
26881 * then the sequence of the element information item's
26882 * element information item [children], if any, taken in
26883 * order, is `valid` with respect to the {content type}'s
26884 * particle, as defined in Element Sequence Locally Valid
26885 * (Particle) ($3.9.4)."
26887 ret = xmlRegExecPushString2(regexCtxt,
26888 vctxt->inode->localName,
26889 vctxt->inode->nsName,
26890 vctxt->inode);
26891 #ifdef DEBUG_AUTOMATA
26892 if (ret < 0)
26893 xmlGenericError(xmlGenericErrorContext,
26894 "AUTOMATON push ERROR for '%s' on '%s'\n",
26895 vctxt->inode->localName, pielem->localName);
26896 else
26897 xmlGenericError(xmlGenericErrorContext,
26898 "AUTOMATON push OK for '%s' on '%s'\n",
26899 vctxt->inode->localName, pielem->localName);
26900 #endif
26901 if (vctxt->err == XML_SCHEMAV_INTERNAL) {
26902 VERROR_INT("xmlSchemaValidateChildElem",
26903 "calling xmlRegExecPushString2()");
26904 return (-1);
26906 if (ret < 0) {
26907 xmlRegExecErrInfo(regexCtxt, NULL, &nbval, &nbneg,
26908 &values[0], &terminal);
26909 xmlSchemaComplexTypeErr(ACTXT_CAST vctxt,
26910 XML_SCHEMAV_ELEMENT_CONTENT, NULL,NULL,
26911 "This element is not expected",
26912 nbval, nbneg, values);
26913 ret = vctxt->err;
26914 goto unexpected_elem;
26915 } else
26916 ret = 0;
26918 break;
26919 case XML_SCHEMA_CONTENT_SIMPLE:
26920 case XML_SCHEMA_CONTENT_BASIC:
26921 ACTIVATE_PARENT_ELEM
26922 if (WXS_IS_COMPLEX(ptype)) {
26924 * SPEC (cvc-complex-type) (2.2)
26925 * "If the {content type} is a simple type definition, then
26926 * the element information item has no element information
26927 * item [children], ..."
26929 ret = XML_SCHEMAV_CVC_COMPLEX_TYPE_2_2;
26930 VERROR(ret, NULL, "Element content is not allowed, "
26931 "because the content type is a simple type definition");
26932 } else {
26934 * SPEC (cvc-type) (3.1.2) "The element information item must
26935 * have no element information item [children]."
26937 ret = XML_SCHEMAV_CVC_TYPE_3_1_2;
26938 VERROR(ret, NULL, "Element content is not allowed, "
26939 "because the type definition is simple");
26941 ACTIVATE_ELEM
26942 ret = vctxt->err;
26943 goto unexpected_elem;
26944 break;
26946 default:
26947 break;
26949 return (ret);
26950 unexpected_elem:
26952 * Pop this element and set the skipDepth to skip
26953 * all further content of the parent element.
26955 vctxt->skipDepth = vctxt->depth;
26956 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_NOT_EXPECTED;
26957 pielem->flags |= XML_SCHEMA_ELEM_INFO_ERR_BAD_CONTENT;
26958 return (ret);
26961 #define XML_SCHEMA_PUSH_TEXT_PERSIST 1
26962 #define XML_SCHEMA_PUSH_TEXT_CREATED 2
26963 #define XML_SCHEMA_PUSH_TEXT_VOLATILE 3
26965 static int
26966 xmlSchemaVPushText(xmlSchemaValidCtxtPtr vctxt,
26967 int nodeType, const xmlChar *value, int len,
26968 int mode, int *consumed)
26971 * Unfortunately we have to duplicate the text sometimes.
26972 * OPTIMIZE: Maybe we could skip it, if:
26973 * 1. content type is simple
26974 * 2. whitespace is "collapse"
26975 * 3. it consists of whitespace only
26977 * Process character content.
26979 if (consumed != NULL)
26980 *consumed = 0;
26981 if (INODE_NILLED(vctxt->inode)) {
26983 * SPEC cvc-elt (3.3.4 - 3.2.1)
26984 * "The element information item must have no character or
26985 * element information item [children]."
26987 VERROR(XML_SCHEMAV_CVC_ELT_3_2_1, NULL,
26988 "Neither character nor element content is allowed "
26989 "because the element is 'nilled'");
26990 return (vctxt->err);
26993 * SPEC (2.1) "If the {content type} is empty, then the
26994 * element information item has no character or element
26995 * information item [children]."
26997 if (vctxt->inode->typeDef->contentType ==
26998 XML_SCHEMA_CONTENT_EMPTY) {
26999 VERROR(XML_SCHEMAV_CVC_COMPLEX_TYPE_2_1, NULL,
27000 "Character content is not allowed, "
27001 "because the content type is empty");
27002 return (vctxt->err);
27005 if (vctxt->inode->typeDef->contentType ==
27006 XML_SCHEMA_CONTENT_ELEMENTS) {
27007 if ((nodeType != XML_TEXT_NODE) ||
27008 (! xmlSchemaIsBlank((xmlChar *) value, len))) {
27010 * SPEC cvc-complex-type (2.3)
27011 * "If the {content type} is element-only, then the
27012 * element information item has no character information
27013 * item [children] other than those whose [character
27014 * code] is defined as a white space in [XML 1.0 (Second
27015 * Edition)]."
27017 VERROR(XML_SCHEMAV_CVC_COMPLEX_TYPE_2_3, NULL,
27018 "Character content other than whitespace is not allowed "
27019 "because the content type is 'element-only'");
27020 return (vctxt->err);
27022 return (0);
27025 if ((value == NULL) || (value[0] == 0))
27026 return (0);
27028 * Save the value.
27029 * NOTE that even if the content type is *mixed*, we need the
27030 * *initial value* for default/fixed value constraints.
27032 if ((vctxt->inode->typeDef->contentType == XML_SCHEMA_CONTENT_MIXED) &&
27033 ((vctxt->inode->decl == NULL) ||
27034 (vctxt->inode->decl->value == NULL)))
27035 return (0);
27037 if (vctxt->inode->value == NULL) {
27039 * Set the value.
27041 switch (mode) {
27042 case XML_SCHEMA_PUSH_TEXT_PERSIST:
27044 * When working on a tree.
27046 vctxt->inode->value = value;
27047 break;
27048 case XML_SCHEMA_PUSH_TEXT_CREATED:
27050 * When working with the reader.
27051 * The value will be freed by the element info.
27053 vctxt->inode->value = value;
27054 if (consumed != NULL)
27055 *consumed = 1;
27056 vctxt->inode->flags |=
27057 XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
27058 break;
27059 case XML_SCHEMA_PUSH_TEXT_VOLATILE:
27061 * When working with SAX.
27062 * The value will be freed by the element info.
27064 if (len != -1)
27065 vctxt->inode->value = BAD_CAST xmlStrndup(value, len);
27066 else
27067 vctxt->inode->value = BAD_CAST xmlStrdup(value);
27068 vctxt->inode->flags |=
27069 XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
27070 break;
27071 default:
27072 break;
27074 } else {
27075 if (len < 0)
27076 len = xmlStrlen(value);
27078 * Concat the value.
27080 if (vctxt->inode->flags & XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES) {
27081 vctxt->inode->value = BAD_CAST xmlStrncat(
27082 (xmlChar *) vctxt->inode->value, value, len);
27083 } else {
27084 vctxt->inode->value =
27085 BAD_CAST xmlStrncatNew(vctxt->inode->value, value, len);
27086 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_VALUES;
27090 return (0);
27093 static int
27094 xmlSchemaValidateElem(xmlSchemaValidCtxtPtr vctxt)
27096 int ret = 0;
27098 if ((vctxt->skipDepth != -1) &&
27099 (vctxt->depth >= vctxt->skipDepth)) {
27100 VERROR_INT("xmlSchemaValidateElem",
27101 "in skip-state");
27102 goto internal_error;
27104 if (vctxt->xsiAssemble) {
27106 * We will stop validation if there was an error during
27107 * dynamic schema construction.
27108 * Note that we simply set @skipDepth to 0, this could
27109 * mean that a streaming document via SAX would be
27110 * still read to the end but it won't be validated any more.
27111 * TODO: If we are sure how to stop the validation at once
27112 * for all input scenarios, then this should be changed to
27113 * instantly stop the validation.
27115 ret = xmlSchemaAssembleByXSI(vctxt);
27116 if (ret != 0) {
27117 if (ret == -1)
27118 goto internal_error;
27119 vctxt->skipDepth = 0;
27120 return(ret);
27123 * Augment the IDC definitions for the main schema and all imported ones
27124 * NOTE: main schema is the first in the imported list
27126 xmlHashScan(vctxt->schema->schemasImports, xmlSchemaAugmentImportedIDC,
27127 vctxt);
27129 if (vctxt->depth > 0) {
27131 * Validate this element against the content model
27132 * of the parent.
27134 ret = xmlSchemaValidateChildElem(vctxt);
27135 if (ret != 0) {
27136 if (ret < 0) {
27137 VERROR_INT("xmlSchemaValidateElem",
27138 "calling xmlSchemaStreamValidateChildElement()");
27139 goto internal_error;
27141 goto exit;
27143 if (vctxt->depth == vctxt->skipDepth)
27144 goto exit;
27145 if ((vctxt->inode->decl == NULL) &&
27146 (vctxt->inode->typeDef == NULL)) {
27147 VERROR_INT("xmlSchemaValidateElem",
27148 "the child element was valid but neither the "
27149 "declaration nor the type was set");
27150 goto internal_error;
27152 } else {
27154 * Get the declaration of the validation root.
27156 vctxt->inode->decl = xmlSchemaGetElem(vctxt->schema,
27157 vctxt->inode->localName,
27158 vctxt->inode->nsName);
27159 if (vctxt->inode->decl == NULL) {
27160 ret = XML_SCHEMAV_CVC_ELT_1;
27161 VERROR(ret, NULL,
27162 "No matching global declaration available "
27163 "for the validation root");
27164 goto exit;
27168 if (vctxt->inode->decl == NULL)
27169 goto type_validation;
27171 if (vctxt->inode->decl->type == XML_SCHEMA_TYPE_ANY) {
27172 int skip;
27174 * Wildcards.
27176 ret = xmlSchemaValidateElemWildcard(vctxt, &skip);
27177 if (ret != 0) {
27178 if (ret < 0) {
27179 VERROR_INT("xmlSchemaValidateElem",
27180 "calling xmlSchemaValidateElemWildcard()");
27181 goto internal_error;
27183 goto exit;
27185 if (skip) {
27186 vctxt->skipDepth = vctxt->depth;
27187 goto exit;
27190 * The declaration might be set by the wildcard validation,
27191 * when the processContents is "lax" or "strict".
27193 if (vctxt->inode->decl->type != XML_SCHEMA_TYPE_ELEMENT) {
27195 * Clear the "decl" field to not confuse further processing.
27197 vctxt->inode->decl = NULL;
27198 goto type_validation;
27202 * Validate against the declaration.
27204 ret = xmlSchemaValidateElemDecl(vctxt);
27205 if (ret != 0) {
27206 if (ret < 0) {
27207 VERROR_INT("xmlSchemaValidateElem",
27208 "calling xmlSchemaValidateElemDecl()");
27209 goto internal_error;
27211 goto exit;
27214 * Validate against the type definition.
27216 type_validation:
27218 if (vctxt->inode->typeDef == NULL) {
27219 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE;
27220 ret = XML_SCHEMAV_CVC_TYPE_1;
27221 VERROR(ret, NULL,
27222 "The type definition is absent");
27223 goto exit;
27225 if (vctxt->inode->typeDef->flags & XML_SCHEMAS_TYPE_ABSTRACT) {
27226 vctxt->inode->flags |= XML_SCHEMA_NODE_INFO_ERR_BAD_TYPE;
27227 ret = XML_SCHEMAV_CVC_TYPE_2;
27228 VERROR(ret, NULL,
27229 "The type definition is abstract");
27230 goto exit;
27233 * Evaluate IDCs. Do it here, since new IDC matchers are registered
27234 * during validation against the declaration. This must be done
27235 * _before_ attribute validation.
27237 if (vctxt->xpathStates != NULL) {
27238 ret = xmlSchemaXPathEvaluate(vctxt, XML_ELEMENT_NODE);
27239 vctxt->inode->appliedXPath = 1;
27240 if (ret == -1) {
27241 VERROR_INT("xmlSchemaValidateElem",
27242 "calling xmlSchemaXPathEvaluate()");
27243 goto internal_error;
27247 * Validate attributes.
27249 if (WXS_IS_COMPLEX(vctxt->inode->typeDef)) {
27250 if ((vctxt->nbAttrInfos != 0) ||
27251 (vctxt->inode->typeDef->attrUses != NULL)) {
27253 ret = xmlSchemaVAttributesComplex(vctxt);
27255 } else if (vctxt->nbAttrInfos != 0) {
27257 ret = xmlSchemaVAttributesSimple(vctxt);
27260 * Clear registered attributes.
27262 if (vctxt->nbAttrInfos != 0)
27263 xmlSchemaClearAttrInfos(vctxt);
27264 if (ret == -1) {
27265 VERROR_INT("xmlSchemaValidateElem",
27266 "calling attributes validation");
27267 goto internal_error;
27270 * Don't return an error if attributes are invalid on purpose.
27272 ret = 0;
27274 exit:
27275 if (ret != 0)
27276 vctxt->skipDepth = vctxt->depth;
27277 return (ret);
27278 internal_error:
27279 return (-1);
27282 #ifdef XML_SCHEMA_READER_ENABLED
27283 static int
27284 xmlSchemaVReaderWalk(xmlSchemaValidCtxtPtr vctxt)
27286 const int WHTSP = 13, SIGN_WHTSP = 14, END_ELEM = 15;
27287 int depth, nodeType, ret = 0, consumed;
27288 xmlSchemaNodeInfoPtr ielem;
27290 vctxt->depth = -1;
27291 ret = xmlTextReaderRead(vctxt->reader);
27293 * Move to the document element.
27295 while (ret == 1) {
27296 nodeType = xmlTextReaderNodeType(vctxt->reader);
27297 if (nodeType == XML_ELEMENT_NODE)
27298 goto root_found;
27299 ret = xmlTextReaderRead(vctxt->reader);
27301 goto exit;
27303 root_found:
27305 do {
27306 depth = xmlTextReaderDepth(vctxt->reader);
27307 nodeType = xmlTextReaderNodeType(vctxt->reader);
27309 if (nodeType == XML_ELEMENT_NODE) {
27311 vctxt->depth++;
27312 if (xmlSchemaValidatorPushElem(vctxt) == -1) {
27313 VERROR_INT("xmlSchemaVReaderWalk",
27314 "calling xmlSchemaValidatorPushElem()");
27315 goto internal_error;
27317 ielem = vctxt->inode;
27318 ielem->localName = xmlTextReaderLocalName(vctxt->reader);
27319 ielem->nsName = xmlTextReaderNamespaceUri(vctxt->reader);
27320 ielem->flags |= XML_SCHEMA_NODE_INFO_FLAG_OWNED_NAMES;
27322 * Is the element empty?
27324 ret = xmlTextReaderIsEmptyElement(vctxt->reader);
27325 if (ret == -1) {
27326 VERROR_INT("xmlSchemaVReaderWalk",
27327 "calling xmlTextReaderIsEmptyElement()");
27328 goto internal_error;
27330 if (ret) {
27331 ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
27334 * Register attributes.
27336 vctxt->nbAttrInfos = 0;
27337 ret = xmlTextReaderMoveToFirstAttribute(vctxt->reader);
27338 if (ret == -1) {
27339 VERROR_INT("xmlSchemaVReaderWalk",
27340 "calling xmlTextReaderMoveToFirstAttribute()");
27341 goto internal_error;
27343 if (ret == 1) {
27344 do {
27346 * VAL TODO: How do we know that the reader works on a
27347 * node tree, to be able to pass a node here?
27349 if (xmlSchemaValidatorPushAttribute(vctxt, NULL,
27350 (const xmlChar *) xmlTextReaderLocalName(vctxt->reader),
27351 xmlTextReaderNamespaceUri(vctxt->reader), 1,
27352 xmlTextReaderValue(vctxt->reader), 1) == -1) {
27354 VERROR_INT("xmlSchemaVReaderWalk",
27355 "calling xmlSchemaValidatorPushAttribute()");
27356 goto internal_error;
27358 ret = xmlTextReaderMoveToNextAttribute(vctxt->reader);
27359 if (ret == -1) {
27360 VERROR_INT("xmlSchemaVReaderWalk",
27361 "calling xmlTextReaderMoveToFirstAttribute()");
27362 goto internal_error;
27364 } while (ret == 1);
27366 * Back to element position.
27368 ret = xmlTextReaderMoveToElement(vctxt->reader);
27369 if (ret == -1) {
27370 VERROR_INT("xmlSchemaVReaderWalk",
27371 "calling xmlTextReaderMoveToElement()");
27372 goto internal_error;
27376 * Validate the element.
27378 ret= xmlSchemaValidateElem(vctxt);
27379 if (ret != 0) {
27380 if (ret == -1) {
27381 VERROR_INT("xmlSchemaVReaderWalk",
27382 "calling xmlSchemaValidateElem()");
27383 goto internal_error;
27385 goto exit;
27387 if (vctxt->depth == vctxt->skipDepth) {
27388 int curDepth;
27390 * Skip all content.
27392 if ((ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY) == 0) {
27393 ret = xmlTextReaderRead(vctxt->reader);
27394 curDepth = xmlTextReaderDepth(vctxt->reader);
27395 while ((ret == 1) && (curDepth != depth)) {
27396 ret = xmlTextReaderRead(vctxt->reader);
27397 curDepth = xmlTextReaderDepth(vctxt->reader);
27399 if (ret < 0) {
27401 * VAL TODO: A reader error occurred; what to do here?
27403 ret = 1;
27404 goto exit;
27407 goto leave_elem;
27410 * READER VAL TODO: Is an END_ELEM really never called
27411 * if the elem is empty?
27413 if (ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
27414 goto leave_elem;
27415 } else if (nodeType == END_ELEM) {
27417 * Process END of element.
27419 leave_elem:
27420 ret = xmlSchemaValidatorPopElem(vctxt);
27421 if (ret != 0) {
27422 if (ret < 0) {
27423 VERROR_INT("xmlSchemaVReaderWalk",
27424 "calling xmlSchemaValidatorPopElem()");
27425 goto internal_error;
27427 goto exit;
27429 if (vctxt->depth >= 0)
27430 ielem = vctxt->inode;
27431 else
27432 ielem = NULL;
27433 } else if ((nodeType == XML_TEXT_NODE) ||
27434 (nodeType == XML_CDATA_SECTION_NODE) ||
27435 (nodeType == WHTSP) ||
27436 (nodeType == SIGN_WHTSP)) {
27438 * Process character content.
27440 xmlChar *value;
27442 if ((nodeType == WHTSP) || (nodeType == SIGN_WHTSP))
27443 nodeType = XML_TEXT_NODE;
27445 value = xmlTextReaderValue(vctxt->reader);
27446 ret = xmlSchemaVPushText(vctxt, nodeType, BAD_CAST value,
27447 -1, XML_SCHEMA_PUSH_TEXT_CREATED, &consumed);
27448 if (! consumed)
27449 xmlFree(value);
27450 if (ret == -1) {
27451 VERROR_INT("xmlSchemaVReaderWalk",
27452 "calling xmlSchemaVPushText()");
27453 goto internal_error;
27455 } else if ((nodeType == XML_ENTITY_NODE) ||
27456 (nodeType == XML_ENTITY_REF_NODE)) {
27458 * VAL TODO: What to do with entities?
27460 TODO
27463 * Read next node.
27465 ret = xmlTextReaderRead(vctxt->reader);
27466 } while (ret == 1);
27468 exit:
27469 return (ret);
27470 internal_error:
27471 return (-1);
27473 #endif
27475 /************************************************************************
27477 * SAX validation handlers *
27479 ************************************************************************/
27482 * Process text content.
27484 static void
27485 xmlSchemaSAXHandleText(void *ctx,
27486 const xmlChar * ch,
27487 int len)
27489 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27491 if (vctxt->depth < 0)
27492 return;
27493 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27494 return;
27495 if (vctxt->inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
27496 vctxt->inode->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
27497 if (xmlSchemaVPushText(vctxt, XML_TEXT_NODE, ch, len,
27498 XML_SCHEMA_PUSH_TEXT_VOLATILE, NULL) == -1) {
27499 VERROR_INT("xmlSchemaSAXHandleCDataSection",
27500 "calling xmlSchemaVPushText()");
27501 vctxt->err = -1;
27502 xmlStopParser(vctxt->parserCtxt);
27507 * Process CDATA content.
27509 static void
27510 xmlSchemaSAXHandleCDataSection(void *ctx,
27511 const xmlChar * ch,
27512 int len)
27514 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27516 if (vctxt->depth < 0)
27517 return;
27518 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27519 return;
27520 if (vctxt->inode->flags & XML_SCHEMA_ELEM_INFO_EMPTY)
27521 vctxt->inode->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
27522 if (xmlSchemaVPushText(vctxt, XML_CDATA_SECTION_NODE, ch, len,
27523 XML_SCHEMA_PUSH_TEXT_VOLATILE, NULL) == -1) {
27524 VERROR_INT("xmlSchemaSAXHandleCDataSection",
27525 "calling xmlSchemaVPushText()");
27526 vctxt->err = -1;
27527 xmlStopParser(vctxt->parserCtxt);
27531 static void
27532 xmlSchemaSAXHandleReference(void *ctx ATTRIBUTE_UNUSED,
27533 const xmlChar * name ATTRIBUTE_UNUSED)
27535 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27537 if (vctxt->depth < 0)
27538 return;
27539 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27540 return;
27541 /* SAX VAL TODO: What to do here? */
27542 TODO
27545 static void
27546 xmlSchemaSAXHandleStartElementNs(void *ctx,
27547 const xmlChar * localname,
27548 const xmlChar * prefix ATTRIBUTE_UNUSED,
27549 const xmlChar * URI,
27550 int nb_namespaces,
27551 const xmlChar ** namespaces,
27552 int nb_attributes,
27553 int nb_defaulted ATTRIBUTE_UNUSED,
27554 const xmlChar ** attributes)
27556 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27557 int ret;
27558 xmlSchemaNodeInfoPtr ielem;
27559 int i, j;
27562 * SAX VAL TODO: What to do with nb_defaulted?
27565 * Skip elements if inside a "skip" wildcard or invalid.
27567 vctxt->depth++;
27568 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
27569 return;
27571 * Push the element.
27573 if (xmlSchemaValidatorPushElem(vctxt) == -1) {
27574 VERROR_INT("xmlSchemaSAXHandleStartElementNs",
27575 "calling xmlSchemaValidatorPushElem()");
27576 goto internal_error;
27578 ielem = vctxt->inode;
27580 * TODO: Is this OK?
27582 ielem->nodeLine = xmlSAX2GetLineNumber(vctxt->parserCtxt);
27583 ielem->localName = localname;
27584 ielem->nsName = URI;
27585 ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
27587 * Register namespaces on the elem info.
27589 if (nb_namespaces != 0) {
27591 * Although the parser builds its own namespace list,
27592 * we have no access to it, so we'll use an own one.
27594 for (i = 0, j = 0; i < nb_namespaces; i++, j += 2) {
27596 * Store prefix and namespace name.
27598 if (ielem->nsBindings == NULL) {
27599 ielem->nsBindings =
27600 (const xmlChar **) xmlMalloc(10 *
27601 sizeof(const xmlChar *));
27602 if (ielem->nsBindings == NULL) {
27603 xmlSchemaVErrMemory(vctxt,
27604 "allocating namespace bindings for SAX validation",
27605 NULL);
27606 goto internal_error;
27608 ielem->nbNsBindings = 0;
27609 ielem->sizeNsBindings = 5;
27610 } else if (ielem->sizeNsBindings <= ielem->nbNsBindings) {
27611 ielem->sizeNsBindings *= 2;
27612 ielem->nsBindings =
27613 (const xmlChar **) xmlRealloc(
27614 (void *) ielem->nsBindings,
27615 ielem->sizeNsBindings * 2 * sizeof(const xmlChar *));
27616 if (ielem->nsBindings == NULL) {
27617 xmlSchemaVErrMemory(vctxt,
27618 "re-allocating namespace bindings for SAX validation",
27619 NULL);
27620 goto internal_error;
27624 ielem->nsBindings[ielem->nbNsBindings * 2] = namespaces[j];
27625 if (namespaces[j+1][0] == 0) {
27627 * Handle xmlns="".
27629 ielem->nsBindings[ielem->nbNsBindings * 2 + 1] = NULL;
27630 } else
27631 ielem->nsBindings[ielem->nbNsBindings * 2 + 1] =
27632 namespaces[j+1];
27633 ielem->nbNsBindings++;
27637 * Register attributes.
27638 * SAX VAL TODO: We are not adding namespace declaration
27639 * attributes yet.
27641 if (nb_attributes != 0) {
27642 int valueLen, k, l;
27643 xmlChar *value;
27645 for (j = 0, i = 0; i < nb_attributes; i++, j += 5) {
27647 * Duplicate the value, changing any &#38; to a literal ampersand.
27649 * libxml2 differs from normal SAX here in that it escapes all ampersands
27650 * as &#38; instead of delivering the raw converted string. Changing the
27651 * behavior at this point would break applications that use this API, so
27652 * we are forced to work around it.
27654 valueLen = attributes[j+4] - attributes[j+3];
27655 value = xmlMallocAtomic(valueLen + 1);
27656 if (value == NULL) {
27657 xmlSchemaVErrMemory(vctxt,
27658 "allocating string for decoded attribute",
27659 NULL);
27660 goto internal_error;
27662 for (k = 0, l = 0; k < valueLen; l++) {
27663 if (k < valueLen - 4 &&
27664 attributes[j+3][k+0] == '&' &&
27665 attributes[j+3][k+1] == '#' &&
27666 attributes[j+3][k+2] == '3' &&
27667 attributes[j+3][k+3] == '8' &&
27668 attributes[j+3][k+4] == ';') {
27669 value[l] = '&';
27670 k += 5;
27671 } else {
27672 value[l] = attributes[j+3][k];
27673 k++;
27676 value[l] = '\0';
27678 * TODO: Set the node line.
27680 ret = xmlSchemaValidatorPushAttribute(vctxt,
27681 NULL, ielem->nodeLine, attributes[j], attributes[j+2], 0,
27682 value, 1);
27683 if (ret == -1) {
27684 VERROR_INT("xmlSchemaSAXHandleStartElementNs",
27685 "calling xmlSchemaValidatorPushAttribute()");
27686 goto internal_error;
27691 * Validate the element.
27693 ret = xmlSchemaValidateElem(vctxt);
27694 if (ret != 0) {
27695 if (ret == -1) {
27696 VERROR_INT("xmlSchemaSAXHandleStartElementNs",
27697 "calling xmlSchemaValidateElem()");
27698 goto internal_error;
27700 goto exit;
27703 exit:
27704 return;
27705 internal_error:
27706 vctxt->err = -1;
27707 xmlStopParser(vctxt->parserCtxt);
27708 return;
27711 static void
27712 xmlSchemaSAXHandleEndElementNs(void *ctx,
27713 const xmlChar * localname ATTRIBUTE_UNUSED,
27714 const xmlChar * prefix ATTRIBUTE_UNUSED,
27715 const xmlChar * URI ATTRIBUTE_UNUSED)
27717 xmlSchemaValidCtxtPtr vctxt = (xmlSchemaValidCtxtPtr) ctx;
27718 int res;
27721 * Skip elements if inside a "skip" wildcard or if invalid.
27723 if (vctxt->skipDepth != -1) {
27724 if (vctxt->depth > vctxt->skipDepth) {
27725 vctxt->depth--;
27726 return;
27727 } else
27728 vctxt->skipDepth = -1;
27731 * SAX VAL TODO: Just a temporary check.
27733 if ((!xmlStrEqual(vctxt->inode->localName, localname)) ||
27734 (!xmlStrEqual(vctxt->inode->nsName, URI))) {
27735 VERROR_INT("xmlSchemaSAXHandleEndElementNs",
27736 "elem pop mismatch");
27738 res = xmlSchemaValidatorPopElem(vctxt);
27739 if (res != 0) {
27740 if (res < 0) {
27741 VERROR_INT("xmlSchemaSAXHandleEndElementNs",
27742 "calling xmlSchemaValidatorPopElem()");
27743 goto internal_error;
27745 goto exit;
27747 exit:
27748 return;
27749 internal_error:
27750 vctxt->err = -1;
27751 xmlStopParser(vctxt->parserCtxt);
27752 return;
27755 /************************************************************************
27757 * Validation interfaces *
27759 ************************************************************************/
27762 * xmlSchemaNewValidCtxt:
27763 * @schema: a precompiled XML Schemas
27765 * Create an XML Schemas validation context based on the given schema.
27767 * Returns the validation context or NULL in case of error
27769 xmlSchemaValidCtxtPtr
27770 xmlSchemaNewValidCtxt(xmlSchemaPtr schema)
27772 xmlSchemaValidCtxtPtr ret;
27774 ret = (xmlSchemaValidCtxtPtr) xmlMalloc(sizeof(xmlSchemaValidCtxt));
27775 if (ret == NULL) {
27776 xmlSchemaVErrMemory(NULL, "allocating validation context", NULL);
27777 return (NULL);
27779 memset(ret, 0, sizeof(xmlSchemaValidCtxt));
27780 ret->type = XML_SCHEMA_CTXT_VALIDATOR;
27781 ret->dict = xmlDictCreate();
27782 ret->nodeQNames = xmlSchemaItemListCreate();
27783 ret->schema = schema;
27784 return (ret);
27788 * xmlSchemaValidateSetFilename:
27789 * @vctxt: the schema validation context
27790 * @filename: the file name
27792 * Workaround to provide file error reporting information when this is
27793 * not provided by current APIs
27795 void
27796 xmlSchemaValidateSetFilename(xmlSchemaValidCtxtPtr vctxt, const char *filename) {
27797 if (vctxt == NULL)
27798 return;
27799 if (vctxt->filename != NULL)
27800 xmlFree(vctxt->filename);
27801 if (filename != NULL)
27802 vctxt->filename = (char *) xmlStrdup((const xmlChar *) filename);
27803 else
27804 vctxt->filename = NULL;
27808 * xmlSchemaClearValidCtxt:
27809 * @vctxt: the schema validation context
27811 * Free the resources associated to the schema validation context;
27812 * leaves some fields alive intended for reuse of the context.
27814 static void
27815 xmlSchemaClearValidCtxt(xmlSchemaValidCtxtPtr vctxt)
27817 if (vctxt == NULL)
27818 return;
27821 * TODO: Should we clear the flags?
27822 * Might be problematic if one reuses the context
27823 * and assumes that the options remain the same.
27825 vctxt->flags = 0;
27826 vctxt->validationRoot = NULL;
27827 vctxt->doc = NULL;
27828 #ifdef LIBXML_READER_ENABLED
27829 vctxt->reader = NULL;
27830 #endif
27831 vctxt->hasKeyrefs = 0;
27833 if (vctxt->value != NULL) {
27834 xmlSchemaFreeValue(vctxt->value);
27835 vctxt->value = NULL;
27838 * Augmented IDC information.
27840 if (vctxt->aidcs != NULL) {
27841 xmlSchemaIDCAugPtr cur = vctxt->aidcs, next;
27842 do {
27843 next = cur->next;
27844 xmlFree(cur);
27845 cur = next;
27846 } while (cur != NULL);
27847 vctxt->aidcs = NULL;
27850 if (vctxt->idcNodes != NULL) {
27851 int i;
27852 xmlSchemaPSVIIDCNodePtr item;
27854 for (i = 0; i < vctxt->nbIdcNodes; i++) {
27855 item = vctxt->idcNodes[i];
27856 xmlFree(item->keys);
27857 xmlFree(item);
27859 xmlFree(vctxt->idcNodes);
27860 vctxt->idcNodes = NULL;
27861 vctxt->nbIdcNodes = 0;
27862 vctxt->sizeIdcNodes = 0;
27865 if (vctxt->idcKeys != NULL) {
27866 int i;
27867 for (i = 0; i < vctxt->nbIdcKeys; i++)
27868 xmlSchemaIDCFreeKey(vctxt->idcKeys[i]);
27869 xmlFree(vctxt->idcKeys);
27870 vctxt->idcKeys = NULL;
27871 vctxt->nbIdcKeys = 0;
27872 vctxt->sizeIdcKeys = 0;
27876 * Note that we won't delete the XPath state pool here.
27878 if (vctxt->xpathStates != NULL) {
27879 xmlSchemaFreeIDCStateObjList(vctxt->xpathStates);
27880 vctxt->xpathStates = NULL;
27883 * Attribute info.
27885 if (vctxt->nbAttrInfos != 0) {
27886 xmlSchemaClearAttrInfos(vctxt);
27889 * Element info.
27891 if (vctxt->elemInfos != NULL) {
27892 int i;
27893 xmlSchemaNodeInfoPtr ei;
27895 for (i = 0; i < vctxt->sizeElemInfos; i++) {
27896 ei = vctxt->elemInfos[i];
27897 if (ei == NULL)
27898 break;
27899 xmlSchemaClearElemInfo(vctxt, ei);
27902 xmlSchemaItemListClear(vctxt->nodeQNames);
27903 /* Recreate the dict. */
27904 xmlDictFree(vctxt->dict);
27906 * TODO: Is is save to recreate it? Do we have a scenario
27907 * where the user provides the dict?
27909 vctxt->dict = xmlDictCreate();
27911 if (vctxt->filename != NULL) {
27912 xmlFree(vctxt->filename);
27913 vctxt->filename = NULL;
27917 * Note that some cleanup functions can move items to the cache,
27918 * so the cache shouldn't be freed too early.
27920 if (vctxt->idcMatcherCache != NULL) {
27921 xmlSchemaIDCMatcherPtr matcher = vctxt->idcMatcherCache, tmp;
27923 while (matcher) {
27924 tmp = matcher;
27925 matcher = matcher->nextCached;
27926 xmlSchemaIDCFreeMatcherList(tmp);
27928 vctxt->idcMatcherCache = NULL;
27933 * xmlSchemaFreeValidCtxt:
27934 * @ctxt: the schema validation context
27936 * Free the resources associated to the schema validation context
27938 void
27939 xmlSchemaFreeValidCtxt(xmlSchemaValidCtxtPtr ctxt)
27941 if (ctxt == NULL)
27942 return;
27943 if (ctxt->value != NULL)
27944 xmlSchemaFreeValue(ctxt->value);
27945 if (ctxt->pctxt != NULL)
27946 xmlSchemaFreeParserCtxt(ctxt->pctxt);
27947 if (ctxt->idcNodes != NULL) {
27948 int i;
27949 xmlSchemaPSVIIDCNodePtr item;
27951 for (i = 0; i < ctxt->nbIdcNodes; i++) {
27952 item = ctxt->idcNodes[i];
27953 xmlFree(item->keys);
27954 xmlFree(item);
27956 xmlFree(ctxt->idcNodes);
27958 if (ctxt->idcKeys != NULL) {
27959 int i;
27960 for (i = 0; i < ctxt->nbIdcKeys; i++)
27961 xmlSchemaIDCFreeKey(ctxt->idcKeys[i]);
27962 xmlFree(ctxt->idcKeys);
27965 if (ctxt->xpathStates != NULL) {
27966 xmlSchemaFreeIDCStateObjList(ctxt->xpathStates);
27967 ctxt->xpathStates = NULL;
27969 if (ctxt->xpathStatePool != NULL) {
27970 xmlSchemaFreeIDCStateObjList(ctxt->xpathStatePool);
27971 ctxt->xpathStatePool = NULL;
27975 * Augmented IDC information.
27977 if (ctxt->aidcs != NULL) {
27978 xmlSchemaIDCAugPtr cur = ctxt->aidcs, next;
27979 do {
27980 next = cur->next;
27981 xmlFree(cur);
27982 cur = next;
27983 } while (cur != NULL);
27985 if (ctxt->attrInfos != NULL) {
27986 int i;
27987 xmlSchemaAttrInfoPtr attr;
27989 /* Just a paranoid call to the cleanup. */
27990 if (ctxt->nbAttrInfos != 0)
27991 xmlSchemaClearAttrInfos(ctxt);
27992 for (i = 0; i < ctxt->sizeAttrInfos; i++) {
27993 attr = ctxt->attrInfos[i];
27994 xmlFree(attr);
27996 xmlFree(ctxt->attrInfos);
27998 if (ctxt->elemInfos != NULL) {
27999 int i;
28000 xmlSchemaNodeInfoPtr ei;
28002 for (i = 0; i < ctxt->sizeElemInfos; i++) {
28003 ei = ctxt->elemInfos[i];
28004 if (ei == NULL)
28005 break;
28006 xmlSchemaClearElemInfo(ctxt, ei);
28007 xmlFree(ei);
28009 xmlFree(ctxt->elemInfos);
28011 if (ctxt->nodeQNames != NULL)
28012 xmlSchemaItemListFree(ctxt->nodeQNames);
28013 if (ctxt->dict != NULL)
28014 xmlDictFree(ctxt->dict);
28015 if (ctxt->filename != NULL)
28016 xmlFree(ctxt->filename);
28017 xmlFree(ctxt);
28021 * xmlSchemaIsValid:
28022 * @ctxt: the schema validation context
28024 * Check if any error was detected during validation.
28026 * Returns 1 if valid so far, 0 if errors were detected, and -1 in case
28027 * of internal error.
28030 xmlSchemaIsValid(xmlSchemaValidCtxtPtr ctxt)
28032 if (ctxt == NULL)
28033 return(-1);
28034 return(ctxt->err == 0);
28038 * xmlSchemaSetValidErrors:
28039 * @ctxt: a schema validation context
28040 * @err: the error function
28041 * @warn: the warning function
28042 * @ctx: the functions context
28044 * Set the error and warning callback information
28046 void
28047 xmlSchemaSetValidErrors(xmlSchemaValidCtxtPtr ctxt,
28048 xmlSchemaValidityErrorFunc err,
28049 xmlSchemaValidityWarningFunc warn, void *ctx)
28051 if (ctxt == NULL)
28052 return;
28053 ctxt->error = err;
28054 ctxt->warning = warn;
28055 ctxt->errCtxt = ctx;
28056 if (ctxt->pctxt != NULL)
28057 xmlSchemaSetParserErrors(ctxt->pctxt, err, warn, ctx);
28061 * xmlSchemaSetValidStructuredErrors:
28062 * @ctxt: a schema validation context
28063 * @serror: the structured error function
28064 * @ctx: the functions context
28066 * Set the structured error callback
28068 void
28069 xmlSchemaSetValidStructuredErrors(xmlSchemaValidCtxtPtr ctxt,
28070 xmlStructuredErrorFunc serror, void *ctx)
28072 if (ctxt == NULL)
28073 return;
28074 ctxt->serror = serror;
28075 ctxt->error = NULL;
28076 ctxt->warning = NULL;
28077 ctxt->errCtxt = ctx;
28078 if (ctxt->pctxt != NULL)
28079 xmlSchemaSetParserStructuredErrors(ctxt->pctxt, serror, ctx);
28083 * xmlSchemaGetValidErrors:
28084 * @ctxt: a XML-Schema validation context
28085 * @err: the error function result
28086 * @warn: the warning function result
28087 * @ctx: the functions context result
28089 * Get the error and warning callback information
28091 * Returns -1 in case of error and 0 otherwise
28094 xmlSchemaGetValidErrors(xmlSchemaValidCtxtPtr ctxt,
28095 xmlSchemaValidityErrorFunc * err,
28096 xmlSchemaValidityWarningFunc * warn, void **ctx)
28098 if (ctxt == NULL)
28099 return (-1);
28100 if (err != NULL)
28101 *err = ctxt->error;
28102 if (warn != NULL)
28103 *warn = ctxt->warning;
28104 if (ctx != NULL)
28105 *ctx = ctxt->errCtxt;
28106 return (0);
28111 * xmlSchemaSetValidOptions:
28112 * @ctxt: a schema validation context
28113 * @options: a combination of xmlSchemaValidOption
28115 * Sets the options to be used during the validation.
28117 * Returns 0 in case of success, -1 in case of an
28118 * API error.
28121 xmlSchemaSetValidOptions(xmlSchemaValidCtxtPtr ctxt,
28122 int options)
28125 int i;
28127 if (ctxt == NULL)
28128 return (-1);
28130 * WARNING: Change the start value if adding to the
28131 * xmlSchemaValidOption.
28132 * TODO: Is there an other, more easy to maintain,
28133 * way?
28135 for (i = 1; i < (int) sizeof(int) * 8; i++) {
28136 if (options & 1<<i)
28137 return (-1);
28139 ctxt->options = options;
28140 return (0);
28144 * xmlSchemaValidCtxtGetOptions:
28145 * @ctxt: a schema validation context
28147 * Get the validation context options.
28149 * Returns the option combination or -1 on error.
28152 xmlSchemaValidCtxtGetOptions(xmlSchemaValidCtxtPtr ctxt)
28155 if (ctxt == NULL)
28156 return (-1);
28157 else
28158 return (ctxt->options);
28161 static int
28162 xmlSchemaVDocWalk(xmlSchemaValidCtxtPtr vctxt)
28164 xmlAttrPtr attr;
28165 int ret = 0;
28166 xmlSchemaNodeInfoPtr ielem = NULL;
28167 xmlNodePtr node, valRoot;
28168 const xmlChar *nsName;
28170 /* DOC VAL TODO: Move this to the start function. */
28171 if (vctxt->validationRoot != NULL)
28172 valRoot = vctxt->validationRoot;
28173 else
28174 valRoot = xmlDocGetRootElement(vctxt->doc);
28175 if (valRoot == NULL) {
28176 /* VAL TODO: Error code? */
28177 VERROR(1, NULL, "The document has no document element");
28178 return (1);
28180 vctxt->depth = -1;
28181 vctxt->validationRoot = valRoot;
28182 node = valRoot;
28183 while (node != NULL) {
28184 if ((vctxt->skipDepth != -1) && (vctxt->depth >= vctxt->skipDepth))
28185 goto next_sibling;
28186 if (node->type == XML_ELEMENT_NODE) {
28189 * Init the node-info.
28191 vctxt->depth++;
28192 if (xmlSchemaValidatorPushElem(vctxt) == -1)
28193 goto internal_error;
28194 ielem = vctxt->inode;
28195 ielem->node = node;
28196 ielem->nodeLine = node->line;
28197 ielem->localName = node->name;
28198 if (node->ns != NULL)
28199 ielem->nsName = node->ns->href;
28200 ielem->flags |= XML_SCHEMA_ELEM_INFO_EMPTY;
28202 * Register attributes.
28203 * DOC VAL TODO: We do not register namespace declaration
28204 * attributes yet.
28206 vctxt->nbAttrInfos = 0;
28207 if (node->properties != NULL) {
28208 attr = node->properties;
28209 do {
28210 if (attr->ns != NULL)
28211 nsName = attr->ns->href;
28212 else
28213 nsName = NULL;
28214 ret = xmlSchemaValidatorPushAttribute(vctxt,
28215 (xmlNodePtr) attr,
28217 * Note that we give it the line number of the
28218 * parent element.
28220 ielem->nodeLine,
28221 attr->name, nsName, 0,
28222 xmlNodeListGetString(attr->doc, attr->children, 1), 1);
28223 if (ret == -1) {
28224 VERROR_INT("xmlSchemaDocWalk",
28225 "calling xmlSchemaValidatorPushAttribute()");
28226 goto internal_error;
28228 attr = attr->next;
28229 } while (attr);
28232 * Validate the element.
28234 ret = xmlSchemaValidateElem(vctxt);
28235 if (ret != 0) {
28236 if (ret == -1) {
28237 VERROR_INT("xmlSchemaDocWalk",
28238 "calling xmlSchemaValidateElem()");
28239 goto internal_error;
28242 * Don't stop validation; just skip the content
28243 * of this element.
28245 goto leave_node;
28247 if ((vctxt->skipDepth != -1) &&
28248 (vctxt->depth >= vctxt->skipDepth))
28249 goto leave_node;
28250 } else if ((node->type == XML_TEXT_NODE) ||
28251 (node->type == XML_CDATA_SECTION_NODE)) {
28253 * Process character content.
28255 if ((ielem != NULL) && (ielem->flags & XML_SCHEMA_ELEM_INFO_EMPTY))
28256 ielem->flags ^= XML_SCHEMA_ELEM_INFO_EMPTY;
28257 ret = xmlSchemaVPushText(vctxt, node->type, node->content,
28258 -1, XML_SCHEMA_PUSH_TEXT_PERSIST, NULL);
28259 if (ret < 0) {
28260 VERROR_INT("xmlSchemaVDocWalk",
28261 "calling xmlSchemaVPushText()");
28262 goto internal_error;
28265 * DOC VAL TODO: Should we skip further validation of the
28266 * element content here?
28268 } else if ((node->type == XML_ENTITY_NODE) ||
28269 (node->type == XML_ENTITY_REF_NODE)) {
28271 * DOC VAL TODO: What to do with entities?
28273 VERROR_INT("xmlSchemaVDocWalk",
28274 "there is at least one entity reference in the node-tree "
28275 "currently being validated. Processing of entities with "
28276 "this XML Schema processor is not supported (yet). Please "
28277 "substitute entities before validation.");
28278 goto internal_error;
28279 } else {
28280 goto leave_node;
28282 * DOC VAL TODO: XInclude nodes, etc.
28286 * Walk the doc.
28288 if (node->children != NULL) {
28289 node = node->children;
28290 continue;
28292 leave_node:
28293 if (node->type == XML_ELEMENT_NODE) {
28295 * Leaving the scope of an element.
28297 if (node != vctxt->inode->node) {
28298 VERROR_INT("xmlSchemaVDocWalk",
28299 "element position mismatch");
28300 goto internal_error;
28302 ret = xmlSchemaValidatorPopElem(vctxt);
28303 if (ret != 0) {
28304 if (ret < 0) {
28305 VERROR_INT("xmlSchemaVDocWalk",
28306 "calling xmlSchemaValidatorPopElem()");
28307 goto internal_error;
28310 if (node == valRoot)
28311 goto exit;
28313 next_sibling:
28314 if (node->next != NULL)
28315 node = node->next;
28316 else {
28317 node = node->parent;
28318 goto leave_node;
28322 exit:
28323 return (ret);
28324 internal_error:
28325 return (-1);
28328 static int
28329 xmlSchemaPreRun(xmlSchemaValidCtxtPtr vctxt) {
28331 * Some initialization.
28333 vctxt->err = 0;
28334 vctxt->nberrors = 0;
28335 vctxt->depth = -1;
28336 vctxt->skipDepth = -1;
28337 vctxt->hasKeyrefs = 0;
28338 #ifdef ENABLE_IDC_NODE_TABLES_TEST
28339 vctxt->createIDCNodeTables = 1;
28340 #else
28341 vctxt->createIDCNodeTables = 0;
28342 #endif
28344 * Create a schema + parser if necessary.
28346 if (vctxt->schema == NULL) {
28347 xmlSchemaParserCtxtPtr pctxt;
28349 vctxt->xsiAssemble = 1;
28351 * If not schema was given then we will create a schema
28352 * dynamically using XSI schema locations.
28354 * Create the schema parser context.
28356 if ((vctxt->pctxt == NULL) &&
28357 (xmlSchemaCreatePCtxtOnVCtxt(vctxt) == -1))
28358 return (-1);
28359 pctxt = vctxt->pctxt;
28360 pctxt->xsiAssemble = 1;
28362 * Create the schema.
28364 vctxt->schema = xmlSchemaNewSchema(pctxt);
28365 if (vctxt->schema == NULL)
28366 return (-1);
28368 * Create the schema construction context.
28370 pctxt->constructor = xmlSchemaConstructionCtxtCreate(pctxt->dict);
28371 if (pctxt->constructor == NULL)
28372 return(-1);
28373 pctxt->constructor->mainSchema = vctxt->schema;
28375 * Take ownership of the constructor to be able to free it.
28377 pctxt->ownsConstructor = 1;
28380 * Augment the IDC definitions for the main schema and all imported ones
28381 * NOTE: main schema if the first in the imported list
28383 xmlHashScan(vctxt->schema->schemasImports, xmlSchemaAugmentImportedIDC,
28384 vctxt);
28386 return(0);
28389 static void
28390 xmlSchemaPostRun(xmlSchemaValidCtxtPtr vctxt) {
28391 if (vctxt->xsiAssemble) {
28392 if (vctxt->schema != NULL) {
28393 xmlSchemaFree(vctxt->schema);
28394 vctxt->schema = NULL;
28397 xmlSchemaClearValidCtxt(vctxt);
28400 static int
28401 xmlSchemaVStart(xmlSchemaValidCtxtPtr vctxt)
28403 int ret = 0;
28405 if (xmlSchemaPreRun(vctxt) < 0)
28406 return(-1);
28408 if (vctxt->doc != NULL) {
28410 * Tree validation.
28412 ret = xmlSchemaVDocWalk(vctxt);
28413 #ifdef LIBXML_READER_ENABLED
28414 } else if (vctxt->reader != NULL) {
28416 * XML Reader validation.
28418 #ifdef XML_SCHEMA_READER_ENABLED
28419 ret = xmlSchemaVReaderWalk(vctxt);
28420 #endif
28421 #endif
28422 } else if ((vctxt->sax != NULL) && (vctxt->parserCtxt != NULL)) {
28424 * SAX validation.
28426 ret = xmlParseDocument(vctxt->parserCtxt);
28427 } else {
28428 VERROR_INT("xmlSchemaVStart",
28429 "no instance to validate");
28430 ret = -1;
28433 xmlSchemaPostRun(vctxt);
28434 if (ret == 0)
28435 ret = vctxt->err;
28436 return (ret);
28440 * xmlSchemaValidateOneElement:
28441 * @ctxt: a schema validation context
28442 * @elem: an element node
28444 * Validate a branch of a tree, starting with the given @elem.
28446 * Returns 0 if the element and its subtree is valid, a positive error
28447 * code number otherwise and -1 in case of an internal or API error.
28450 xmlSchemaValidateOneElement(xmlSchemaValidCtxtPtr ctxt, xmlNodePtr elem)
28452 if ((ctxt == NULL) || (elem == NULL) || (elem->type != XML_ELEMENT_NODE))
28453 return (-1);
28455 if (ctxt->schema == NULL)
28456 return (-1);
28458 ctxt->doc = elem->doc;
28459 ctxt->node = elem;
28460 ctxt->validationRoot = elem;
28461 return(xmlSchemaVStart(ctxt));
28465 * xmlSchemaValidateDoc:
28466 * @ctxt: a schema validation context
28467 * @doc: a parsed document tree
28469 * Validate a document tree in memory.
28471 * Returns 0 if the document is schemas valid, a positive error code
28472 * number otherwise and -1 in case of internal or API error.
28475 xmlSchemaValidateDoc(xmlSchemaValidCtxtPtr ctxt, xmlDocPtr doc)
28477 if ((ctxt == NULL) || (doc == NULL))
28478 return (-1);
28480 ctxt->doc = doc;
28481 ctxt->node = xmlDocGetRootElement(doc);
28482 if (ctxt->node == NULL) {
28483 xmlSchemaCustomErr(ACTXT_CAST ctxt,
28484 XML_SCHEMAV_DOCUMENT_ELEMENT_MISSING,
28485 (xmlNodePtr) doc, NULL,
28486 "The document has no document element", NULL, NULL);
28487 return (ctxt->err);
28489 ctxt->validationRoot = ctxt->node;
28490 return (xmlSchemaVStart(ctxt));
28494 /************************************************************************
28496 * Function and data for SAX streaming API *
28498 ************************************************************************/
28499 typedef struct _xmlSchemaSplitSAXData xmlSchemaSplitSAXData;
28500 typedef xmlSchemaSplitSAXData *xmlSchemaSplitSAXDataPtr;
28502 struct _xmlSchemaSplitSAXData {
28503 xmlSAXHandlerPtr user_sax;
28504 void *user_data;
28505 xmlSchemaValidCtxtPtr ctxt;
28506 xmlSAXHandlerPtr schemas_sax;
28509 #define XML_SAX_PLUG_MAGIC 0xdc43ba21
28511 struct _xmlSchemaSAXPlug {
28512 unsigned int magic;
28514 /* the original callbacks information */
28515 xmlSAXHandlerPtr *user_sax_ptr;
28516 xmlSAXHandlerPtr user_sax;
28517 void **user_data_ptr;
28518 void *user_data;
28520 /* the block plugged back and validation information */
28521 xmlSAXHandler schemas_sax;
28522 xmlSchemaValidCtxtPtr ctxt;
28525 /* All those functions just bounces to the user provided SAX handlers */
28526 static void
28527 internalSubsetSplit(void *ctx, const xmlChar *name,
28528 const xmlChar *ExternalID, const xmlChar *SystemID)
28530 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28531 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28532 (ctxt->user_sax->internalSubset != NULL))
28533 ctxt->user_sax->internalSubset(ctxt->user_data, name, ExternalID,
28534 SystemID);
28537 static int
28538 isStandaloneSplit(void *ctx)
28540 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28541 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28542 (ctxt->user_sax->isStandalone != NULL))
28543 return(ctxt->user_sax->isStandalone(ctxt->user_data));
28544 return(0);
28547 static int
28548 hasInternalSubsetSplit(void *ctx)
28550 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28551 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28552 (ctxt->user_sax->hasInternalSubset != NULL))
28553 return(ctxt->user_sax->hasInternalSubset(ctxt->user_data));
28554 return(0);
28557 static int
28558 hasExternalSubsetSplit(void *ctx)
28560 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28561 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28562 (ctxt->user_sax->hasExternalSubset != NULL))
28563 return(ctxt->user_sax->hasExternalSubset(ctxt->user_data));
28564 return(0);
28567 static void
28568 externalSubsetSplit(void *ctx, const xmlChar *name,
28569 const xmlChar *ExternalID, const xmlChar *SystemID)
28571 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28572 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28573 (ctxt->user_sax->externalSubset != NULL))
28574 ctxt->user_sax->externalSubset(ctxt->user_data, name, ExternalID,
28575 SystemID);
28578 static xmlParserInputPtr
28579 resolveEntitySplit(void *ctx, const xmlChar *publicId, const xmlChar *systemId)
28581 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28582 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28583 (ctxt->user_sax->resolveEntity != NULL))
28584 return(ctxt->user_sax->resolveEntity(ctxt->user_data, publicId,
28585 systemId));
28586 return(NULL);
28589 static xmlEntityPtr
28590 getEntitySplit(void *ctx, const xmlChar *name)
28592 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28593 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28594 (ctxt->user_sax->getEntity != NULL))
28595 return(ctxt->user_sax->getEntity(ctxt->user_data, name));
28596 return(NULL);
28599 static xmlEntityPtr
28600 getParameterEntitySplit(void *ctx, const xmlChar *name)
28602 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28603 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28604 (ctxt->user_sax->getParameterEntity != NULL))
28605 return(ctxt->user_sax->getParameterEntity(ctxt->user_data, name));
28606 return(NULL);
28610 static void
28611 entityDeclSplit(void *ctx, const xmlChar *name, int type,
28612 const xmlChar *publicId, const xmlChar *systemId, xmlChar *content)
28614 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28615 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28616 (ctxt->user_sax->entityDecl != NULL))
28617 ctxt->user_sax->entityDecl(ctxt->user_data, name, type, publicId,
28618 systemId, content);
28621 static void
28622 attributeDeclSplit(void *ctx, const xmlChar * elem,
28623 const xmlChar * name, int type, int def,
28624 const xmlChar * defaultValue, xmlEnumerationPtr tree)
28626 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28627 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28628 (ctxt->user_sax->attributeDecl != NULL)) {
28629 ctxt->user_sax->attributeDecl(ctxt->user_data, elem, name, type,
28630 def, defaultValue, tree);
28631 } else {
28632 xmlFreeEnumeration(tree);
28636 static void
28637 elementDeclSplit(void *ctx, const xmlChar *name, int type,
28638 xmlElementContentPtr content)
28640 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28641 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28642 (ctxt->user_sax->elementDecl != NULL))
28643 ctxt->user_sax->elementDecl(ctxt->user_data, name, type, content);
28646 static void
28647 notationDeclSplit(void *ctx, const xmlChar *name,
28648 const xmlChar *publicId, const xmlChar *systemId)
28650 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28651 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28652 (ctxt->user_sax->notationDecl != NULL))
28653 ctxt->user_sax->notationDecl(ctxt->user_data, name, publicId,
28654 systemId);
28657 static void
28658 unparsedEntityDeclSplit(void *ctx, const xmlChar *name,
28659 const xmlChar *publicId, const xmlChar *systemId,
28660 const xmlChar *notationName)
28662 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28663 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28664 (ctxt->user_sax->unparsedEntityDecl != NULL))
28665 ctxt->user_sax->unparsedEntityDecl(ctxt->user_data, name, publicId,
28666 systemId, notationName);
28669 static void
28670 setDocumentLocatorSplit(void *ctx, xmlSAXLocatorPtr loc)
28672 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28673 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28674 (ctxt->user_sax->setDocumentLocator != NULL))
28675 ctxt->user_sax->setDocumentLocator(ctxt->user_data, loc);
28678 static void
28679 startDocumentSplit(void *ctx)
28681 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28682 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28683 (ctxt->user_sax->startDocument != NULL))
28684 ctxt->user_sax->startDocument(ctxt->user_data);
28687 static void
28688 endDocumentSplit(void *ctx)
28690 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28691 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28692 (ctxt->user_sax->endDocument != NULL))
28693 ctxt->user_sax->endDocument(ctxt->user_data);
28696 static void
28697 processingInstructionSplit(void *ctx, const xmlChar *target,
28698 const xmlChar *data)
28700 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28701 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28702 (ctxt->user_sax->processingInstruction != NULL))
28703 ctxt->user_sax->processingInstruction(ctxt->user_data, target, data);
28706 static void
28707 commentSplit(void *ctx, const xmlChar *value)
28709 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28710 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28711 (ctxt->user_sax->comment != NULL))
28712 ctxt->user_sax->comment(ctxt->user_data, value);
28716 * Varargs error callbacks to the user application, harder ...
28719 static void XMLCDECL
28720 warningSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
28721 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28722 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28723 (ctxt->user_sax->warning != NULL)) {
28724 TODO
28727 static void XMLCDECL
28728 errorSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
28729 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28730 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28731 (ctxt->user_sax->error != NULL)) {
28732 TODO
28735 static void XMLCDECL
28736 fatalErrorSplit(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
28737 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28738 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28739 (ctxt->user_sax->fatalError != NULL)) {
28740 TODO
28745 * Those are function where both the user handler and the schemas handler
28746 * need to be called.
28748 static void
28749 charactersSplit(void *ctx, const xmlChar *ch, int len)
28751 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28752 if (ctxt == NULL)
28753 return;
28754 if ((ctxt->user_sax != NULL) && (ctxt->user_sax->characters != NULL))
28755 ctxt->user_sax->characters(ctxt->user_data, ch, len);
28756 if (ctxt->ctxt != NULL)
28757 xmlSchemaSAXHandleText(ctxt->ctxt, ch, len);
28760 static void
28761 ignorableWhitespaceSplit(void *ctx, const xmlChar *ch, int len)
28763 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28764 if (ctxt == NULL)
28765 return;
28766 if ((ctxt->user_sax != NULL) &&
28767 (ctxt->user_sax->ignorableWhitespace != NULL))
28768 ctxt->user_sax->ignorableWhitespace(ctxt->user_data, ch, len);
28769 if (ctxt->ctxt != NULL)
28770 xmlSchemaSAXHandleText(ctxt->ctxt, ch, len);
28773 static void
28774 cdataBlockSplit(void *ctx, const xmlChar *value, int len)
28776 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28777 if (ctxt == NULL)
28778 return;
28779 if ((ctxt->user_sax != NULL) &&
28780 (ctxt->user_sax->cdataBlock != NULL))
28781 ctxt->user_sax->cdataBlock(ctxt->user_data, value, len);
28782 if (ctxt->ctxt != NULL)
28783 xmlSchemaSAXHandleCDataSection(ctxt->ctxt, value, len);
28786 static void
28787 referenceSplit(void *ctx, const xmlChar *name)
28789 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28790 if (ctxt == NULL)
28791 return;
28792 if ((ctxt != NULL) && (ctxt->user_sax != NULL) &&
28793 (ctxt->user_sax->reference != NULL))
28794 ctxt->user_sax->reference(ctxt->user_data, name);
28795 if (ctxt->ctxt != NULL)
28796 xmlSchemaSAXHandleReference(ctxt->user_data, name);
28799 static void
28800 startElementNsSplit(void *ctx, const xmlChar * localname,
28801 const xmlChar * prefix, const xmlChar * URI,
28802 int nb_namespaces, const xmlChar ** namespaces,
28803 int nb_attributes, int nb_defaulted,
28804 const xmlChar ** attributes) {
28805 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28806 if (ctxt == NULL)
28807 return;
28808 if ((ctxt->user_sax != NULL) &&
28809 (ctxt->user_sax->startElementNs != NULL))
28810 ctxt->user_sax->startElementNs(ctxt->user_data, localname, prefix,
28811 URI, nb_namespaces, namespaces,
28812 nb_attributes, nb_defaulted,
28813 attributes);
28814 if (ctxt->ctxt != NULL)
28815 xmlSchemaSAXHandleStartElementNs(ctxt->ctxt, localname, prefix,
28816 URI, nb_namespaces, namespaces,
28817 nb_attributes, nb_defaulted,
28818 attributes);
28821 static void
28822 endElementNsSplit(void *ctx, const xmlChar * localname,
28823 const xmlChar * prefix, const xmlChar * URI) {
28824 xmlSchemaSAXPlugPtr ctxt = (xmlSchemaSAXPlugPtr) ctx;
28825 if (ctxt == NULL)
28826 return;
28827 if ((ctxt->user_sax != NULL) &&
28828 (ctxt->user_sax->endElementNs != NULL))
28829 ctxt->user_sax->endElementNs(ctxt->user_data, localname, prefix, URI);
28830 if (ctxt->ctxt != NULL)
28831 xmlSchemaSAXHandleEndElementNs(ctxt->ctxt, localname, prefix, URI);
28835 * xmlSchemaSAXPlug:
28836 * @ctxt: a schema validation context
28837 * @sax: a pointer to the original xmlSAXHandlerPtr
28838 * @user_data: a pointer to the original SAX user data pointer
28840 * Plug a SAX based validation layer in a SAX parsing event flow.
28841 * The original @saxptr and @dataptr data are replaced by new pointers
28842 * but the calls to the original will be maintained.
28844 * Returns a pointer to a data structure needed to unplug the validation layer
28845 * or NULL in case of errors.
28847 xmlSchemaSAXPlugPtr
28848 xmlSchemaSAXPlug(xmlSchemaValidCtxtPtr ctxt,
28849 xmlSAXHandlerPtr *sax, void **user_data)
28851 xmlSchemaSAXPlugPtr ret;
28852 xmlSAXHandlerPtr old_sax;
28854 if ((ctxt == NULL) || (sax == NULL) || (user_data == NULL))
28855 return(NULL);
28858 * We only allow to plug into SAX2 event streams
28860 old_sax = *sax;
28861 if ((old_sax != NULL) && (old_sax->initialized != XML_SAX2_MAGIC))
28862 return(NULL);
28863 if ((old_sax != NULL) &&
28864 (old_sax->startElementNs == NULL) && (old_sax->endElementNs == NULL) &&
28865 ((old_sax->startElement != NULL) || (old_sax->endElement != NULL)))
28866 return(NULL);
28869 * everything seems right allocate the local data needed for that layer
28871 ret = (xmlSchemaSAXPlugPtr) xmlMalloc(sizeof(xmlSchemaSAXPlugStruct));
28872 if (ret == NULL) {
28873 return(NULL);
28875 memset(ret, 0, sizeof(xmlSchemaSAXPlugStruct));
28876 ret->magic = XML_SAX_PLUG_MAGIC;
28877 ret->schemas_sax.initialized = XML_SAX2_MAGIC;
28878 ret->ctxt = ctxt;
28879 ret->user_sax_ptr = sax;
28880 ret->user_sax = old_sax;
28881 if (old_sax == NULL) {
28883 * go direct, no need for the split block and functions.
28885 ret->schemas_sax.startElementNs = xmlSchemaSAXHandleStartElementNs;
28886 ret->schemas_sax.endElementNs = xmlSchemaSAXHandleEndElementNs;
28888 * Note that we use the same text-function for both, to prevent
28889 * the parser from testing for ignorable whitespace.
28891 ret->schemas_sax.ignorableWhitespace = xmlSchemaSAXHandleText;
28892 ret->schemas_sax.characters = xmlSchemaSAXHandleText;
28894 ret->schemas_sax.cdataBlock = xmlSchemaSAXHandleCDataSection;
28895 ret->schemas_sax.reference = xmlSchemaSAXHandleReference;
28897 ret->user_data = ctxt;
28898 *user_data = ctxt;
28899 } else {
28901 * for each callback unused by Schemas initialize it to the Split
28902 * routine only if non NULL in the user block, this can speed up
28903 * things at the SAX level.
28905 if (old_sax->internalSubset != NULL)
28906 ret->schemas_sax.internalSubset = internalSubsetSplit;
28907 if (old_sax->isStandalone != NULL)
28908 ret->schemas_sax.isStandalone = isStandaloneSplit;
28909 if (old_sax->hasInternalSubset != NULL)
28910 ret->schemas_sax.hasInternalSubset = hasInternalSubsetSplit;
28911 if (old_sax->hasExternalSubset != NULL)
28912 ret->schemas_sax.hasExternalSubset = hasExternalSubsetSplit;
28913 if (old_sax->resolveEntity != NULL)
28914 ret->schemas_sax.resolveEntity = resolveEntitySplit;
28915 if (old_sax->getEntity != NULL)
28916 ret->schemas_sax.getEntity = getEntitySplit;
28917 if (old_sax->entityDecl != NULL)
28918 ret->schemas_sax.entityDecl = entityDeclSplit;
28919 if (old_sax->notationDecl != NULL)
28920 ret->schemas_sax.notationDecl = notationDeclSplit;
28921 if (old_sax->attributeDecl != NULL)
28922 ret->schemas_sax.attributeDecl = attributeDeclSplit;
28923 if (old_sax->elementDecl != NULL)
28924 ret->schemas_sax.elementDecl = elementDeclSplit;
28925 if (old_sax->unparsedEntityDecl != NULL)
28926 ret->schemas_sax.unparsedEntityDecl = unparsedEntityDeclSplit;
28927 if (old_sax->setDocumentLocator != NULL)
28928 ret->schemas_sax.setDocumentLocator = setDocumentLocatorSplit;
28929 if (old_sax->startDocument != NULL)
28930 ret->schemas_sax.startDocument = startDocumentSplit;
28931 if (old_sax->endDocument != NULL)
28932 ret->schemas_sax.endDocument = endDocumentSplit;
28933 if (old_sax->processingInstruction != NULL)
28934 ret->schemas_sax.processingInstruction = processingInstructionSplit;
28935 if (old_sax->comment != NULL)
28936 ret->schemas_sax.comment = commentSplit;
28937 if (old_sax->warning != NULL)
28938 ret->schemas_sax.warning = warningSplit;
28939 if (old_sax->error != NULL)
28940 ret->schemas_sax.error = errorSplit;
28941 if (old_sax->fatalError != NULL)
28942 ret->schemas_sax.fatalError = fatalErrorSplit;
28943 if (old_sax->getParameterEntity != NULL)
28944 ret->schemas_sax.getParameterEntity = getParameterEntitySplit;
28945 if (old_sax->externalSubset != NULL)
28946 ret->schemas_sax.externalSubset = externalSubsetSplit;
28949 * the 6 schemas callback have to go to the splitter functions
28950 * Note that we use the same text-function for ignorableWhitespace
28951 * if possible, to prevent the parser from testing for ignorable
28952 * whitespace.
28954 ret->schemas_sax.characters = charactersSplit;
28955 if ((old_sax->ignorableWhitespace != NULL) &&
28956 (old_sax->ignorableWhitespace != old_sax->characters))
28957 ret->schemas_sax.ignorableWhitespace = ignorableWhitespaceSplit;
28958 else
28959 ret->schemas_sax.ignorableWhitespace = charactersSplit;
28960 ret->schemas_sax.cdataBlock = cdataBlockSplit;
28961 ret->schemas_sax.reference = referenceSplit;
28962 ret->schemas_sax.startElementNs = startElementNsSplit;
28963 ret->schemas_sax.endElementNs = endElementNsSplit;
28965 ret->user_data_ptr = user_data;
28966 ret->user_data = *user_data;
28967 *user_data = ret;
28971 * plug the pointers back.
28973 *sax = &(ret->schemas_sax);
28974 ctxt->sax = *sax;
28975 ctxt->flags |= XML_SCHEMA_VALID_CTXT_FLAG_STREAM;
28976 xmlSchemaPreRun(ctxt);
28977 return(ret);
28981 * xmlSchemaSAXUnplug:
28982 * @plug: a data structure returned by xmlSchemaSAXPlug
28984 * Unplug a SAX based validation layer in a SAX parsing event flow.
28985 * The original pointers used in the call are restored.
28987 * Returns 0 in case of success and -1 in case of failure.
28990 xmlSchemaSAXUnplug(xmlSchemaSAXPlugPtr plug)
28992 xmlSAXHandlerPtr *sax;
28993 void **user_data;
28995 if ((plug == NULL) || (plug->magic != XML_SAX_PLUG_MAGIC))
28996 return(-1);
28997 plug->magic = 0;
28999 xmlSchemaPostRun(plug->ctxt);
29000 /* restore the data */
29001 sax = plug->user_sax_ptr;
29002 *sax = plug->user_sax;
29003 if (plug->user_sax != NULL) {
29004 user_data = plug->user_data_ptr;
29005 *user_data = plug->user_data;
29008 /* free and return */
29009 xmlFree(plug);
29010 return(0);
29014 * xmlSchemaValidateSetLocator:
29015 * @vctxt: a schema validation context
29016 * @f: the locator function pointer
29017 * @ctxt: the locator context
29019 * Allows to set a locator function to the validation context,
29020 * which will be used to provide file and line information since
29021 * those are not provided as part of the SAX validation flow
29022 * Setting @f to NULL disable the locator.
29025 void
29026 xmlSchemaValidateSetLocator(xmlSchemaValidCtxtPtr vctxt,
29027 xmlSchemaValidityLocatorFunc f,
29028 void *ctxt)
29030 if (vctxt == NULL) return;
29031 vctxt->locFunc = f;
29032 vctxt->locCtxt = ctxt;
29036 * xmlSchemaValidateStreamLocator:
29037 * @ctx: the xmlTextReaderPtr used
29038 * @file: returned file information
29039 * @line: returned line information
29041 * Internal locator function for the readers
29043 * Returns 0 in case the Schema validation could be (de)activated and
29044 * -1 in case of error.
29046 static int
29047 xmlSchemaValidateStreamLocator(void *ctx, const char **file,
29048 unsigned long *line) {
29049 xmlParserCtxtPtr ctxt;
29051 if ((ctx == NULL) || ((file == NULL) && (line == NULL)))
29052 return(-1);
29054 if (file != NULL)
29055 *file = NULL;
29056 if (line != NULL)
29057 *line = 0;
29059 ctxt = (xmlParserCtxtPtr) ctx;
29060 if (ctxt->input != NULL) {
29061 if (file != NULL)
29062 *file = ctxt->input->filename;
29063 if (line != NULL)
29064 *line = ctxt->input->line;
29065 return(0);
29067 return(-1);
29071 * xmlSchemaValidateStream:
29072 * @ctxt: a schema validation context
29073 * @input: the input to use for reading the data
29074 * @enc: an optional encoding information
29075 * @sax: a SAX handler for the resulting events
29076 * @user_data: the context to provide to the SAX handler.
29078 * Validate an input based on a flow of SAX event from the parser
29079 * and forward the events to the @sax handler with the provided @user_data
29080 * the user provided @sax handler must be a SAX2 one.
29082 * Returns 0 if the document is schemas valid, a positive error code
29083 * number otherwise and -1 in case of internal or API error.
29086 xmlSchemaValidateStream(xmlSchemaValidCtxtPtr ctxt,
29087 xmlParserInputBufferPtr input, xmlCharEncoding enc,
29088 xmlSAXHandlerPtr sax, void *user_data)
29090 xmlSchemaSAXPlugPtr plug = NULL;
29091 xmlParserCtxtPtr pctxt = NULL;
29092 xmlParserInputPtr inputStream = NULL;
29093 int ret;
29095 if ((ctxt == NULL) || (input == NULL))
29096 return (-1);
29099 * prepare the parser
29101 if (sax != NULL) {
29102 pctxt = xmlNewSAXParserCtxt(sax, user_data);
29103 if (pctxt == NULL)
29104 return (-1);
29105 } else {
29106 pctxt = xmlNewParserCtxt();
29107 if (pctxt == NULL)
29108 return (-1);
29109 /* We really want pctxt->sax to be NULL here. */
29110 xmlFree(pctxt->sax);
29111 pctxt->sax = NULL;
29113 #if 0
29114 if (options)
29115 xmlCtxtUseOptions(pctxt, options);
29116 #endif
29117 pctxt->linenumbers = 1;
29118 xmlSchemaValidateSetLocator(ctxt, xmlSchemaValidateStreamLocator, pctxt);
29120 inputStream = xmlNewIOInputStream(pctxt, input, enc);;
29121 if (inputStream == NULL) {
29122 ret = -1;
29123 goto done;
29125 inputPush(pctxt, inputStream);
29126 ctxt->parserCtxt = pctxt;
29127 ctxt->input = input;
29130 * Plug the validation and launch the parsing
29132 plug = xmlSchemaSAXPlug(ctxt, &(pctxt->sax), &(pctxt->userData));
29133 if (plug == NULL) {
29134 ret = -1;
29135 goto done;
29137 ctxt->input = input;
29138 ctxt->enc = enc;
29139 ctxt->sax = pctxt->sax;
29140 ctxt->flags |= XML_SCHEMA_VALID_CTXT_FLAG_STREAM;
29141 ret = xmlSchemaVStart(ctxt);
29143 if ((ret == 0) && (! ctxt->parserCtxt->wellFormed)) {
29144 ret = ctxt->parserCtxt->errNo;
29145 if (ret == 0)
29146 ret = 1;
29149 done:
29150 ctxt->parserCtxt = NULL;
29151 ctxt->sax = NULL;
29152 ctxt->input = NULL;
29153 if (plug != NULL) {
29154 xmlSchemaSAXUnplug(plug);
29156 /* cleanup */
29157 if (pctxt != NULL) {
29158 xmlFreeParserCtxt(pctxt);
29160 return (ret);
29164 * xmlSchemaValidateFile:
29165 * @ctxt: a schema validation context
29166 * @filename: the URI of the instance
29167 * @options: a future set of options, currently unused
29169 * Do a schemas validation of the given resource, it will use the
29170 * SAX streamable validation internally.
29172 * Returns 0 if the document is valid, a positive error code
29173 * number otherwise and -1 in case of an internal or API error.
29176 xmlSchemaValidateFile(xmlSchemaValidCtxtPtr ctxt,
29177 const char * filename,
29178 int options ATTRIBUTE_UNUSED)
29180 int ret;
29181 xmlParserInputBufferPtr input;
29183 if ((ctxt == NULL) || (filename == NULL))
29184 return (-1);
29186 input = xmlParserInputBufferCreateFilename(filename,
29187 XML_CHAR_ENCODING_NONE);
29188 if (input == NULL)
29189 return (-1);
29190 ret = xmlSchemaValidateStream(ctxt, input, XML_CHAR_ENCODING_NONE,
29191 NULL, NULL);
29192 return (ret);
29196 * xmlSchemaValidCtxtGetParserCtxt:
29197 * @ctxt: a schema validation context
29199 * allow access to the parser context of the schema validation context
29201 * Returns the parser context of the schema validation context or NULL
29202 * in case of error.
29204 xmlParserCtxtPtr
29205 xmlSchemaValidCtxtGetParserCtxt(xmlSchemaValidCtxtPtr ctxt)
29207 if (ctxt == NULL)
29208 return(NULL);
29209 return (ctxt->parserCtxt);
29212 #endif /* LIBXML_SCHEMAS_ENABLED */